Devicetree
 help / color / mirror / Atom feed
* Re: [PATCH v10] gpio: add a driver for the Synopsys DesignWare APB GPIO block
From: delicious quinoa @ 2014-02-06 22:09 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Linus Walleij, linux-kernel@vger.kernel.org,
	linux-gpio@vger.kernel.org, linux-doc@vger.kernel.org, Jamie Iles,
	devicetree@vger.kernel.org, Grant Likely, rob.herring@calxeda.com,
	Steffen Trumtrar, Sebastian Hesselbarth, Heiko Stuebner,
	Alan Tull, Dinh Nguyen, Yves Vandervennet
In-Reply-To: <20140206170325.GF16551@e106331-lin.cambridge.arm.com>

On Thu, Feb 6, 2014 at 11:03 AM, Mark Rutland <mark.rutland@arm.com> wrote:
> On Thu, Feb 06, 2014 at 03:55:47PM +0000, Alan Tull wrote:
>> From: Jamie Iles <jamie@jamieiles.com>
>>
>> The Synopsys DesignWare block is used in some ARM devices (picoxcell)
>> and can be configured to provide multiple banks of GPIO pins.
>>
>> Signed-off-by: Jamie Iles <jamie@jamieiles.com>
>> Signed-off-by: Alan Tull <atull@altera.com>
>> Reviewed-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
>>
>> v10:    - in documentation nr-gpio -> nr-gpios
>> v9:     - cleanup in dt bindings doc
>>         - use of_get_child_count()
>> v8:     - remove socfpga.dtsi changes
>>         - minor cleanup in devicetree documentation
>> v7:     - use irq_generic_chip
>>         - support one irq per gpio line or one irq for many
>>         - s/bank/port/ and other cleanup
>> v6:     - (atull) squash the set of patches
>>         - use linear irq domain
>>         - build fixes. Original driver was reviewed on v3.2.
>>         - Fix setting irq edge type for 'rising' and 'both'.
>>         - Support as a loadable module.
>>         - Use bgpio_chip's spinlock during register access.
>>         - Clean up register names to match spec
>>         - s/bank/port/ because register names use the word 'port'
>>         - s/nr-gpio/nr-gpios/
>>         - don't get/put the of_node
>>         - remove signoffs/acked-by's because of changes
>>         - other cleanup
>> v5:     - handle sparse bank population correctly
>> v3:     - depend on rather than select IRQ_DOMAIN
>>         - split IRQ support into a separate patch
>> v2:     - use Rob Herring's irqdomain in generic irq chip patches
>>         - use reg property to indicate bank index
>>         - support irqs on both edges based on LinusW's u300 driver
>> ---
>>  .../devicetree/bindings/gpio/snps-dwapb-gpio.txt   |   59 +++
>>  drivers/gpio/Kconfig                               |    9 +
>>  drivers/gpio/Makefile                              |    1 +
>>  drivers/gpio/gpio-dwapb.c                          |  415 ++++++++++++++++++++
>>  4 files changed, 484 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
>>  create mode 100644 drivers/gpio/gpio-dwapb.c
>>
>> diff --git a/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt b/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
>> new file mode 100644
>> index 0000000..cb01f9f
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
>> @@ -0,0 +1,59 @@
>> +* Synopsys DesignWare APB GPIO controller
>> +
>> +Required properties:
>> +- compatible : Should contain "snps,dw-apb-gpio"
>> +- reg : Address and length of the register set for the device
>
> Presumably #address-cells and #size-cells should be described here?
>
>> +
>> +The GPIO controller has a configurable number of ports, each of which are
>> +represented as child nodes with the following properties:
>> +
>> +Required properties:
>> +- compatible : "snps,dw-apb-gpio-port"
>> +- 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 optional parameters (currently
>> +  unused).
>
> Why not just have this as one cell for now if the second cell is unused?
>
> If it needs to be expanded the driver can read #gpio-cells to figure out
> what to do at runtime, and it prevents crap DTSs in the mean time that
> could get in the way if you need to use additional cells in future.
>
>> +- reg : The integer port index of the port, a single cell.
>> +- #address-cells : should be 1.
>> +- #size-cells : should be 0.
>
> As mentioned above, presumably #address-cells and #size-cells should be
> in the parent node, as is the case in the example?
>
>> +
>> +Optional properties:
>> +- interrupt-controller : The first port may be configured to be an interrupt
>> +controller.
>> +- #interrupt-cells : Specifies the number of cells needed to encode an
>> +interrupt.  Shall be set to 2.  The first cell defines the interrupt number,
>> +the second encodes the triger flags encoded as described in
>> +Documentation/devicetree/bindings/interrupts.txt
>> +- interrupt-parent : The parent interrupt controller.
>> +- interrupts : The interrupts to the parent controller raised when GPIOs
>> +generate the interrupts.
>
> How many are expected?
>
> Otherwise, the binding looks ok to me.
>
> [...]
>
>> +static void dwapb_configure_irqs(struct dwapb_gpio *gpio,
>> +                                struct dwapb_gpio_port *port)
>> +{
>> +       struct gpio_chip *gc = &port->bgc.gc;
>> +       struct device_node *node =  gc->of_node;
>> +       struct irq_chip_generic *irq_gc;
>> +       unsigned int hwirq, ngpio = gc->ngpio;
>> +       struct irq_chip_type *ct;
>> +       int reg, err, irq;
>> +
>> +       if (of_get_property(node, "interrupts", &reg) == NULL)
>> +               return;
>
> of_get_property can take a NULL lenp (core OF code depends on this
> fact), so you don't need the somewhat confusing &reg here.
>
> Cheers,
> Mark.

Hi Mark,

Thanks for the feedback.  I have made the changes in v11, which I just sent out.

Alan Tull
aka
delicious quinoa

^ permalink raw reply

* [PATCH 0/2] Add Ether DT support for R8A7791/Koelsch reference board
From: Sergei Shtylyov @ 2014-02-06 22:10 UTC (permalink / raw)
  To: horms, linux-sh, devicetree
  Cc: magnus.damm, linux, linux-arm-kernel, robh+dt, pawel.moll,
	mark.rutland, ijc+devicetree, galak

Hello.

   Here's the set of 2 patches against Simon Horman's 'renesas.git' repo,
'renesas-devel-v3.14-rc1-20140206v2' tag. Here we add the Ether device tree
support working on the R8A7791/Koelsch reference board. The patchset requires
the 'sh_eth' driver device tree support posted earlier in order to work.

[1/2] ARM: shmobile: r8a7791: add Ether DT support
[2/2] ARM: shmobile: koelsch: add Ether DT support

WBR, Sergei

^ permalink raw reply

* [PATCH 1/2] ARM: shmobile: r8a7791: add Ether DT support
From: Sergei Shtylyov @ 2014-02-06 22:12 UTC (permalink / raw)
  To: horms, linux-sh, devicetree, robh+dt, pawel.moll, mark.rutland,
	ijc+devicetree, galak
  Cc: magnus.damm, linux, linux-arm-kernel

Define the generic R8A7791 part of the Ether device node. 

Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>

---
 arch/arm/boot/dts/r8a7791.dtsi |   15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

Index: renesas/arch/arm/boot/dts/r8a7791.dtsi
===================================================================
--- renesas.orig/arch/arm/boot/dts/r8a7791.dtsi
+++ renesas/arch/arm/boot/dts/r8a7791.dtsi
@@ -2,7 +2,8 @@
  * Device Tree Source for the r8a7791 SoC
  *
  * Copyright (C) 2013 Renesas Electronics Corporation
- * Copyright (C) 2013 Renesas Solutions Corp.
+ * Copyright (C) 2013-2014 Renesas Solutions Corp.
+ * Copyright (C) 2014 Cogent Embedded Inc.
  *
  * This file is licensed under the terms of the GNU General Public License
  * version 2.  This program is licensed "as is" without any warranty of any
@@ -366,6 +367,18 @@
 		status = "disabled";
 	};
 
+	ether: ethernet@ee700000 {
+		compatible = "renesas,ether-r8a7791";
+		reg = <0 0xee700000 0 0x400>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 162 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp8_clks R8A7791_CLK_ETHER>;
+		phy-mode = "rmii";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
 	sata0: sata@ee300000 {
 		compatible = "renesas,sata-r8a7791";
 		reg = <0 0xee300000 0 0x2000>;

^ permalink raw reply

* [PATCH 2/2] ARM: shmobile: koelsch: add Ether DT support
From: Sergei Shtylyov @ 2014-02-06 22:14 UTC (permalink / raw)
  To: horms, robh+dt, pawel.moll, mark.rutland, ijc+devicetree, galak
  Cc: linux-sh, devicetree, magnus.damm, linux, linux-arm-kernel
In-Reply-To: <201402070110.18561.sergei.shtylyov@cogentembedded.com>

Define the Koelsch board dependent part of the Ether device node. 

Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>

---
 arch/arm/boot/dts/r8a7791-koelsch.dts |   31 ++++++++++++++++++++++++++++++-
 1 file changed, 30 insertions(+), 1 deletion(-)

Index: renesas/arch/arm/boot/dts/r8a7791-koelsch.dts
===================================================================
--- renesas.orig/arch/arm/boot/dts/r8a7791-koelsch.dts
+++ renesas/arch/arm/boot/dts/r8a7791-koelsch.dts
@@ -2,7 +2,8 @@
  * Device Tree Source for the Koelsch board
  *
  * Copyright (C) 2013 Renesas Electronics Corporation
- * Copyright (C) 2013 Renesas Solutions Corp.
+ * Copyright (C) 2013-2014 Renesas Solutions Corp.
+ * Copyright (C) 2014 Cogent Embedded, Inc.
  *
  * This file is licensed under the terms of the GNU General Public License
  * version 2.  This program is licensed "as is" without any warranty of any
@@ -122,12 +123,40 @@
 		renesas,function = "scif1";
 	};
 
+	ether_pins: ether {
+		renesas,groups = "eth_link", "eth_mdio", "eth_rmii";
+		renesas,function = "eth";
+	};
+
+	phy1_pins: phy1 {
+		renesas,groups = "intc_irq0";
+		renesas,function = "intc";
+	};
+
 	qspi_pins: spi {
 		renesas,groups = "qspi_ctrl", "qspi_data4";
 		renesas,function = "qspi";
 	};
 };
 
+&ether {
+	pinctrl-0 = <&ether_pins>;
+	pinctrl-names = "default";
+
+	phy-handle = <&phy1>;
+	renesas,ether-link-active-low;
+	status = "ok";
+
+	phy1: ethernet-phy@1 {
+		reg = <1>;
+		interrupt-parent = <&irqc0>;
+		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+
+		pinctrl-0 = <&phy1_pins>;
+		pinctrl-names = "default";
+	};
+};
+
 &sata0 {
 	status = "okay";
 };

^ permalink raw reply

* [PATCHv2 1/2] net: stmmac: Add SOCFPGA glue driver
From: dinguyen-EIB2kfCEclfQT0dZR+AlfA @ 2014-02-06 23:19 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA
  Cc: dinh.linux-Re5JQEeQqe8AvxtiuMwx3w,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Dinh Nguyen,
	Giuseppe Cavallaro, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Vince Bridgers

From: Dinh Nguyen <dinguyen-EIB2kfCEclfQT0dZR+AlfA@public.gmane.org>

Like the STi series SOCs, Altera's SOCFPGA also needs a glue layer on top of the
Synopsys gmac IP.

This patch adds the platform driver for the glue layer which configures the IP
before the generic STMMAC driver takes over.

Signed-off-by: Dinh Nguyen <dinguyen-EIB2kfCEclfQT0dZR+AlfA@public.gmane.org>
Cc: Giuseppe Cavallaro <peppe.cavallaro-qxv4g6HH51o@public.gmane.org>
Cc: Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Cc: Pawel Moll <pawel.moll-5wv7dgnIgG8@public.gmane.org>
Cc: Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>
Cc: Ian Campbell <ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg@public.gmane.org>
Cc: Kumar Gala <galak-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
Cc: Vince Bridgers <vbridgers2013-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
v2: Use the dwmac-sti as an example for a glue layer and split patch up
to have dts as a separate patch. Also cc dts maintainers since there is
a new binding.
---
 drivers/net/ethernet/stmicro/stmmac/Makefile       |    1 +
 .../net/ethernet/stmicro/stmmac/dwmac-socfpga.c    |  184 ++++++++++++++++++++
 2 files changed, 185 insertions(+)
 create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c

diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index ecadece..73df8b6 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_STMMAC_ETH) += stmmac.o
+stmmac-$(CONFIG_ARCH_SOCFPGA) += dwmac-socfpga.o
 stmmac-$(CONFIG_STMMAC_PLATFORM) += stmmac_platform.o
 stmmac-$(CONFIG_STMMAC_PCI) += stmmac_pci.o
 stmmac-$(CONFIG_DWMAC_SUNXI) += dwmac-sunxi.o
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
new file mode 100644
index 0000000..0a6da3e
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
@@ -0,0 +1,184 @@
+/*  Copyright (C) 2014 Altera Corporation
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Adopted from dwmac-sti.c
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_net.h>
+#include <linux/of_platform.h>
+#include <linux/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/stmmac.h>
+
+#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII 0x0
+#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII 0x1
+#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII 0x2
+#define SYSMGR_EMACGRP_CTRL_PHYSEL_WIDTH 2
+#define SYSMGR_EMACGRP_CTRL_PHYSEL_MASK 0x00000003
+
+struct socfpga_dwmac {
+	int	interface;
+	u32	reg_offset;
+	struct	device *dev;
+	struct regmap *sys_mgr_base_addr;
+	struct	device_node *dwmac_np;
+};
+
+static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *dev)
+{
+	struct device_node *np	= dev->of_node;
+	struct device_node *stmmac_np;
+	struct regmap *sys_mgr_base_addr;
+	u32 reg_offset;
+	int ret;
+
+	stmmac_np = of_get_next_available_child(np, NULL);
+	if (!stmmac_np) {
+		dev_info(dev, "No dwmac node found\n");
+		return -EINVAL;
+	}
+
+	if (!of_device_is_compatible(stmmac_np, "snps,dwmac")) {
+		dev_info(dev, "dwmac node isn't compatible with snps,dwmac\n");
+		return -EINVAL;
+	}
+
+	dwmac->interface = of_get_phy_mode(stmmac_np);
+	of_node_put(stmmac_np);
+
+	sys_mgr_base_addr = syscon_regmap_lookup_by_phandle(np, "altr,sysmgr-syscon");
+	if (IS_ERR(sys_mgr_base_addr)) {
+		dev_info(dev, "No sysmgr-syscon node found\n");
+		return PTR_ERR(sys_mgr_base_addr);
+	}
+
+	ret = of_property_read_u32_index(np, "altr,sysmgr-syscon", 1, &reg_offset);
+	if (ret) {
+		dev_info(dev, "Could not reg_offset into sysmgr-syscon!\n");
+		return -EINVAL;
+	}
+
+	dwmac->reg_offset = reg_offset;
+	dwmac->sys_mgr_base_addr = sys_mgr_base_addr;
+	dwmac->dwmac_np = stmmac_np;
+	dwmac->dev = dev;
+
+	return 0;
+}
+
+static int socfpga_dwmac_setup(struct socfpga_dwmac *dwmac)
+{
+	struct regmap *sys_mgr_base_addr = dwmac->sys_mgr_base_addr;
+	int phymode = dwmac->interface;
+	u32 reg_offset = dwmac->reg_offset;
+	u32 ctrl, val, shift = 0;
+
+	if (of_machine_is_compatible("altr,socfpga-vt"))
+		return 0;
+
+	switch (phymode) {
+	case PHY_INTERFACE_MODE_RGMII:
+		val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII;
+		break;
+	case PHY_INTERFACE_MODE_MII:
+	case PHY_INTERFACE_MODE_GMII:
+		val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII;
+		break;
+	default:
+		dev_err(dwmac->dev, "bad phy mode %d\n", phymode);
+		return -EINVAL;
+	}
+
+	regmap_read(sys_mgr_base_addr, reg_offset, &ctrl);
+	ctrl &= ~(SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << shift);
+	ctrl |= val << shift;
+
+	regmap_write(sys_mgr_base_addr, reg_offset, ctrl);
+	return 0;
+}
+
+static int socfpga_dwmac_probe(struct platform_device *pdev)
+{
+	struct device		*dev = &pdev->dev;
+	struct device_node	*node = dev->of_node;
+	int			ret = -ENOMEM;
+	struct socfpga_dwmac	*dwmac;
+
+	dwmac = devm_kzalloc(dev, sizeof(*dwmac), GFP_KERNEL);
+	if (!dwmac)
+		return -ENOMEM;
+
+	ret = socfpga_dwmac_parse_data(dwmac, dev);
+	if (ret) {
+		dev_err(dev, "Unable to parse OF data\n");
+		return ret;
+	}
+
+	ret = socfpga_dwmac_setup(dwmac);
+	if (ret) {
+		dev_err(dev, "couldn't setup SoC glue (%d)\n", ret);
+		return ret;
+	}
+
+	if (node) {
+		ret = of_platform_populate(node, NULL, NULL, dev);
+		if (ret) {
+			dev_err(dev, "failed to add dwmac core\n");
+			return ret;
+		}
+	} else {
+		dev_err(dev, "no device node, failed to add dwmac core\n");
+		return -ENODEV;
+	}
+
+	platform_set_drvdata(pdev, dwmac);
+
+	return 0;
+}
+
+static int socfpga_dwmac_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static const struct of_device_id socfpga_dwmac_match[] = {
+	{ .compatible = "altr,socfpga-stmmac" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, socfpga_dwmac_match);
+
+static struct platform_driver socfpga_dwmac_driver = {
+	.probe		= socfpga_dwmac_probe,
+	.remove		= socfpga_dwmac_remove,
+	.driver		= {
+		.name	= "socfpga-dwmac",
+		.of_match_table = of_match_ptr(socfpga_dwmac_match),
+	},
+};
+
+module_platform_driver(socfpga_dwmac_driver);
+
+MODULE_ALIAS("platform:socfpga-dwmac");
+MODULE_AUTHOR("Dinh Nguyen <dinguyen-EIB2kfCEclfQT0dZR+AlfA@public.gmane.org>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Altera SOCFPGA DWMAC Glue Layer");
+
-- 
1.7.9.5

--
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

* [PATCHv2 2/2] dts: socfpga: Add DTS entry for adding the stmmac glue layer for stmmac.
From: dinguyen @ 2014-02-06 23:19 UTC (permalink / raw)
  To: netdev
  Cc: dinh.linux, devicetree, Dinh Nguyen, Giuseppe Cavallaro,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Vince Bridgers
In-Reply-To: <1391728795-30435-1-git-send-email-dinguyen@altera.com>

From: Dinh Nguyen <dinguyen@altera.com>

This patch adds the dts bindings documenation for the Altera SOCFPGA glue
layer for the Synopsys STMMAC ethernet driver.

Signed-off-by: Dinh Nguyen <dinguyen@altera.com>
Cc: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
Cc: Kumar Gala <galak@codeaurora.org>
Cc: Vince Bridgers <vbridgers2013@gmail.com>
---
v2: Use the dwmac-sti as an example for a glue layer and split patch up
to have dts as a separate patch. Also cc dts maintainers since there is
a new binding.
---
 .../devicetree/bindings/net/socfpga-dwmac.txt      |   35 ++++++++++++++
 arch/arm/boot/dts/socfpga.dtsi                     |   51 +++++++++++++-------
 arch/arm/boot/dts/socfpga_arria5_socdk.dts         |   24 +++++++++
 arch/arm/boot/dts/socfpga_cyclone5.dtsi            |    6 ---
 arch/arm/boot/dts/socfpga_cyclone5_socdk.dts       |   18 +++++++
 arch/arm/boot/dts/socfpga_cyclone5_sockit.dts      |   22 ++++++++-
 arch/arm/boot/dts/socfpga_vt.dts                   |   13 +++--
 7 files changed, 140 insertions(+), 29 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/net/socfpga-dwmac.txt

diff --git a/Documentation/devicetree/bindings/net/socfpga-dwmac.txt b/Documentation/devicetree/bindings/net/socfpga-dwmac.txt
new file mode 100644
index 0000000..d53d376
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/socfpga-dwmac.txt
@@ -0,0 +1,35 @@
+Altera SOCFPGA SoC DWMAC controller
+
+The device node has following properties.
+
+Required properties:
+ - compatible	: Should contain "altr,socfpga-stmmac"
+ - altr,sysmgr-syscon : Should be the phandle to the system manager node that
+   encompasses the glue register, and the register offset.
+
+Sub-nodes:
+The dwmac core should be added as subnode to SOCFPGA dwmac glue.
+- dwmac :	The binding details of dwmac can be found in
+  Documentation/devicetree/bindings/net/stmmac.txt
+
+Example:
+
+ethernet0: ethernet0 {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	compatible = "altr,socfpga-stmmac";
+	altr,sysmgr-syscon = <&sysmgr 0x60>;
+	status = "disabled";
+	ranges;
+
+	gmac0: gmac0@ff700000 {
+		compatible = "snps,dwmac-3.70a", "snps,dwmac";
+		reg = <0xff700000 0x2000>;
+		interrupts = <0 115 4>;
+		interrupt-names = "macirq";
+		mac-address = [00 00 00 00 00 00];/* Filled in by U-Boot */
+		clocks = <&emac0_clk>;
+		clock-names = "stmmaceth";
+	};
+};
diff --git a/arch/arm/boot/dts/socfpga.dtsi b/arch/arm/boot/dts/socfpga.dtsi
index 8c4adb7..ebf6113 100644
--- a/arch/arm/boot/dts/socfpga.dtsi
+++ b/arch/arm/boot/dts/socfpga.dtsi
@@ -442,26 +442,43 @@
 				};
 			};
 
-		gmac0: ethernet@ff700000 {
-			compatible = "altr,socfpga-stmmac", "snps,dwmac-3.70a", "snps,dwmac";
-			reg = <0xff700000 0x2000>;
-			interrupts = <0 115 4>;
-			interrupt-names = "macirq";
-			mac-address = [00 00 00 00 00 00];/* Filled in by U-Boot */
-			clocks = <&emac0_clk>;
-			clock-names = "stmmaceth";
+		ethernet0: ethernet0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "altr,socfpga-stmmac";
+			altr,sysmgr-syscon = <&sysmgr 0x60>;
 			status = "disabled";
+			ranges;
+
+			gmac0: gmac0@ff700000 {
+				compatible = "snps,dwmac-3.70a", "snps,dwmac";
+				reg = <0xff700000 0x2000>;
+				interrupts = <0 115 4>;
+				interrupt-names = "macirq";
+				mac-address = [00 00 00 00 00 00];/* Filled in by U-Boot */
+				clocks = <&emac0_clk>;
+				clock-names = "stmmaceth";
+			};
 		};
 
-		gmac1: ethernet@ff702000 {
-			compatible = "altr,socfpga-stmmac", "snps,dwmac-3.70a", "snps,dwmac";
-			reg = <0xff702000 0x2000>;
-			interrupts = <0 120 4>;
-			interrupt-names = "macirq";
-			mac-address = [00 00 00 00 00 00];/* Filled in by U-Boot */
-			clocks = <&emac1_clk>;
-			clock-names = "stmmaceth";
+		ethernet1: ethernet1 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "altr,socfpga-stmmac";
+			altr,sysmgr-syscon = <&sysmgr 0x60>;
 			status = "disabled";
+			ranges;
+
+			gmac1: gmac1@ff702000 {
+				device_type = "network";
+				compatible = "snps,dwmac-3.70a", "snps,dwmac";
+				reg = <0xff702000 0x2000>;
+				interrupts = <0 120 4>;
+				interrupt-names = "macirq";
+				mac-address = [00 00 00 00 00 00];/* Filled in by U-Boot */
+				clocks = <&emac1_clk>;
+				clock-names = "stmmaceth";
+			};
 		};
 
 		L2: l2-cache@fffef000 {
@@ -538,7 +555,7 @@
 			reg = <0xffd05000 0x1000>;
 		};
 
-		sysmgr@ffd08000 {
+		sysmgr: sysmgr@ffd08000 {
 				compatible = "altr,sys-mgr", "syscon";
 				reg = <0xffd08000 0x4000>;
 			};
diff --git a/arch/arm/boot/dts/socfpga_arria5_socdk.dts b/arch/arm/boot/dts/socfpga_arria5_socdk.dts
index 5beffb2..2d6b38b 100644
--- a/arch/arm/boot/dts/socfpga_arria5_socdk.dts
+++ b/arch/arm/boot/dts/socfpga_arria5_socdk.dts
@@ -37,4 +37,28 @@
 		*/
 		ethernet0 = &gmac1;
 	};
+
+	aliases {
+		/* this allow the ethaddr uboot environmnet variable contents
+		 * to be added to the gmac1 device tree blob.
+		 */
+		ethernet0 = &gmac1;
+	};
+};
+
+&ethernet1 {
+	status = "okay";
+};
+
+&gmac1 {
+	phy-mode = "rgmii";
+
+	rxd0-skew-ps = <0>;
+	rxd1-skew-ps = <0>;
+	rxd2-skew-ps = <0>;
+	rxd3-skew-ps = <0>;
+	txen-skew-ps = <0>;
+	txc-skew-ps = <2600>;
+	rxdv-skew-ps = <0>;
+	rxc-skew-ps = <2000>;
 };
diff --git a/arch/arm/boot/dts/socfpga_cyclone5.dtsi b/arch/arm/boot/dts/socfpga_cyclone5.dtsi
index ca41b0e..454148d 100644
--- a/arch/arm/boot/dts/socfpga_cyclone5.dtsi
+++ b/arch/arm/boot/dts/socfpga_cyclone5.dtsi
@@ -39,12 +39,6 @@
 			};
 		};
 
-		ethernet@ff702000 {
-			phy-mode = "rgmii";
-			phy-addr = <0xffffffff>; /* probe for phy addr */
-			status = "okay";
-		};
-
 		timer0@ffc08000 {
 			clock-frequency = <100000000>;
 		};
diff --git a/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts b/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts
index 2ee52ab..9b3b01b 100644
--- a/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts
+++ b/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts
@@ -38,3 +38,21 @@
 		ethernet0 = &gmac1;
 	};
 };
+
+&ethernet1 {
+	status = "okay";
+};
+
+&gmac1 {
+	phy-mode = "rgmii";
+
+	rxd0-skew-ps = <0>;
+	rxd1-skew-ps = <0>;
+	rxd2-skew-ps = <0>;
+	rxd3-skew-ps = <0>;
+	txen-skew-ps = <0>;
+	txc-skew-ps = <2600>;
+	rxdv-skew-ps = <0>;
+	rxc-skew-ps = <2000>;
+};
+
diff --git a/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts b/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts
index 50b99a2..469bb5c 100644
--- a/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts
+++ b/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts
@@ -30,8 +30,28 @@
 		device_type = "memory";
 		reg = <0x0 0x40000000>; /* 1GB */
 	};
+
+	aliases {
+		/* this allow the ethaddr uboot environmnet variable contents
+		 * to be added to the gmac1 device tree blob.
+		 */
+		ethernet0 = &gmac1;
+	};
 };
 
-&gmac1 {
+&ethernet1 {
 	status = "okay";
 };
+
+&gmac1 {
+	phy-mode = "rgmii";
+
+	rxd0-skew-ps = <0>;
+	rxd1-skew-ps = <0>;
+	rxd2-skew-ps = <0>;
+	rxd3-skew-ps = <0>;
+	txen-skew-ps = <0>;
+	txc-skew-ps = <2600>;
+	rxdv-skew-ps = <0>;
+	rxc-skew-ps = <2000>;
+};
diff --git a/arch/arm/boot/dts/socfpga_vt.dts b/arch/arm/boot/dts/socfpga_vt.dts
index 222313f..418472c 100644
--- a/arch/arm/boot/dts/socfpga_vt.dts
+++ b/arch/arm/boot/dts/socfpga_vt.dts
@@ -52,11 +52,6 @@
 			};
 		};
 
-		ethernet@ff700000 {
-			phy-mode = "gmii";
-			status = "okay";
-		};
-
 		timer0@ffc08000 {
 			clock-frequency = <7000000>;
 		};
@@ -86,3 +81,11 @@
 		};
 	};
 };
+
+&ethernet0 {
+        status = "okay";
+};
+
+&gmac0 {
+	phy-mode = "gmii";
+};
-- 
1.7.9.5

^ permalink raw reply related

* Re: [PATCH v5 02/20] clocksource: orion: Use atomic access for shared registers
From: Daniel Lezcano @ 2014-02-06 23:47 UTC (permalink / raw)
  To: Ezequiel Garcia, Jason Cooper
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA, Lior Amsalem, Andrew Lunn,
	Tawfik Bayouk, Wim Van Sebroeck, Arnd Bergmann, Gregory Clement,
	Guenter Roeck, Sebastian Hesselbarth
In-Reply-To: <20140205231903.GA30244@localhost>

On 02/05/2014 11:19 PM, Ezequiel Garcia wrote:
> On Wed, Feb 05, 2014 at 02:10:35PM -0500, Jason Cooper wrote:
>> On Mon, Jan 27, 2014 at 12:27:02PM -0300, Ezequiel Garcia wrote:
>>> Replace the driver-specific thread-safe shared register API
>>> by the recently introduced atomic_io_clear_set().
>>>
>>> Cc: Daniel Lezcano <daniel.lezcano-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>>> Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>>> Signed-off-by: Ezequiel Garcia <ezequiel.garcia-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
>>> ---
>>>   drivers/clocksource/time-orion.c | 28 ++++++++++------------------
>>>   1 file changed, 10 insertions(+), 18 deletions(-)
>>
>> The MMIO patch this depends on:
>>
>>    c5ca95b507c8 ARM: 7930/1: Introduce atomic MMIO modify
>>
>> made it in to v3.14-rc1.  It looks like this change is independent of
>> the rest of the watchdog series, so:
>>
>> Acked-by: Jason Cooper <jason-NLaQJdtUoK4Be96aLqz0jA@public.gmane.org>
>>
>
> Thanks, Jason.
>
> Daniel: If you can pick this I'll drop it from the next watchdog patchset
> submission.

Yep, ok. I am out of the office for the moment, I will take care of it 
Monday.

Thanks
   -- Daniel


-- 
  <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog

--
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 v3] sh_eth: add device tree support
From: Simon Horman @ 2014-02-07  1:29 UTC (permalink / raw)
  To: Sergei Shtylyov
  Cc: robh+dt, pawel.moll, mark.rutland, grant.likely, devicetree,
	linux-sh, ijc+devicetree, galak, nobuhiro.iwamatsu.yj, rob,
	linux-doc
In-Reply-To: <201402060258.57025.sergei.shtylyov@cogentembedded.com>

On Thu, Feb 06, 2014 at 02:58:56AM +0300, Sergei Shtylyov wrote:
> Add support of the device tree probing for the Renesas SH-Mobile SoCs
> documenting the device tree binding as necessary.
> 
> This work is loosely based on the original patch by Nobuhiro Iwamatsu
> <nobuhiro.iwamatsu.yj@renesas.com>.
> 
> Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>

Acked-by: Simon Horman <horms+renesas@verge.net.au>


> ---
> This patch is against DaveM's 'net-next.git' repo but should also apply to the
> recent 'renesas.git' repo's 'devel' branch. It assumes the patch documenting all
> Ethernet bindings in one file to be applied as well.
> Not posting it to netdev@vger.kernel.org this time, or Dave will scold me. :-)

I would prefer if such orthogonal dependencies weren't introduced.
I'm quite fine if you want to refactor things, but from my point
of view it would be nice to tackle such projects after merging new features.

> 
> Changes in version 3:
> - added probing for R8A7791 and R7S72100;
> - added irq_of_parse_and_map() call to read PHY IRQ from device tree;
> - removed '!phy' check before reading the PHY node's "reg" property;
> - replaced "phy-handle" and "phy-mode" property descriptions with references to
>   the common Ethernet bindings file;
> - added "clocks" required property; 
> - removed "local-mac-address" optional property; 
> - replaced Armadiallo800EVA board with Lager board in the binding example;
> - updated driver's copyrights;
> - refreshed the patch.
> 
> Changes in version 2:
> - added sh_eth_match_table[] entry for "renesas,ether-r8a7778", documented it;
> - clarified descriptions of the "reg" and "interrupt" properties;
> - moved "interrupt-parent" from required properties to optional;
> - mentioned the necessary PHY subnode to the "phy-handle" property description,
>   documented the requered "#address-cells" and "#size-cells" properties;
> - clarified the types/descriptions of the Renesas specific properties;
> - refreshed the patch.
> 
>  Documentation/devicetree/bindings/net/sh_eth.txt |   55 ++++++++++++++++
>  drivers/net/ethernet/renesas/sh_eth.c            |   75 ++++++++++++++++++++++-
>  2 files changed, 127 insertions(+), 3 deletions(-)
> 
> Index: net-next/Documentation/devicetree/bindings/net/sh_eth.txt
> ===================================================================
> --- /dev/null
> +++ net-next/Documentation/devicetree/bindings/net/sh_eth.txt
> @@ -0,0 +1,55 @@
> +* Renesas Electronics SH EtherMAC
> +
> +This file provides information on what the device node for the SH EtherMAC
> +interface contains.
> +
> +Required properties:
> +- compatible: "renesas,gether-r8a7740" if the device is a part of R8A7740 SoC.
> +	      "renesas,ether-r8a7778"  if the device is a part of R8A7778 SoC.
> +	      "renesas,ether-r8a7779"  if the device is a part of R8A7779 SoC.
> +	      "renesas,ether-r8a7790"  if the device is a part of R8A7790 SoC.
> +	      "renesas,ether-r8a7791"  if the device is a part of R8A7791 SoC.
> +	      "renesas,ether-r7s72100" if the device is a part of R7S72100 SoC.
> +- reg: offset and length of (1) the E-DMAC/feLic register block (required),
> +       (2) the TSU register block (optional).
> +- interrupts: interrupt specifier for the sole interrupt.
> +- phy-mode: see ethernet.txt file in the same directory.
> +- phy-handle: see ethernet.txt file in the same directory.
> +- #address-cells: number of address cells for the MDIO bus, must be equal to 1.
> +- #size-cells: number of size cells on the MDIO bus, must be equal to 0.
> +- clocks: clock phandle and specifier pair.
> +- pinctrl-0: phandle, referring to a default pin configuration node.
> +
> +Optional properties:
> +- interrupt-parent: the phandle for the interrupt controller that services
> +		    interrupts for this device.
> +- pinctrl-names: pin configuration state name ("default").
> +- renesas,no-ether-link: boolean, specify when a board does not provide a proper
> +			 Ether LINK signal.
> +- renesas,ether-link-active-low: boolean, specify when the Ether LINK signal is
> +				 active-low instead of normal active-high.
> +
> +Example (Lager board):
> +
> +	ethernet@ee700000 {
> +		compatible = "renesas,ether-r8a7790";
> +		reg = <0 0xee700000 0 0x400>;
> +		interrupt-parent = <&gic>;
> +		interrupts = <0 162 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&mstp8_clks R8A7790_CLK_ETHER>;
> +		phy-mode = "rmii";
> +		phy-handle = <&phy1>;
> +		pinctrl-0 = <&ether_pins>;
> +		pinctrl-names = "default";
> +		renesas,ether-link-active-low;
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		phy1: ethernet-phy@1 {
> +			reg = <1>;
> +			interrupt-parent = <&irqc0>;
> +			interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
> +			pinctrl-0 = <&phy1_pins>;
> +			pinctrl-names = "default";
> +		};
> +	};
> Index: net-next/drivers/net/ethernet/renesas/sh_eth.c
> ===================================================================
> --- net-next.orig/drivers/net/ethernet/renesas/sh_eth.c
> +++ net-next/drivers/net/ethernet/renesas/sh_eth.c
> @@ -1,8 +1,8 @@
>  /*  SuperH Ethernet device driver
>   *
>   *  Copyright (C) 2006-2012 Nobuhiro Iwamatsu
> - *  Copyright (C) 2008-2013 Renesas Solutions Corp.
> - *  Copyright (C) 2013 Cogent Embedded, Inc.
> + *  Copyright (C) 2008-2014 Renesas Solutions Corp.
> + *  Copyright (C) 2013-2014 Cogent Embedded, Inc.
>   *
>   *  This program is free software; you can redistribute it and/or modify it
>   *  under the terms and conditions of the GNU General Public License,
> @@ -27,6 +27,10 @@
>  #include <linux/platform_device.h>
>  #include <linux/mdio-bitbang.h>
>  #include <linux/netdevice.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/of_irq.h>
> +#include <linux/of_net.h>
>  #include <linux/phy.h>
>  #include <linux/cache.h>
>  #include <linux/io.h>
> @@ -2710,6 +2714,56 @@ static const struct net_device_ops sh_et
>  	.ndo_change_mtu		= eth_change_mtu,
>  };
>  
> +#ifdef CONFIG_OF
> +static struct sh_eth_plat_data *sh_eth_parse_dt(struct device *dev)
> +{
> +	struct device_node *np = dev->of_node;
> +	struct sh_eth_plat_data *pdata;
> +	struct device_node *phy;
> +	const char *mac_addr;
> +
> +	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
> +	if (!pdata)
> +		return NULL;
> +
> +	pdata->phy_interface = of_get_phy_mode(np);
> +
> +	phy = of_parse_phandle(np, "phy-handle", 0);
> +	if (of_property_read_u32(phy, "reg", &pdata->phy)) {
> +		devm_kfree(dev, pdata);
> +		return NULL;
> +	}
> +	pdata->phy_irq = irq_of_parse_and_map(phy, 0);
> +
> +	mac_addr = of_get_mac_address(np);
> +	if (mac_addr)
> +		memcpy(pdata->mac_addr, mac_addr, ETH_ALEN);
> +
> +	pdata->no_ether_link =
> +		of_property_read_bool(np, "renesas,no-ether-link");
> +	pdata->ether_link_active_low =
> +		of_property_read_bool(np, "renesas,ether-link-active-low");
> +
> +	return pdata;
> +}
> +
> +static const struct of_device_id sh_eth_match_table[] = {
> +	{ .compatible = "renesas,gether-r8a7740", .data = &r8a7740_data },
> +	{ .compatible = "renesas,ether-r8a7778", .data = &r8a777x_data },
> +	{ .compatible = "renesas,ether-r8a7779", .data = &r8a777x_data },
> +	{ .compatible = "renesas,ether-r8a7790", .data = &r8a779x_data },
> +	{ .compatible = "renesas,ether-r8a7791", .data = &r8a779x_data },
> +	{ .compatible = "renesas,ether-r7s72100", .data = &r7s72100_data },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(of, sh_eth_match_table);
> +#else
> +static inline struct sh_eth_plat_data *sh_eth_parse_dt(struct device *dev)
> +{
> +	return NULL;
> +}
> +#endif
> +
>  static int sh_eth_drv_probe(struct platform_device *pdev)
>  {
>  	int ret, devno = 0;
> @@ -2763,6 +2817,8 @@ static int sh_eth_drv_probe(struct platf
>  	pm_runtime_enable(&pdev->dev);
>  	pm_runtime_resume(&pdev->dev);
>  
> +	if (pdev->dev.of_node)
> +		pd = sh_eth_parse_dt(&pdev->dev);
>  	if (!pd) {
>  		dev_err(&pdev->dev, "no platform data\n");
>  		ret = -EINVAL;
> @@ -2778,7 +2834,19 @@ static int sh_eth_drv_probe(struct platf
>  	mdp->ether_link_active_low = pd->ether_link_active_low;
>  
>  	/* set cpu data */
> -	mdp->cd = (struct sh_eth_cpu_data *)id->driver_data;
> +	if (id) {
> +		mdp->cd = (struct sh_eth_cpu_data *)id->driver_data;
> +	} else	{
> +		const struct of_device_id *match;
> +
> +		match = of_match_device(of_match_ptr(sh_eth_match_table),
> +					&pdev->dev);
> +		if (!match) {
> +			ret = -EINVAL;
> +			goto out_release;
> +		}
> +		mdp->cd = (struct sh_eth_cpu_data *)match->data;
> +	}
>  	mdp->reg_offset = sh_eth_get_register_offset(mdp->cd->register_type);
>  	sh_eth_set_default_cpu_data(mdp->cd);
>  
> @@ -2920,6 +2988,7 @@ static struct platform_driver sh_eth_dri
>  	.driver = {
>  		   .name = CARDNAME,
>  		   .pm = SH_ETH_PM_OPS,
> +		   .of_match_table = of_match_ptr(sh_eth_match_table),
>  	},
>  };
>  
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sh" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply

* Re: [PATCH v2 6/8] hwmon: da9055: Remove use of regmap_irq_get_virq()
From: Guenter Roeck @ 2014-02-07  1:29 UTC (permalink / raw)
  To: Adam Thomson, Mark Brown, Lee Jones
  Cc: alsa-devel, linux-kernel, devicetree, Rob Herring, Linus Walleij,
	Dmitry Torokhov, Alessandro Zummo
In-Reply-To: <43bbe337fea5ac7e19b97179f2abb7e74684d0eb.1391705989.git.Adam.Thomson.Opensource@diasemi.com>

On 02/06/2014 10:03 AM, Adam Thomson wrote:
> Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
> ---

Applied (after adding the explanation from the introduction).

Thanks,
Guenter

^ permalink raw reply

* Re: [PATCH v6 05/19] watchdog: orion: Make sure the watchdog is initially stopped
From: Guenter Roeck @ 2014-02-07  2:02 UTC (permalink / raw)
  To: Ezequiel Garcia, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA, Wim Van Sebroeck,
	Jason Cooper
  Cc: Thomas Petazzoni, Gregory Clement, Lior Amsalem,
	Sebastian Hesselbarth, Andrew Lunn
In-Reply-To: <1391707226-18258-6-git-send-email-ezequiel.garcia-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>

On 02/06/2014 09:20 AM, Ezequiel Garcia wrote:
> Having the watchdog initially fully stopped is important to avoid
> any spurious watchdog triggers, in case the registers are not in
> its reset state.
>
> Reviewed-by: Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org>
> Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Tested-by: Willy Tarreau <w@1wt.eu>
> Signed-off-by: Ezequiel Garcia <ezequiel.garcia-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> ---
>   drivers/watchdog/orion_wdt.c | 3 +++
>   1 file changed, 3 insertions(+)
>
> diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c
> index 6746033..2dbeee9 100644
> --- a/drivers/watchdog/orion_wdt.c
> +++ b/drivers/watchdog/orion_wdt.c
> @@ -142,6 +142,9 @@ static int orion_wdt_probe(struct platform_device *pdev)
>   	orion_wdt.max_timeout = wdt_max_duration;
>   	watchdog_init_timeout(&orion_wdt, heartbeat, &pdev->dev);
>
> +	/* Let's make sure the watchdog is fully stopped */
> +	orion_wdt_stop(&orion_wdt);
> +

Actually we just had that in another driver, and I stumbled over it there.

Problem with stopping the watchdog in probe unconditionally is that you can
use it to defeat nowayout: unload the module, then load it again,
and the watchdog is stopped even if nowayout is true.

Is this really what you want ? Or, in other words, what is the problem
you are trying to solve ?

Thanks,
Guenter


>   	watchdog_set_nowayout(&orion_wdt, nowayout);
>   	ret = watchdog_register_device(&orion_wdt);
>   	if (ret)
>

--
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 v6 17/19] watchdog: orion: Enable the build on ARCH_MVEBU
From: Guenter Roeck @ 2014-02-07  2:07 UTC (permalink / raw)
  To: Ezequiel Garcia, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA, Wim Van Sebroeck,
	Jason Cooper
  Cc: Thomas Petazzoni, Gregory Clement, Lior Amsalem,
	Sebastian Hesselbarth, Andrew Lunn
In-Reply-To: <1391707226-18258-18-git-send-email-ezequiel.garcia-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>

On 02/06/2014 09:20 AM, Ezequiel Garcia wrote:
> After adding support for Armada 370/XP SoC let's enable the build on
> these platforms.
>
> Tested-by: Willy Tarreau <w@1wt.eu>
> Signed-off-by: Ezequiel Garcia <ezequiel.garcia-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>

Reviewed-by: Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org>

> ---
>   drivers/watchdog/Kconfig | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> index 4c4c566..2dda6c0 100644
> --- a/drivers/watchdog/Kconfig
> +++ b/drivers/watchdog/Kconfig
> @@ -291,7 +291,7 @@ config DAVINCI_WATCHDOG
>
>   config ORION_WATCHDOG
>   	tristate "Orion watchdog"
> -	depends on ARCH_ORION5X || ARCH_KIRKWOOD || ARCH_DOVE
> +	depends on ARCH_ORION5X || ARCH_KIRKWOOD || ARCH_DOVE || ARCH_MVEBU
>   	select WATCHDOG_CORE
>   	help
>   	  Say Y here if to include support for the watchdog timer
>

--
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 v1 1/3] net: stmmac:sti: Add STi SOC glue driver.
From: David Miller @ 2014-02-07  3:53 UTC (permalink / raw)
  To: srinivas.kandagatla
  Cc: netdev, robh+dt, pawel.moll, mark.rutland, ijc+devicetree, galak,
	rob, linux, stuart.menefy, peppe.cavallaro, devicetree, linux-doc,
	linux-kernel, linux-arm-kernel, kernel
In-Reply-To: <1391428868-27245-1-git-send-email-srinivas.kandagatla@st.com>

From: <srinivas.kandagatla@st.com>
Date: Mon, 3 Feb 2014 12:01:08 +0000

> +	res = platform_get_resource_byname(pdev,
> +				IORESOURCE_MEM, "sti-ethconf");

This is not the correct way to format multi-line function calls,
you'll need to fix this up in this entire series.

The arguments on the second and subsequent lines must start at
the first column after the openning parenthesis of the function
call.  You must use the appropriate number of both space and
TAB characters necessary to do so.

If you're only using TAB characters to indent, you're doing it
wrong.

Thank you.

^ permalink raw reply

* Re: [PATCH v5 00/14] Add support for MSM's mmio clock/reset controller
From: Frank Rowand @ 2014-02-07  4:15 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Mike Turquette, linux-kernel, linux-arm-msm, linux-arm-kernel,
	devicetree, Saravana Kannan
In-Reply-To: <1389811654-21397-1-git-send-email-sboyd@codeaurora.org>

On 1/15/2014 10:47 AM, Stephen Boyd wrote:
> The first breaks a reset-controller include ordering requirement. It got
> an ack so I think we're ok for it to go through the clock tree.
> 

< snip >

checkpatch is whining about patches

  4
  5
  6
  7
  8

(Just for completeness if someone thinks I did not check all the patches,
it also whines about patch 11, but I think the whining should be ignored,
and it whines about patch 1 but I think that might be a checkpatch bug.)

-Frank

^ permalink raw reply

* Re: [PATCH v5 00/14] Add support for MSM's mmio clock/reset controller
From: Frank Rowand @ 2014-02-07  4:32 UTC (permalink / raw)
  To: frowand.list, Stephen Boyd
  Cc: Mike Turquette, linux-kernel, linux-arm-msm, linux-arm-kernel,
	devicetree, Saravana Kannan
In-Reply-To: <52F45DEE.8020400@gmail.com>

On 2/6/2014 8:15 PM, Frank Rowand wrote:
> On 1/15/2014 10:47 AM, Stephen Boyd wrote:
>> The first breaks a reset-controller include ordering requirement. It got
>> an ack so I think we're ok for it to go through the clock tree.
>>
> 
> < snip >
> 
> checkpatch is whining about patches
> 

< snip >

Never mind....  I see that the patches are already in 3.14-rc1.

-Frank

^ permalink raw reply

* [PATCH 0/3] Add i.MX6q Kosagi Novena support
From: Sean Cross @ 2014-02-07  5:05 UTC (permalink / raw)
  To: devicetree-u79uwXL29TY76Z2rM5mHXA,
	alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw
  Cc: Shawn Guo, Sascha Hauer, Mark Brown, Liam Girdwood, Sean Cross

The Kosagi Novena board contains an i.MX6 Quad processor.  This patchset
adds support for this platform, along with support for its own audio codec.

The platform uses an ES8328-based codec, which is currently unsupported in
the Linux kernel.  The audio codec supports playback and recording, as well
as jack detection support for the headset.  Audio codec support is required
as an uninitialized audio codec pulls I2C2 lines down, preventing the bus
from working.

There are two known issues with this patch, and I would like some feedback
on them:

    * I'm unclear on how audio routing works.  The ES8328 has five outputs:
      LOUT1, ROUT1, LOUT2, ROUT2, and OUT3.  It also has four inputs.  The
      board maps Headphone L/R to L/ROUT2, and Speaker to L/ROUT1.  What is
      the proper way to describe this audio routing?
    * The snd-soc-imx-novena.ko module oopses when removing it.  The backtrace
      shows that it's caused by "Unable to handle kernel paging request at
      virtual address", due to snd_jack_dev_free possibly getting called twice.
      What could be causing this?  I never explicitly free the jack device:
 (snd_ctl_remove) from [<804c73d0>] (snd_jack_dev_free+0x48/0x68)
 (snd_jack_dev_free) from [<804c6ef8>] (snd_device_free+0xd0/0x148)
 (snd_device_free) from [<804c72b0>] (snd_device_free_all+0x90/0xb0)
 (snd_device_free_all) from [<804c20ac>] (snd_card_do_free+0x40/0xec)
 (snd_card_do_free) from [<804c22b4>] (snd_card_free+0x74/0x80)
 (snd_card_free) from [<804de444>] (soc_cleanup_card_resources+0xb4/0xbc)
 (soc_cleanup_card_resources) from [<804de460>] (snd_soc_unregister_card+0x14/0x1c)
 (snd_soc_unregister_card) from [<7f032014>] (imx_novena_remove+0x14/0x1c [snd_soc_imx_novena])
 (imx_novena_remove [snd_soc_imx_novena]) from [<8035c258>] (__device_release_driver+0x64/0xb0)
 (__device_release_driver) from [<8035c81c>] (driver_detach+0xa4/0xcc)
 (driver_detach) from [<8035be88>] (bus_remove_driver+0x64/0x9c)
 (bus_remove_driver) from [<8007ea44>] (SyS_delete_module+0x110/0x188)
 (SyS_delete_module) from [<8000e080>] (ret_fast_syscall+0x0/0x30)


Sean Cross (3):
  sound: soc: codecs: Add es8328 codec
  sound: soc: fsl: Add support for Novena onboard audio
  dts: imx: add kosagi novena imx6q dts file

 arch/arm/boot/dts/imx6q-novena.dts | 517 +++++++++++++++++++++++++++++++
 sound/soc/codecs/Kconfig           |   4 +
 sound/soc/codecs/Makefile          |   2 +
 sound/soc/codecs/es8328.c          | 611 +++++++++++++++++++++++++++++++++++++
 sound/soc/codecs/es8328.h          | 240 +++++++++++++++
 sound/soc/fsl/Kconfig              |  13 +
 sound/soc/fsl/Makefile             |   2 +
 sound/soc/fsl/imx-novena.c         | 344 +++++++++++++++++++++
 8 files changed, 1733 insertions(+)
 create mode 100644 arch/arm/boot/dts/imx6q-novena.dts
 create mode 100644 sound/soc/codecs/es8328.c
 create mode 100644 sound/soc/codecs/es8328.h
 create mode 100644 sound/soc/fsl/imx-novena.c

-- 
1.8.3.2

--
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 1/3] sound: soc: codecs: Add es8328 codec
From: Sean Cross @ 2014-02-07  5:05 UTC (permalink / raw)
  To: devicetree-u79uwXL29TY76Z2rM5mHXA,
	alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw
  Cc: Shawn Guo, Sascha Hauer, Mark Brown, Liam Girdwood, Sean Cross
In-Reply-To: <1391749517-11787-1-git-send-email-xobs-nXMMniAx+RbQT0dZR+AlfA@public.gmane.org>

Add support for the ES8328 audio codec.
---
 sound/soc/codecs/Kconfig  |   4 +
 sound/soc/codecs/Makefile |   2 +
 sound/soc/codecs/es8328.c | 611 ++++++++++++++++++++++++++++++++++++++++++++++
 sound/soc/codecs/es8328.h | 240 ++++++++++++++++++
 4 files changed, 857 insertions(+)
 create mode 100644 sound/soc/codecs/es8328.c
 create mode 100644 sound/soc/codecs/es8328.h

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 983d087a..2b0a821 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -43,6 +43,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_DA732X if I2C
 	select SND_SOC_DA9055 if I2C
 	select SND_SOC_BT_SCO
+	select SND_SOC_ES8328 if I2C
 	select SND_SOC_ISABELLE if I2C
 	select SND_SOC_JZ4740_CODEC
 	select SND_SOC_LM4857 if I2C
@@ -283,6 +284,9 @@ config SND_SOC_BT_SCO
 config SND_SOC_DMIC
 	tristate
 
+config SND_SOC_ES8328
+	tristate
+
 config SND_SOC_ISABELLE
         tristate
 
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index bc12676..1b62c93 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -30,6 +30,7 @@ snd-soc-da732x-objs := da732x.o
 snd-soc-da9055-objs := da9055.o
 snd-soc-bt-sco-objs := bt-sco.o
 snd-soc-dmic-objs := dmic.o
+snd-soc-es8328-objs := es8328.o
 snd-soc-isabelle-objs := isabelle.o
 snd-soc-jz4740-codec-objs := jz4740.o
 snd-soc-l3-objs := l3.o
@@ -163,6 +164,7 @@ obj-$(CONFIG_SND_SOC_DA732X)	+= snd-soc-da732x.o
 obj-$(CONFIG_SND_SOC_DA9055)	+= snd-soc-da9055.o
 obj-$(CONFIG_SND_SOC_BT_SCO)	+= snd-soc-bt-sco.o
 obj-$(CONFIG_SND_SOC_DMIC)	+= snd-soc-dmic.o
+obj-$(CONFIG_SND_SOC_ES8328)    += snd-soc-es8328.o
 obj-$(CONFIG_SND_SOC_ISABELLE)	+= snd-soc-isabelle.o
 obj-$(CONFIG_SND_SOC_JZ4740_CODEC)	+= snd-soc-jz4740-codec.o
 obj-$(CONFIG_SND_SOC_L3)	+= snd-soc-l3.o
diff --git a/sound/soc/codecs/es8328.c b/sound/soc/codecs/es8328.c
new file mode 100644
index 0000000..db118f4
--- /dev/null
+++ b/sound/soc/codecs/es8328.c
@@ -0,0 +1,611 @@
+/*
+ * es8328.c  --  ES8328 ALSA SoC Audio driver
+ *
+ * Copyright 2014 Sutajio Ko-Usagi PTE LTD
+ *
+ * Author: Sean Cross <xobs-nXMMniAx+RbQT0dZR+AlfA@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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/spi/spi.h>
+#include <linux/slab.h>
+#include <linux/of_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include "es8328.h"
+
+/* Run the codec at 22.5792 MHz to support these rates */
+enum es8328_rate {
+	ES8328_RATE_8019,
+	ES8328_RATE_11025,
+	ES8328_RATE_22050,
+	ES8328_RATE_44100,
+};
+
+uint8_t sample_ratios[] = {
+	[ES8328_RATE_8019 ] = 0x9,
+	[ES8328_RATE_11025] = 0x7,
+	[ES8328_RATE_22050] = 0x4,
+	[ES8328_RATE_44100] = 0x2,
+};
+
+#define ES8328_RATES (SNDRV_PCM_RATE_44100 | \
+		SNDRV_PCM_RATE_22050 | \
+		SNDRV_PCM_RATE_11025)
+#define ES8328_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
+
+/* codec private data */
+struct es8328_priv {
+	struct regmap *regmap;
+	int sysclk;
+};
+
+static const DECLARE_TLV_DB_SCALE(play_tlv, -3000, 100, 0);
+static const DECLARE_TLV_DB_SCALE(cap_tlv, -9600, 50, 0);
+static const DECLARE_TLV_DB_SCALE(pga_tlv, 0, 300, 0);
+
+static const struct snd_kcontrol_new es8328_snd_controls[] = {
+SOC_DOUBLE_R_TLV("Speaker Playback Volume",
+		ES8328_DACCONTROL26, ES8328_DACCONTROL27, 0, 0x24, 0, play_tlv),
+SOC_DOUBLE_R_TLV("Headphone Playback Volume",
+		ES8328_DACCONTROL24, ES8328_DACCONTROL25, 0, 0x24, 0, play_tlv),
+
+SOC_DOUBLE_R_TLV("Mic Capture Volume",
+		ES8328_ADCCONTROL8, ES8328_ADCCONTROL9, 0, 0xc0, 1, cap_tlv),
+SOC_DOUBLE_TLV("Mic PGA Volume",
+		ES8328_ADCCONTROL1, 4, 0, 0x08, 0, pga_tlv),
+};
+
+/*
+ * DAPM controls.
+ */
+static const struct snd_soc_dapm_widget es8328_dapm_widgets[] = {
+	SND_SOC_DAPM_DAC("Speaker Volume", "HiFi Playback", SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_OUTPUT("VOUTL"),
+	SND_SOC_DAPM_OUTPUT("VOUTR"),
+        SND_SOC_DAPM_INPUT("LINE_IN"),
+        SND_SOC_DAPM_INPUT("MIC_IN"),
+        SND_SOC_DAPM_OUTPUT("HP_OUT"),
+        SND_SOC_DAPM_OUTPUT("SPK_OUT"),
+};
+
+
+static const struct snd_soc_dapm_route es8328_intercon[] = {
+	{"VOUTL", NULL, "DAC"},
+	{"VOUTR", NULL, "DAC"},
+};
+
+static int es8328_mute(struct snd_soc_dai *dai, int mute)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	u16 mute_reg = snd_soc_read(codec, ES8328_DACCONTROL3);
+
+	if (mute)
+		mute_reg |= ES8328_DACCONTROL3_DACMUTE;
+	else
+		mute_reg &= ~ES8328_DACCONTROL3_DACMUTE;
+	return snd_soc_write(codec, ES8328_DACCONTROL3, mute_reg);
+}
+
+static int es8328_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;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		u8 dac = snd_soc_read(codec, ES8328_DACCONTROL2);
+		dac &= ~ES8328_DACCONTROL2_RATEMASK;
+
+		switch (params_rate(params)) {
+		case 8000:
+			dac |= sample_ratios[ES8328_RATE_8019];
+			break;
+		case 11025:
+			dac |= sample_ratios[ES8328_RATE_11025];
+			break;
+		case 22050:
+			dac |= sample_ratios[ES8328_RATE_22050];
+			break;
+		case 44100:
+			dac |= sample_ratios[ES8328_RATE_44100];
+			break;
+		default:
+			dev_err(codec->dev, "%s: unknown rate %d\n",
+				 __func__, params_rate(params));
+			return -EINVAL;
+		}
+		snd_soc_write(codec, ES8328_DACCONTROL2, dac);
+	}
+
+	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+		u8 adc = snd_soc_read(codec, ES8328_ADCCONTROL5);
+		adc &= ~ES8328_ADCCONTROL5_RATEMASK;
+
+		switch (params_rate(params)) {
+		case 8000:
+			adc |= sample_ratios[ES8328_RATE_8019];
+			break;
+		case 11025:
+			adc |= sample_ratios[ES8328_RATE_11025];
+			break;
+		case 22050:
+			adc |= sample_ratios[ES8328_RATE_22050];
+			break;
+		case 44100:
+			adc |= sample_ratios[ES8328_RATE_44100];
+			break;
+		default:
+			dev_err(codec->dev, "%s: unknown rate %d\n",
+				 __func__, params_rate(params));
+			return -EINVAL;
+		}
+		snd_soc_write(codec, ES8328_ADCCONTROL5, adc);
+	}
+
+	return 0;
+}
+
+static int es8328_set_dai_fmt(struct snd_soc_dai *codec_dai,
+		unsigned int fmt)
+{
+	if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) != SND_SOC_DAIFMT_I2S)
+		return -EINVAL;
+
+	if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBM_CFM)
+		return -EINVAL;
+
+	if ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int es8328_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+			         int clk_id, unsigned int freq, int dir)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct es8328_priv *es8328 = snd_soc_codec_get_drvdata(codec);
+
+	switch (clk_id) {
+	case 0:
+		es8328->sysclk = freq;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int es8328_adc_enable(struct snd_soc_codec *codec)
+{
+	u16 reg = snd_soc_read(codec, ES8328_CHIPPOWER);
+	reg &= ~(ES8328_CHIPPOWER_ADCVREF_OFF |
+		 ES8328_CHIPPOWER_ADCPLL_OFF |
+		 ES8328_CHIPPOWER_ADCSTM_RESET |
+		 ES8328_CHIPPOWER_ADCDIG_OFF);
+	snd_soc_write(codec, ES8328_CHIPPOWER, reg);
+
+	/* Set up microphone to be differential input */
+	snd_soc_write(codec, ES8328_ADCCONTROL2, 0xf0);
+
+	/* Set ADC to act as I2S master */
+	snd_soc_write(codec, ES8328_ADCCONTROL3, 0x02);
+
+	/* Set I2S to 16-bit mode */
+	snd_soc_write(codec, ES8328_ADCCONTROL4, 0x18);
+
+	/* Frequency clock of 272 */
+	snd_soc_write(codec, ES8328_ADCCONTROL5, 0x02);
+
+	return 0;
+}
+
+static int es8328_dac_enable(struct snd_soc_codec *codec)
+{
+	u16 old_volumes[4];
+	u16 reg;
+	int i;
+
+	for (i = 0; i < 4; i++) {
+		old_volumes[i] = snd_soc_read(codec, i + ES8328_DACCONTROL24);
+		snd_soc_write(codec, i + ES8328_DACCONTROL24, 0);
+	}
+
+	/* Power up LOUT2 ROUT2, and power down xOUT1 */
+	snd_soc_write(codec, ES8328_DACPOWER,
+			ES8328_DACPOWER_ROUT2_ON |
+			ES8328_DACPOWER_LOUT2_ON);
+
+	/* Enable click-free power up */
+	snd_soc_write(codec, ES8328_DACCONTROL6, ES8328_DACCONTROL6_CLICKFREE);
+	snd_soc_write(codec, ES8328_DACCONTROL3, 0x36);
+
+	/* Set I2S to 16-bit mode */
+	snd_soc_write(codec, ES8328_DACCONTROL1, ES8328_DACCONTROL1_DACWL_16);
+
+	/* No attenuation */
+	snd_soc_write(codec, ES8328_DACCONTROL4, 0x00);
+	snd_soc_write(codec, ES8328_DACCONTROL5, 0x00);
+
+	/* Set LIN2 for the output mixer */
+	snd_soc_write(codec, ES8328_DACCONTROL16,
+			ES8328_DACCONTROL16_RMIXSEL_RIN2 |
+			ES8328_DACCONTROL16_LMIXSEL_LIN2);
+
+	/* Point the left DAC at the left mixer */
+	snd_soc_write(codec, ES8328_DACCONTROL17, ES8328_DACCONTROL17_LD2LO);
+	/* Point the right DAC at the right mixer */
+	snd_soc_write(codec, ES8328_DACCONTROL20, ES8328_DACCONTROL20_RD2RO);
+
+	/* Disable all other outputs */
+	snd_soc_write(codec, ES8328_DACCONTROL18, 0x00);
+	snd_soc_write(codec, ES8328_DACCONTROL19, 0x00);
+
+
+	/* Disable mono mode for DACL, and mute DACR */
+	snd_soc_write(codec, ES8328_DACCONTROL7, 0x00);
+
+	for (i = 0; i < 4; i++)
+		snd_soc_write(codec, i + ES8328_DACCONTROL24, old_volumes[i]);
+
+	reg = snd_soc_read(codec, ES8328_CHIPPOWER);
+	reg &= ~(ES8328_CHIPPOWER_DACVREF_OFF |
+		 ES8328_CHIPPOWER_DACPLL_OFF |
+		 ES8328_CHIPPOWER_DACSTM_RESET |
+		 ES8328_CHIPPOWER_DACDIG_OFF);
+	snd_soc_write(codec, ES8328_CHIPPOWER, reg);
+	snd_soc_write(codec, ES8328_DACCONTROL3, 0x32);
+
+	return 0;
+}
+
+static int es8328_pcm_prepare(struct snd_pcm_substream *substream,
+			      struct snd_soc_dai *dai)
+{
+	struct snd_soc_codec *codec = dai->codec;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		es8328_dac_enable(codec);
+
+	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+		es8328_adc_enable(codec);
+
+	return 0;
+}
+
+static void es8328_pcm_shutdown(struct snd_pcm_substream *substream,
+				struct snd_soc_dai *dai)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	u16 reg;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		/* Mute DAC */
+		snd_soc_write(codec, ES8328_DACCONTROL3,
+				ES8328_DACCONTROL3_DACZEROCROSS |
+				ES8328_DACCONTROL3_DACSOFTRAMP |
+				ES8328_DACCONTROL3_DACMUTE);
+
+		/* Power down DAC and disable LOUT/ROUT */
+		snd_soc_write(codec, ES8328_DACPOWER,
+				ES8328_DACPOWER_LDAC_OFF |
+				ES8328_DACPOWER_RDAC_OFF);
+
+		/* Power down DEM and STM */
+		reg = snd_soc_read(codec, ES8328_CHIPPOWER);
+		reg |= (ES8328_CHIPPOWER_DACVREF_OFF |
+			ES8328_CHIPPOWER_DACPLL_OFF |
+			ES8328_CHIPPOWER_DACDIG_OFF);
+		snd_soc_write(codec, ES8328_CHIPPOWER, reg);
+	}
+
+	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+		/* Mute ADC */
+		snd_soc_write(codec, ES8328_ADCCONTROL7,
+			ES8328_ADCCONTROL7_ADC_LER |
+			ES8328_ADCCONTROL7_ADC_ZERO_CROSS |
+			ES8328_ADCCONTROL7_ADC_SOFT_RAMP);
+
+		/* Power down ADC */
+		snd_soc_write(codec, ES8328_ADCPOWER,
+			ES8328_ADCPOWER_ADC_BIAS_GEN_OFF |
+			ES8328_ADCPOWER_MIC_BIAS_OFF |
+			ES8328_ADCPOWER_ADCR_OFF |
+			ES8328_ADCPOWER_ADCL_OFF |
+			ES8328_ADCPOWER_AINR_OFF |
+			ES8328_ADCPOWER_AINL_OFF);
+
+		/* Power down DEM and STM */
+		reg = snd_soc_read(codec, ES8328_CHIPPOWER);
+		reg |= (ES8328_CHIPPOWER_ADCVREF_OFF |
+			ES8328_CHIPPOWER_ADCPLL_OFF |
+			ES8328_CHIPPOWER_ADCDIG_OFF);
+		snd_soc_write(codec, ES8328_CHIPPOWER, reg);
+	}
+
+	return;
+}
+
+static int es8328_init(struct snd_soc_codec *codec)
+{
+	/* Master serial port mode */
+	snd_soc_write(codec, ES8328_MASTERMODE,
+			ES8328_MASTERMODE_MCLKDIV2 |
+			ES8328_MASTERMODE_MSC);
+
+	/* Power everything down and reset the cip */
+	snd_soc_write(codec, ES8328_CHIPPOWER,
+			ES8328_CHIPPOWER_DACSTM_RESET |
+			ES8328_CHIPPOWER_ADCSTM_RESET |
+			ES8328_CHIPPOWER_DACDIG_OFF |
+			ES8328_CHIPPOWER_ADCDIG_OFF |
+			ES8328_CHIPPOWER_DACVREF_OFF |
+			ES8328_CHIPPOWER_ADCVREF_OFF);
+
+	/* Power up.  Set ADC and DAC to use different frequency ratios */
+	snd_soc_write(codec, ES8328_CONTROL1,
+			ES8328_CONTROL1_VMIDSEL_50k |
+			ES8328_CONTROL1_ENREF);
+
+	/* Power up more blocks */
+	snd_soc_write(codec, ES8328_CONTROL2,
+			ES8328_CONTROL2_OVERCURRENT_ON |
+			ES8328_CONTROL2_THERMAL_SHUTDOWN_ON);
+
+
+	/* Power on the chip (but leave VRET off) */
+	/*
+	snd_soc_write(codec, ES8328_CHIPPOWER,
+			ES8328_CHIPPOWER_DACVREF_OFF |
+			ES8328_CHIPPOWER_ADCVREF_OFF);
+	*/
+
+
+	/* Enable muting, and turn on zerocross */
+	snd_soc_write(codec, ES8328_DACCONTROL3,
+			ES8328_DACCONTROL3_DACZEROCROSS |
+			ES8328_DACCONTROL3_DACSOFTRAMP |
+			ES8328_DACCONTROL3_DACMUTE);
+
+	return 0;
+}
+
+static const struct snd_soc_dai_ops es8328_dai_ops = {
+	.hw_params	= es8328_hw_params,
+	.prepare	= es8328_pcm_prepare,
+	.shutdown	= es8328_pcm_shutdown,
+//	.digital_mute	= es8328_mute,
+	.set_fmt	= es8328_set_dai_fmt,
+	.set_sysclk	= es8328_set_dai_sysclk,
+};
+
+static struct snd_soc_dai_driver es8328_dai = {
+	.name = "es8328-hifi-analog",
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = ES8328_RATES,
+		.formats = ES8328_FORMATS,
+	},
+	.capture = {
+		.stream_name = "Capture",
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = ES8328_RATES,
+		.formats = ES8328_FORMATS,
+	},
+	.ops = &es8328_dai_ops,
+};
+
+static int es8328_suspend(struct snd_soc_codec *codec)
+{
+	return 0;
+}
+
+static int es8328_resume(struct snd_soc_codec *codec)
+{
+	es8328_init(codec);
+	return 0;
+}
+
+static int es8328_probe(struct snd_soc_codec *codec)
+{
+	int ret;
+	struct device *dev = codec->dev;
+
+	ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
+	if (ret < 0) {
+		dev_err(dev, "failed to configure cache I/O: %d\n", ret);
+		return ret;
+	}
+
+	/* power on device */
+	es8328_init(codec);
+
+	return 0;
+}
+
+static int es8328_remove(struct snd_soc_codec *codec)
+{
+	/* Power everything down and reset the cip */
+	snd_soc_write(codec, ES8328_CHIPPOWER,
+			ES8328_CHIPPOWER_DACSTM_RESET |
+			ES8328_CHIPPOWER_ADCSTM_RESET |
+			ES8328_CHIPPOWER_DACDIG_OFF |
+			ES8328_CHIPPOWER_ADCDIG_OFF |
+			ES8328_CHIPPOWER_DACVREF_OFF |
+			ES8328_CHIPPOWER_ADCVREF_OFF);
+
+	return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_es8328 = {
+	.probe =		es8328_probe,
+	.remove =		es8328_remove,
+	.suspend =		es8328_suspend,
+	.resume =		es8328_resume,
+	.controls =		es8328_snd_controls,
+	.num_controls =		ARRAY_SIZE(es8328_snd_controls),
+	.dapm_widgets =		es8328_dapm_widgets,
+	.num_dapm_widgets =	ARRAY_SIZE(es8328_dapm_widgets),
+	.dapm_routes =		es8328_intercon,
+	.num_dapm_routes =	ARRAY_SIZE(es8328_intercon),
+};
+
+static const struct of_device_id es8328_of_match[] = {
+	{ .compatible = "everest,es8328", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, es8328_of_match);
+
+static const struct regmap_config es8328_regmap = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = ES8328_REG_MAX,
+
+	.cache_type = REGCACHE_NONE,
+};
+
+#if defined(CONFIG_SPI_MASTER)
+static int es8328_spi_probe(struct spi_device *spi)
+{
+	struct es8328_priv *es8328;
+	int ret;
+
+	es8328 = devm_kzalloc(&spi->dev, sizeof(struct es8328_priv),
+			      GFP_KERNEL);
+	if (es8328 == NULL)
+		return -ENOMEM;
+
+	es8328->regmap = devm_regmap_init_spi(spi, &es8328_regmap);
+	if (IS_ERR(es8328->regmap))
+		return PTR_ERR(es8328->regmap);
+
+	spi_set_drvdata(spi, es8328);
+
+	ret = snd_soc_register_codec(&spi->dev,
+			&soc_codec_dev_es8328, &es8328_dai, 1);
+	if (ret < 0)
+		dev_err(&spi->dev, "unable to register codec: %d\n", ret);
+
+	return ret;
+}
+
+static int es8328_spi_remove(struct spi_device *spi)
+{
+	snd_soc_unregister_codec(&spi->dev);
+
+	return 0;
+}
+
+static struct spi_driver es8328_spi_driver = {
+	.driver = {
+		.name	= "es8328",
+		.owner	= THIS_MODULE,
+		.of_match_table = es8328_of_match,
+	},
+	.probe		= es8328_spi_probe,
+	.remove		= es8328_spi_remove,
+};
+#endif /* CONFIG_SPI_MASTER */
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static int es8328_i2c_probe(struct i2c_client *i2c,
+			    const struct i2c_device_id *id)
+{
+	struct es8328_priv *es8328;
+	int ret;
+
+	es8328 = devm_kzalloc(&i2c->dev, sizeof(struct es8328_priv),
+			      GFP_KERNEL);
+	if (es8328 == NULL)
+		return -ENOMEM;
+
+	es8328->regmap = devm_regmap_init_i2c(i2c, &es8328_regmap);
+	if (IS_ERR(es8328->regmap))
+		return PTR_ERR(es8328->regmap);
+
+	i2c_set_clientdata(i2c, es8328);
+
+	ret =  snd_soc_register_codec(&i2c->dev,
+			&soc_codec_dev_es8328, &es8328_dai, 1);
+
+	return ret;
+}
+
+static int es8328_i2c_remove(struct i2c_client *client)
+{
+	snd_soc_unregister_codec(&client->dev);
+	return 0;
+}
+
+static const struct i2c_device_id es8328_i2c_id[] = {
+	{ "es8328", 0x11 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, es8328_i2c_id);
+
+static struct i2c_driver es8328_i2c_driver = {
+	.driver = {
+		.name = "es8328-codec",
+		.owner = THIS_MODULE,
+		.of_match_table = es8328_of_match,
+	},
+	.probe =    es8328_i2c_probe,
+	.remove =   es8328_i2c_remove,
+	.id_table = es8328_i2c_id,
+};
+#endif
+
+static int __init es8328_modinit(void)
+{
+	int ret = 0;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+	ret = i2c_add_driver(&es8328_i2c_driver);
+	if (ret != 0) {
+		pr_err("failed to register es8328 I2C driver: %d\n", ret);
+	}
+#endif
+#if defined(CONFIG_SPI_MASTER)
+	ret = spi_register_driver(&es8328_spi_driver);
+	if (ret != 0) {
+		pr_err("Failed to register es8328 SPI driver: %d\n", ret);
+	}
+#endif
+	return ret;
+}
+module_init(es8328_modinit);
+
+static void __exit es8328_exit(void)
+{
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+	i2c_del_driver(&es8328_i2c_driver);
+#endif
+#if defined(CONFIG_SPI_MASTER)
+	spi_unregister_driver(&es8328_spi_driver);
+#endif
+}
+module_exit(es8328_exit);
+
+MODULE_DESCRIPTION("ASoC ES8328 driver");
+MODULE_AUTHOR("Sean Cross <xobs-nXMMniAx+RbQT0dZR+AlfA@public.gmane.org>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/es8328.h b/sound/soc/codecs/es8328.h
new file mode 100644
index 0000000..234a6cb
--- /dev/null
+++ b/sound/soc/codecs/es8328.h
@@ -0,0 +1,240 @@
+/*
+ * es8328.h  --  ES8328 ALSA SoC Audio driver
+ */
+
+#ifndef _ES8328_H
+#define _ES8328_H
+
+#define ES8328_DACLVOL 46
+#define ES8328_DACRVOL 47
+#define ES8328_DACCTL 28
+
+#define ES8328_CONTROL1		0x00
+#define ES8328_CONTROL1_VMIDSEL_OFF (0 << 0)
+#define ES8328_CONTROL1_VMIDSEL_50k (1 << 0)
+#define ES8328_CONTROL1_VMIDSEL_500k (2 << 0)
+#define ES8328_CONTROL1_VMIDSEL_5k (3 << 0)
+#define ES8328_CONTROL1_ENREF (1 << 2)
+#define ES8328_CONTROL1_SEQEN (1 << 3)
+#define ES8328_CONTROL1_SAMEFS (1 << 4)
+#define ES8328_CONTROL1_DACMCLK_ADC (0 << 5)
+#define ES8328_CONTROL1_DACMCLK_DAC (1 << 5)
+#define ES8328_CONTROL1_LRCM (1 << 6)
+#define ES8328_CONTROL1_SCP_RESET (1 << 7)
+
+#define ES8328_CONTROL2		0x01
+#define ES8328_CONTROL2_VREF_BUF_OFF (1 << 0)
+#define ES8328_CONTROL2_VREF_LOWPOWER (1 << 1)
+#define ES8328_CONTROL2_IBIASGEN_OFF (1 << 2)
+#define ES8328_CONTROL2_ANALOG_OFF (1 << 3)
+#define ES8328_CONTROL2_VREF_BUF_LOWPOWER (1 << 4)
+#define ES8328_CONTROL2_VCM_MOD_LOWPOWER (1 << 5)
+#define ES8328_CONTROL2_OVERCURRENT_ON (1 << 6)
+#define ES8328_CONTROL2_THERMAL_SHUTDOWN_ON (1 << 7)
+
+#define ES8328_CHIPPOWER	0x02
+#define ES8328_CHIPPOWER_DACVREF_OFF (1 << 0)
+#define ES8328_CHIPPOWER_ADCVREF_OFF (1 << 1)
+#define ES8328_CHIPPOWER_DACPLL_OFF (1 << 2)
+#define ES8328_CHIPPOWER_ADCPLL_OFF (1 << 3)
+#define ES8328_CHIPPOWER_DACSTM_RESET (1 << 4)
+#define ES8328_CHIPPOWER_ADCSTM_RESET (1 << 5)
+#define ES8328_CHIPPOWER_DACDIG_OFF (1 << 6)
+#define ES8328_CHIPPOWER_ADCDIG_OFF (1 << 7)
+
+#define ES8328_ADCPOWER		0x03
+#define ES8328_ADCPOWER_INT1_LOWPOWER (1 << 0)
+#define ES8328_ADCPOWER_FLASH_ADC_LOWPOWER (1 << 1)
+#define ES8328_ADCPOWER_ADC_BIAS_GEN_OFF (1 << 2)
+#define ES8328_ADCPOWER_MIC_BIAS_OFF (1 << 3)
+#define ES8328_ADCPOWER_ADCR_OFF (1 << 4)
+#define ES8328_ADCPOWER_ADCL_OFF (1 << 5)
+#define ES8328_ADCPOWER_AINR_OFF (1 << 6)
+#define ES8328_ADCPOWER_AINL_OFF (1 << 7)
+
+#define ES8328_DACPOWER		0x04
+#define ES8328_DACPOWER_OUT3_ON (1 << 0)
+#define ES8328_DACPOWER_MONO_ON (1 << 1)
+#define ES8328_DACPOWER_ROUT2_ON (1 << 2)
+#define ES8328_DACPOWER_LOUT2_ON (1 << 3)
+#define ES8328_DACPOWER_ROUT1_ON (1 << 4)
+#define ES8328_DACPOWER_LOUT1_ON (1 << 5)
+#define ES8328_DACPOWER_RDAC_OFF (1 << 6)
+#define ES8328_DACPOWER_LDAC_OFF (1 << 7)
+
+#define ES8328_CHIPLOPOW1	0x05
+#define ES8328_CHIPLOPOW2	0x06
+#define ES8328_ANAVOLMANAG	0x07
+
+#define ES8328_MASTERMODE	0x08
+#define ES8328_MASTERMODE_BCLKDIV (0 << 0)
+#define ES8328_MASTERMODE_BCLK_INV (1 << 5)
+#define ES8328_MASTERMODE_MCLKDIV2 (1 << 6)
+#define ES8328_MASTERMODE_MSC (1 << 7)
+
+#define ES8328_ADCCONTROL1	0x09
+#define ES8328_ADCCONTROL2	0x0a
+#define ES8328_ADCCONTROL3	0x0b
+#define ES8328_ADCCONTROL4	0x0c
+#define ES8328_ADCCONTROL5	0x0d
+#define ES8328_ADCCONTROL5_RATEMASK (0x1f << 0)
+
+#define ES8328_ADCCONTROL6	0x0e
+
+#define ES8328_ADCCONTROL7	0x0f
+#define ES8328_ADCCONTROL7_ADC_MUTE (1 << 2)
+#define ES8328_ADCCONTROL7_ADC_LER (1 << 3)
+#define ES8328_ADCCONTROL7_ADC_ZERO_CROSS (1 << 4)
+#define ES8328_ADCCONTROL7_ADC_SOFT_RAMP (1 << 5)
+#define ES8328_ADCCONTROL7_ADC_RAMP_RATE_4 (0 << 6)
+#define ES8328_ADCCONTROL7_ADC_RAMP_RATE_8 (1 << 6)
+#define ES8328_ADCCONTROL7_ADC_RAMP_RATE_16 (2 << 6)
+#define ES8328_ADCCONTROL7_ADC_RAMP_RATE_32 (3 << 6)
+
+#define ES8328_ADCCONTROL8	0x10
+#define ES8328_ADCCONTROL9	0x11
+#define ES8328_ADCCONTROL10	0x12
+#define ES8328_ADCCONTROL11	0x13
+#define ES8328_ADCCONTROL12	0x14
+#define ES8328_ADCCONTROL13	0x15
+#define ES8328_ADCCONTROL14	0x16
+
+#define ES8328_DACCONTROL1	0x17
+#define ES8328_DACCONTROL1_DACFORMAT_I2S (0 << 1)
+#define ES8328_DACCONTROL1_DACFORMAT_LJUST (1 << 1)
+#define ES8328_DACCONTROL1_DACFORMAT_RJUST (2 << 1)
+#define ES8328_DACCONTROL1_DACFORMAT_PCM (3 << 1)
+#define ES8328_DACCONTROL1_DACWL_24 (0 << 3)
+#define ES8328_DACCONTROL1_DACWL_20 (1 << 3)
+#define ES8328_DACCONTROL1_DACWL_18 (2 << 3)
+#define ES8328_DACCONTROL1_DACWL_16 (3 << 3)
+#define ES8328_DACCONTROL1_DACWL_32 (4 << 3)
+#define ES8328_DACCONTROL1_DACLRP_I2S_POL_NORMAL (0 << 6)
+#define ES8328_DACCONTROL1_DACLRP_I2S_POL_INV (1 << 6)
+#define ES8328_DACCONTROL1_DACLRP_PCM_MSB_CLK2 (0 << 6)
+#define ES8328_DACCONTROL1_DACLRP_PCM_MSB_CLK1 (0 << 6)
+#define ES8328_DACCONTROL1_LRSWAP (1 << 7)
+
+#define ES8328_DACCONTROL2	0x18
+#define ES8328_DACCONTROL2_RATEMASK (0x1f << 0)
+
+#define ES8328_DACCONTROL3	0x19
+#define ES8328_DACCONTROL3_AUTOMUTE (1 << 2)
+#define ES8328_DACCONTROL3_DACMUTE (1 << 2)
+#define ES8328_DACCONTROL3_LEFTGAINVOL (1 << 3)
+#define ES8328_DACCONTROL3_DACZEROCROSS (1 << 4)
+#define ES8328_DACCONTROL3_DACSOFTRAMP (1 << 5)
+#define ES8328_DACCONTROL3_DACRAMPRATE (3 << 6)
+
+#define ES8328_DACCONTROL4	0x1a
+#define ES8328_DACCONTROL5	0x1b
+
+#define ES8328_DACCONTROL6	0x1c
+#define ES8328_DACCONTROL6_CLICKFREE (1 << 3)
+#define ES8328_DACCONTROL6_DAC_INVR (1 << 4)
+#define ES8328_DACCONTROL6_DAC_INVL (1 << 5)
+#define ES8328_DACCONTROL6_DEEMPH_OFF (0 << 6)
+#define ES8328_DACCONTROL6_DEEMPH_32k (1 << 6)
+#define ES8328_DACCONTROL6_DEEMPH_44_1k (2 << 6)
+#define ES8328_DACCONTROL6_DEEMPH_48k (3 << 6)
+
+#define ES8328_DACCONTROL7	0x1d
+#define ES8328_DACCONTROL8	0x1e
+#define ES8328_DACCONTROL9	0x1f
+#define ES8328_DACCONTROL10	0x20
+#define ES8328_DACCONTROL11	0x21
+#define ES8328_DACCONTROL12	0x22
+#define ES8328_DACCONTROL13	0x23
+#define ES8328_DACCONTROL14	0x24
+#define ES8328_DACCONTROL15	0x25
+
+#define ES8328_DACCONTROL16	0x26
+#define ES8328_DACCONTROL16_RMIXSEL_RIN1 (0 << 0)
+#define ES8328_DACCONTROL16_RMIXSEL_RIN2 (1 << 0)
+#define ES8328_DACCONTROL16_RMIXSEL_RIN3 (2 << 0)
+#define ES8328_DACCONTROL16_RMIXSEL_RADC (3 << 0)
+#define ES8328_DACCONTROL16_LMIXSEL_LIN1 (0 << 3)
+#define ES8328_DACCONTROL16_LMIXSEL_LIN2 (1 << 3)
+#define ES8328_DACCONTROL16_LMIXSEL_LIN3 (2 << 3)
+#define ES8328_DACCONTROL16_LMIXSEL_LADC (3 << 3)
+
+#define ES8328_DACCONTROL17	0x27
+#define ES8328_DACCONTROL17_LI2LOVOL (7 << 3)
+#define ES8328_DACCONTROL17_LI2LO (1 << 6)
+#define ES8328_DACCONTROL17_LD2LO (1 << 7)
+
+#define ES8328_DACCONTROL18	0x28
+#define ES8328_DACCONTROL18_RI2LOVOL (7 << 3)
+#define ES8328_DACCONTROL18_RI2LO (1 << 6)
+#define ES8328_DACCONTROL18_RD2LO (1 << 7)
+
+#define ES8328_DACCONTROL19	0x29
+#define ES8328_DACCONTROL19_LI2ROVOL (7 << 3)
+#define ES8328_DACCONTROL19_LI2RO (1 << 6)
+#define ES8328_DACCONTROL19_LD2RO (1 << 7)
+
+#define ES8328_DACCONTROL20	0x2a
+#define ES8328_DACCONTROL20_RI2ROVOL (7 << 3)
+#define ES8328_DACCONTROL20_RI2RO (1 << 6)
+#define ES8328_DACCONTROL20_RD2RO (1 << 7)
+
+#define ES8328_DACCONTROL21	0x2b
+#define ES8328_DACCONTROL22	0x2c
+#define ES8328_DACCONTROL23	0x2d
+#define ES8328_DACCONTROL24	0x2e
+#define ES8328_DACCONTROL25	0x2f
+#define ES8328_DACCONTROL26	0x30
+#define ES8328_DACCONTROL27	0x31
+#define ES8328_DACCONTROL28	0x32
+#define ES8328_DACCONTROL29	0x33
+#define ES8328_DACCONTROL30	0x34
+#define ES8328_SYSCLK		0
+
+#define ES8328_REG_MAX		0x35
+
+#define ES8328_PLL1		0
+#define ES8328_PLL2		1
+
+/* clock inputs */
+#define ES8328_MCLK		0
+#define ES8328_PCMCLK		1
+
+/* clock divider id's */
+#define ES8328_PCMDIV		0
+#define ES8328_BCLKDIV		1
+#define ES8328_VXCLKDIV		2
+
+/* PCM clock dividers */
+#define ES8328_PCM_DIV_1	(0 << 6)
+#define ES8328_PCM_DIV_3	(2 << 6)
+#define ES8328_PCM_DIV_5_5	(3 << 6)
+#define ES8328_PCM_DIV_2	(4 << 6)
+#define ES8328_PCM_DIV_4	(5 << 6)
+#define ES8328_PCM_DIV_6	(6 << 6)
+#define ES8328_PCM_DIV_8	(7 << 6)
+
+/* BCLK clock dividers */
+#define ES8328_BCLK_DIV_1	(0 << 7)
+#define ES8328_BCLK_DIV_2	(1 << 7)
+#define ES8328_BCLK_DIV_4	(2 << 7)
+#define ES8328_BCLK_DIV_8	(3 << 7)
+
+/* VXCLK clock dividers */
+#define ES8328_VXCLK_DIV_1	(0 << 6)
+#define ES8328_VXCLK_DIV_2	(1 << 6)
+#define ES8328_VXCLK_DIV_4	(2 << 6)
+#define ES8328_VXCLK_DIV_8	(3 << 6)
+#define ES8328_VXCLK_DIV_16	(4 << 6)
+
+#define ES8328_DAI_HIFI		0
+#define ES8328_DAI_VOICE	1
+
+#define ES8328_1536FS		1536
+#define ES8328_1024FS		1024
+#define ES8328_768FS		768
+#define ES8328_512FS		512
+#define ES8328_384FS		384
+#define ES8328_256FS		256
+#define ES8328_128FS		128
+
+#endif
-- 
1.8.3.2

--
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 2/3] sound: soc: fsl: Add support for Novena onboard audio
From: Sean Cross @ 2014-02-07  5:05 UTC (permalink / raw)
  To: devicetree-u79uwXL29TY76Z2rM5mHXA,
	alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw
  Cc: Shawn Guo, Sascha Hauer, Mark Brown, Liam Girdwood, Sean Cross
In-Reply-To: <1391749517-11787-1-git-send-email-xobs-nXMMniAx+RbQT0dZR+AlfA@public.gmane.org>

Novena uses an ES8328 audio codec connected via I2S.
---
 sound/soc/fsl/Kconfig      |  13 ++
 sound/soc/fsl/Makefile     |   2 +
 sound/soc/fsl/imx-novena.c | 344 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 359 insertions(+)
 create mode 100644 sound/soc/fsl/imx-novena.c

diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 07f8f14..88e7fbf 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -163,6 +163,19 @@ config SND_SOC_PHYCORE_AC97
 	  Say Y if you want to add support for SoC audio on Phytec phyCORE
 	  and phyCARD boards in AC97 mode
 
+config SND_SOC_IMX_NOVENA
+	tristate "SoC Audio support for i.MX6-based Novena boards"
+	depends on OF && I2C
+	select SND_SOC_ES8328
+	select SND_SOC_IMX_PCM_DMA
+	select SND_SOC_IMX_AUDMUX
+	select SND_SOC_FSL_SSI
+	select SND_SOC_FSL_UTILS
+	select SND_SOC_IMX_PCM_FIQ
+	help
+	  Say Y if you want to add support for SoC audio on an i.MX board with
+	  an audio codec connected via SSI/I2S.
+
 config SND_SOC_EUKREA_TLV320
 	tristate "Eukrea TLV320"
 	depends on MACH_EUKREA_MBIMX27_BASEBOARD \
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index b12ad4b..fc89017 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -47,6 +47,7 @@ snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o
 snd-soc-phycore-ac97-objs := phycore-ac97.o
 snd-soc-mx27vis-aic32x4-objs := mx27vis-aic32x4.o
 snd-soc-wm1133-ev1-objs := wm1133-ev1.o
+snd-soc-imx-novena-objs := imx-novena.o
 snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o
 snd-soc-imx-wm8962-objs := imx-wm8962.o
 snd-soc-imx-spdif-objs := imx-spdif.o
@@ -56,6 +57,7 @@ obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o
 obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o
 obj-$(CONFIG_SND_SOC_MX27VIS_AIC32X4) += snd-soc-mx27vis-aic32x4.o
 obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o
+obj-$(CONFIG_SND_SOC_IMX_NOVENA) += snd-soc-imx-novena.o
 obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o
 obj-$(CONFIG_SND_SOC_IMX_WM8962) += snd-soc-imx-wm8962.o
 obj-$(CONFIG_SND_SOC_IMX_SPDIF) += snd-soc-imx-spdif.o
diff --git a/sound/soc/fsl/imx-novena.c b/sound/soc/fsl/imx-novena.c
new file mode 100644
index 0000000..6e06de9
--- /dev/null
+++ b/sound/soc/fsl/imx-novena.c
@@ -0,0 +1,344 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2012 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/i2c.h>
+#include <linux/clk.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/clk-provider.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+
+#include "imx-audmux.h"
+
+#define DAI_NAME_SIZE	32
+#define IMX6Q_SYSCLK 0x00
+
+struct imx_novena_data {
+	struct device *dev;
+	struct snd_soc_dai_link dai;
+	struct snd_soc_card card;
+	char codec_dai_name[DAI_NAME_SIZE];
+	char platform_name[DAI_NAME_SIZE];
+	struct clk *codec_clk;
+	struct clk *codec_clk_src;
+	struct clk *codec_clk_sel;
+	struct clk *codec_clk_post_div;
+	struct clk *system_cko;
+	unsigned int clk_freq_src;
+	unsigned int clk_frequency;
+	int power_gpio;
+	int jack_gpio;
+};
+
+static struct snd_soc_jack_gpio headset_jack_gpios[] = {
+	{
+		.gpio = -1,
+		.name = "headset-gpio",
+		.report = SND_JACK_HEADSET,
+		.invert = 0,
+		.debounce_time = 200,
+	},
+};
+
+static struct snd_soc_jack headset_jack;
+
+static int imx_novena_dai_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct imx_novena_data *data = container_of(rtd->card,
+					struct imx_novena_data, card);
+	struct device *dev = rtd->card->dev;
+	int ret;
+
+	ret = snd_soc_dai_set_sysclk(rtd->codec_dai, IMX6Q_SYSCLK,
+				     data->clk_frequency, SND_SOC_CLOCK_IN);
+	if (ret) {
+		dev_err(dev, "could not set codec driver clock params to %d\n",
+			data->clk_frequency);
+		return ret;
+	}
+
+	/* Headphone jack detection */
+	if (gpio_is_valid(data->jack_gpio)) {
+		ret = snd_soc_jack_new(rtd->codec, "Headset",
+				       SND_JACK_HEADSET | SND_JACK_BTN_0,
+				       &headset_jack);
+		if (ret)
+			return ret;
+
+		headset_jack_gpios[0].gpio = data->jack_gpio;
+		ret = snd_soc_jack_add_gpios(&headset_jack,
+					     ARRAY_SIZE(headset_jack_gpios),
+					     headset_jack_gpios);
+	}
+
+	return ret;
+}
+
+static const struct snd_soc_dapm_widget imx_novena_dapm_widgets[] = {
+	SND_SOC_DAPM_MIC("Mic Jack", NULL),
+	SND_SOC_DAPM_HP("Headphone Jack", NULL),
+	SND_SOC_DAPM_SPK("Ext Spk", NULL),
+};
+
+static int imx_set_frequency(struct imx_novena_data *data, int freq) {
+	int ret;
+
+	ret = clk_set_parent(data->system_cko, data->codec_clk);
+	if (ret) {
+		dev_err(data->dev, "unable to set clk output");
+		return ret;
+	}
+
+	ret = clk_set_parent(data->codec_clk_sel, data->codec_clk_post_div);
+	if (ret) {
+		dev_err(data->dev, "unable to set clk parent");
+		return ret;
+	}
+
+	data->clk_freq_src = clk_round_rate(data->codec_clk_src, freq*32);
+	data->clk_frequency = clk_round_rate(data->codec_clk, freq);
+	dev_dbg(data->dev, "clock source frequency: %d\n", data->clk_freq_src);
+	dev_dbg(data->dev, "clock frequency: %d\n", data->clk_frequency);
+
+	ret = clk_set_rate(data->codec_clk_src, data->clk_freq_src);
+	if (ret) {
+		dev_err(data->dev, "unable to set source clock rate\n");
+		return ret;
+	}
+
+	ret = clk_set_rate(data->codec_clk, data->clk_frequency);
+	if (ret) {
+		dev_err(data->dev, "unable to set codec clock rate\n");
+		return ret;
+	}
+
+	ret = clk_prepare_enable(data->codec_clk);
+	if (ret) {
+		dev_err(data->dev, "unable to prepare codec clk\n");
+		return ret;
+	}
+
+	ret = clk_prepare_enable(data->codec_clk_src);
+	if (ret) {
+		dev_err(data->dev, "unable to prepare codec clk source\n");
+		return ret;
+	}
+	return ret;
+}
+
+static int imx_novena_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct device_node *ssi_np, *codec_np;
+	struct platform_device *ssi_pdev;
+	struct i2c_client *codec_dev;
+	struct imx_novena_data *data;
+	int int_port, ext_port;
+	int ret;
+	struct device *dev = &pdev->dev;
+
+	ret = of_property_read_u32(np, "mux-int-port", &int_port);
+	if (ret) {
+		dev_err(&pdev->dev, "mux-int-port missing or invalid\n");
+		return ret;
+	}
+	ret = of_property_read_u32(np, "mux-ext-port", &ext_port);
+	if (ret) {
+		dev_err(&pdev->dev, "mux-ext-port missing or invalid\n");
+		return ret;
+	}
+
+	/*
+	 * The port numbering in the hardware manual starts at 1, while
+	 * the audmux API expects it starts at 0.
+	 */
+	int_port--;
+	ext_port--;
+	ret = imx_audmux_v2_configure_port(int_port,
+			IMX_AUDMUX_V2_PTCR_SYN |
+			IMX_AUDMUX_V2_PTCR_TFSEL(ext_port) |
+			IMX_AUDMUX_V2_PTCR_TCSEL(ext_port) |
+			IMX_AUDMUX_V2_PTCR_TFSDIR |
+			IMX_AUDMUX_V2_PTCR_TCLKDIR,
+			IMX_AUDMUX_V2_PDCR_RXDSEL(ext_port));
+	if (ret) {
+		dev_err(&pdev->dev, "audmux internal port setup failed\n");
+		return ret;
+	}
+	ret = imx_audmux_v2_configure_port(ext_port,
+			IMX_AUDMUX_V2_PTCR_SYN,
+			IMX_AUDMUX_V2_PDCR_RXDSEL(int_port));
+	if (ret) {
+		dev_err(&pdev->dev, "audmux external port setup failed\n");
+		return ret;
+	}
+
+	ssi_np = of_parse_phandle(pdev->dev.of_node, "ssi-controller", 0);
+	codec_np = of_parse_phandle(pdev->dev.of_node, "audio-codec", 0);
+	if (!ssi_np || !codec_np) {
+		dev_err(&pdev->dev, "phandle missing or invalid\n");
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	ssi_pdev = of_find_device_by_node(ssi_np);
+	if (!ssi_pdev) {
+		dev_err(&pdev->dev, "failed to find SSI platform device\n");
+		ret = -EINVAL;
+		goto fail;
+	}
+	codec_dev = of_find_i2c_device_by_node(codec_np);
+	if (!codec_dev) {
+		dev_err(&pdev->dev, "failed to find codec platform device\n");
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	data->dev = dev;
+
+	data->jack_gpio = of_get_named_gpio(pdev->dev.of_node,
+				"jack-gpio", 0);
+
+	data->power_gpio = of_get_named_gpio(pdev->dev.of_node,
+				"power-gpio", 0);
+	if (gpio_is_valid(data->power_gpio))
+		devm_gpio_request_one(&pdev->dev, data->power_gpio,
+				    GPIOF_OUT_INIT_HIGH,
+				    "audio codec power switch");
+
+	/* Setup clocks */
+	data->codec_clk = devm_clk_get(dev, "cko1");
+	if (IS_ERR(data->codec_clk)) {
+		dev_err(dev,
+			"codec clock missing or invalid\n");
+		goto fail;
+	}
+
+	data->codec_clk_sel = devm_clk_get(dev, "cko1_sel");
+	if (IS_ERR(data->codec_clk_sel)) {
+		dev_err(dev,
+			"codec clock select missing or invalid\n");
+		goto fail;
+	}
+
+	data->codec_clk_src = devm_clk_get(dev, "pll4_audio");
+	if (IS_ERR(data->codec_clk_src)) {
+		dev_err(dev,
+			"codec clock source missing or invalid\n");
+		goto fail;
+	}
+
+	data->codec_clk_post_div = devm_clk_get(dev, "pll4_post_div");
+	if (IS_ERR(data->codec_clk_post_div)) {
+		dev_err(dev,
+			"codec clock post-div missing or invalid\n");
+		goto fail;
+	}
+
+	data->system_cko = devm_clk_get(dev, "cko_sel");
+	if (IS_ERR(data->system_cko)) {
+		dev_err(dev,
+			"system clock missing or invalid\n");
+		goto fail;
+	}
+
+	ret = imx_set_frequency(data, 22579200);
+	if (ret)
+		goto fail;
+
+
+	data->dai.name = "hifi";
+	data->dai.stream_name = "hifi";
+	data->dai.codec_dai_name = "es8328-hifi-analog";
+	data->dai.codec_of_node = codec_np;
+	data->dai.cpu_of_node = ssi_np;
+	data->dai.platform_of_node = ssi_np;
+	data->dai.init = &imx_novena_dai_init;
+	data->dai.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+			    SND_SOC_DAIFMT_CBM_CFM;
+
+	data->card.dev = &pdev->dev;
+	ret = snd_soc_of_parse_card_name(&data->card, "model");
+	if (ret)
+		goto fail;
+	ret = snd_soc_of_parse_audio_routing(&data->card, "audio-routing");
+	if (ret)
+		goto fail;
+	data->card.num_links = 1;
+	data->card.owner = THIS_MODULE;
+	data->card.dai_link = &data->dai;
+	data->card.dapm_widgets = imx_novena_dapm_widgets;
+	data->card.num_dapm_widgets = ARRAY_SIZE(imx_novena_dapm_widgets);
+
+	ret = snd_soc_register_card(&data->card);
+	if (ret)
+		goto fail;
+
+	platform_set_drvdata(pdev, data);
+fail:
+	if (ssi_np)
+		of_node_put(ssi_np);
+	if (codec_np)
+		of_node_put(codec_np);
+
+	return ret;
+}
+
+static int imx_novena_remove(struct platform_device *pdev)
+{
+	struct imx_novena_data *data = platform_get_drvdata(pdev);
+
+	snd_soc_jack_free_gpios(&headset_jack, ARRAY_SIZE(headset_jack_gpios),
+				headset_jack_gpios);
+
+	if (data->codec_clk)
+		clk_disable_unprepare(data->codec_clk);
+
+	if (data->codec_clk_src)
+		clk_disable_unprepare(data->codec_clk_src);
+
+	snd_soc_unregister_card(&data->card);
+
+	return 0;
+}
+
+static const struct of_device_id imx_novena_dt_ids[] = {
+	{ .compatible = "kosagi,imx-audio-novena", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_novena_dt_ids);
+
+static struct platform_driver imx_novena_driver = {
+	.driver = {
+		.name = "imx-novena",
+		.owner = THIS_MODULE,
+		.of_match_table = imx_novena_dt_ids,
+	},
+	.probe = imx_novena_probe,
+	.remove = imx_novena_remove,
+};
+module_platform_driver(imx_novena_driver);
+
+MODULE_AUTHOR("Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>");
+MODULE_DESCRIPTION("Kosagi i.MX6 Novena ASoC machine driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:imx-audio-novena");
-- 
1.8.3.2

--
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 3/3] dts: imx: add kosagi novena imx6q dts file
From: Sean Cross @ 2014-02-07  5:05 UTC (permalink / raw)
  To: devicetree-u79uwXL29TY76Z2rM5mHXA,
	alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw
  Cc: Shawn Guo, Sascha Hauer, Mark Brown, Liam Girdwood, Sean Cross
In-Reply-To: <1391749517-11787-1-git-send-email-xobs-nXMMniAx+RbQT0dZR+AlfA@public.gmane.org>

Add a device tree file for the Novena i.MX6q-based board.
---
 arch/arm/boot/dts/imx6q-novena.dts | 517 +++++++++++++++++++++++++++++++++++++
 1 file changed, 517 insertions(+)
 create mode 100644 arch/arm/boot/dts/imx6q-novena.dts

diff --git a/arch/arm/boot/dts/imx6q-novena.dts b/arch/arm/boot/dts/imx6q-novena.dts
new file mode 100644
index 0000000..ea95168
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-novena.dts
@@ -0,0 +1,517 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+
+/ {
+	model = "Kosagi Novena (i.MX6 Quad)";
+	compatible = "kosagi,imx6q-novena", "fsl,imx6q";
+
+	memory {
+		reg = <0x10000000 0x40000000>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+
+		reg_2p5v: 2p5v {
+			compatible = "regulator-fixed";
+			regulator-name = "2P5V";
+			regulator-min-microvolt = <2500000>;
+			regulator-max-microvolt = <2500000>;
+			regulator-always-on;
+		};
+
+		reg_3p3v: 3p3v {
+			compatible = "regulator-fixed";
+			regulator-name = "3P3V";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+
+		reg_usb_otg_vbus: usb_otg_vbus {
+			compatible = "regulator-fixed";
+			regulator-name = "usb_otg_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+		};
+		reg_audio_codec: es8328-regulator {
+			compatible = "regulator-fixed";
+			regulator-name = "es8328-power";
+			regulator-boot-on;
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			startup-delay-us = <400000>;
+			gpio = <&gpio5 17 0>;
+			enable-active-high;
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		user-button {
+			label = "User Button";
+			gpios = <&gpio4 14 1>;
+			gpio-key,wakeup;
+			linux,code = <116>; /* KEY_POWER */
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		heartbeat {
+			label = "novena::usr0";
+			gpios = <&gpio3 19 0>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+
+        backlight {
+                compatible = "pwm-backlight";
+                pwms = <&pwm1 0 10000>;
+
+                brightness-levels = <0 3 6 12 16 24 32 48 64 96 128 192 255>;
+                default-brightness-level = <12>;
+        };
+
+        imx-drm {
+		compatible = "fsl,imx-drm";
+		crtcs = <&ipu1 0>, <&ipu1 1>;
+		connectors = <&ldb>;
+	};
+
+	sound {
+		compatible = "fsl,imx-audio-novena";
+		model = "imx-audio-novena";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_sound_novena>;
+		clocks = <&clks 169>, <&clks 57>, <&clks 173>, <&clks 203>, <&clks 201>;
+		clock-names = "cko1", "cko1_sel", "pll4_audio", "pll4_post_div", "cko_sel";
+		ssi-controller = <&ssi1>;
+		audio-codec = <&codec>;
+		jack-gpio = <&gpio5 15 0>;
+		audio-routing =
+			"MIC_IN", "Mic Jack",
+			"Mic Jack", "Mic Bias",
+			"Headphone Jack", "HP_OUT",
+			"Ext Spk", "SPK_OUT";
+		mux-int-port = <1>;
+		mux-ext-port = <3>;
+	};
+};
+
+&ssi1 {
+	fsl,mode = "i2s-slave";
+	status = "okay";
+};
+
+&uart2 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2_1>;
+};
+
+&uart3 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart3_1>;
+};
+
+&uart4 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart4_novena>;
+};
+
+&sata {
+	status = "okay";
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	hog {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				/* Touchscreen interrupt */
+				MX6QDL_PAD_DISP0_DAT19__GPIO5_IO13 0x80000000
+
+				/* GPIO LED */
+				MX6QDL_PAD_EIM_D19__GPIO3_IO19  0x80000000
+
+				/* FPGA power */
+				MX6QDL_PAD_SD1_DAT1__GPIO1_IO17 0x80000000
+
+				/* User button */
+				MX6QDL_PAD_SD2_DAT1__GPIO1_IO14 0x80000000
+			>;
+		};
+	};
+
+	pcie {
+		pinctrl_pcie_novena: pciegrp-novena {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D22__GPIO3_IO22  0x80000000 /* Wakeup */
+				MX6QDL_PAD_EIM_D29__GPIO3_IO29  0x80000000 /* Reset */
+				MX6QDL_PAD_GPIO_17__GPIO7_IO12  0x80000000 /* Power On */
+				MX6QDL_PAD_EIM_A22__GPIO2_IO16  0x80000000 /* Wifi kill */
+			>;
+		};
+	};
+
+	enet {
+		pinctrl_enet_novena: enetgrp-novena {
+			fsl,pins = <
+				MX6QDL_PAD_ENET_MDIO__ENET_MDIO       0x1b0b0
+				MX6QDL_PAD_ENET_MDC__ENET_MDC         0x1b0b0
+				MX6QDL_PAD_RGMII_TXC__RGMII_TXC       0x1b020
+				MX6QDL_PAD_RGMII_TD0__RGMII_TD0       0x1b028
+				MX6QDL_PAD_RGMII_TD1__RGMII_TD1       0x1b028
+				MX6QDL_PAD_RGMII_TD2__RGMII_TD2       0x1b028
+				MX6QDL_PAD_RGMII_TD3__RGMII_TD3       0x1b028
+				MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b028
+				MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK  0x1b0b0
+				MX6QDL_PAD_RGMII_RXC__RGMII_RXC       0x1b0b0
+				MX6QDL_PAD_RGMII_RD0__RGMII_RD0       0x1b0b0
+				MX6QDL_PAD_RGMII_RD1__RGMII_RD1       0x1b0b0
+				MX6QDL_PAD_RGMII_RD2__RGMII_RD2       0x1b0b0
+				MX6QDL_PAD_RGMII_RD3__RGMII_RD3       0x1b0b0
+				MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
+				MX6QDL_PAD_GPIO_16__ENET_REF_CLK      0x4001b0a8
+
+				/* Ethernet reset */
+				MX6QDL_PAD_EIM_D23__GPIO3_IO23  0x80000000
+			>;
+		};
+	};
+
+	uart4 {
+		pinctrl_uart4_novena: uart4-novena {
+			fsl,pins = <
+				MX6QDL_PAD_CSI0_DAT12__UART4_TX_DATA 0x1b0b1
+				MX6QDL_PAD_CSI0_DAT13__UART4_RX_DATA 0x1b0b1
+			>;
+		};
+	};
+
+	sound {
+		pinctrl_sound_novena: sound-novena {
+			fsl,pins = <
+				/* Audio power regulator */
+				MX6QDL_PAD_DISP0_DAT23__GPIO5_IO17 0x80000000
+
+				/* Headphone plug */
+				MX6QDL_PAD_DISP0_DAT21__GPIO5_IO15 0x80000000
+
+				MX6QDL_PAD_GPIO_0__CCM_CLKO1       0x80000000
+			>;
+		};
+	};
+
+	usdhc2 {
+		pinctrl_usdhc2_novena: usdhc2-novena {
+			fsl,pins = <
+				MX6QDL_PAD_SD2_CMD__SD2_CMD    0x17059
+				MX6QDL_PAD_SD2_CLK__SD2_CLK    0x10059
+				MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
+				MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
+				MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
+				MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
+
+				/* Write protect */
+				MX6QDL_PAD_GPIO_2__GPIO1_IO02   0x80000000
+
+				/* Card detect */
+				MX6QDL_PAD_GPIO_4__GPIO1_IO04   0x80000000
+			>;
+		};
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet_novena>;
+	phy-mode = "rgmii";
+	phy-reset-gpios = <&gpio3 23 0>;
+	mac-address = [00 22 C6 87 72 03];
+	rxc-skew-ps = <3000>;
+	rxdv-skew-ps = <0>;
+	txc-skew-ps = <3000>;
+	txen-skew-ps = <0>;
+	rxd0-skew-ps = <0>;
+	rxd1-skew-ps = <0>;
+	rxd2-skew-ps = <0>;
+	rxd3-skew-ps = <0>;
+	txd0-skew-ps = <3000>;
+	txd1-skew-ps = <3000>;
+	txd2-skew-ps = <3000>;
+	txd3-skew-ps = <3000>;
+};
+
+&usdhc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc2_1>;
+	pinctrl-0 = <&pinctrl_usdhc2_novena>;
+	cd-gpios = <&gpio1 4 0>;
+	wp-gpios = <&gpio1 2 0>;
+	status = "okay";
+};
+
+&usdhc3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc3_2>;
+	non-removable;
+	status = "okay";
+};
+
+&usbotg {
+	vbus-supply = <&reg_usb_otg_vbus>;
+	dr_mode = "otg";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg_2>;
+	disable-over-current;
+	status = "okay";
+};
+
+&usbh1 {
+	status = "okay";
+};
+
+&audmux {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux_2>;
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1_1>;
+	status = "okay";
+
+	stmpe610@0 {
+		compatible = "st,stmpe610";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x44>;
+		irq-over-gpio;
+		irq-gpios = <&gpio5 13 0>;
+		id = <0>;
+		blocks = <0x5>;
+		irq-trigger = <0x1>;
+
+		stmpe_adc {
+			compatible = "st,stmpe-adc";
+		};
+		stmpe_touchscreen {
+			compatible = "st,stmpe-ts";
+			ts,sample-time = <4>;
+			ts,mod-12b = <1>;
+			ts,ref-sel = <0>;
+			ts,adc-freq = <1>;
+			ts,ave-ctrl = <1>;
+			ts,touch-det-delay = <2>;
+			ts,settling = <2>;
+			ts,fraction-z = <7>;
+			ts,i-drive = <1>;
+		};
+	};
+};
+
+&i2c2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2_1>;
+	status = "okay";
+
+	pmic: pfuze100@08 {
+		compatible = "fsl,pfuze100";
+		reg = <0x08>;
+
+		regulators {
+			sw1a_reg: sw1ab {
+				regulator-min-microvolt = <300000>;
+				regulator-max-microvolt = <1875000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-ramp-delay = <6250>;
+			};
+
+			sw1c_reg: sw1c {
+				regulator-min-microvolt = <300000>;
+				regulator-max-microvolt = <1875000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw2_reg: sw2 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw3a_reg: sw3a {
+				regulator-min-microvolt = <400000>;
+				regulator-max-microvolt = <1975000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw3b_reg: sw3b {
+				regulator-min-microvolt = <400000>;
+				regulator-max-microvolt = <1975000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw4_reg: sw4 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			swbst_reg: swbst {
+				regulator-min-microvolt = <5000000>;
+				regulator-max-microvolt = <5150000>;
+			};
+
+			snvs_reg: vsnvs {
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vref_reg: vrefddr {
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vgen1_reg: vgen1 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1550000>;
+			};
+
+			vgen2_reg: vgen2 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1550000>;
+			};
+
+			vgen3_reg: vgen3 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			vgen4_reg: vgen4 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vgen5_reg: vgen5 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vgen6_reg: vgen6 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			coin_reg: coin {
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+		};
+	};
+};
+
+&i2c3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3_1>;
+	status = "okay";
+
+	codec: es8328@11 {
+		compatible = "everest,es8328";
+		reg = <0x11>;
+		status = "disabled";
+	};
+
+	stdp4028@73 {
+		compatible = "st,stdp4028";
+		power-switch = <&gpio5 28 0>;
+		reg = <0x73>;
+		status = "disabled";
+	};
+
+	/*
+	eepromoops@56 {
+		compatible = "kosagi,eepromoops";
+		reg = <0x56>;
+		status = "okay";
+	};
+	*/
+};
+
+&ecspi3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi3_1>;
+	fsl,spi-num-chipselects = <3>;
+	status = "okay";
+
+	spidev@0x00 {
+		compatible = "spidev";
+		spi-max-frequency = <30000000>;
+		reg = <0>;
+	};
+};
+
+&pcie {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pcie_novena>;
+	reset-gpio = <&gpio3 29 0>;
+	power-on-gpio = <&gpio7 12 0>;
+	wake-up-gpio = <&gpio3 22 0>;
+	disable-gpio = <&gpio2 16 0>;
+};
+
+&ldb {
+	fsl,dual-channel;
+	status = "disabled";
+        lvds-channel@0 {
+		fsl,data-mapping = "jeida";
+		fsl,data-width = <24>;
+		crtcs = <&ipu2 0>, <&ipu2 1>;
+                display-timings {
+			2560x1700p50 {
+				clock-frequency = <185000000>;
+				hactive = <2560>;
+				vactive = <1700>;
+				hback-porch = <80>;
+				hfront-porch = <48>;
+				hsync-len = <32>;
+				vback-porch = <36>;
+				vfront-porch = <3>;
+				vsync-len = <10>;
+				hsync-active = <1>;
+				vsync-active = <1>;
+			};
+                };
+        };
+};
-- 
1.8.3.2

--
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 v5 00/14] Add support for MSM's mmio clock/reset controller
From: Joe Perches @ 2014-02-07  5:11 UTC (permalink / raw)
  To: frowand.list
  Cc: Stephen Boyd, Mike Turquette, linux-kernel, linux-arm-msm,
	linux-arm-kernel, devicetree, Saravana Kannan
In-Reply-To: <52F45DEE.8020400@gmail.com>

On Thu, 2014-02-06 at 20:15 -0800, Frank Rowand wrote:
> On 1/15/2014 10:47 AM, Stephen Boyd wrote:
> > The first breaks a reset-controller include ordering requirement. It got
> > an ack so I think we're ok for it to go through the clock tree.
> > 
> 
> < snip >
> 
> checkpatch is whining about patches
> 
>   4
>   5
>   6
>   7
>   8
> 
> (Just for completeness if someone thinks I did not check all the patches,
> it also whines about patch 11, but I think the whining should be ignored,
> and it whines about patch 1 but I think that might be a checkpatch bug.)

Hi Frank.

For patch 1, what checkpatch bug might that be?

I think all the checkpatch whinges in patch 11 are correct.

I didn't check any of 4-8.

^ permalink raw reply

* Re: [PATCH V2] ARM: dts: imx6qdl-sabresd: correct gpio key's active state
From: Shawn Guo @ 2014-02-07  6:03 UTC (permalink / raw)
  To: Anson Huang
  Cc: s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ, devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1390219358-22157-1-git-send-email-b20788-KZfg59tc24xl57MIdRCFDg@public.gmane.org>

On Mon, Jan 20, 2014 at 08:02:38PM +0800, Anson Huang wrote:
> From schematic, the power, vol+/- key's active state is low,
> so we need to set the gpio flag to active low.
> 
> Signed-off-by: Anson Huang <b20788-KZfg59tc24xl57MIdRCFDg@public.gmane.org>

Applied, thanks.  Sorry for the delay.

Shawn

--
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 2/2] spi: Add Qualcomm QUP SPI controller support
From: Andy Gross @ 2014-02-07  7:39 UTC (permalink / raw)
  To: Ivan T. Ivanov
  Cc: Mark Brown, Grant Likely, Rob Herring, linux-spi, linux-arm-msm,
	linux-kernel, devicetree, Alok Chauhan, Gilad Avidov, Kiran Gunda,
	Sagar Dharia
In-Reply-To: <1391705868-20091-3-git-send-email-iivanov@mm-sol.com>

On Thu, Feb 06, 2014 at 06:57:48PM +0200, Ivan T. Ivanov wrote:
> From: "Ivan T. Ivanov" <iivanov@mm-sol.com>
> 
> Qualcomm Universal Peripheral (QUP) core is an AHB slave that
> provides a common data path (an output FIFO and an input FIFO)
> for serial peripheral interface (SPI) mini-core. SPI in master mode
> support up to 50MHz, up to four chip selects, and a programmable
> data path from 4 bits to 32 bits; MODE0..3 protocols
> 
> Signed-off-by: Ivan T. Ivanov <iivanov@mm-sol.com>
> Cc: Alok Chauhan <alokc@codeaurora.org>
> Cc: Gilad Avidov <gavidov@codeaurora.org>
> Cc: Kiran Gunda <kgunda@codeaurora.org>
> Cc: Sagar Dharia <sdharia@codeaurora.org>
> ---
>  drivers/spi/Kconfig   |   14 +
>  drivers/spi/Makefile  |    1 +
>  drivers/spi/spi-qup.c |  898 +++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 913 insertions(+)
>  create mode 100644 drivers/spi/spi-qup.c
> 
> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> index ba9310b..bf8ce6b 100644
> --- a/drivers/spi/Kconfig
> +++ b/drivers/spi/Kconfig
> @@ -381,6 +381,20 @@ config SPI_RSPI
>  	help
>  	  SPI driver for Renesas RSPI blocks.
>  
> +config SPI_QUP
> +	tristate "Qualcomm SPI Support with QUP interface"
> +	depends on ARCH_MSM

I'd change to ARCH_MSM_DT.  This ensures the OF component is there.

> +	help
> +	  Qualcomm Universal Peripheral (QUP) core is an AHB slave that
> +	  provides a common data path (an output FIFO and an input FIFO)
> +	  for serial peripheral interface (SPI) mini-core. SPI in master
> +	  mode support up to 50MHz, up to four chip selects, and a
> +	  programmable data path from 4 bits to 32 bits; supports numerous
> +	  protocol variants.
> +
> +	  This driver can also be built as a module.  If so, the module
> +	  will be called spi_qup.
> +
>  config SPI_S3C24XX
>  	tristate "Samsung S3C24XX series SPI"
>  	depends on ARCH_S3C24XX
> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
> index 95af48d..e598147 100644
> --- a/drivers/spi/Makefile
> +++ b/drivers/spi/Makefile
> @@ -59,6 +59,7 @@ spi-pxa2xx-platform-$(CONFIG_SPI_PXA2XX_PXADMA)	+= spi-pxa2xx-pxadma.o
>  spi-pxa2xx-platform-$(CONFIG_SPI_PXA2XX_DMA)	+= spi-pxa2xx-dma.o
>  obj-$(CONFIG_SPI_PXA2XX)		+= spi-pxa2xx-platform.o
>  obj-$(CONFIG_SPI_PXA2XX_PCI)		+= spi-pxa2xx-pci.o
> +obj-$(CONFIG_SPI_QUP)			+= spi-qup.o
>  obj-$(CONFIG_SPI_RSPI)			+= spi-rspi.o
>  obj-$(CONFIG_SPI_S3C24XX)		+= spi-s3c24xx-hw.o
>  spi-s3c24xx-hw-y			:= spi-s3c24xx.o
> diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c
> new file mode 100644
> index 0000000..5eb5e8f
> --- /dev/null
> +++ b/drivers/spi/spi-qup.c
> @@ -0,0 +1,898 @@
> +/*
> + * Copyright (c) 2008-2014, The Linux foundation. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License rev 2 and
> + * only rev 2 as published by the free Software foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or fITNESS fOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/err.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/list.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_runtime.h>

Remove this for now.  No runtime support.

> +#include <linux/spi/spi.h>
> +
> +#define QUP_CONFIG			0x0000
> +#define QUP_STATE			0x0004
> +#define QUP_IO_M_MODES			0x0008
> +#define QUP_SW_RESET			0x000c
> +#define QUP_OPERATIONAL			0x0018
> +#define QUP_ERROR_FLAGS			0x001c
> +#define QUP_ERROR_FLAGS_EN		0x0020
> +#define QUP_OPERATIONAL_MASK		0x0028
> +#define QUP_HW_VERSION			0x0030
> +#define QUP_MX_OUTPUT_CNT		0x0100
> +#define QUP_OUTPUT_FIFO			0x0110
> +#define QUP_MX_WRITE_CNT		0x0150
> +#define QUP_MX_INPUT_CNT		0x0200
> +#define QUP_MX_READ_CNT			0x0208
> +#define QUP_INPUT_FIFO			0x0218
> +
> +#define SPI_CONFIG			0x0300
> +#define SPI_IO_CONTROL			0x0304
> +#define SPI_ERROR_FLAGS			0x0308
> +#define SPI_ERROR_FLAGS_EN		0x030c
> +
> +/* QUP_CONFIG fields */
> +#define QUP_CONFIG_SPI_MODE		(1 << 8)
> +#define QUP_CONFIG_NO_INPUT		BIT(7)
> +#define QUP_CONFIG_NO_OUTPUT		BIT(6)
> +#define QUP_CONFIG_N			0x001f
> +
> +/* QUP_STATE fields */
> +#define QUP_STATE_VALID			BIT(2)
> +#define QUP_STATE_RESET			0
> +#define QUP_STATE_RUN			1
> +#define QUP_STATE_PAUSE			3
> +#define QUP_STATE_MASK			3
> +#define QUP_STATE_CLEAR			2
> +
> +#define QUP_HW_VERSION_2_1_1		0x20010001
> +
> +/* QUP_IO_M_MODES fields */
> +#define QUP_IO_M_PACK_EN		BIT(15)
> +#define QUP_IO_M_UNPACK_EN		BIT(14)
> +#define QUP_IO_M_INPUT_MODE_MASK_SHIFT	12
> +#define QUP_IO_M_OUTPUT_MODE_MASK_SHIFT	10
> +#define QUP_IO_M_INPUT_MODE_MASK	(3 << QUP_IO_M_INPUT_MODE_MASK_SHIFT)
> +#define QUP_IO_M_OUTPUT_MODE_MASK	(3 << QUP_IO_M_OUTPUT_MODE_MASK_SHIFT)
> +
> +#define QUP_IO_M_OUTPUT_BLOCK_SIZE(x)	(((x) & (0x03 << 0)) >> 0)
> +#define QUP_IO_M_OUTPUT_FIFO_SIZE(x)	(((x) & (0x07 << 2)) >> 2)
> +#define QUP_IO_M_INPUT_BLOCK_SIZE(x)	(((x) & (0x03 << 5)) >> 5)
> +#define QUP_IO_M_INPUT_FIFO_SIZE(x)	(((x) & (0x07 << 7)) >> 7)
> +
> +#define QUP_IO_M_MODE_FIFO		0
> +#define QUP_IO_M_MODE_BLOCK		1
> +#define QUP_IO_M_MODE_DMOV		2
> +#define QUP_IO_M_MODE_BAM		3
> +
> +/* QUP_OPERATIONAL fields */
> +#define QUP_OP_MAX_INPUT_DONE_FLAG	BIT(11)
> +#define QUP_OP_MAX_OUTPUT_DONE_FLAG	BIT(10)
> +#define QUP_OP_IN_SERVICE_FLAG		BIT(9)
> +#define QUP_OP_OUT_SERVICE_FLAG		BIT(8)
> +#define QUP_OP_IN_FIFO_FULL		BIT(7)
> +#define QUP_OP_OUT_FIFO_FULL		BIT(6)
> +#define QUP_OP_IN_FIFO_NOT_EMPTY	BIT(5)
> +#define QUP_OP_OUT_FIFO_NOT_EMPTY	BIT(4)
> +
> +/* QUP_ERROR_FLAGS and QUP_ERROR_FLAGS_EN fields */
> +#define QUP_ERROR_OUTPUT_OVER_RUN	BIT(5)
> +#define QUP_ERROR_INPUT_UNDER_RUN	BIT(4)
> +#define QUP_ERROR_OUTPUT_UNDER_RUN	BIT(3)
> +#define QUP_ERROR_INPUT_OVER_RUN	BIT(2)
> +
> +/* SPI_CONFIG fields */
> +#define SPI_CONFIG_HS_MODE		BIT(10)
> +#define SPI_CONFIG_INPUT_FIRST		BIT(9)
> +#define SPI_CONFIG_LOOPBACK		BIT(8)
> +
> +/* SPI_IO_CONTROL fields */
> +#define SPI_IO_C_FORCE_CS		BIT(11)
> +#define SPI_IO_C_CLK_IDLE_HIGH		BIT(10)
> +#define SPI_IO_C_MX_CS_MODE		BIT(8)
> +#define SPI_IO_C_CS_N_POLARITY_0	BIT(4)
> +#define SPI_IO_C_CS_SELECT(x)		(((x) & 3) << 2)
> +#define SPI_IO_C_CS_SELECT_MASK		0x000c
> +#define SPI_IO_C_TRISTATE_CS		BIT(1)
> +#define SPI_IO_C_NO_TRI_STATE		BIT(0)
> +
> +/* SPI_ERROR_FLAGS and SPI_ERROR_FLAGS_EN fields */
> +#define SPI_ERROR_CLK_OVER_RUN		BIT(1)
> +#define SPI_ERROR_CLK_UNDER_RUN		BIT(0)
> +
> +#define SPI_NUM_CHIPSELECTS		4
> +
> +/* high speed mode is when bus rate is greater then 26MHz */
> +#define SPI_HS_MIN_RATE			26000000
> +
> +#define SPI_DELAY_THRESHOLD		1
> +#define SPI_DELAY_RETRY			10
> +
> +struct spi_qup_device {
> +	int bits_per_word;
> +	int chip_select;
> +	int speed_hz;
> +	u16 mode;
> +};
> +
> +struct spi_qup {
> +	void __iomem		*base;
> +	struct device		*dev;
> +	struct clk		*cclk;	/* core clock */
> +	struct clk		*iclk;	/* interface clock */
> +	int			irq;
> +	u32			max_speed_hz;
> +	u32			speed_hz;
> +
> +	int			in_fifo_sz;
> +	int			out_fifo_sz;
> +	int			in_blk_sz;
> +	int			out_blk_sz;
> +
> +	struct spi_transfer	*xfer;
> +	struct completion	done;
> +	int			error;
> +	int			bytes_per_word;
> +	int			tx_bytes;
> +	int			rx_bytes;
> +};
> +
> +
> +static inline bool spi_qup_is_valid_state(struct spi_qup *controller)
> +{
> +	u32 opstate = readl_relaxed(controller->base + QUP_STATE);
> +
> +	return opstate & QUP_STATE_VALID;
> +}
> +
> +static int spi_qup_set_state(struct spi_qup *controller, u32 state)
> +{
> +	unsigned long loop = 0;
> +	u32 cur_state;
> +
> +	cur_state = readl_relaxed(controller->base + QUP_STATE);
> +	/*
> +	 * Per spec: for PAUSE_STATE to RESET_STATE, two writes
> +	 * of (b10) are required
> +	 */
> +	if (((cur_state & QUP_STATE_MASK) == QUP_STATE_PAUSE) &&
> +	    (state == QUP_STATE_RESET)) {
> +		writel_relaxed(QUP_STATE_CLEAR, controller->base + QUP_STATE);
> +		writel_relaxed(QUP_STATE_CLEAR, controller->base + QUP_STATE);
> +	} else {
> +		cur_state &= ~QUP_STATE_MASK;
> +		cur_state |= state;
> +		writel_relaxed(cur_state, controller->base + QUP_STATE);
> +	}
> +
> +	while (!spi_qup_is_valid_state(controller)) {
> +
> +		usleep_range(SPI_DELAY_THRESHOLD, SPI_DELAY_THRESHOLD * 2);
> +
> +		if (++loop > SPI_DELAY_RETRY)
> +			return -EIO;
> +	}
> +
> +	return 0;
> +}
> +
> +static void spi_qup_deassert_cs(struct spi_qup *controller,
> +				struct spi_qup_device *chip)
> +{
> +	u32 iocontol, mask;
> +
> +	iocontol = readl_relaxed(controller->base + SPI_IO_CONTROL);
> +
> +	/* Disable auto CS toggle and use manual */
> +	iocontol &= ~SPI_IO_C_MX_CS_MODE;
> +	iocontol |= SPI_IO_C_FORCE_CS;
> +
> +	iocontol &= ~SPI_IO_C_CS_SELECT_MASK;
> +	iocontol |= SPI_IO_C_CS_SELECT(chip->chip_select);
> +
> +	mask = SPI_IO_C_CS_N_POLARITY_0 << chip->chip_select;
> +
> +	if (chip->mode & SPI_CS_HIGH)
> +		iocontol &= ~mask;
> +	else
> +		iocontol |= mask;
> +
> +	writel_relaxed(iocontol, controller->base + SPI_IO_CONTROL);
> +}
> +
> +static void spi_qup_assert_cs(struct spi_qup *controller,
> +			      struct spi_qup_device *chip)
> +{
> +	u32 iocontol, mask;
> +
> +	iocontol = readl_relaxed(controller->base + SPI_IO_CONTROL);
> +
> +	/* Disable auto CS toggle and use manual */
> +	iocontol &= ~SPI_IO_C_MX_CS_MODE;
> +	iocontol |= SPI_IO_C_FORCE_CS;
> +
> +	iocontol &= ~SPI_IO_C_CS_SELECT_MASK;
> +	iocontol |= SPI_IO_C_CS_SELECT(chip->chip_select);
> +
> +	mask = SPI_IO_C_CS_N_POLARITY_0 << chip->chip_select;
> +
> +	if (chip->mode & SPI_CS_HIGH)
> +		iocontol |= mask;
> +	else
> +		iocontol &= ~mask;
> +
> +	writel_relaxed(iocontol, controller->base + SPI_IO_CONTROL);
> +}
> +
> +static void spi_qup_fifo_read(struct spi_qup *controller,
> +			      struct spi_transfer *xfer)
> +{
> +	u8 *rx_buf = xfer->rx_buf;
> +	u32 word, state;
> +	int idx, shift;
> +
> +	while (controller->rx_bytes < xfer->len) {
> +
> +		state = readl_relaxed(controller->base + QUP_OPERATIONAL);
> +		if (0 == (state & QUP_OP_IN_FIFO_NOT_EMPTY))
> +			break;
> +
> +		word = readl_relaxed(controller->base + QUP_INPUT_FIFO);
> +
> +		for (idx = 0; idx < controller->bytes_per_word &&
> +		     controller->rx_bytes < xfer->len; idx++,
> +		     controller->rx_bytes++) {
> +
> +			if (!rx_buf)
> +				continue;
> +			/*
> +			 * The data format depends on bytes_per_word:
> +			 *  4 bytes: 0x12345678
> +			 *  2 bytes: 0x00001234
> +			 *  1 byte : 0x00000012
> +			 */
> +			shift = BITS_PER_BYTE;
> +			shift *= (controller->bytes_per_word - idx - 1);
> +			rx_buf[controller->rx_bytes] = word >> shift;
> +		}
> +	}
> +}
> +
> +static void spi_qup_fifo_write(struct spi_qup *controller,
> +			       struct spi_transfer *xfer)
> +{
> +	const u8 *tx_buf = xfer->tx_buf;
> +	u32 word, state, data;
> +	int idx;
> +
> +	while (controller->tx_bytes < xfer->len) {
> +
> +		state = readl_relaxed(controller->base + QUP_OPERATIONAL);
> +		if (state & QUP_OP_OUT_FIFO_FULL)
> +			break;
> +
> +		word = 0;
> +		for (idx = 0; idx < controller->bytes_per_word &&
> +		     controller->tx_bytes < xfer->len; idx++,
> +		     controller->tx_bytes++) {
> +
> +			if (!tx_buf)
> +				continue;
> +
> +			data = tx_buf[controller->tx_bytes];
> +			word |= data << (BITS_PER_BYTE * (3 - idx));
> +		}
> +
> +		writel_relaxed(word, controller->base + QUP_OUTPUT_FIFO);
> +	}
> +}
> +
> +static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id)
> +{
> +	struct spi_qup *controller = dev_id;
> +	struct spi_transfer *xfer;
> +	u32 opflags, qup_err, spi_err;
> +
> +	xfer = controller->xfer;
> +
> +	qup_err = readl_relaxed(controller->base + QUP_ERROR_FLAGS);
> +	spi_err = readl_relaxed(controller->base + SPI_ERROR_FLAGS);
> +	opflags = readl_relaxed(controller->base + QUP_OPERATIONAL);
> +
> +	writel_relaxed(qup_err, controller->base + QUP_ERROR_FLAGS);
> +	writel_relaxed(spi_err, controller->base + SPI_ERROR_FLAGS);
> +	writel_relaxed(opflags, controller->base + QUP_OPERATIONAL);
> +
> +	if (!xfer)
> +		return IRQ_HANDLED;
> +
> +	if (qup_err) {
> +		if (qup_err & QUP_ERROR_OUTPUT_OVER_RUN)
> +			dev_warn(controller->dev, "OUTPUT_OVER_RUN\n");
> +		if (qup_err & QUP_ERROR_INPUT_UNDER_RUN)
> +			dev_warn(controller->dev, "INPUT_UNDER_RUN\n");
> +		if (qup_err & QUP_ERROR_OUTPUT_UNDER_RUN)
> +			dev_warn(controller->dev, "OUTPUT_UNDER_RUN\n");
> +		if (qup_err & QUP_ERROR_INPUT_OVER_RUN)
> +			dev_warn(controller->dev, "INPUT_OVER_RUN\n");
> +
> +		controller->error = -EIO;
> +	}
> +
> +	if (spi_err) {
> +		if (spi_err & SPI_ERROR_CLK_OVER_RUN)
> +			dev_warn(controller->dev, "CLK_OVER_RUN\n");
> +		if (spi_err & SPI_ERROR_CLK_UNDER_RUN)
> +			dev_warn(controller->dev, "CLK_UNDER_RUN\n");
> +
> +		controller->error = -EIO;
> +	}
> +
> +	if (opflags & QUP_OP_IN_SERVICE_FLAG) {
> +		writel_relaxed(QUP_OP_IN_SERVICE_FLAG,
> +		       controller->base + QUP_OPERATIONAL);
> +		spi_qup_fifo_read(controller, xfer);
> +	}
> +
> +	if (opflags & QUP_OP_OUT_SERVICE_FLAG) {
> +		writel_relaxed(QUP_OP_OUT_SERVICE_FLAG,
> +		       controller->base + QUP_OPERATIONAL);
> +		spi_qup_fifo_write(controller, xfer);
> +	}
> +
> +	if (controller->rx_bytes == xfer->len ||
> +	    controller->error)
> +		complete(&controller->done);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int spi_qup_transfer_do(struct spi_qup *controller,
> +			       struct spi_qup_device *chip,
> +			       struct spi_transfer *xfer)
> +{
> +	unsigned long timeout;
> +	int ret = -EIO;
> +
> +	reinit_completion(&controller->done);
> +
> +	timeout = DIV_ROUND_UP(controller->speed_hz, MSEC_PER_SEC);
> +	timeout = DIV_ROUND_UP(xfer->len * 8, timeout);
> +	timeout = 100 * msecs_to_jiffies(timeout);
> +
> +	controller->rx_bytes = 0;
> +	controller->tx_bytes = 0;
> +	controller->error = 0;
> +	controller->xfer = xfer;
> +
> +	if (spi_qup_set_state(controller, QUP_STATE_RUN)) {
> +		dev_warn(controller->dev, "cannot set RUN state\n");
> +		goto exit;
> +	}
> +
> +	if (spi_qup_set_state(controller, QUP_STATE_PAUSE)) {
> +		dev_warn(controller->dev, "cannot set PAUSE state\n");
> +		goto exit;
> +	}
> +
> +	spi_qup_fifo_write(controller, xfer);
> +
> +	if (spi_qup_set_state(controller, QUP_STATE_RUN)) {
> +		dev_warn(controller->dev, "cannot set EXECUTE state\n");
> +		goto exit;
> +	}
> +
> +	if (!wait_for_completion_timeout(&controller->done, timeout))
> +		ret = -ETIMEDOUT;
> +	else
> +		ret = controller->error;
> +exit:
> +	controller->xfer = NULL;

Should the manipulation of controller->xfer be protected by spinlock?

> +	controller->error = 0;
> +	controller->rx_bytes = 0;
> +	controller->tx_bytes = 0;
> +	spi_qup_set_state(controller, QUP_STATE_RESET);
> +	return ret;
> +}
> +
> +static int spi_qup_setup(struct spi_device *spi)
> +{
> +	struct spi_qup *controller = spi_master_get_devdata(spi->master);
> +	struct spi_qup_device *chip = spi_get_ctldata(spi);
> +
> +	if (spi->chip_select >= spi->master->num_chipselect) {
> +		dev_err(controller->dev, "invalid chip_select %d\n",
> +			spi->chip_select);
> +		return -EINVAL;
> +	}
> +
> +	if (spi->max_speed_hz > controller->max_speed_hz) {
> +		dev_err(controller->dev, "invalid max_speed_hz %d\n",
> +			spi->max_speed_hz);
> +		return -EINVAL;
> +	}
> +
> +	if (!chip) {
> +		/* First setup */
> +		chip = kzalloc(sizeof(*chip), GFP_KERNEL);
> +		if (!chip) {
> +			dev_err(controller->dev, "no memory for chip data\n");
> +			return -ENOMEM;
> +		}
> +
> +		spi_set_ctldata(spi, chip);
> +	}
> +
> +	return 0;
> +}
> +
> +static void spi_qup_cleanup(struct spi_device *spi)
> +{
> +	struct spi_qup_device *chip = spi_get_ctldata(spi);
> +
> +	if (!chip)
> +		return;
> +
> +	spi_set_ctldata(spi, NULL);
> +	kfree(chip);
> +}
> +
> +/* set clock freq, clock ramp, bits per work */
> +static int spi_qup_io_setup(struct spi_device *spi,
> +			  struct spi_transfer *xfer)
> +{
> +	struct spi_qup *controller = spi_master_get_devdata(spi->master);
> +	struct spi_qup_device *chip = spi_get_ctldata(spi);
> +	u32 iocontol, config, iomode, mode;
> +	int ret, n_words;
> +
> +	if (spi->mode & SPI_LOOP && xfer->len > controller->in_fifo_sz) {
> +		dev_err(controller->dev, "too big size for loopback %d > %d\n",
> +			xfer->len, controller->in_fifo_sz);
> +		return -EIO;
> +	}
> +
> +	chip->mode = spi->mode;
> +	chip->speed_hz = spi->max_speed_hz;
> +	if (xfer->speed_hz)
> +		chip->speed_hz = xfer->speed_hz;
> +
> +	if (controller->speed_hz != chip->speed_hz) {
> +		ret = clk_set_rate(controller->cclk, chip->speed_hz);
> +		if (ret) {
> +			dev_err(controller->dev, "fail to set frequency %d",
> +				chip->speed_hz);
> +			return -EIO;
> +		}
> +	}
> +
> +	controller->speed_hz = chip->speed_hz;
> +
> +	chip->bits_per_word = spi->bits_per_word;
> +	if (xfer->bits_per_word)
> +		chip->bits_per_word = xfer->bits_per_word;
> +
> +	if (chip->bits_per_word <= 8)
> +		controller->bytes_per_word = 1;
> +	else if (chip->bits_per_word <= 16)
> +		controller->bytes_per_word = 2;
> +	else
> +		controller->bytes_per_word = 4;
> +
> +	if (controller->bytes_per_word > xfer->len ||
> +	    xfer->len % controller->bytes_per_word != 0){
> +		/* No partial transfers */
> +		dev_err(controller->dev, "invalid len %d for %d bits\n",
> +			xfer->len, chip->bits_per_word);
> +		return -EIO;
> +	}
> +
> +	n_words = xfer->len / controller->bytes_per_word;
> +
> +	if (spi_qup_set_state(controller, QUP_STATE_RESET)) {
> +		dev_err(controller->dev, "cannot set RESET state\n");
> +		return -EIO;
> +	}
> +
> +	if (n_words <= controller->in_fifo_sz) {
> +		mode = QUP_IO_M_MODE_FIFO;
> +		writel_relaxed(n_words, controller->base + QUP_MX_READ_CNT);
> +		writel_relaxed(n_words, controller->base + QUP_MX_WRITE_CNT);
> +		/* must be zero for FIFO */
> +		writel_relaxed(0, controller->base + QUP_MX_INPUT_CNT);
> +		writel_relaxed(0, controller->base + QUP_MX_OUTPUT_CNT);
> +	} else {
> +		mode = QUP_IO_M_MODE_BLOCK;
> +		writel_relaxed(n_words, controller->base + QUP_MX_INPUT_CNT);
> +		writel_relaxed(n_words, controller->base + QUP_MX_OUTPUT_CNT);
> +		/* must be zero for BLOCK and BAM */
> +		writel_relaxed(0, controller->base + QUP_MX_READ_CNT);
> +		writel_relaxed(0, controller->base + QUP_MX_WRITE_CNT);
> +	}
> +
> +	iomode = readl_relaxed(controller->base + QUP_IO_M_MODES);
> +	/* Set input and output transfer mode */
> +	iomode &= ~(QUP_IO_M_INPUT_MODE_MASK | QUP_IO_M_OUTPUT_MODE_MASK);
> +	iomode &= ~(QUP_IO_M_PACK_EN | QUP_IO_M_UNPACK_EN);
> +	iomode |= (mode << QUP_IO_M_OUTPUT_MODE_MASK_SHIFT);
> +	iomode |= (mode << QUP_IO_M_INPUT_MODE_MASK_SHIFT);
> +
> +	writel_relaxed(iomode, controller->base + QUP_IO_M_MODES);
> +
> +	config = readl_relaxed(controller->base + SPI_CONFIG);
> +
> +	if (chip->mode & SPI_LOOP)
> +		config |= SPI_CONFIG_LOOPBACK;
> +	else
> +		config &= ~SPI_CONFIG_LOOPBACK;
> +
> +	if (chip->mode & SPI_CPHA)
> +		config &= ~SPI_CONFIG_INPUT_FIRST;
> +	else
> +		config |= SPI_CONFIG_INPUT_FIRST;
> +
> +	/*
> +	 * HS_MODE improves signal stability for spi-clk high rates
> +	 * but is invalid in loop back mode.
> +	 */
> +	if ((controller->speed_hz >= SPI_HS_MIN_RATE) &&
> +	    !(chip->mode & SPI_LOOP))
> +		config |= SPI_CONFIG_HS_MODE;
> +	else
> +		config &= ~SPI_CONFIG_HS_MODE;
> +
> +	writel_relaxed(config, controller->base + SPI_CONFIG);
> +
> +	config = readl_relaxed(controller->base + QUP_CONFIG);
> +	config &= ~(QUP_CONFIG_NO_INPUT | QUP_CONFIG_NO_OUTPUT | QUP_CONFIG_N);
> +	config |= chip->bits_per_word - 1;
> +	config |= QUP_CONFIG_SPI_MODE;
> +	writel_relaxed(config, controller->base + QUP_CONFIG);
> +
> +	iocontol = readl_relaxed(controller->base + SPI_IO_CONTROL);
> +
> +	/* Disable auto CS toggle */
> +	iocontol &= ~SPI_IO_C_MX_CS_MODE;
> +
> +	if (chip->mode & SPI_CPOL)
> +		iocontol |= SPI_IO_C_CLK_IDLE_HIGH;
> +	else
> +		iocontol &= ~SPI_IO_C_CLK_IDLE_HIGH;
> +
> +	writel_relaxed(iocontol, controller->base + SPI_IO_CONTROL);
> +
> +	/*
> +	 * TODO: In BAM mode mask INPUT and OUTPUT service flags in
> +	 * to prevent IRQs on FIFO status change.
> +	 */

Remove the TODO.  Not necessary.  This stuff can be added when it becomes BAM
enabled.

> +	writel_relaxed(0, controller->base + QUP_OPERATIONAL_MASK);
> +
> +	return 0;
> +}
> +
> +static int spi_qup_transfer_one(struct spi_master *master,
> +				struct spi_message *msg)
> +{
> +	struct spi_qup *controller = spi_master_get_devdata(master);
> +	struct spi_qup_device *chip = spi_get_ctldata(msg->spi);
> +	struct spi_transfer *xfer;
> +	struct spi_device *spi;
> +	unsigned cs_change;
> +	int status;
> +
> +	spi = msg->spi;
> +	cs_change = 1;
> +	status = 0;
> +
> +	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
> +
> +		status = spi_qup_io_setup(spi, xfer);
> +		if (status)
> +			break;
> +

no locking?  This whole code block needs to have some type of mutex_lock to keep
others from trouncing the hardware while you are doing this transfer.

> +		if (cs_change)
> +			spi_qup_assert_cs(controller, chip);

Should the CS be done outside the loop?  I'd expect the following sequence to
happen:
- change CS
- Loop and do some transfers
- deassert CS

In this code, you reinitialize and assert/deassert CS for every transaction.

> +
> +		cs_change = xfer->cs_change;
> +
> +		/* Do actual transfer */
> +		status = spi_qup_transfer_do(controller, chip, xfer);
> +		if (status)
> +			break;
> +
> +		msg->actual_length += xfer->len;
> +
> +		if (xfer->delay_usecs)
> +			udelay(xfer->delay_usecs);
> +
> +		if (cs_change)
> +			spi_qup_deassert_cs(controller, chip);
> +	}
> +
> +	if (status || !cs_change)
> +		spi_qup_deassert_cs(controller, chip);
> +
> +	msg->status = status;
> +	spi_finalize_current_message(master);
> +	return status;
> +}
> +
> +static int spi_qup_probe(struct platform_device *pdev)
> +{
> +	struct spi_master *master;
> +	struct clk *iclk, *cclk;
> +	struct spi_qup *controller;
> +	struct resource *res;
> +	struct device *dev;
> +	void __iomem *base;
> +	u32 data, max_freq, iomode;
> +	int ret, irq, size;
> +
> +	dev = &pdev->dev;
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	base = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(base))
> +		return PTR_ERR(base);
> +
> +	irq = platform_get_irq(pdev, 0);
> +
> +	if (irq < 0)
> +		return irq;
> +
> +	cclk = devm_clk_get(dev, "core");
> +	if (IS_ERR(cclk)) {
> +		dev_err(dev, "cannot get core clock\n");
No need to error print.  devm_clk_get already outputs something
> +		return PTR_ERR(cclk);
> +	}
> +
> +	iclk = devm_clk_get(dev, "iface");
> +	if (IS_ERR(iclk)) {
> +		dev_err(dev, "cannot get iface clock\n");

No need to error print.  devm_clk_get already outputs something

> +		return PTR_ERR(iclk);
> +	}
> +
> +	if (of_property_read_u32(dev->of_node, "spi-max-frequency", &max_freq))
> +		max_freq = 19200000;

I'd set the default to 50MHz as that is the max supported by hardware.  I'd just
set max_freq declaration to 50MHz and then check the value if it is changed via
DT.

> +
> +	if (!max_freq) {
> +		dev_err(dev, "invalid clock frequency %d\n", max_freq);
> +		return -ENXIO;
> +	}

This is buggy.  Remove this and collapse into the of_property_read_u32 if
statement.  On non-zero, check the range for validity.

> +
> +	ret = clk_set_rate(cclk, max_freq);
> +	if (ret)
> +		dev_warn(dev, "fail to set SPI frequency %d\n", max_freq);

Bail here?

> +
> +	ret = clk_prepare_enable(cclk);
> +	if (ret) {
> +		dev_err(dev, "cannot enable core clock\n");
> +		return ret;
> +	}
> +
> +	ret = clk_prepare_enable(iclk);
> +	if (ret) {
> +		clk_disable_unprepare(cclk);
> +		dev_err(dev, "cannot enable iface clock\n");
> +		return ret;
> +	}
> +
> +	data = readl_relaxed(base + QUP_HW_VERSION);
> +
> +	if (data < QUP_HW_VERSION_2_1_1) {
> +		clk_disable_unprepare(cclk);
> +		clk_disable_unprepare(iclk);
> +		dev_err(dev, "v.%08x is not supported\n", data);
> +		return -ENXIO;
> +	}
> +
> +	master = spi_alloc_master(dev, sizeof(struct spi_qup));
> +	if (!master) {
> +		clk_disable_unprepare(cclk);
> +		clk_disable_unprepare(iclk);
> +		dev_err(dev, "cannot allocate master\n");
> +		return -ENOMEM;
> +	}
> +
> +	master->bus_num = pdev->id;
> +	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;
> +	master->num_chipselect = SPI_NUM_CHIPSELECTS;
> +	master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
> +	master->setup = spi_qup_setup;
> +	master->cleanup = spi_qup_cleanup;
> +	master->transfer_one_message = spi_qup_transfer_one;
> +	master->dev.of_node = pdev->dev.of_node;
> +	master->auto_runtime_pm = true;

Remove this.  No runtime support

> +
> +	platform_set_drvdata(pdev, master);
> +
> +	controller = spi_master_get_devdata(master);
> +
> +	controller->dev  = dev;
> +	controller->base = base;
> +	controller->iclk = iclk;
> +	controller->cclk = cclk;
> +	controller->irq  = irq;
> +	controller->max_speed_hz = clk_get_rate(cclk);
> +	controller->speed_hz = controller->max_speed_hz;
> +
> +	init_completion(&controller->done);
> +
> +	iomode = readl_relaxed(base + QUP_IO_M_MODES);
> +
> +	size = QUP_IO_M_OUTPUT_BLOCK_SIZE(iomode);
> +	if (size)
> +		controller->out_blk_sz = size * 16;
> +	else
> +		controller->out_blk_sz = 4;
> +
> +	size = QUP_IO_M_INPUT_BLOCK_SIZE(iomode);
> +	if (size)
> +		controller->in_blk_sz = size * 16;
> +	else
> +		controller->in_blk_sz = 4;
> +
> +	size = QUP_IO_M_OUTPUT_FIFO_SIZE(iomode);
> +	controller->out_fifo_sz = controller->out_blk_sz * (2 << size);
> +
> +	size = QUP_IO_M_INPUT_FIFO_SIZE(iomode);
> +	controller->in_fifo_sz = controller->in_blk_sz * (2 << size);
> +
> +	dev_info(dev, "v.%08x IN:block:%d, fifo:%d, OUT:block:%d, fifo:%d\n",
> +		 data, controller->in_blk_sz, controller->in_fifo_sz,
> +		 controller->out_blk_sz, controller->out_fifo_sz);
> +
> +	writel_relaxed(1, base + QUP_SW_RESET);
> +
> +	ret = spi_qup_set_state(controller, QUP_STATE_RESET);
> +	if (ret) {
> +		dev_err(dev, "cannot set RESET state\n");
> +		goto error;
> +	}
> +
> +	writel_relaxed(0, base + QUP_OPERATIONAL);
> +	writel_relaxed(0, base + QUP_IO_M_MODES);
> +	writel_relaxed(0, base + QUP_OPERATIONAL_MASK);
> +	writel_relaxed(SPI_ERROR_CLK_UNDER_RUN | SPI_ERROR_CLK_OVER_RUN,
> +		       base + SPI_ERROR_FLAGS_EN);
> +
> +	writel_relaxed(0, base + SPI_CONFIG);
> +	writel_relaxed(SPI_IO_C_NO_TRI_STATE, base + SPI_IO_CONTROL);
> +
> +	ret = devm_request_irq(dev, irq, spi_qup_qup_irq,
> +			       IRQF_TRIGGER_HIGH, pdev->name, controller);
> +	if (ret) {
> +		dev_err(dev, "cannot request IRQ %d\n", irq);

unnecessary print

> +		goto error;
> +	}
> +
> +	ret = devm_spi_register_master(dev, master);
> +	if (!ret) {
> +		pm_runtime_set_autosuspend_delay(dev, MSEC_PER_SEC);
> +		pm_runtime_use_autosuspend(dev);
> +		pm_runtime_set_active(dev);
> +		pm_runtime_enable(dev);

Remove all the runtime stuff.  not supported right now.

> +		return ret;
> +	}
> +error:
> +	clk_disable_unprepare(cclk);
> +	clk_disable_unprepare(iclk);
> +	spi_master_put(master);
> +	return ret;
> +}
> +
> +#ifdef CONFIG_PM_RUNTIME

Remove all the runtime stuff.  not supported right now.

> +static int spi_qup_pm_suspend_runtime(struct device *device)
> +{
> +	struct spi_master *master = dev_get_drvdata(device);
> +	struct spi_qup *controller = spi_master_get_devdata(master);
> +
> +	disable_irq(controller->irq);
> +	clk_disable_unprepare(controller->cclk);
> +	clk_disable_unprepare(controller->iclk);
> +	dev_dbg(device, "suspend runtime\n");
> +	return 0;
> +}
> +
> +static int spi_qup_pm_resume_runtime(struct device *device)
> +{
> +	struct spi_master *master = dev_get_drvdata(device);
> +	struct spi_qup *controller = spi_master_get_devdata(master);
> +
> +	clk_prepare_enable(controller->cclk);
> +	clk_prepare_enable(controller->iclk);
> +	enable_irq(controller->irq);
> +	dev_dbg(device, "resume runtime\n");
> +	return 0;
> +}
> +#endif /* CONFIG_PM_RUNTIME */
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int spi_qup_suspend(struct device *device)
> +{
> +	struct spi_master *master = dev_get_drvdata(device);
> +	struct spi_qup *controller = spi_master_get_devdata(master);
> +	int status;
> +
> +	status = spi_master_suspend(master);
> +	if (!status) {
> +		disable_irq(controller->irq);
> +		clk_disable_unprepare(controller->cclk);
> +		clk_disable_unprepare(controller->iclk);
> +	}
> +
> +	dev_dbg(device, "system suspend %d\n", status);
> +	return status;
> +}

Remove all the suspend/resume stuff.  not supported right now.

> +
> +static int spi_qup_resume(struct device *device)
> +{
> +	struct spi_master *master = dev_get_drvdata(device);
> +	struct spi_qup *controller = spi_master_get_devdata(master);
> +	int status;
> +
> +	clk_prepare_enable(controller->cclk);
> +	clk_prepare_enable(controller->iclk);
> +
> +	status = spi_master_resume(master);
> +
> +	dev_dbg(device, "system resume %d\n", status);
> +	return status;
> +}
> +#endif /* CONFIG_PM_SLEEP */

Remove all the suspend/resume stuff.  not supported right now.

> +
> +static int spi_qup_remove(struct platform_device *pdev)
> +{
> +	struct spi_master *master = dev_get_drvdata(&pdev->dev);
> +	struct spi_qup *controller = spi_master_get_devdata(master);
> +
> +	pm_runtime_get_sync(&pdev->dev);
> +

Do we need to wait for any current transactions to complete
and do a devm_free_irq()?

> +	clk_disable_unprepare(controller->cclk);
> +	clk_disable_unprepare(controller->iclk);
> +
> +	pm_runtime_put_noidle(&pdev->dev);
> +	pm_runtime_disable(&pdev->dev);
> +	return 0;
> +}
> +
> +static struct of_device_id spi_qup_dt_match[] = {
> +	{ .compatible = "qcom,spi-qup-v2", },

Need compatible tags of qcom,spi-qup-v2.1.1 (msm8974 v1) or qcom,spi-qup-v2.2.1
(msm8974 v2)

> +	{ }
> +};
> +MODULE_DEVICE_TABLE(of, spi_qup_dt_match);
> +
> +static const struct dev_pm_ops spi_qup_dev_pm_ops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(spi_qup_suspend, spi_qup_resume)
> +	SET_RUNTIME_PM_OPS(spi_qup_pm_suspend_runtime,
> +			   spi_qup_pm_resume_runtime,
> +			   NULL)
> +};

Remove this for now.

> +
> +static struct platform_driver spi_qup_driver = {
> +	.driver = {
> +		.name		= "spi_qup",
> +		.owner		= THIS_MODULE,
> +		.pm		= &spi_qup_dev_pm_ops,
> +		.of_match_table = spi_qup_dt_match,
> +	},
> +	.probe = spi_qup_probe,
> +	.remove = spi_qup_remove,
> +};
> +module_platform_driver(spi_qup_driver);
> +
> +MODULE_LICENSE("GPL v2");
> +MODULE_VERSION("0.4");
> +MODULE_ALIAS("platform:spi_qup");
> -- 
> 1.7.9.5
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply

* Re: [PATCH 1/2] spi: qup: Add device tree bindings information
From: Andy Gross @ 2014-02-07  7:43 UTC (permalink / raw)
  To: Ivan T. Ivanov
  Cc: Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Rob Landley, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1391705868-20091-2-git-send-email-iivanov-NEYub+7Iv8PQT0dZR+AlfA@public.gmane.org>

On Thu, Feb 06, 2014 at 06:57:47PM +0200, Ivan T. Ivanov wrote:
> From: "Ivan T. Ivanov" <iivanov-NEYub+7Iv8PQT0dZR+AlfA@public.gmane.org>
> 
> The Qualcomm Universal Peripheral (QUP) core is an
> AHB slave that provides a common data path (an output
> FIFO and an input FIFO) for serial peripheral interface
> (SPI) mini-core.
> 
> Signed-off-by: Ivan T. Ivanov <iivanov-NEYub+7Iv8PQT0dZR+AlfA@public.gmane.org>
> ---
>  .../devicetree/bindings/spi/qcom,spi-qup.txt       |   86 ++++++++++++++++++++
>  1 file changed, 86 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/spi/qcom,spi-qup.txt
> 
> diff --git a/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt b/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt
> new file mode 100644
> index 0000000..74565f1
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt
> @@ -0,0 +1,86 @@
> +Qualcomm Universal Peripheral (QUP) Serial Peripheral Interface (SPI)
> +
> +The QUP core is an AHB slave that provides a common data path (an output FIFO
> +and an input FIFO) for serial peripheral interface (SPI) mini-core.
> +
> +SPI in master mode support up to 50MHz, up to four chip selects, and a
> +programmable data path from 4 bits to 32 bits; supports numerous protocol
> +variants.
> +
> +Required properties:
> +- compatible: 		Should contain "qcom,spi-qup-v2".

Could be more descriptive.  qcom,spi-qup-v2.1.1 for MSM8974 v1 and
qcom,spi-qup-v2.2.1 for MSM8974 v2.

> +- reg: 				Should contain base register location and length
> +- interrupts: 		Interrupt number used by this controller
> +
> +- clocks: 			Should contain the core clock and the AHB clock.
> +- clock-names: 		Should be "core" for the core clock and "iface" for the
> +                	AHB clock.
> +
> +- #address-cells: 	Number of cells required to define a chip select
> +					address on the SPI bus. Should be set to 1.
> +- #size-cells: 		Should be zero.
> +
> +Optional properties:
> +- spi-max-frequency: Specifies maximum SPI clock frequency, Units - Hz. Definition
> +                    as per Documentation/devicetree/bindings/spi/spi-bus.txt
> +
> +SPI slave nodes must be children of the SPI master node and can
> +contain properties described in Documentation/devicetree/bindings/spi/spi-bus.txt
> +
> +Example:
> +
> +	spi_8: spi@f9964000 { /* BLSP2 QUP2 */
> +
> +		compatible = "qcom,spi-qup-v2";
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +		reg = <0xf9964000 0x1000>;
> +		interrupts = <0 102 0>;
> +		spi-max-frequency = <19200000>;
> +
> +		clocks = <&gcc GCC_BLSP2_QUP2_SPI_APPS_CLK>, <&gcc GCC_BLSP2_AHB_CLK>;
> +		clock-names = "core", "iface";
> +
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&spi8_default>;
> +
> +		device@0 {
> +			compatible = "arm,pl022-dummy";
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +			reg = <0>; /* Chip select 0 */
> +			spi-max-frequency = <19200000>;
> +			spi-cpol;
> +		};
> +
> +		device@1 {
> +			compatible = "arm,pl022-dummy";
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +			reg = <1>; /* Chip select 1 */
> +			spi-max-frequency = <9600000>;
> +			spi-cpha;
> +		};
> +
> +		device@2 {
> +			compatible = "arm,pl022-dummy";
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +			reg = <2>; /* Chip select 2 */
> +			spi-max-frequency = <19200000>;
> +			spi-cpol;
> +			spi-cpha;
> +		};
> +
> +		device@3 {
> +			compatible = "arm,pl022-dummy";
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +			reg = <3>; /* Chip select 3 */
> +			spi-max-frequency = <19200000>;
> +			spi-cpol;
> +			spi-cpha;
> +			spi-cs-high;
> +		};
> +	};
> +
> -- 
> 1.7.9.5
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
--
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 RESEND 1/2] spi: qup: Add device tree bindings information
From: Ivan T. Ivanov @ 2014-02-07  7:43 UTC (permalink / raw)
  To: Mark Brown, Grant Likely, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Rob Landley
  Cc: Ivan T. Ivanov, linux-spi, devicetree, linux-doc, linux-arm-msm,
	linux-kernel
In-Reply-To: <20140206175059.GW32298@sirena.org.uk>

From: "Ivan T. Ivanov" <iivanov@mm-sol.com>

The Qualcomm Universal Peripheral (QUP) core is an
AHB slave that provides a common data path (an output
FIFO and an input FIFO) for serial peripheral interface
(SPI) mini-core.

Signed-off-by: Ivan T. Ivanov <iivanov@mm-sol.com>
---
 .../devicetree/bindings/spi/qcom,spi-qup.txt       |   86 ++++++++++++++++++++
 1 file changed, 86 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/spi/qcom,spi-qup.txt

diff --git a/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt b/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt
new file mode 100644
index 0000000..74565f1
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt
@@ -0,0 +1,86 @@
+Qualcomm Universal Peripheral (QUP) Serial Peripheral Interface (SPI)
+
+The QUP core is an AHB slave that provides a common data path (an output FIFO
+and an input FIFO) for serial peripheral interface (SPI) mini-core.
+
+SPI in master mode support up to 50MHz, up to four chip selects, and a
+programmable data path from 4 bits to 32 bits; supports numerous protocol
+variants.
+
+Required properties:
+- compatible: 		Should contain "qcom,spi-qup-v2".
+- reg: 				Should contain base register location and length
+- interrupts: 		Interrupt number used by this controller
+
+- clocks: 			Should contain the core clock and the AHB clock.
+- clock-names: 		Should be "core" for the core clock and "iface" for the
+                	AHB clock.
+
+- #address-cells: 	Number of cells required to define a chip select
+					address on the SPI bus. Should be set to 1.
+- #size-cells: 		Should be zero.
+
+Optional properties:
+- spi-max-frequency: Specifies maximum SPI clock frequency, Units - Hz. Definition
+                    as per Documentation/devicetree/bindings/spi/spi-bus.txt
+
+SPI slave nodes must be children of the SPI master node and can
+contain properties described in Documentation/devicetree/bindings/spi/spi-bus.txt
+
+Example:
+
+	spi_8: spi@f9964000 { /* BLSP2 QUP2 */
+
+		compatible = "qcom,spi-qup-v2";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0xf9964000 0x1000>;
+		interrupts = <0 102 0>;
+		spi-max-frequency = <19200000>;
+
+		clocks = <&gcc GCC_BLSP2_QUP2_SPI_APPS_CLK>, <&gcc GCC_BLSP2_AHB_CLK>;
+		clock-names = "core", "iface";
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&spi8_default>;
+
+		device@0 {
+			compatible = "arm,pl022-dummy";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0>; /* Chip select 0 */
+			spi-max-frequency = <19200000>;
+			spi-cpol;
+		};
+
+		device@1 {
+			compatible = "arm,pl022-dummy";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <1>; /* Chip select 1 */
+			spi-max-frequency = <9600000>;
+			spi-cpha;
+		};
+
+		device@2 {
+			compatible = "arm,pl022-dummy";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <2>; /* Chip select 2 */
+			spi-max-frequency = <19200000>;
+			spi-cpol;
+			spi-cpha;
+		};
+
+		device@3 {
+			compatible = "arm,pl022-dummy";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <3>; /* Chip select 3 */
+			spi-max-frequency = <19200000>;
+			spi-cpol;
+			spi-cpha;
+			spi-cs-high;
+		};
+	};
+
-- 
1.7.9.5

^ permalink raw reply related

* Re: [PATCH 4/4] ARM: Kirkwood: Add support for many Synology NAS devices
From: Ben Peddell @ 2014-02-07  7:44 UTC (permalink / raw)
  To: Andrew Lunn, Jason Cooper
  Cc: linux ARM, devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
	pawel.moll-5wv7dgnIgG8, Mark Rutland, Ian Campbell, Kumar Gala
In-Reply-To: <20140206160126.GH29860-g2DYL2Zd6BY@public.gmane.org>

On 7/02/2014 2:01 AM, Andrew Lunn wrote:
> On Thu, Feb 06, 2014 at 10:39:39AM -0500, Jason Cooper wrote:
>>
>> + devicetree ML, DT maintainers
>>
>> On Wed, Feb 05, 2014 at 10:05:09PM +0100, Andrew Lunn wrote:
>>> Add device tree fragments and files to support many of the kirkwood
>>> based Synology NAS devices. This is a translation of the board setup
>>> file maintained by Ben Peddell <klightspeed-aslSrjg9ejhWX4hkXwHRhw@public.gmane.org>
>>>
>>> Signed-off-by: Andrew Lunn <andrew-g2DYL2Zd6BY@public.gmane.org>
>>> Tested by Ben Peddell <klightspeed-aslSrjg9ejhWX4hkXwHRhw@public.gmane.org>
>>> cc: Ben Peddell <klightspeed-aslSrjg9ejhWX4hkXwHRhw@public.gmane.org>
>>> ---
>>>
>>> v2:
>>> Fix gpio's which should be gpo.
>>> Rebase onto v3-14-rc1
>>> Update RTC nodes with vendor name.
>>> Update SPI flash node with vendor name.
>>> ---
>>>  arch/arm/boot/dts/Makefile                     |   15 ++++
>>>  arch/arm/boot/dts/kirkwood-ds109.dts           |   33 +++++++
>>>  arch/arm/boot/dts/kirkwood-ds110jv10.dts       |   33 +++++++
>>>  arch/arm/boot/dts/kirkwood-ds111.dts           |   33 +++++++
>>>  arch/arm/boot/dts/kirkwood-ds112.dts           |   34 +++++++
>>>  arch/arm/boot/dts/kirkwood-ds209.dts           |   33 +++++++
>>>  arch/arm/boot/dts/kirkwood-ds210.dts           |   35 ++++++++
>>>  arch/arm/boot/dts/kirkwood-ds212.dts           |   37 ++++++++
>>>  arch/arm/boot/dts/kirkwood-ds212j.dts          |   34 +++++++
>>>  arch/arm/boot/dts/kirkwood-ds409.dts           |   34 +++++++
>>>  arch/arm/boot/dts/kirkwood-ds409slim.dts       |   32 +++++++
>>>  arch/arm/boot/dts/kirkwood-ds411.dts           |   35 ++++++++
>>>  arch/arm/boot/dts/kirkwood-ds411j.dts          |   34 +++++++
>>>  arch/arm/boot/dts/kirkwood-ds411slim.dts       |   34 +++++++
>>>  arch/arm/boot/dts/kirkwood-rs212.dts           |   34 +++++++
>>>  arch/arm/boot/dts/kirkwood-rs409.dts           |   33 +++++++
>>>  arch/arm/boot/dts/kirkwood-rs411.dts           |   34 +++++++
>>>  arch/arm/boot/dts/synology/alarm-led-12.dtsi   |   28 ++++++
>>>  arch/arm/boot/dts/synology/common.dtsi         |  112 ++++++++++++++++++++++++
>>>  arch/arm/boot/dts/synology/ethernet-1.dtsi     |   15 ++++
>>>  arch/arm/boot/dts/synology/fan-alarm-18.dtsi   |   22 +++++
>>>  arch/arm/boot/dts/synology/fan-alarm-35-1.dtsi |   22 +++++
>>>  arch/arm/boot/dts/synology/fan-alarm-35-3.dtsi |   32 +++++++
>>>  arch/arm/boot/dts/synology/fan-gpios-15.dtsi   |   34 +++++++
>>>  arch/arm/boot/dts/synology/fan-gpios-32.dtsi   |   34 +++++++
>>>  arch/arm/boot/dts/synology/fan-speed-100.dtsi  |   20 +++++
>>>  arch/arm/boot/dts/synology/fan-speed-120.dtsi  |   20 +++++
>>>  arch/arm/boot/dts/synology/fan-speed-150.dtsi  |   20 +++++
>>>  arch/arm/boot/dts/synology/hdd-leds-20.dtsi    |   90 +++++++++++++++++++
>>>  arch/arm/boot/dts/synology/hdd-leds-21-1.dtsi  |   36 ++++++++
>>>  arch/arm/boot/dts/synology/hdd-leds-21-2.dtsi  |   52 +++++++++++
>>>  arch/arm/boot/dts/synology/hdd-leds-36.dtsi    |  103 ++++++++++++++++++++++
>>>  arch/arm/boot/dts/synology/hdd-leds-38.dtsi    |   52 +++++++++++
>>>  arch/arm/boot/dts/synology/hdd-power-29.dtsi   |   56 ++++++++++++
>>>  arch/arm/boot/dts/synology/hdd-power-30-1.dtsi |   40 +++++++++
>>>  arch/arm/boot/dts/synology/hdd-power-30-2.dtsi |   56 ++++++++++++
>>>  arch/arm/boot/dts/synology/hdd-power-30-4.dtsi |   89 +++++++++++++++++++
>>>  arch/arm/boot/dts/synology/hdd-power-31.dtsi   |   40 +++++++++
>>>  arch/arm/boot/dts/synology/hdd-power-34.dtsi   |   73 +++++++++++++++
>>>  arch/arm/boot/dts/synology/i2c-rtc-ricoh.dtsi  |   18 ++++
>>>  arch/arm/boot/dts/synology/i2c-rtc-seiko.dtsi  |   18 ++++
>>>  arch/arm/boot/dts/synology/pcie-2.dtsi         |   19 ++++
>>>  42 files changed, 1658 insertions(+)
>>>  create mode 100644 arch/arm/boot/dts/kirkwood-ds109.dts
>>>  create mode 100644 arch/arm/boot/dts/kirkwood-ds110jv10.dts
>>>  create mode 100644 arch/arm/boot/dts/kirkwood-ds111.dts
>>>  create mode 100644 arch/arm/boot/dts/kirkwood-ds112.dts
>>>  create mode 100644 arch/arm/boot/dts/kirkwood-ds209.dts
>>>  create mode 100644 arch/arm/boot/dts/kirkwood-ds210.dts
>>>  create mode 100644 arch/arm/boot/dts/kirkwood-ds212.dts
>>>  create mode 100644 arch/arm/boot/dts/kirkwood-ds212j.dts
>>>  create mode 100644 arch/arm/boot/dts/kirkwood-ds409.dts
>>>  create mode 100644 arch/arm/boot/dts/kirkwood-ds409slim.dts
>>>  create mode 100644 arch/arm/boot/dts/kirkwood-ds411.dts
>>>  create mode 100644 arch/arm/boot/dts/kirkwood-ds411j.dts
>>>  create mode 100644 arch/arm/boot/dts/kirkwood-ds411slim.dts
>>>  create mode 100644 arch/arm/boot/dts/kirkwood-rs212.dts
>>>  create mode 100644 arch/arm/boot/dts/kirkwood-rs409.dts
>>>  create mode 100644 arch/arm/boot/dts/kirkwood-rs411.dts
>>>  create mode 100644 arch/arm/boot/dts/synology/alarm-led-12.dtsi
>>>  create mode 100644 arch/arm/boot/dts/synology/common.dtsi
>>>  create mode 100644 arch/arm/boot/dts/synology/ethernet-1.dtsi
>>>  create mode 100644 arch/arm/boot/dts/synology/fan-alarm-18.dtsi
>>>  create mode 100644 arch/arm/boot/dts/synology/fan-alarm-35-1.dtsi
>>>  create mode 100644 arch/arm/boot/dts/synology/fan-alarm-35-3.dtsi
>>>  create mode 100644 arch/arm/boot/dts/synology/fan-gpios-15.dtsi
>>>  create mode 100644 arch/arm/boot/dts/synology/fan-gpios-32.dtsi
>>>  create mode 100644 arch/arm/boot/dts/synology/fan-speed-100.dtsi
>>>  create mode 100644 arch/arm/boot/dts/synology/fan-speed-120.dtsi
>>>  create mode 100644 arch/arm/boot/dts/synology/fan-speed-150.dtsi

If we're not worried about the non-linearity of the 150R+120R+100R and
182R+150R+100R fan controllers (vs the 150R/100R/33R ones), these fan
speed blocks could be collapsed into common.dtsi.

>>>  create mode 100644 arch/arm/boot/dts/synology/hdd-leds-20.dtsi
>>>  create mode 100644 arch/arm/boot/dts/synology/hdd-leds-21-1.dtsi
>>>  create mode 100644 arch/arm/boot/dts/synology/hdd-leds-21-2.dtsi
>>>  create mode 100644 arch/arm/boot/dts/synology/hdd-leds-36.dtsi
>>>  create mode 100644 arch/arm/boot/dts/synology/hdd-leds-38.dtsi
>>>  create mode 100644 arch/arm/boot/dts/synology/hdd-power-29.dtsi
>>>  create mode 100644 arch/arm/boot/dts/synology/hdd-power-30-1.dtsi
>>>  create mode 100644 arch/arm/boot/dts/synology/hdd-power-30-2.dtsi
>>>  create mode 100644 arch/arm/boot/dts/synology/hdd-power-30-4.dtsi
>>>  create mode 100644 arch/arm/boot/dts/synology/hdd-power-31.dtsi
>>>  create mode 100644 arch/arm/boot/dts/synology/hdd-power-34.dtsi
>>>  create mode 100644 arch/arm/boot/dts/synology/i2c-rtc-ricoh.dtsi
>>>  create mode 100644 arch/arm/boot/dts/synology/i2c-rtc-seiko.dtsi
>>>  create mode 100644 arch/arm/boot/dts/synology/pcie-2.dtsi
>>
>> Holy sh*t!  I know we're adding 15 boards
> 
> More than 15 actually. Most .dts files support multiple devices. So
> there should be about 30 devices supported by these .dts files.
> 
>> , but this is, imho,
>> over-fragmenting.  I'm sure there's a reason you chose this path, but
>> you haven't explained why in your commit log. So I'm left guessing...
> 
> Synology seem to build there devices like lego. They have two
> different RTC blocks. They have three different fan alarm blocks, four
> different led blocks, etc. And to build a product, the just select a
> group of blocks and put them together.

The Ricoh RTC seems to be only used in the pre-2010 units.  Everything
else uses the Seiko RTC.

Most of the 1-bay and 2-bay units use the GPIOs that are multiplexed
with the built-in SATA interface activity/presence pins on mpp 20-23,
while the 4-bay units use ge01 and a PCIe SATA controller, and put the
software controlled HDD leds on mpp 36-43.

Most of the 6281 units with HDD power controls use mpp 29 and 31, while
most of the 6282 units with HDD power controls use mpp 30, 34, 44 and 45
and provide a model ID on mpp 28, 29, 46 and 47.  Pre-2012 units and
4-bay units didn't have a separate power control for HDD1.  These power
controls are presumably to limit startup current from the 12V brick
power supply.

From
http://forum.synology.com/wiki/index.php/What_kind_of_CPU_does_my_NAS_have,
it doesn't look like there are any new 6281 or 6282 models for 2014.

> 
> The board setup code which Ben Peddell wrote has a somewhat similar
> structure:
> 
> http://klightspeed.killerwolves.net/synology/linux-3.4-synology-0.1.patch

A more up-to-date version is at:
http://klightspeed.killerwolves.net/synology/linux-3.7-synology-0.2.patch

> 
> It has a set of functions which add platform devices. And a table
> driven piece of code which based on the product name calls these
> functions to add the needed platform devices. Take a look at the table
> to get a better idea of the re-use factor of the blocks.
> 
> In this DT version, i have a dtsi file for each function, and a dti
> file for each table entry.
> 
> I will add to the changelog in the next version.



-- 
Ben Peddell
IT Support Bowen, Collinsville and Proserpine Catholic schools
http://klightspeed.killerwolves.net/
--
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 v1 1/3] net: stmmac:sti: Add STi SOC glue driver.
From: srinivas kandagatla @ 2014-02-07  7:54 UTC (permalink / raw)
  To: David Miller
  Cc: mark.rutland, devicetree, linux, kernel, pawel.moll,
	ijc+devicetree, netdev, linux-doc, linux-kernel, stuart.menefy,
	robh+dt, rob, galak, peppe.cavallaro, linux-arm-kernel
In-Reply-To: <20140206.195342.1998479313077409827.davem@davemloft.net>

Thankyou Dave,

On 07/02/14 03:53, David Miller wrote:
> From: <srinivas.kandagatla@st.com>
> Date: Mon, 3 Feb 2014 12:01:08 +0000
> 
>> +	res = platform_get_resource_byname(pdev,
>> +				IORESOURCE_MEM, "sti-ethconf");
> 
> This is not the correct way to format multi-line function calls,
> you'll need to fix this up in this entire series.

I will fix this in next version.


> 
> The arguments on the second and subsequent lines must start at
> the first column after the openning parenthesis of the function
> call.  You must use the appropriate number of both space and
> TAB characters necessary to do so.
> 
> If you're only using TAB characters to indent, you're doing it
> wrong.
> 
> Thank you.
> 
> 

Thanks,
srini

^ permalink raw reply


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