Devicetree
 help / color / mirror / Atom feed
* Re: [PATCHv2 net-next 11/16] net: mvpp2: handle misc PPv2.1/PPv2.2 differences
From: Russell King - ARM Linux @ 2017-01-07 20:10 UTC (permalink / raw)
  To: Thomas Petazzoni
  Cc: Mark Rutland, devicetree-u79uwXL29TY76Z2rM5mHXA, Yehuda Yitschak,
	Jason Cooper, Pawel Moll, Ian Campbell,
	netdev-u79uwXL29TY76Z2rM5mHXA, Hanna Hawa, Nadav Haklai,
	Rob Herring, Andrew Lunn, Kumar Gala, Gregory Clement,
	Stefan Chulski, Marcin Wojtas, David S. Miller,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	Sebastian Hesselbarth
In-Reply-To: <20170107093834.GJ14217-l+eeeJia6m9URfEZ8mYm6t73F7V6hmMc@public.gmane.org>

On Sat, Jan 07, 2017 at 09:38:34AM +0000, Russell King - ARM Linux wrote:
> On Wed, Dec 28, 2016 at 05:46:27PM +0100, Thomas Petazzoni wrote:
> > @@ -6511,7 +6515,9 @@ static int mvpp2_port_probe(struct platform_device *pdev,
> >  		dev_err(&pdev->dev, "failed to init port %d\n", id);
> >  		goto err_free_stats;
> >  	}
> > -	mvpp2_port_power_up(port);
> > +
> > +	if (priv->hw_version == MVPP21)
> > +		mvpp21_port_power_up(port);
> 
> This has the side effect that nothing clears the port reset bit in the
> GMAC, which means there's no hope of the interface working - with the
> reset bit set, the port is well and truely held in "link down" state.
> 
> In any case, the GMAC part is much the same as mvneta, and I think
> that code should be shared rather than writing new versions of it.
> There are some subtle differences between neta, pp2.1 and pp2.2, but
> it's entirely doable (I have an implementation here as I wasn't going
> to duplicate this code for my phylink conversion.)

In addition to comphy configuration and the above, I also need the
following to have working SGMII.  The change of MACMODE is needed
because uboot has configured the port for 10Gbase-R mode (it has a
10G PHY on it, but the PHY switches to SGMII in <10G modes.)  The
GMAC control register 4 is needed to properly configure for SGMII
mode.  I also included RGMII mode as well in there, as I expect you'd
need it to have GMAC properly configured for RGMII.

With this in place (and the other bits mentioned above), I can ping
the clearfog switch on the other end of eth0's cable:

# ping6 -I eth0 fe80::250:43ff:fe02:302
PING fe80::250:43ff:fe02:302(fe80::250:43ff:fe02:302) from fe80::200:ff:fe00:1 eth0: 56 data bytes
64 bytes from fe80::250:43ff:fe02:302: icmp_seq=1 ttl=64 time=0.297 ms

diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index bc97eebf7eee..4b6ec6213e9c 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -345,7 +345,17 @@
 #define      MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK	0x1fc0
 #define      MVPP2_GMAC_TX_FIFO_MIN_TH_MASK(v)	(((v) << 6) & \
 					MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK)
+#define MVPP22_GMAC_CTRL_4_REG			0x90
+#define      MVPP22_CTRL4_EXT_PIN_GMII_SEL	BIT(0)
+#define      MVPP22_CTRL4_DP_CLK_SEL		BIT(5)
+#define      MVPP22_CTRL4_SYNC_BYPASS		BIT(6)
+#define      MVPP22_CTRL4_QSGMII_BYPASS_ACTIVE	BIT(7)
+
+#define MVPP22_XLG_CTRL3_REG			0x11c
+#define      MVPP22_XLG_CTRL3_MACMODESELECT_MASK	(7 << 13)
+#define      MVPP22_XLG_CTRL3_MACMODESELECT_GMAC	(0 << 13)
 
+/* offsets from iface_base */
 #define MVPP22_SMI_MISC_CFG_REG			0x2a204
 #define      MVPP22_SMI_POLLING_EN		BIT(10)
 
@@ -4171,6 +4181,23 @@ static void mvpp2_port_mii_set(struct mvpp2_port *port)
 {
 	u32 val;
 
+	if (port->priv->hw_version == MVPP22) {
+		val = readl(port->base + MVPP22_XLG_CTRL3_REG);
+		val &= ~MVPP22_XLG_CTRL3_MACMODESELECT_MASK;
+		val |= MVPP22_XLG_CTRL3_MACMODESELECT_GMAC;
+		writel(val, port->base + MVPP22_XLG_CTRL3_REG);
+
+		val = readl(port->base + MVPP22_GMAC_CTRL_4_REG);
+		if (port->phy_interface == PHY_INTERFACE_MODE_RGMII)
+			val |= MVPP22_CTRL4_EXT_PIN_GMII_SEL;
+		else
+			val &= ~MVPP22_CTRL4_EXT_PIN_GMII_SEL;
+		val &= ~MVPP22_CTRL4_DP_CLK_SEL;
+		val |= MVPP22_CTRL4_SYNC_BYPASS;
+		val |= MVPP22_CTRL4_QSGMII_BYPASS_ACTIVE;
+		writel(val, port->base + MVPP22_GMAC_CTRL_4_REG);
+	}
+
 	val = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
 
 	switch (port->phy_interface) {


-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.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 related

* Re: [PATCH v2 0/9] Use mmio-sram driver for Keystone MSMC RAM
From: santosh.shilimkar @ 2017-01-07 20:36 UTC (permalink / raw)
  To: Suman Anna, Santosh Shilimkar
  Cc: devicetree, Russell King, Vitaly Andrianov, linux-kernel,
	Tero Kristo, Rob Herring, Murali Karicheri, linux-arm-kernel
In-Reply-To: <20170106215733.41637-1-s-anna@ti.com>

On 1/6/17 1:57 PM, Suman Anna wrote:
> Hi,
>
> The Keystone 2 family of SoCs have an on-chip RAM called the
> Multicore Shared Memory (MSM) RAM. This RAM is accessible through
> the Multicore Shared Memory Controller (MSMC). This series represents
> these on-chip RAMs as sram nodes so that the memory allocations
> can be managed by the in-kernel mmio-sram driver.
>
> This is v2 of the previous series [1], and now includes 4 additional
> patches that reserve the portions of the MSMC RAM used by the
> Keystone Boot Monitor. The first 5 patches are essentially the same
> as in v1, with minor commit description updates for using the proper
> SoC names, but no code changes.
>
> Patches baselined on 4.10-rc1.
>
Applied. Should start showing up next soon. thanks !!

Regards,
Santosh

^ permalink raw reply

* [PATCH] Documentation: display: fix wrong documentation paths
From: Yegor Yefremov @ 2017-01-07 21:14 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	airlied-cv59FeDIM0c, Yegor Yefremov

Signed-off-by: Yegor Yefremov <yegorslists-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
---
 Documentation/devicetree/bindings/display/arm,pl11x.txt                 | 2 +-
 Documentation/devicetree/bindings/display/bridge/analogix_dp.txt        | 2 +-
 Documentation/devicetree/bindings/display/cirrus,clps711x-fb.txt        | 2 +-
 Documentation/devicetree/bindings/display/exynos/exynos7-decon.txt      | 2 +-
 Documentation/devicetree/bindings/display/exynos/samsung-fimd.txt       | 2 +-
 Documentation/devicetree/bindings/display/imx/fsl,imx-fb.txt            | 2 +-
 Documentation/devicetree/bindings/display/imx/ldb.txt                   | 2 +-
 Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt    | 2 +-
 Documentation/devicetree/bindings/display/msm/dsi.txt                   | 2 +-
 Documentation/devicetree/bindings/display/msm/edp.txt                   | 2 +-
 Documentation/devicetree/bindings/display/msm/hdmi.txt                  | 2 +-
 Documentation/devicetree/bindings/display/panel/samsung,ld9040.txt      | 2 +-
 Documentation/devicetree/bindings/display/panel/samsung,s6e8aa0.txt     | 2 +-
 .../devicetree/bindings/display/rockchip/analogix_dp-rockchip.txt       | 2 +-
 Documentation/devicetree/bindings/display/tilcdc/panel.txt              | 2 +-
 15 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/arm,pl11x.txt b/Documentation/devicetree/bindings/display/arm,pl11x.txt
index 3e3039a..ef89ab4 100644
--- a/Documentation/devicetree/bindings/display/arm,pl11x.txt
+++ b/Documentation/devicetree/bindings/display/arm,pl11x.txt
@@ -22,7 +22,7 @@ Required properties:
 
 - clocks: contains phandle and clock specifier pairs for the entries
 	in the clock-names property. See
-	Documentation/devicetree/binding/clock/clock-bindings.txt
+	Documentation/devicetree/bindings/clock/clock-bindings.txt
 
 Optional properties:
 
diff --git a/Documentation/devicetree/bindings/display/bridge/analogix_dp.txt b/Documentation/devicetree/bindings/display/bridge/analogix_dp.txt
index 4a0f4f7..0c7473dd 100644
--- a/Documentation/devicetree/bindings/display/bridge/analogix_dp.txt
+++ b/Documentation/devicetree/bindings/display/bridge/analogix_dp.txt
@@ -33,7 +33,7 @@ Optional properties for dp-controller:
 		in Documentation/devicetree/bindings/media/video-interfaces.txt,
 		please refer to the SoC specific binding document:
 		* Documentation/devicetree/bindings/display/exynos/exynos_dp.txt
-		* Documentation/devicetree/bindings/video/analogix_dp-rockchip.txt
+		* Documentation/devicetree/bindings/display/rockchip/analogix_dp-rockchip.txt
 
 [1]: Documentation/devicetree/bindings/media/video-interfaces.txt
 -------------------------------------------------------------------------------
diff --git a/Documentation/devicetree/bindings/display/cirrus,clps711x-fb.txt b/Documentation/devicetree/bindings/display/cirrus,clps711x-fb.txt
index e9c6574..b0e5066 100644
--- a/Documentation/devicetree/bindings/display/cirrus,clps711x-fb.txt
+++ b/Documentation/devicetree/bindings/display/cirrus,clps711x-fb.txt
@@ -6,7 +6,7 @@ Required properties:
               location and size of the framebuffer memory.
 - clocks    : phandle + clock specifier pair of the FB reference clock.
 - display   : phandle to a display node as described in
-              Documentation/devicetree/bindings/display/display-timing.txt.
+              Documentation/devicetree/bindings/display/panel/display-timing.txt.
               Additionally, the display node has to define properties:
   - bits-per-pixel: Bits per pixel.
   - ac-prescale   : LCD AC bias frequency. This frequency is the required
diff --git a/Documentation/devicetree/bindings/display/exynos/exynos7-decon.txt b/Documentation/devicetree/bindings/display/exynos/exynos7-decon.txt
index 3938caa..027d6c2 100644
--- a/Documentation/devicetree/bindings/display/exynos/exynos7-decon.txt
+++ b/Documentation/devicetree/bindings/display/exynos/exynos7-decon.txt
@@ -38,7 +38,7 @@ Optional Properties:
 		Can be used in case timings cannot be provided otherwise
 		or to override timings provided by the panel.
 
-[1]: Documentation/devicetree/bindings/display/display-timing.txt
+[1]: Documentation/devicetree/bindings/display/panel/display-timing.txt
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/display/exynos/samsung-fimd.txt b/Documentation/devicetree/bindings/display/exynos/samsung-fimd.txt
index c7c6b9a..18645e0 100644
--- a/Documentation/devicetree/bindings/display/exynos/samsung-fimd.txt
+++ b/Documentation/devicetree/bindings/display/exynos/samsung-fimd.txt
@@ -83,7 +83,7 @@ in [2]. The following are properties specific to those nodes:
 		3 - for parallel output,
 		4 - for write-back interface
 
-[1]: Documentation/devicetree/bindings/display/display-timing.txt
+[1]: Documentation/devicetree/bindings/display/panel/display-timing.txt
 [2]: Documentation/devicetree/bindings/media/video-interfaces.txt
 
 Example:
diff --git a/Documentation/devicetree/bindings/display/imx/fsl,imx-fb.txt b/Documentation/devicetree/bindings/display/imx/fsl,imx-fb.txt
index 00d5f8e..7a5c0e2 100644
--- a/Documentation/devicetree/bindings/display/imx/fsl,imx-fb.txt
+++ b/Documentation/devicetree/bindings/display/imx/fsl,imx-fb.txt
@@ -9,7 +9,7 @@ Required properties:
 
 Required nodes:
 - display: Phandle to a display node as described in
-	Documentation/devicetree/bindings/display/display-timing.txt
+	Documentation/devicetree/bindings/display/panel/display-timing.txt
 	Additional, the display node has to define properties:
 	- bits-per-pixel: Bits per pixel
 	- fsl,pcr: LCDC PCR value
diff --git a/Documentation/devicetree/bindings/display/imx/ldb.txt b/Documentation/devicetree/bindings/display/imx/ldb.txt
index a407462..38c637f 100644
--- a/Documentation/devicetree/bindings/display/imx/ldb.txt
+++ b/Documentation/devicetree/bindings/display/imx/ldb.txt
@@ -64,7 +64,7 @@ Required properties:
 Optional properties (required if display-timings are used):
  - ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
  - display-timings : A node that describes the display timings as defined in
-   Documentation/devicetree/bindings/display/display-timing.txt.
+   Documentation/devicetree/bindings/display/panel/display-timing.txt.
  - fsl,data-mapping : should be "spwg" or "jeida"
                       This describes how the color bits are laid out in the
                       serialized LVDS signal.
diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt b/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt
index db6e77e..708f566 100644
--- a/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt
@@ -55,7 +55,7 @@ Required properties (DMA function blocks):
 	"mediatek,<chip>-disp-rdma"
 	"mediatek,<chip>-disp-wdma"
 - larb: Should contain a phandle pointing to the local arbiter device as defined
-  in Documentation/devicetree/bindings/soc/mediatek/mediatek,smi-larb.txt
+  in Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt
 - iommus: Should point to the respective IOMMU block with master port as
   argument, see Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
   for details.
diff --git a/Documentation/devicetree/bindings/display/msm/dsi.txt b/Documentation/devicetree/bindings/display/msm/dsi.txt
index 6b1cab1..fa00e62 100644
--- a/Documentation/devicetree/bindings/display/msm/dsi.txt
+++ b/Documentation/devicetree/bindings/display/msm/dsi.txt
@@ -108,7 +108,7 @@ Optional properties:
 - qcom,dsi-phy-regulator-ldo-mode: Boolean value indicating if the LDO mode PHY
   regulator is wanted.
 
-[1] Documentation/devicetree/bindings/clocks/clock-bindings.txt
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
 [2] Documentation/devicetree/bindings/graph.txt
 [3] Documentation/devicetree/bindings/media/video-interfaces.txt
 [4] Documentation/devicetree/bindings/display/panel/
diff --git a/Documentation/devicetree/bindings/display/msm/edp.txt b/Documentation/devicetree/bindings/display/msm/edp.txt
index 3a20f6e..e63032b 100644
--- a/Documentation/devicetree/bindings/display/msm/edp.txt
+++ b/Documentation/devicetree/bindings/display/msm/edp.txt
@@ -10,7 +10,7 @@ Required properties:
 - interrupts: The interrupt signal from the eDP block.
 - power-domains: Should be <&mmcc MDSS_GDSC>.
 - clocks: device clocks
-  See Documentation/devicetree/bindings/clocks/clock-bindings.txt for details.
+  See Documentation/devicetree/bindings/clock/clock-bindings.txt for details.
 - clock-names: the following clocks are required:
   * "core_clk"
   * "iface_clk"
diff --git a/Documentation/devicetree/bindings/display/msm/hdmi.txt b/Documentation/devicetree/bindings/display/msm/hdmi.txt
index 2ad5789..2d306f4 100644
--- a/Documentation/devicetree/bindings/display/msm/hdmi.txt
+++ b/Documentation/devicetree/bindings/display/msm/hdmi.txt
@@ -49,7 +49,7 @@ Required properties:
     * "hdmi_tx_l4"
 - power-domains: Should be <&mmcc MDSS_GDSC>.
 - clocks: device clocks
-  See Documentation/devicetree/bindings/clocks/clock-bindings.txt for details.
+  See Documentation/devicetree/bindings/clock/clock-bindings.txt for details.
 - core-vdda-supply: phandle to vdda regulator device node
 
 Example:
diff --git a/Documentation/devicetree/bindings/display/panel/samsung,ld9040.txt b/Documentation/devicetree/bindings/display/panel/samsung,ld9040.txt
index fc595d9..354d4d1 100644
--- a/Documentation/devicetree/bindings/display/panel/samsung,ld9040.txt
+++ b/Documentation/devicetree/bindings/display/panel/samsung,ld9040.txt
@@ -20,7 +20,7 @@ The device node can contain one 'port' child node with one child
 'endpoint' node, according to the bindings defined in [3]. This
 node should describe panel's video bus.
 
-[1]: Documentation/devicetree/bindings/display/display-timing.txt
+[1]: Documentation/devicetree/bindings/display/panel/display-timing.txt
 [2]: Documentation/devicetree/bindings/spi/spi-bus.txt
 [3]: Documentation/devicetree/bindings/media/video-interfaces.txt
 
diff --git a/Documentation/devicetree/bindings/display/panel/samsung,s6e8aa0.txt b/Documentation/devicetree/bindings/display/panel/samsung,s6e8aa0.txt
index 25701c8..9e766c5 100644
--- a/Documentation/devicetree/bindings/display/panel/samsung,s6e8aa0.txt
+++ b/Documentation/devicetree/bindings/display/panel/samsung,s6e8aa0.txt
@@ -21,7 +21,7 @@ The device node can contain one 'port' child node with one child
 'endpoint' node, according to the bindings defined in [2]. This
 node should describe panel's video bus.
 
-[1]: Documentation/devicetree/bindings/display/display-timing.txt
+[1]: Documentation/devicetree/bindings/display/panel/display-timing.txt
 [2]: Documentation/devicetree/bindings/media/video-interfaces.txt
 
 Example:
diff --git a/Documentation/devicetree/bindings/display/rockchip/analogix_dp-rockchip.txt b/Documentation/devicetree/bindings/display/rockchip/analogix_dp-rockchip.txt
index 01cced1..47665a1 100644
--- a/Documentation/devicetree/bindings/display/rockchip/analogix_dp-rockchip.txt
+++ b/Documentation/devicetree/bindings/display/rockchip/analogix_dp-rockchip.txt
@@ -35,7 +35,7 @@ Optional property for different chips:
 	       Required elements: "grf"
 
 For the below properties, please refer to Analogix DP binding document:
- * Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt
+ * Documentation/devicetree/bindings/display/bridge/analogix_dp.txt
 - phys (required)
 - phy-names (required)
 - hpd-gpios (optional)
diff --git a/Documentation/devicetree/bindings/display/tilcdc/panel.txt b/Documentation/devicetree/bindings/display/tilcdc/panel.txt
index f20b31c..8082163 100644
--- a/Documentation/devicetree/bindings/display/tilcdc/panel.txt
+++ b/Documentation/devicetree/bindings/display/tilcdc/panel.txt
@@ -15,7 +15,7 @@ Required properties:
  - display-timings: typical videomode of lcd panel.  Multiple video modes
    can be listed if the panel supports multiple timings, but the 'native-mode'
    should be the preferred/default resolution.  Refer to
-   Documentation/devicetree/bindings/display/display-timing.txt for display
+   Documentation/devicetree/bindings/display/panel/display-timing.txt for display
    timing binding details.
 
 Optional properties:
-- 
2.7.4

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

^ permalink raw reply related

* Re: [PATCH v3 2/2] ARM: dts: imx6q: Add mccmon6 board support
From: Lukasz Majewski @ 2017-01-07 21:24 UTC (permalink / raw)
  To: Rob Herring, Mark Rutland, Russell King, Shawn Guo, Fabio Estevam,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	Vladimir Zapolskiy
  Cc: Sascha Hauer, Zerlauth Karl (LWN), Lukasz Majewski
In-Reply-To: <1483440381-24268-2-git-send-email-lukma-ynQEQJNshbs@public.gmane.org>

Dear All,

> From: Lukasz Majewski <l.majewski-AM3owJQeAb5mR6Xm/wNWPw@public.gmane.org>
> 
> This patch provides support for Liebherr's Monitor 6 board
> (abverrated as mccmon6) to Linux kernel.
> 
> Signed-off-by: Lukasz Majewski <lukma-ynQEQJNshbs@public.gmane.org>
> ---
> Changes for v3:
> - Reorganize the dts file according to Shawn Guo's comments
> 
> Changes for v2:
> - Reorganize the dts file according to Valdimir Zapolskiy's comments

Do you have any more comments for this DTS file?


Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd-ynQEQJNshbs@public.gmane.org
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 1/1] iio: adc: tlc4541: add support for TI tlc4541 adc
From: Jonathan Cameron @ 2017-01-07 22:27 UTC (permalink / raw)
  To: Peter Meerwald-Stadler, Phil Reid
  Cc: lars-Qo5EllUWu/uELgA04lAiVw, linux-iio-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <alpine.DEB.2.02.1701051004320.16779-jW+XmwGofnusTnJN9+BGXg@public.gmane.org>

On 05/01/17 09:21, Peter Meerwald-Stadler wrote:
> 
>> This adds TI's tlc4541 16-bit ADC driver. Which is a single channel
>> ADC. Supports raw and trigger buffer access.
> 
> comments below
>  
>> Signed-off-by: Phil Reid <preid-qgqNFa1JUf/o2iN0hyhwsIdd74u8MsAO@public.gmane.org>
>> ---
>>  .../devicetree/bindings/iio/adc/ti-tlc4541.txt     |  16 ++
>>  drivers/iio/adc/Kconfig                            |  11 +
>>  drivers/iio/adc/Makefile                           |   1 +
>>  drivers/iio/adc/ti-tlc4541.c                       | 266 +++++++++++++++++++++
>>  4 files changed, 294 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/iio/adc/ti-tlc4541.txt
>>  create mode 100644 drivers/iio/adc/ti-tlc4541.c
>>
>> diff --git a/Documentation/devicetree/bindings/iio/adc/ti-tlc4541.txt b/Documentation/devicetree/bindings/iio/adc/ti-tlc4541.txt
>> new file mode 100644
>> index 0000000..67caccd
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/iio/adc/ti-tlc4541.txt
>> @@ -0,0 +1,16 @@
>> +* Texas Instruments' TLC4541
>> +
>> +Required properties:
>> + - compatible: Should be one of
>> +	* "ti,tlc4541"
>> + - reg: spi chip select number for the device
> 
> SPI
> 
>> + - vref-supply: The regulator supply for ADC reference voltage
>> + - spi-max-frequency: Max SPI frequency to use (<= 200000)
>> +
>> +Example:
>> +adc@0 {
>> +	compatible = "ti,adc0832";
>> +	reg = <0>;
>> +	vref-supply = <&vdd_supply>;
>> +	spi-max-frequency = <200000>;
>> +};
>> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
>> index 99c0514..4dda3f0 100644
>> --- a/drivers/iio/adc/Kconfig
>> +++ b/drivers/iio/adc/Kconfig
>> @@ -525,6 +525,17 @@ config TI_AM335X_ADC
>>  	  To compile this driver as a module, choose M here: the module will be
>>  	  called ti_am335x_adc.
>>  
>> +config TI_TLC4541
>> +	tristate "Texas Instruments TLC4541 ADC driver"
>> +	depends on SPI
>> +	select IIO_BUFFER
>> +	select IIO_TRIGGERED_BUFFER
>> +	help
>> +	  Say yes here to build support for Texas Instruments TLC4541 ADC chip.
>> +
>> +	  This driver can also be built as a module. If so, the module will be
>> +	  called ti-tlc4541.
>> +
>>  config TWL4030_MADC
>>  	tristate "TWL4030 MADC (Monitoring A/D Converter)"
>>  	depends on TWL4030_CORE
>> diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
>> index 7a40c04..9bf2377 100644
>> --- a/drivers/iio/adc/Makefile
>> +++ b/drivers/iio/adc/Makefile
>> @@ -49,6 +49,7 @@ obj-$(CONFIG_TI_ADC161S626) += ti-adc161s626.o
>>  obj-$(CONFIG_TI_ADS1015) += ti-ads1015.o
>>  obj-$(CONFIG_TI_ADS8688) += ti-ads8688.o
>>  obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o
>> +obj-$(CONFIG_TI_TLC4541) += ti-tlc4541.o
>>  obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o
>>  obj-$(CONFIG_TWL6030_GPADC) += twl6030-gpadc.o
>>  obj-$(CONFIG_VF610_ADC) += vf610_adc.o
>> diff --git a/drivers/iio/adc/ti-tlc4541.c b/drivers/iio/adc/ti-tlc4541.c
>> new file mode 100644
>> index 0000000..a767707
>> --- /dev/null
>> +++ b/drivers/iio/adc/ti-tlc4541.c
>> @@ -0,0 +1,266 @@
>> +/*
>> + * TI tlc4541 ADC Driver
>> + *
>> + * Copyright (C) 2017 Phil Reid
>> + *
>> + * Datasheets can be found here:
>> + * http://www.ti.com/lit/gpn/tlc4541
>> + *
>> + * 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.
>> + *
>> + * The tlc4541 requires 24 clock cycles to start a transfer.
>> + * Conversion then takes 2.94us to complete before data is ready
>> + */
>> +
>> +#include <linux/delay.h>
>> +#include <linux/device.h>
>> +#include <linux/err.h>
>> +#include <linux/interrupt.h>
>> +#include <linux/iio/iio.h>
>> +#include <linux/iio/sysfs.h>
>> +#include <linux/iio/buffer.h>
>> +#include <linux/iio/trigger_consumer.h>
>> +#include <linux/iio/triggered_buffer.h>
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> +#include <linux/regulator/consumer.h>
>> +#include <linux/slab.h>
>> +#include <linux/spi/spi.h>
>> +#include <linux/sysfs.h>
>> +
>> +struct tlc4541_state {
>> +	struct spi_device               *spi;
>> +	struct regulator                *reg;
>> +	struct spi_transfer             scan_single_xfer[3];
>> +	struct spi_message              scan_single_msg;
>> +
>> +	/*
>> +	 * DMA (thus cache coherency maintenance) requires the
>> +	 * transfer buffers to live in their own cache lines.
>> +	 */
>> +	__be16                          rx_buf[2] ____cacheline_aligned;
>> +};
>> +
>> +struct tlc4541_chip_info {
>> +	const struct iio_chan_spec *channels;
>> +	unsigned int num_channels;
>> +};
>> +
>> +enum tlc4541_id {
>> +	TLC4541,
>> +};
>> +
>> +#define TLC4541_V_CHAN(index, bits) {                                 \
>> +		.type = IIO_VOLTAGE,                                  \
>> +		.indexed = 1,                                         \
> 
> no need if there is just one channel
> 
>> +		.channel = index,                                     \
>> +		.info_mask_separate       = BIT(IIO_CHAN_INFO_RAW),   \
>> +		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
>> +		.address = index,                                     \
> 
> .address not needed
> 
>> +		.scan_index = index,                                  \
>> +		.scan_type = {                                        \
>> +			.sign = 'u',                                  \
>> +			.realbits = (bits),                           \
>> +			.storagebits = 16,                            \
>> +			.endianness = IIO_BE,                         \
>> +		},                                                    \
>> +	}
>> +
>> +#define DECLARE_TLC4541_CHANNELS(name, bits) \
> 
> this flexibility is only needed when further chips are added; maybe start 
> simple and only implement what is needed at first
The only exception to keeping it simple as Peter has suggested would
be if this was just the first of a series of patches and later ones would
add the support for other devices.  If this is the case, please mention it
in the patch description.

If the other device support doesn't show up reasonably soon after the initial
driver, chances are someone will 'simplify' the code by removing this stuff.

Jonathan
> 
>> +const struct iio_chan_spec name ## _channels[] = { \
>> +	TLC4541_V_CHAN(0, bits), \
>> +	IIO_CHAN_SOFT_TIMESTAMP(1), \
>> +}
>> +
>> +static DECLARE_TLC4541_CHANNELS(tlc4541, 16);
>> +
>> +static const struct tlc4541_chip_info tlc4541_chip_info[] = {
>> +	[TLC4541] = {
>> +		.channels = tlc4541_channels,
>> +		.num_channels = ARRAY_SIZE(tlc4541_channels),
>> +	},
>> +};
>> +
>> +static irqreturn_t tlc4541_trigger_handler(int irq, void *p)
>> +{
>> +	struct iio_poll_func *pf = p;
>> +	struct iio_dev *indio_dev = pf->indio_dev;
>> +	struct tlc4541_state *st = iio_priv(indio_dev);
>> +	u16 buf[8]; /* 2 bytes data + 6 bytes padding + 8 bytes timestamp */
>> +	int ret;
>> +
>> +	ret = spi_sync(st->spi, &st->scan_single_msg);
>> +	if (ret < 0)
>> +		goto done;
>> +
>> +	buf[0] = be16_to_cpu(st->rx_buf[0]);
> 
> endianness is set to IIO_BE in scan_type, so this conversion is not needed 
> and maybe also buf and the copy can be avoided if rx_buf is large enough
> 
>> +	iio_push_to_buffers_with_timestamp(indio_dev, buf,
>> +					   iio_get_time_ns(indio_dev));
>> +
>> +done:
>> +	iio_trigger_notify_done(indio_dev->trig);
>> +	return IRQ_HANDLED;
>> +}
>> +
>> +static int tlc4541_get_range(struct tlc4541_state *st)
>> +{
>> +	int vref;
>> +
>> +	vref = regulator_get_voltage(st->reg);
>> +	if (vref < 0)
>> +		return vref;
>> +
>> +	vref /= 1000;
>> +
>> +	return vref;
>> +}
>> +
>> +static int tlc4541_read_raw(struct iio_dev *indio_dev,
>> +			    struct iio_chan_spec const *chan,
>> +			    int *val,
>> +			    int *val2,
>> +			    long m)
>> +{
>> +	int ret = 0;
>> +	struct tlc4541_state *st = iio_priv(indio_dev);
>> +
>> +	switch (m) {
>> +	case IIO_CHAN_INFO_RAW:
>> +		ret = iio_device_claim_direct_mode(indio_dev);
>> +		if (ret)
>> +			return ret;
>> +		ret = spi_sync(st->spi, &st->scan_single_msg);
>> +		iio_device_release_direct_mode(indio_dev);
>> +		if (ret < 0)
>> +			return ret;
>> +		*val = be16_to_cpu(st->rx_buf[0]);
> 
> on page 12 of the datasheet, the conversion results is in two registers? 
> and rx_buf has two elements?
> 
> haven't investigated in detail -- maybe a comment would be good to detail 
> operation?
> 
>> +		return IIO_VAL_INT;
>> +	case IIO_CHAN_INFO_SCALE:
>> +		ret = tlc4541_get_range(st);
>> +		if (ret < 0)
>> +			return ret;
>> +		*val = ret;
>> +		*val2 = chan->scan_type.realbits;
>> +		return IIO_VAL_FRACTIONAL_LOG2;
>> +	}
>> +	return -EINVAL;
>> +}
>> +
>> +static const struct iio_info tlc4541_info = {
>> +	.read_raw = &tlc4541_read_raw,
>> +	.driver_module = THIS_MODULE,
>> +};
>> +
>> +static int tlc4541_probe(struct spi_device *spi)
>> +{
>> +	struct tlc4541_state *st;
>> +	struct iio_dev *indio_dev;
>> +	const struct tlc4541_chip_info *info;
>> +	int ret;
>> +	int8_t device_init = 0;
>> +
>> +	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
>> +	if (indio_dev == NULL)
>> +		return -ENOMEM;
>> +
>> +	st = iio_priv(indio_dev);
>> +
>> +	spi_set_drvdata(spi, indio_dev);
>> +
>> +	st->spi = spi;
>> +
>> +	info = &tlc4541_chip_info[spi_get_device_id(spi)->driver_data];
>> +
>> +	indio_dev->name = spi_get_device_id(spi)->name;
>> +	indio_dev->dev.parent = &spi->dev;
>> +	indio_dev->modes = INDIO_DIRECT_MODE;
>> +	indio_dev->channels = info->channels;
>> +	indio_dev->num_channels = info->num_channels;
>> +	indio_dev->info = &tlc4541_info;
>> +
>> +	/* perform reset */
>> +	spi_write(spi, &device_init, 1);
>> +
>> +	/* Setup default message */
>> +	st->scan_single_xfer[0].rx_buf = &st->rx_buf[0];
>> +	st->scan_single_xfer[0].len = 3;
>> +	st->scan_single_xfer[1].delay_usecs = 3;
>> +	st->scan_single_xfer[2].rx_buf = &st->rx_buf[0];
>> +	st->scan_single_xfer[2].len = 2;
>> +
>> +	spi_message_init(&st->scan_single_msg);
>> +	spi_message_add_tail(&st->scan_single_xfer[0], &st->scan_single_msg);
>> +	spi_message_add_tail(&st->scan_single_xfer[1], &st->scan_single_msg);
>> +	spi_message_add_tail(&st->scan_single_xfer[2], &st->scan_single_msg);
>> +
>> +	st->reg = devm_regulator_get(&spi->dev, "vref");
>> +	if (IS_ERR(st->reg))
>> +		return PTR_ERR(st->reg);
>> +
>> +	ret = regulator_enable(st->reg);
>> +	if (ret)
>> +		return ret;
>> +
>> +	ret = iio_triggered_buffer_setup(indio_dev, NULL,
>> +			&tlc4541_trigger_handler, NULL);
>> +	if (ret)
>> +		goto error_disable_reg;
>> +
>> +	ret = iio_device_register(indio_dev);
>> +	if (ret)
>> +		goto error_cleanup_buffer;
>> +
>> +	return 0;
>> +
>> +error_cleanup_buffer:
>> +	iio_triggered_buffer_cleanup(indio_dev);
>> +error_disable_reg:
>> +	regulator_disable(st->reg);
>> +
>> +	return ret;
>> +}
>> +
>> +static int tlc4541_remove(struct spi_device *spi)
>> +{
>> +	struct iio_dev *indio_dev = spi_get_drvdata(spi);
>> +	struct tlc4541_state *st = iio_priv(indio_dev);
>> +
>> +	iio_device_unregister(indio_dev);
>> +	iio_triggered_buffer_cleanup(indio_dev);
>> +	regulator_disable(st->reg);
>> +
>> +	return 0;
>> +}
>> +
>> +#ifdef CONFIG_OF
>> +
>> +static const struct of_device_id tlc4541_dt_ids[] = {
>> +	{ .compatible = "ti,tlc4541", },
>> +	{}
>> +};
>> +MODULE_DEVICE_TABLE(of, tlc4541_dt_ids);
>> +
>> +#endif
>> +
>> +static const struct spi_device_id tlc4541_id[] = {
>> +	{"tlc4541", TLC4541},
>> +	{}
>> +};
>> +MODULE_DEVICE_TABLE(spi, tlc4541_id);
>> +
>> +static struct spi_driver tlc4541_driver = {
>> +	.driver = {
>> +		.name   = "tlc4541",
>> +		.of_match_table = of_match_ptr(tlc4541_dt_ids),
>> +	},
>> +	.probe          = tlc4541_probe,
>> +	.remove         = tlc4541_remove,
>> +	.id_table       = tlc4541_id,
>> +};
>> +module_spi_driver(tlc4541_driver);
>> +
>> +MODULE_AUTHOR("Phil Reid <preid-qgqNFa1JUf/o2iN0hyhwsIdd74u8MsAO@public.gmane.org>");
>> +MODULE_DESCRIPTION("Texas Instruments TLC4541 ADC");
>> +MODULE_LICENSE("GPL v2");
>>
> 

--
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 v7 09/12] dt-bindings: i2c: i2c-mux-simple: document i2c-mux-simple bindings
From: Jonathan Cameron @ 2017-01-07 22:28 UTC (permalink / raw)
  To: Peter Rosin, linux-kernel
  Cc: Wolfram Sang, Rob Herring, Mark Rutland, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Jonathan Corbet,
	Arnd Bergmann, Greg Kroah-Hartman, linux-i2c, devicetree,
	linux-iio, linux-doc
In-Reply-To: <1483532187-28494-10-git-send-email-peda@axentia.se>

On 04/01/17 12:16, Peter Rosin wrote:
> Signed-off-by: Peter Rosin <peda@axentia.se>
Looks good to me.
Acked-by: Jonathan Cameron <jic23@kernel.org>
> ---
>  .../devicetree/bindings/i2c/i2c-mux-simple.txt     | 81 ++++++++++++++++++++++
>  1 file changed, 81 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mux-simple.txt
> 
> diff --git a/Documentation/devicetree/bindings/i2c/i2c-mux-simple.txt b/Documentation/devicetree/bindings/i2c/i2c-mux-simple.txt
> new file mode 100644
> index 000000000000..253d5027843b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/i2c/i2c-mux-simple.txt
> @@ -0,0 +1,81 @@
> +Simple I2C Bus Mux
> +
> +This binding describes an I2C bus multiplexer that uses a mux controller
> +from the mux subsystem to route the I2C signals.
> +
> +                                  .-----.  .-----.
> +                                  | dev |  | dev |
> +    .------------.                '-----'  '-----'
> +    | SoC        |                   |        |
> +    |            |          .--------+--------'
> +    |   .------. |  .------+    child bus A, on MUX value set to 0
> +    |   | I2C  |-|--| Mux  |
> +    |   '------' |  '--+---+    child bus B, on MUX value set to 1
> +    |   .------. |     |    '----------+--------+--------.
> +    |   | MUX- | |     |               |        |        |
> +    |   | Ctrl |-|-----+            .-----.  .-----.  .-----.
> +    |   '------' |                  | dev |  | dev |  | dev |
> +    '------------'                  '-----'  '-----'  '-----'
> +
> +Required properties:
> +- compatible: i2c-mux-simple,mux-locked or i2c-mux-simple,parent-locked
> +- i2c-parent: The phandle of the I2C bus that this multiplexer's master-side
> +  port is connected to.
> +- mux-controls: The phandle of the mux controller to use for operating the
> +  mux.
> +* Standard I2C mux properties. See i2c-mux.txt in this directory.
> +* I2C child bus nodes. See i2c-mux.txt in this directory. The sub-bus number
> +  is also the mux-controller state described in ../mux/mux-controller.txt
> +
> +For each i2c child node, an I2C child bus will be created. They will
> +be numbered based on their order in the device tree.
> +
> +Whenever an access is made to a device on a child bus, the value set
> +in the relevant node's reg property will be set as the state in the
> +mux controller.
> +
> +Example:
> +	mux: mux-controller {
> +		compatible = "mux-gpio";
> +		#mux-control-cells = <0>;
> +
> +		mux-gpios = <&pioA 0 GPIO_ACTIVE_HIGH>,
> +			    <&pioA 1 GPIO_ACTIVE_HIGH>;
> +	};
> +
> +	i2c-mux {
> +		compatible = "i2c-mux-simple,mux-locked";
> +		i2c-parent = <&i2c1>;
> +
> +		mux-controls = <&mux>;
> +
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		i2c@1 {
> +			reg = <1>;
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +
> +			ssd1307: oled@3c {
> +				compatible = "solomon,ssd1307fb-i2c";
> +				reg = <0x3c>;
> +				pwms = <&pwm 4 3000>;
> +				reset-gpios = <&gpio2 7 1>;
> +				reset-active-low;
> +			};
> +		};
> +
> +		i2c@3 {
> +			reg = <3>;
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +
> +			pca9555: pca9555@20 {
> +				compatible = "nxp,pca9555";
> +				gpio-controller;
> +				#gpio-cells = <2>;
> +				reg = <0x20>;
> +			};
> +		};
> +	};
> 

^ permalink raw reply

* Re: [PATCH v7 01/12] devres: trivial whitespace fix
From: Jonathan Cameron @ 2017-01-07 22:29 UTC (permalink / raw)
  To: Peter Rosin, linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Wolfram Sang, Rob Herring, Mark Rutland, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Jonathan Corbet,
	Arnd Bergmann, Greg Kroah-Hartman,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-iio-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1483532187-28494-2-git-send-email-peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>

On 04/01/17 12:16, Peter Rosin wrote:
> Signed-off-by: Peter Rosin <peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>
Acked-by: Jonathan Cameron <jic23-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> ---
>  Documentation/driver-model/devres.txt | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
> index ca9d1eb46bc0..dc51fb024190 100644
> --- a/Documentation/driver-model/devres.txt
> +++ b/Documentation/driver-model/devres.txt
> @@ -330,7 +330,7 @@ MEM
>    devm_kzalloc()
>  
>  MFD
> - devm_mfd_add_devices()
> +  devm_mfd_add_devices()
>  
>  PER-CPU MEM
>    devm_alloc_percpu()
> 

--
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 v5 5/5] arm64: dts: exynos: Add tm2 touchkey node
From: Chanwoo Choi @ 2017-01-08  5:14 UTC (permalink / raw)
  To: Andi Shyti
  Cc: Andi Shyti, Dmitry Torokhov, Rob Herring, Mark Rutland,
	Catalin Marinas, Will Deacon, Kukjin Kim, Krzysztof Kozlowski,
	Javier Martinez Canillas, Chanwoo Choi, Beomho Seo,
	linux-arm-kernel, linux-input, devicetree, linux-kernel,
	linux-samsung-soc, Jaechul Lee, Jaechul Lee
In-Reply-To: <20170107124026.gl447hl5bucdflyk@jack.zhora.eu>

Hi Andi,

2017-01-07 21:40 GMT+09:00 Andi Shyti <andi@etezian.org>:
> Hi Chanwoo,
>
>> >>> +       touchkey@20 {
>> >>> +               compatible = "samsung,tm2-touchkey";
>> >>> +               reg = <0x20>;
>> >>> +               interrupt-parent = <&gpa3>;
>> >>> +               interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
>> >>> +               vcc-supply = <&ldo32_reg>;
>> >>> +               vdd-supply = <&ldo33_reg>;
>> >>> +       };
>> >>> +};
>> >>> +
>> >>>  &ldo31_reg {
>> >>>         regulator-name = "TSP_VDD_1.85V_AP";
>> >>>         regulator-min-microvolt = <1850000>;
>>
>> I repiled the touchkey driver against compatible name.
>> Usually, when developing the device driver, we use the specific h/w name
>> but in this patch, the touckey dt node uses the h/w board name instead of
>> original touckhey name.
>
> this should be a device specifically done for the tm2 and we are
> not sure who is the manufacturer of the device. In order to not

As I knew, this touchkey was made by Cypress semiconductor.
But, for more correct information, you may try to find it.

> assign the device to the wrong manufacturer, we preferred calling
> it Samsung as it is in a Samsung device.

As you mentioned, Samsung made not this touchkey device. It is
certainly wrong manufacturer. I have not seen to use the h/w board
name as the peripheral device name.

I don't prefer to use the inaccurate manufacturer and device name.

-- 
Best Regards,
Chanwoo Choi

^ permalink raw reply

* Re: [PATCH v5 5/5] arm64: dts: exynos: Add tm2 touchkey node
From: Andi Shyti @ 2017-01-08  5:45 UTC (permalink / raw)
  To: Chanwoo Choi
  Cc: Andi Shyti, Andi Shyti, Dmitry Torokhov, Rob Herring,
	Mark Rutland, Catalin Marinas, Will Deacon, Kukjin Kim,
	Krzysztof Kozlowski, Javier Martinez Canillas, Chanwoo Choi,
	Beomho Seo, linux-arm-kernel, linux-input-u79uwXL29TY76Z2rM5mHXA,
	devicetree, linux-kernel, linux-samsung-soc, Jaechul Lee,
	Jaechul Lee
In-Reply-To: <CAGTfZH35sx5v-XcxkDG7TVRmW8cLirAXRxA=kGZQDBnpw3vYhg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

Hi Chanwoo,

> >> >>> +       touchkey@20 {
> >> >>> +               compatible = "samsung,tm2-touchkey";
> >> >>> +               reg = <0x20>;
> >> >>> +               interrupt-parent = <&gpa3>;
> >> >>> +               interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
> >> >>> +               vcc-supply = <&ldo32_reg>;
> >> >>> +               vdd-supply = <&ldo33_reg>;
> >> >>> +       };
> >> >>> +};
> >> >>> +
> >> >>>  &ldo31_reg {
> >> >>>         regulator-name = "TSP_VDD_1.85V_AP";
> >> >>>         regulator-min-microvolt = <1850000>;
> >>
> >> I repiled the touchkey driver against compatible name.
> >> Usually, when developing the device driver, we use the specific h/w name
> >> but in this patch, the touckey dt node uses the h/w board name instead of
> >> original touckhey name.
> >
> > this should be a device specifically done for the tm2 and we are
> > not sure who is the manufacturer of the device. In order to not
> 
> As I knew, this touchkey was made by Cypress semiconductor.
> But, for more correct information, you may try to find it.

The Android Kernel says that this is the cy8cmbr3xxx. I
downloaded the datasheets, but it doesn't have any similarity
with the device. Which means that on tm2 we don't the
cy8cmbr3xxx bot something else that I even doubt comes from
cypress, but I strongly believe it's a dedicated hardware.

Now we have two choices:

1. drop support because we are not 100% sure on the device and
supplier.

2. call it Samsung and provide support anyway as, at the end, it
is a samsung hardware.

With Jaechul we chose option 2.

> > assign the device to the wrong manufacturer, we preferred calling
> > it Samsung as it is in a Samsung device.
> 
> As you mentioned, Samsung made not this touchkey device. It is
> certainly wrong manufacturer. I have not seen to use the h/w board
> name as the peripheral device name.
> 
> I don't prefer to use the inaccurate manufacturer and device name.

Eventually, Jaechul can assign the device to cypress, but the
name has to remain tm2-touchkey. Something like this:

	compatible = "cypress,tm2-touchkey";

What do you think?

Andi
--
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 v5 5/5] arm64: dts: exynos: Add tm2 touchkey node
From: Chanwoo Choi @ 2017-01-08  6:07 UTC (permalink / raw)
  To: Andi Shyti
  Cc: Andi Shyti, Dmitry Torokhov, Rob Herring, Mark Rutland,
	Catalin Marinas, Will Deacon, Kukjin Kim, Krzysztof Kozlowski,
	Javier Martinez Canillas, Chanwoo Choi, Beomho Seo,
	linux-arm-kernel, linux-input-u79uwXL29TY76Z2rM5mHXA, devicetree,
	linux-kernel, linux-samsung-soc, Jaechul Lee, Jaechul Lee
In-Reply-To: <20170108054504.fssqicmeovufar2r-A05emIGRluN/OPZsa/fw/Q@public.gmane.org>

Hi Andi,

2017-01-08 14:45 GMT+09:00 Andi Shyti <andi-ahk0KpmfxKRAfugRpC6u6w@public.gmane.org>:
> Hi Chanwoo,
>
>> >> >>> +       touchkey@20 {
>> >> >>> +               compatible = "samsung,tm2-touchkey";
>> >> >>> +               reg = <0x20>;
>> >> >>> +               interrupt-parent = <&gpa3>;
>> >> >>> +               interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
>> >> >>> +               vcc-supply = <&ldo32_reg>;
>> >> >>> +               vdd-supply = <&ldo33_reg>;
>> >> >>> +       };
>> >> >>> +};
>> >> >>> +
>> >> >>>  &ldo31_reg {
>> >> >>>         regulator-name = "TSP_VDD_1.85V_AP";
>> >> >>>         regulator-min-microvolt = <1850000>;
>> >>
>> >> I repiled the touchkey driver against compatible name.
>> >> Usually, when developing the device driver, we use the specific h/w name
>> >> but in this patch, the touckey dt node uses the h/w board name instead of
>> >> original touckhey name.
>> >
>> > this should be a device specifically done for the tm2 and we are
>> > not sure who is the manufacturer of the device. In order to not
>>
>> As I knew, this touchkey was made by Cypress semiconductor.
>> But, for more correct information, you may try to find it.
>
> The Android Kernel says that this is the cy8cmbr3xxx. I
> downloaded the datasheets, but it doesn't have any similarity
> with the device. Which means that on tm2 we don't the
> cy8cmbr3xxx bot something else that I even doubt comes from
> cypress, but I strongly believe it's a dedicated hardware.

Although this device is a dedicated h/w, you should keep the principal.
Did you check the schematic document of TM2? The schematic document
might include the specific device name.

Sometimes, the downloaded datasheet does not include the
all of information of device because of confidential information.
But, I’m not sure. Just it is guess as my experience.

I want to check the manufacturer and name of device with you
on next Monday.

>
> Now we have two choices:
>
> 1. drop support because we are not 100% sure on the device and
> supplier.
>
> 2. call it Samsung and provide support anyway as, at the end, it
> is a samsung hardware.
>
> With Jaechul we chose option 2.
>
>> > assign the device to the wrong manufacturer, we preferred calling
>> > it Samsung as it is in a Samsung device.
>>
>> As you mentioned, Samsung made not this touchkey device. It is
>> certainly wrong manufacturer. I have not seen to use the h/w board
>> name as the peripheral device name.
>>
>> I don't prefer to use the inaccurate manufacturer and device name.
>
> Eventually, Jaechul can assign the device to cypress, but the
> name has to remain tm2-touchkey. Something like this:
>
>         compatible = "cypress,tm2-touchkey";
>
> What do you think?

If we never to find the correct device name, we might use your suggestion.
As I already said, I’d like to check it again with you.

-- 
Best Regards,
Chanwoo Choi
Samsung Electronics
--
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 v5 5/5] arm64: dts: exynos: Add tm2 touchkey node
From: Andi Shyti @ 2017-01-08  6:13 UTC (permalink / raw)
  To: Chanwoo Choi
  Cc: Andi Shyti, Andi Shyti, Dmitry Torokhov, Rob Herring,
	Mark Rutland, Catalin Marinas, Will Deacon, Kukjin Kim,
	Krzysztof Kozlowski, Javier Martinez Canillas, Chanwoo Choi,
	Beomho Seo, linux-arm-kernel, linux-input-u79uwXL29TY76Z2rM5mHXA,
	devicetree, linux-kernel, linux-samsung-soc, Jaechul Lee,
	Jaechul Lee
In-Reply-To: <CAGTfZH1CuMxhaqPJCzxgF8p39OAu+o0GDJEsh5DVGtU-hqfxvQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

Hi Chanwoo,

> >> >> >>> +       touchkey@20 {
> >> >> >>> +               compatible = "samsung,tm2-touchkey";
> >> >> >>> +               reg = <0x20>;
> >> >> >>> +               interrupt-parent = <&gpa3>;
> >> >> >>> +               interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
> >> >> >>> +               vcc-supply = <&ldo32_reg>;
> >> >> >>> +               vdd-supply = <&ldo33_reg>;
> >> >> >>> +       };
> >> >> >>> +};
> >> >> >>> +
> >> >> >>>  &ldo31_reg {
> >> >> >>>         regulator-name = "TSP_VDD_1.85V_AP";
> >> >> >>>         regulator-min-microvolt = <1850000>;
> >> >>
> >> >> I repiled the touchkey driver against compatible name.
> >> >> Usually, when developing the device driver, we use the specific h/w name
> >> >> but in this patch, the touckey dt node uses the h/w board name instead of
> >> >> original touckhey name.
> >> >
> >> > this should be a device specifically done for the tm2 and we are
> >> > not sure who is the manufacturer of the device. In order to not
> >>
> >> As I knew, this touchkey was made by Cypress semiconductor.
> >> But, for more correct information, you may try to find it.
> >
> > The Android Kernel says that this is the cy8cmbr3xxx. I
> > downloaded the datasheets, but it doesn't have any similarity
> > with the device. Which means that on tm2 we don't the
> > cy8cmbr3xxx bot something else that I even doubt comes from
> > cypress, but I strongly believe it's a dedicated hardware.
> 
> Although this device is a dedicated h/w, you should keep the principal.
> Did you check the schematic document of TM2? The schematic document
> might include the specific device name.
> 
> Sometimes, the downloaded datasheet does not include the
> all of information of device because of confidential information.
> But, I’m not sure. Just it is guess as my experience.
> 
> I want to check the manufacturer and name of device with you
> on next Monday.

Yes, I checked everything, but didn't find the exact device name.

Anyway, let's take this discussion offline and find the correct
way.

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

^ permalink raw reply

* Re: [PATCH V2 1/3] cfg80211: allow passing struct device in the wiphy_new call
From: kbuild test robot @ 2017-01-08  7:38 UTC (permalink / raw)
  To: Rafał Miłecki
  Cc: kbuild-all-JC7UmRfGjtg, Johannes Berg,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA, Martin Blumenstingl,
	Felix Fietkau, Arend van Spriel, Arnd Bergmann,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Rafał Miłecki
In-Reply-To: <20170102132747.3491-1-zajec5-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

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

Hi Rafał,

[auto build test WARNING on mac80211-next/master]
[also build test WARNING on v4.10-rc2 next-20170106]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Rafa-Mi-ecki/cfg80211-allow-passing-struct-device-in-the-wiphy_new-call/20170103-014525
base:   https://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git master
config: x86_64-randconfig-s2-01081447 (attached as .config)
compiler: gcc-4.4 (Debian 4.4.7-8) 4.4.7
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All warnings (new ones prefixed by >>):

   drivers/net/wireless/intersil/orinoco/cfg.c: In function 'orinoco_wiphy_init':
>> drivers/net/wireless/intersil/orinoco/cfg.c:26: warning: unused variable 'priv'
   drivers/net/wireless/intersil/orinoco/cfg.o: warning: objtool: orinoco_set_wiphy_params()+0x1e: function has unreachable instruction

vim +/priv +26 drivers/net/wireless/intersil/orinoco/cfg.c

ea60a6aa drivers/net/wireless/orinoco/cfg.c David Kilroy 2009-06-18  10  
ea60a6aa drivers/net/wireless/orinoco/cfg.c David Kilroy 2009-06-18  11  #include "cfg.h"
ea60a6aa drivers/net/wireless/orinoco/cfg.c David Kilroy 2009-06-18  12  
ea60a6aa drivers/net/wireless/orinoco/cfg.c David Kilroy 2009-06-18  13  /* Supported bitrates. Must agree with hw.c */
ea60a6aa drivers/net/wireless/orinoco/cfg.c David Kilroy 2009-06-18  14  static struct ieee80211_rate orinoco_rates[] = {
ea60a6aa drivers/net/wireless/orinoco/cfg.c David Kilroy 2009-06-18  15  	{ .bitrate = 10 },
ea60a6aa drivers/net/wireless/orinoco/cfg.c David Kilroy 2009-06-18  16  	{ .bitrate = 20 },
ea60a6aa drivers/net/wireless/orinoco/cfg.c David Kilroy 2009-06-18  17  	{ .bitrate = 55 },
ea60a6aa drivers/net/wireless/orinoco/cfg.c David Kilroy 2009-06-18  18  	{ .bitrate = 110 },
ea60a6aa drivers/net/wireless/orinoco/cfg.c David Kilroy 2009-06-18  19  };
ea60a6aa drivers/net/wireless/orinoco/cfg.c David Kilroy 2009-06-18  20  
ea60a6aa drivers/net/wireless/orinoco/cfg.c David Kilroy 2009-06-18  21  static const void * const orinoco_wiphy_privid = &orinoco_wiphy_privid;
ea60a6aa drivers/net/wireless/orinoco/cfg.c David Kilroy 2009-06-18  22  
ea60a6aa drivers/net/wireless/orinoco/cfg.c David Kilroy 2009-06-18  23  /* Called after orinoco_private is allocated. */
ea60a6aa drivers/net/wireless/orinoco/cfg.c David Kilroy 2009-06-18  24  void orinoco_wiphy_init(struct wiphy *wiphy)
ea60a6aa drivers/net/wireless/orinoco/cfg.c David Kilroy 2009-06-18  25  {
ea60a6aa drivers/net/wireless/orinoco/cfg.c David Kilroy 2009-06-18 @26  	struct orinoco_private *priv = wiphy_priv(wiphy);
ea60a6aa drivers/net/wireless/orinoco/cfg.c David Kilroy 2009-06-18  27  
ea60a6aa drivers/net/wireless/orinoco/cfg.c David Kilroy 2009-06-18  28  	wiphy->privid = orinoco_wiphy_privid;
ea60a6aa drivers/net/wireless/orinoco/cfg.c David Kilroy 2009-06-18  29  }
ea60a6aa drivers/net/wireless/orinoco/cfg.c David Kilroy 2009-06-18  30  
ea60a6aa drivers/net/wireless/orinoco/cfg.c David Kilroy 2009-06-18  31  /* Called after firmware is initialised */
ea60a6aa drivers/net/wireless/orinoco/cfg.c David Kilroy 2009-06-18  32  int orinoco_wiphy_register(struct wiphy *wiphy)
ea60a6aa drivers/net/wireless/orinoco/cfg.c David Kilroy 2009-06-18  33  {
ea60a6aa drivers/net/wireless/orinoco/cfg.c David Kilroy 2009-06-18  34  	struct orinoco_private *priv = wiphy_priv(wiphy);

:::::: The code at line 26 was first introduced by commit
:::::: ea60a6aaf55984a13a7150568cc103d006e86ab2 orinoco: initiate cfg80211 conversion

:::::: TO: David Kilroy <kilroyd-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
:::::: CC: John W. Linville <linville-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 26253 bytes --]

^ permalink raw reply

* Re: [PATCH 19/19] staging: iio: isl29028: remove legacy device tree binding
From: Jonathan Cameron @ 2017-01-08  9:50 UTC (permalink / raw)
  To: Brian Masney, linux-iio
  Cc: devel, devicetree, lars, gregkh, linux-kernel, Rob Herring,
	ldewangan, pmeerw, knaack.h, Mark Rutland
In-Reply-To: <927a9b4b-31e5-0f63-4526-97936a578648@kernel.org>

Sorry all, appears some replies got stuck in my outbox and have just managed to send for some reason!

Jonathan

On 04/12/16 11:55, Jonathan Cameron wrote:
> On 04/12/16 02:19, Brian Masney wrote:
>> The isl29028 staging driver contains a legacy binding of "isl,isl29028"
>> that is marked as legacy and to not use. There are no in tree references
>> to that binding. This patch removes the legacy binding in preparation
>> for moving the driver out of staging. Otherwise, we will have to support
>> this binding indefinitely.
> Leave this be.  Given it exists there almost certainly device trees out there
> using it. Lets not break them just to save on one line of code.
> 
> Supporting legacy bindings isn't exactly costly!
> 
> I'm happy with all the patches I haven't commented on. Just can't apply
> them because they have dependencies on early patches that I have
> raised questions on.
> 
> Another generally nice bit of cleanup.
> 
> Thanks,
> 
> Jonathan
>>
>> Signed-off-by: Brian Masney <masneyb@onstation.org>
>> Cc: devicetree@vger.kernel.org
>> Cc: Rob Herring <robh+dt@kernel.org>
>> Cc: Mark Rutland <Mark.Rutland@arm.com>
>> ---
>>  drivers/staging/iio/light/isl29028.c | 1 -
>>  1 file changed, 1 deletion(-)
>>
>> diff --git a/drivers/staging/iio/light/isl29028.c b/drivers/staging/iio/light/isl29028.c
>> index ae6896f..6be9aa7 100644
>> --- a/drivers/staging/iio/light/isl29028.c
>> +++ b/drivers/staging/iio/light/isl29028.c
>> @@ -611,7 +611,6 @@ static const struct i2c_device_id isl29028_id[] = {
>>  MODULE_DEVICE_TABLE(i2c, isl29028_id);
>>  
>>  static const struct of_device_id isl29028_of_match[] = {
>> -	{ .compatible = "isl,isl29028", }, /* for backward compat., don't use */
>>  	{ .compatible = "isil,isl29028", },
>>  	{ },
>>  };
>>
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" 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 v7 03/12] mux: minimal mux subsystem and gpio-based mux controller
From: Jonathan Cameron @ 2017-01-08 10:23 UTC (permalink / raw)
  To: Peter Rosin, linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Wolfram Sang, Rob Herring, Mark Rutland, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Jonathan Corbet,
	Arnd Bergmann, Greg Kroah-Hartman,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-iio-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1483532187-28494-4-git-send-email-peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>

On 04/01/17 12:16, Peter Rosin wrote:
> Add a new minimalistic subsystem that handles multiplexer controllers.
> When multiplexers are used in various places in the kernel, and the
> same multiplexer controller can be used for several independent things,
> there should be one place to implement support for said multiplexer
> controller.
> 
> A single multiplexer controller can also be used to control several
> parallel multiplexers, that are in turn used by different subsystems
> in the kernel, leading to a need to coordinate multiplexer accesses.
> The multiplexer subsystem handles this coordination.
> 
> This new mux controller subsystem initially comes with a single backend
> driver that controls gpio based multiplexers. Even though not needed by
> this initial driver, the mux controller subsystem is prepared to handle
> chips with multiple (independent) mux controllers.
> 
> Signed-off-by: Peter Rosin <peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>
Reviewed-by: Jonathan Cameron <jic23-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> ---
>  Documentation/driver-model/devres.txt |   8 +
>  MAINTAINERS                           |   2 +
>  drivers/Kconfig                       |   2 +
>  drivers/Makefile                      |   1 +
>  drivers/mux/Kconfig                   |  33 +++
>  drivers/mux/Makefile                  |   6 +
>  drivers/mux/mux-core.c                | 398 ++++++++++++++++++++++++++++++++++
>  drivers/mux/mux-gpio.c                | 120 ++++++++++
>  include/linux/mux.h                   | 244 +++++++++++++++++++++
>  9 files changed, 814 insertions(+)
>  create mode 100644 drivers/mux/Kconfig
>  create mode 100644 drivers/mux/Makefile
>  create mode 100644 drivers/mux/mux-core.c
>  create mode 100644 drivers/mux/mux-gpio.c
>  create mode 100644 include/linux/mux.h
> 
> diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
> index dc51fb024190..1e9ae701a587 100644
> --- a/Documentation/driver-model/devres.txt
> +++ b/Documentation/driver-model/devres.txt
> @@ -332,6 +332,14 @@ MEM
>  MFD
>    devm_mfd_add_devices()
>  
> +MUX
> +  devm_mux_chip_alloc()
> +  devm_mux_chip_free()
> +  devm_mux_chip_register()
> +  devm_mux_chip_unregister()
> +  devm_mux_control_get()
> +  devm_mux_control_put()
> +
>  PER-CPU MEM
>    devm_alloc_percpu()
>    devm_free_percpu()
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 32abef2b6d05..ebe96f3e25a0 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -8442,6 +8442,8 @@ MULTIPLEXER SUBSYSTEM
>  M:	Peter Rosin <peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>
>  S:	Maintained
>  F:	Documentation/devicetree/bindings/mux/
> +F:	include/linux/mux.h
> +F:	drivers/mux/
>  
>  MULTISOUND SOUND DRIVER
>  M:	Andrew Veliath <andrewtv-Jdbf3xiKgS8@public.gmane.org>
> diff --git a/drivers/Kconfig b/drivers/Kconfig
> index e1e2066cecdb..993aeb65affa 100644
> --- a/drivers/Kconfig
> +++ b/drivers/Kconfig
> @@ -76,6 +76,8 @@ source "drivers/hwmon/Kconfig"
>  
>  source "drivers/thermal/Kconfig"
>  
> +source "drivers/mux/Kconfig"
> +

Why this location in the list?  I think the convention for new subystems is
to just go last in the list.

>  source "drivers/watchdog/Kconfig"
>  
>  source "drivers/ssb/Kconfig"
> diff --git a/drivers/Makefile b/drivers/Makefile
> index 060026a02f59..d089baa57965 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -112,6 +112,7 @@ obj-$(CONFIG_W1)		+= w1/
>  obj-y				+= power/
>  obj-$(CONFIG_HWMON)		+= hwmon/
>  obj-$(CONFIG_THERMAL)		+= thermal/
> +obj-$(CONFIG_MULTIPLEXER)	+= mux/
>  obj-$(CONFIG_WATCHDOG)		+= watchdog/
>  obj-$(CONFIG_MD)		+= md/
>  obj-$(CONFIG_BT)		+= bluetooth/
> diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig
> new file mode 100644
> index 000000000000..de5a35ffe7af
> --- /dev/null
> +++ b/drivers/mux/Kconfig
> @@ -0,0 +1,33 @@
> +#
> +# Multiplexer devices
> +#
> +
> +menuconfig MULTIPLEXER
> +	bool "Multiplexer subsystem"
> +	help
> +	  Multiplexer controller subsystem. Multiplexers are used in a
> +	  variety of settings, and this subsystem abstracts their use
> +	  so that the rest of the kernel sees a common interface. When
> +	  multiple parallel multiplexers are controlled by one single
> +	  multiplexer controller, this subsystem also coordinates the
> +	  multiplexer accesses.
> +
> +	  If unsure, say no.
> +
> +if MULTIPLEXER
> +
> +config MUX_GPIO
> +	tristate "GPIO-controlled Multiplexer"
> +	depends on OF && GPIOLIB
> +	help
> +	  GPIO-controlled Multiplexer controller.
> +
> +	  The driver builds a single multiplexer controller using a number
> +	  of gpio pins. For N pins, there will be 2^N possible multiplexer
> +	  states. The GPIO pins can be connected (by the hardware) to several
> +	  multiplexers, which in that case will be operated in parallel.
> +
> +	  To compile this driver as a module, choose M here: the module will
> +	  be called mux-gpio.
> +
> +endif
> diff --git a/drivers/mux/Makefile b/drivers/mux/Makefile
> new file mode 100644
> index 000000000000..facc43da3648
> --- /dev/null
> +++ b/drivers/mux/Makefile
> @@ -0,0 +1,6 @@
> +#
> +# Makefile for multiplexer devices.
> +#
> +
> +obj-$(CONFIG_MULTIPLEXER)      	+= mux-core.o
> +obj-$(CONFIG_MUX_GPIO)		+= mux-gpio.o
> diff --git a/drivers/mux/mux-core.c b/drivers/mux/mux-core.c
> new file mode 100644
> index 000000000000..21da15a264ad
> --- /dev/null
> +++ b/drivers/mux/mux-core.c
> @@ -0,0 +1,398 @@
> +/*
> + * Multiplexer subsystem
> + *
> + * Copyright (C) 2016 Axentia Technologies AB
> + *
> + * Author: Peter Rosin <peda-koto5C5qi+TLoDKTGw+V6w@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.
> + */
> +
> +#define pr_fmt(fmt) "mux-core: " fmt
> +
> +#include <linux/device.h>
> +#include <linux/err.h>
> +#include <linux/idr.h>
> +#include <linux/module.h>
> +#include <linux/mux.h>
> +#include <linux/of.h>
> +#include <linux/of_platform.h>
> +#include <linux/slab.h>
> +
> +static struct class mux_class = {
> +	.name = "mux",
> +	.owner = THIS_MODULE,
> +};
> +
> +static int __init mux_init(void)
> +{
> +	return class_register(&mux_class);
> +}
> +
> +static DEFINE_IDA(mux_ida);
> +
> +static void mux_chip_release(struct device *dev)
> +{
> +	struct mux_chip *mux_chip = to_mux_chip(dev);
> +
> +	ida_simple_remove(&mux_ida, mux_chip->id);
> +	kfree(mux_chip);
> +}
> +
> +static struct device_type mux_type = {
> +	.name = "mux-chip",
> +	.release = mux_chip_release,
> +};
> +
> +struct mux_chip *mux_chip_alloc(struct device *dev,
> +				unsigned int controllers, size_t sizeof_priv)
> +{
> +	struct mux_chip *mux_chip;
> +	int i;
> +
> +	if (!dev || !controllers)
> +		return NULL;
> +
> +	mux_chip = kzalloc(sizeof(*mux_chip) +
> +			   controllers * sizeof(*mux_chip->mux) +
> +			   sizeof_priv, GFP_KERNEL);
> +	if (!mux_chip)
> +		return NULL;
> +
> +	mux_chip->mux = (struct mux_control *)(mux_chip + 1);
> +	mux_chip->dev.class = &mux_class;
> +	mux_chip->dev.type = &mux_type;
> +	mux_chip->dev.parent = dev;
> +	mux_chip->dev.of_node = dev->of_node;
> +	dev_set_drvdata(&mux_chip->dev, mux_chip);
> +
> +	mux_chip->id = ida_simple_get(&mux_ida, 0, 0, GFP_KERNEL);
> +	if (mux_chip->id < 0) {
> +		pr_err("muxchipX failed to get a device id\n");
> +		kfree(mux_chip);
> +		return NULL;
> +	}
> +	dev_set_name(&mux_chip->dev, "muxchip%d", mux_chip->id);
> +
> +	mux_chip->controllers = controllers;
> +	for (i = 0; i < controllers; ++i) {
> +		struct mux_control *mux = &mux_chip->mux[i];
> +
> +		mux->chip = mux_chip;
> +		init_rwsem(&mux->lock);
> +		mux->cached_state = -1;
> +		mux->idle_state = -1;
> +	}
> +
> +	device_initialize(&mux_chip->dev);
> +
> +	return mux_chip;
> +}
> +EXPORT_SYMBOL_GPL(mux_chip_alloc);
> +
> +static int mux_control_set(struct mux_control *mux, int state)
> +{
> +	int ret = mux->chip->ops->set(mux, state);
> +
> +	mux->cached_state = ret < 0 ? -1 : state;
> +
> +	return ret;
> +}
> +
> +int mux_chip_register(struct mux_chip *mux_chip)
> +{
> +	int i;
> +	int ret;
> +
> +	for (i = 0; i < mux_chip->controllers; ++i) {
> +		struct mux_control *mux = &mux_chip->mux[i];
> +
> +		if (mux->idle_state == mux->cached_state)
> +			continue;
> +
> +		ret = mux_control_set(mux, mux->idle_state);
> +		if (ret < 0)
> +			return ret;
> +	}
> +
> +	return device_add(&mux_chip->dev);
> +}
> +EXPORT_SYMBOL_GPL(mux_chip_register);
> +
> +void mux_chip_unregister(struct mux_chip *mux_chip)
> +{
> +	device_del(&mux_chip->dev);
> +}
> +EXPORT_SYMBOL_GPL(mux_chip_unregister);
> +
> +void mux_chip_free(struct mux_chip *mux_chip)
> +{
> +	if (!mux_chip)
> +		return;
> +
> +	put_device(&mux_chip->dev);
> +}
> +EXPORT_SYMBOL_GPL(mux_chip_free);
> +
> +static void devm_mux_chip_release(struct device *dev, void *res)
> +{
> +	struct mux_chip *mux_chip = *(struct mux_chip **)res;
> +
> +	mux_chip_free(mux_chip);
> +}
> +
> +struct mux_chip *devm_mux_chip_alloc(struct device *dev,
> +				     unsigned int controllers,
> +				     size_t sizeof_priv)
> +{
> +	struct mux_chip **ptr, *mux_chip;
> +
> +	ptr = devres_alloc(devm_mux_chip_release, sizeof(*ptr), GFP_KERNEL);
> +	if (!ptr)
> +		return ERR_PTR(-ENOMEM);
> +
> +	mux_chip = mux_chip_alloc(dev, controllers, sizeof_priv);
> +	if (IS_ERR(mux_chip)) {
> +		devres_free(ptr);
> +		return mux_chip;
> +	}
> +
> +	*ptr = mux_chip;
> +	devres_add(dev, ptr);
> +
> +	return mux_chip;
> +}
> +EXPORT_SYMBOL_GPL(devm_mux_chip_alloc);
> +
> +static int devm_mux_chip_match(struct device *dev, void *res, void *data)
> +{
> +	struct mux_chip **r = res;
> +
> +	if (!r || !*r) {
> +		WARN_ON(!r || !*r);
> +		return 0;
> +	}
> +
> +	return *r == data;
> +}
> +
> +void devm_mux_chip_free(struct device *dev, struct mux_chip *mux_chip)
> +{
> +	WARN_ON(devres_release(dev, devm_mux_chip_release,
> +			       devm_mux_chip_match, mux_chip));
> +}
> +EXPORT_SYMBOL_GPL(devm_mux_chip_free);
> +
> +static void devm_mux_chip_reg_release(struct device *dev, void *res)
> +{
> +	struct mux_chip *mux_chip = *(struct mux_chip **)res;
> +
> +	mux_chip_unregister(mux_chip);
> +}
> +
> +int devm_mux_chip_register(struct device *dev,
> +			   struct mux_chip *mux_chip)
> +{
> +	struct mux_chip **ptr;
> +	int res;
> +
> +	ptr = devres_alloc(devm_mux_chip_reg_release, sizeof(*ptr), GFP_KERNEL);
> +	if (!ptr)
> +		return -ENOMEM;
> +
> +	res = mux_chip_register(mux_chip);
> +	if (res) {
> +		devres_free(ptr);
> +		return res;
> +	}
> +
> +	*ptr = mux_chip;
> +	devres_add(dev, ptr);
> +
> +	return res;
> +}
> +EXPORT_SYMBOL_GPL(devm_mux_chip_register);
> +
> +void devm_mux_chip_unregister(struct device *dev, struct mux_chip *mux_chip)
> +{
> +	WARN_ON(devres_release(dev, devm_mux_chip_reg_release,
> +			       devm_mux_chip_match, mux_chip));
> +}
> +EXPORT_SYMBOL_GPL(devm_mux_chip_unregister);
> +
> +int mux_control_select(struct mux_control *mux, int state)
> +{
> +	int ret;
> +
> +	if (down_read_trylock(&mux->lock)) {
> +		if (mux->cached_state == state)
> +			return 0;
> +
> +		/* Sigh, the mux needs updating... */
> +		up_read(&mux->lock);
> +	}
> +
> +	/* ...or it's just contended. */
> +	down_write(&mux->lock);
> +
> +	if (mux->cached_state == state) {
> +		/*
> +		 * Hmmm, someone else changed the mux to my liking.
> +		 * That makes me wonder how long I waited for nothing?
> +		 */
> +		downgrade_write(&mux->lock);
> +		return 0;
> +	}
> +
> +	ret = mux_control_set(mux, state);
> +	if (ret < 0) {
> +		if (mux->idle_state != -1)
> +			mux_control_set(mux, mux->idle_state);
> +
> +		up_write(&mux->lock);
> +		return ret;
> +	}
> +
> +	downgrade_write(&mux->lock);
> +
> +	return 1;
> +}
> +EXPORT_SYMBOL_GPL(mux_control_select);
> +
> +int mux_control_deselect(struct mux_control *mux)
> +{
> +	int ret = 0;
> +
> +	if (mux->idle_state != -1 && mux->cached_state != mux->idle_state)
> +		ret = mux_control_set(mux, mux->idle_state);
> +
> +	up_read(&mux->lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(mux_control_deselect);
> +
> +static int of_dev_node_match(struct device *dev, const void *data)
> +{
> +	return dev->of_node == data;
> +}
> +
> +static struct mux_chip *of_find_mux_chip_by_node(struct device_node *np)
> +{
> +	struct device *dev;
> +
> +	dev = class_find_device(&mux_class, NULL, np, of_dev_node_match);
> +
> +	return dev ? to_mux_chip(dev) : NULL;
> +}
> +
> +struct mux_control *mux_control_get(struct device *dev, const char *mux_name)
> +{
> +	struct device_node *np = dev->of_node;
> +	struct of_phandle_args args;
> +	struct mux_chip *mux_chip;
> +	unsigned int controller;
> +	int index = 0;
> +	int ret;
> +
> +	if (mux_name) {
> +		index = of_property_match_string(np, "mux-control-names",
> +						 mux_name);
> +		if (index < 0)
> +			return ERR_PTR(index);
> +	}
> +
> +	ret = of_parse_phandle_with_args(np,
> +					 "mux-controls", "#mux-control-cells",
> +					 index, &args);
> +	if (ret) {
> +		dev_err(dev, "%s: failed to get mux-control %s(%i)\n",
> +			np->full_name, mux_name ?: "", index);
> +		return ERR_PTR(ret);
> +	}
> +
> +	mux_chip = of_find_mux_chip_by_node(args.np);
> +	of_node_put(args.np);
> +	if (!mux_chip)
> +		return ERR_PTR(-EPROBE_DEFER);
> +
> +	if (args.args_count > 1 ||
> +	    (!args.args_count && (mux_chip->controllers > 1))) {
> +		dev_err(dev, "%s: wrong #mux-control-cells for %s\n",
> +			np->full_name, args.np->full_name);
> +		return ERR_PTR(-EINVAL);
> +	}
> +
> +	controller = 0;
> +	if (args.args_count)
> +		controller = args.args[0];
> +
> +	if (controller >= mux_chip->controllers)
> +		return ERR_PTR(-EINVAL);
> +
> +	get_device(&mux_chip->dev);
> +	return &mux_chip->mux[controller];
> +}
> +EXPORT_SYMBOL_GPL(mux_control_get);
> +
> +void mux_control_put(struct mux_control *mux)
> +{
> +	put_device(&mux->chip->dev);
> +}
> +EXPORT_SYMBOL_GPL(mux_control_put);
> +
> +static void devm_mux_control_release(struct device *dev, void *res)
> +{
> +	struct mux_control *mux = *(struct mux_control **)res;
> +
> +	mux_control_put(mux);
> +}
> +
> +struct mux_control *devm_mux_control_get(struct device *dev,
> +					 const char *mux_name)
> +{
> +	struct mux_control **ptr, *mux;
> +
> +	ptr = devres_alloc(devm_mux_control_release, sizeof(*ptr), GFP_KERNEL);
> +	if (!ptr)
> +		return ERR_PTR(-ENOMEM);
> +
> +	mux = mux_control_get(dev, mux_name);
> +	if (IS_ERR(mux)) {
> +		devres_free(ptr);
> +		return mux;
> +	}
> +
> +	*ptr = mux;
> +	devres_add(dev, ptr);
> +
> +	return mux;
> +}
> +EXPORT_SYMBOL_GPL(devm_mux_control_get);
> +
> +static int devm_mux_control_match(struct device *dev, void *res, void *data)
> +{
> +	struct mux_control **r = res;
> +
> +	if (!r || !*r) {
> +		WARN_ON(!r || !*r);
> +		return 0;
> +	}
> +
> +	return *r == data;
> +}
> +
> +void devm_mux_control_put(struct device *dev, struct mux_control *mux)
> +{
> +	WARN_ON(devres_release(dev, devm_mux_control_release,
> +			       devm_mux_control_match, mux));
> +}
> +EXPORT_SYMBOL_GPL(devm_mux_control_put);
> +
> +subsys_initcall(mux_init);
> +
> +MODULE_DESCRIPTION("Multiplexer subsystem");
> +MODULE_AUTHOR("Peter Rosin <peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org");
> +MODULE_LICENSE("GPL v2");
> diff --git a/drivers/mux/mux-gpio.c b/drivers/mux/mux-gpio.c
> new file mode 100644
> index 000000000000..76b52bc63470
> --- /dev/null
> +++ b/drivers/mux/mux-gpio.c
> @@ -0,0 +1,120 @@
> +/*
> + * GPIO-controlled multiplexer driver
> + *
> + * Copyright (C) 2016 Axentia Technologies AB
> + *
> + * Author: Peter Rosin <peda-koto5C5qi+TLoDKTGw+V6w@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/err.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/module.h>
> +#include <linux/mux.h>
> +#include <linux/of_platform.h>
> +#include <linux/platform_device.h>
> +#include <linux/property.h>
> +
> +struct mux_gpio {
> +	struct gpio_descs *gpios;
> +	int *val;
> +};
> +
> +static int mux_gpio_set(struct mux_control *mux, int state)
> +{
> +	struct mux_gpio *mux_gpio = mux_chip_priv(mux->chip);
> +	int i;
> +
> +	for (i = 0; i < mux_gpio->gpios->ndescs; i++)
> +		mux_gpio->val[i] = (state >> i) & 1;
> +
> +	gpiod_set_array_value_cansleep(mux_gpio->gpios->ndescs,
> +				       mux_gpio->gpios->desc,
> +				       mux_gpio->val);
> +
> +	return 0;
> +}
> +
> +static const struct mux_control_ops mux_gpio_ops = {
> +	.set = mux_gpio_set,
> +};
> +
> +static const struct of_device_id mux_gpio_dt_ids[] = {
> +	{ .compatible = "mux-gpio", },
> +	{ /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(of, mux_gpio_dt_ids);
> +
> +static int mux_gpio_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct device_node *np = dev->of_node;
> +	struct mux_chip *mux_chip;
> +	struct mux_gpio *mux_gpio;
> +	int pins;
> +	u32 idle_state;
> +	int ret;
> +
> +	if (!np)
> +		return -ENODEV;
> +
> +	pins = gpiod_count(dev, "mux");
> +	if (pins < 0)
> +		return pins;
> +
> +	mux_chip = devm_mux_chip_alloc(dev, 1, sizeof(*mux_gpio) +
> +				       pins * sizeof(*mux_gpio->val));
> +	if (!mux_chip)
> +		return -ENOMEM;
> +
> +	mux_gpio = mux_chip_priv(mux_chip);
> +	mux_gpio->val = (int *)(mux_gpio + 1);
> +	mux_chip->ops = &mux_gpio_ops;
> +
> +	mux_gpio->gpios = devm_gpiod_get_array(dev, "mux", GPIOD_OUT_LOW);
> +	if (IS_ERR(mux_gpio->gpios)) {
> +		ret = PTR_ERR(mux_gpio->gpios);
> +		if (ret != -EPROBE_DEFER)
> +			dev_err(dev, "failed to get gpios\n");
> +		return ret;
> +	}
> +	WARN_ON(pins != mux_gpio->gpios->ndescs);
> +	mux_chip->mux->states = 1 << pins;
> +
> +	ret = device_property_read_u32(dev, "idle-state", &idle_state);
> +	if (ret >= 0) {
> +		if (idle_state >= mux_chip->mux->states) {
> +			dev_err(dev, "invalid idle-state %u\n", idle_state);
> +			return -EINVAL;
> +		}
> +
> +		mux_chip->mux->idle_state = idle_state;
> +	}
> +
> +	ret = devm_mux_chip_register(dev, mux_chip);
> +	if (ret < 0) {
> +		dev_err(dev, "failed to register mux-chip\n");
> +		return ret;
> +	}
> +
> +	dev_info(dev, "%u-way mux-controller registered\n",
> +		 mux_chip->mux->states);
> +
> +	return 0;
> +}
> +
> +static struct platform_driver mux_gpio_driver = {
> +	.driver = {
> +		.name = "mux-gpio",
> +		.of_match_table	= of_match_ptr(mux_gpio_dt_ids),
> +	},
> +	.probe = mux_gpio_probe,
> +};
> +module_platform_driver(mux_gpio_driver);
> +
> +MODULE_DESCRIPTION("GPIO-controlled multiplexer driver");
> +MODULE_AUTHOR("Peter Rosin <peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org");
> +MODULE_LICENSE("GPL v2");
> diff --git a/include/linux/mux.h b/include/linux/mux.h
> new file mode 100644
> index 000000000000..3b9439927f11
> --- /dev/null
> +++ b/include/linux/mux.h
> @@ -0,0 +1,244 @@
> +/*
> + * mux.h - definitions for the multiplexer interface
> + *
> + * Copyright (C) 2016 Axentia Technologies AB
> + *
> + * Author: Peter Rosin <peda-koto5C5qi+TLoDKTGw+V6w@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.
> + */
> +
> +#ifndef _LINUX_MUX_H
> +#define _LINUX_MUX_H
> +
> +#include <linux/device.h>
> +#include <linux/rwsem.h>
> +
> +struct mux_chip;
> +struct mux_control;
> +struct platform_device;
> +
> +struct mux_control_ops {
> +	int (*set)(struct mux_control *mux, int state);
> +};
> +
> +/**
> + * struct mux_control - Represents a mux controller.
> + * @lock:		Protects the mux controller state.
> + * @chip:		The mux chip that is handling this mux controller.
> + * @states:		The number of mux controller states.
> + * @cached_state:	The current mux controller state, or -1 if none.
> + * @idle_state:		The mux controller state to use when inactive, or -1
> + *			for none.
> + */
> +struct mux_control {
> +	struct rw_semaphore lock; /* protects the state of the mux */
> +
> +	struct mux_chip *chip;
> +
> +	unsigned int states;
> +	int cached_state;
> +	int idle_state;
> +};
> +
> +/**
> + * struct mux_chip -	Represents a chip holding mux controllers.
> + * @controllers:	Number of mux controllers handled by the chip.
> + * @mux:		Array of mux controllers that is handled.
> + * @dev:		Device structure.
> + * @id:			Used to identify the device internally.
> + * @ops:		Mux controller operations.
> + */
> +struct mux_chip {
> +	unsigned int controllers;
> +	struct mux_control *mux;
> +	struct device dev;
> +	int id;
> +
> +	const struct mux_control_ops *ops;
> +};
> +
> +#define to_mux_chip(x) container_of((x), struct mux_chip, dev)
> +
> +/**
> + * mux_chip_priv() - Get the extra memory reserved by mux_chip_alloc().
> + * @mux_chip: The mux-chip to get the private memory from.
> + *
> + * Return: Pointer to the private memory reserved by the allocator.
> + */
> +static inline void *mux_chip_priv(struct mux_chip *mux_chip)
> +{
> +	return &mux_chip->mux[mux_chip->controllers];
> +}
> +
> +/**
> + * mux_chip_alloc() - Allocate a mux-chip.
> + * @dev: The parent device implementing the mux interface.
> + * @controllers: The number of mux controllers to allocate for this chip.
> + * @sizeof_priv: Size of extra memory area for private use by the caller.
> + *
> + * Return: A pointer to the new mux-chip, NULL on failure.
> + */
> +struct mux_chip *mux_chip_alloc(struct device *dev,
> +				unsigned int controllers, size_t sizeof_priv);
> +
> +/**
> + * mux_chip_register() - Register a mux-chip, thus readying the controllers
> + *			 for use.
> + * @mux_chip: The mux-chip to register.
> + *
> + * Do not retry registration of the same mux-chip on failure. You should
> + * instead put it away with mux_chip_free() and allocate a new one, if you
> + * for some reason would like to retry registration.
> + *
> + * Return: Zero on success or a negative errno on error.
> + */
> +int mux_chip_register(struct mux_chip *mux_chip);
> +
> +/**
> + * mux_chip_unregister() - Take the mux-chip off-line.
> + * @mux_chip: The mux-chip to unregister.
> + *
> + * mux_chip_unregister() reverses the effects of mux_chip_register().
> + * But not completely, you should not try to call mux_chip_register()
> + * on a mux-chip that has been registered before.
> + */
> +void mux_chip_unregister(struct mux_chip *mux_chip);
> +
> +/**
> + * mux_chip_free() - Free the mux-chip for good.
> + * @mux_chip: The mux-chip to free.
> + *
> + * mux_chip_free() reverses the effects of mux_chip_alloc().
> + */
> +void mux_chip_free(struct mux_chip *mux_chip);
> +
> +/**
> + * devm_mux_chip_alloc() - Resource-managed version of mux_chip_alloc().
> + * @dev: The parent device implementing the mux interface.
> + * @controllers: The number of mux controllers to allocate for this chip.
> + * @sizeof_priv: Size of extra memory area for private use by the caller.
> + *
> + * See mux_chip_alloc() for more details.
> + *
> + * Return: A pointer to the new mux-chip, NULL on failure.
> + */
> +struct mux_chip *devm_mux_chip_alloc(struct device *dev,
> +				     unsigned int controllers,
> +				     size_t sizeof_priv);
> +
> +/**
> + * devm_mux_chip_register() - Resource-managed version mux_chip_register().
> + * @dev: The parent device implementing the mux interface.
> + * @mux_chip: The mux-chip to register.
> + *
> + * See mux_chip_register() for more details.
> + *
> + * Return: Zero on success or a negative errno on error.
> + */
> +int devm_mux_chip_register(struct device *dev, struct mux_chip *mux_chip);
> +
> +/**
> + * devm_mux_chip_unregister() - Resource-managed version mux_chip_unregister().
> + * @dev: The device that originally registered the mux-chip.
> + * @mux_chip: The mux-chip to unregister.
> + *
> + * See mux_chip_unregister() for more details.
> + *
> + * Note that you do not normally need to call this function.
> + */
> +void devm_mux_chip_unregister(struct device *dev, struct mux_chip *mux_chip);
> +
> +/**
> + * devm_mux_chip_free() - Resource-managed version mux_chip_free().
> + * @dev: The device that originally got the mux-chip.
> + * @mux_chip: The mux-chip to free.
> + *
> + * See mux_chip_free() for more details.
> + *
> + * Note that you do not normally need to call this function.
> + */
> +void devm_mux_chip_free(struct device *dev, struct mux_chip *mux_chip);
> +
> +/**
> + * mux_control_select() - Select the given multiplexer state.
> + * @mux: The mux-control to request a change of state from.
> + * @state: The new requested state.
> + *
> + * Make sure to call mux_control_deselect() when the operation is complete and
> + * the mux-control is free for others to use, but do not call
> + * mux_control_deselect() if mux_control_select() fails.
> + *
> + * Return: 0 if the requested state was already active, or 1 it the
> + * mux-control state was changed to the requested state. Or a negavive
> + * errno on error.
> + *
> + * Note that the difference in return value of zero or one is of
> + * questionable value; especially if the mux-control has several independent
> + * consumers, which is something the consumers should perhaps not be making
> + * assumptions about.
> + */
> +int mux_control_select(struct mux_control *mux, int state);
> +
> +/**
> + * mux_control_deselect() - Deselect the previously selected multiplexer state.
> + * @mux: The mux-control to deselect.
> + *
> + * Return: 0 on success and a negative errno on error. An error can only
> + * occur if the mux has an idle state. Note that even if an error occurs, the
> + * mux-control is unlocked for others to access.
> + */
> +int mux_control_deselect(struct mux_control *mux);
> +
> +/**
> + * mux_control_get_index() - Get the index of the given mux controller
> + * @mux: The mux-control to the the index for.
> + *
> + * Return: The index of the mux controller within the mux chip the mux
> + * controller is a part of.
> + */
> +static inline unsigned int mux_control_get_index(struct mux_control *mux)
> +{
> +	return mux - mux->chip->mux;
> +}
> +
> +/**
> + * mux_control_get() - Get the mux-control for a device.
> + * @dev: The device that needs a mux-control.
> + * @mux_name: The name identifying the mux-control.
> + *
> + * Return: A pointer to the mux-control, or an ERR_PTR with a negative errno.
> + */
> +struct mux_control *mux_control_get(struct device *dev, const char *mux_name);
> +
> +/**
> + * mux_control_put() - Put away the mux-control for good.
> + * @mux: The mux-control to put away.
> + *
> + * mux_control_put() reverses the effects of mux_control_get().
> + */
> +void mux_control_put(struct mux_control *mux);
> +
> +/**
> + * devm_mux_control_get() - Get the mux-control for a device, with resource
> + *			    management.
> + * @dev: The device that needs a mux-control.
> + * @mux_name: The name identifying the mux-control.
> + *
> + * Return: Pointer to the mux-control, or an ERR_PTR with a negative errno.
> + */
> +struct mux_control *devm_mux_control_get(struct device *dev,
> +					 const char *mux_name);
> +
> +/**
> + * devm_mux_control_put() - Resource-managed version mux_control_put().
> + * @dev: The device that originally got the mux-control.
> + * @mux: The mux-control to put away.
> + *
> + * Note that you do not normally need to call this function.
> + */
> +void devm_mux_control_put(struct device *dev, struct mux_control *mux);
> +
> +#endif /* _LINUX_MUX_H */
> 

^ permalink raw reply

* Re: [PATCH v7 04/12] dt-bindings: simplified bindings for single-user gpio mux
From: Jonathan Cameron @ 2017-01-08 10:25 UTC (permalink / raw)
  To: Peter Rosin, linux-kernel
  Cc: Wolfram Sang, Rob Herring, Mark Rutland, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Jonathan Corbet,
	Arnd Bergmann, Greg Kroah-Hartman, linux-i2c, devicetree,
	linux-iio, linux-doc
In-Reply-To: <1483532187-28494-5-git-send-email-peda@axentia.se>

On 04/01/17 12:16, Peter Rosin wrote:
> Signed-off-by: Peter Rosin <peda@axentia.se>
Looks neat and tidy to me.

Acked-by: Jonathan Cameron <jic23@kernel.org>
> ---
>  .../devicetree/bindings/mux/mux-controller.txt     | 26 ++++++++++++++++++++++
>  1 file changed, 26 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/mux/mux-controller.txt b/Documentation/devicetree/bindings/mux/mux-controller.txt
> index 42b2177e5ae1..4e89df8b2392 100644
> --- a/Documentation/devicetree/bindings/mux/mux-controller.txt
> +++ b/Documentation/devicetree/bindings/mux/mux-controller.txt
> @@ -125,3 +125,29 @@ An example mux controller might look like this:
>  		reg = <0x50>;
>  		#mux-control-cells = <1>;
>  	};
> +
> +
> +Combinded controller and consumer of a GPIO mux
> +-----------------------------------------------
> +
> +For the common case of a single consumer of a GPIO controlled mux, there is
> +a simplified binding which will instantiate an implicit mux controller. Just
> +specify a mux-gpios property with the same interpretation as in mux-gpio.txt.
> +Note that other properties described in mux-gpio.txt are not available in
> +this simplified form and that the mux controller is unnamed. If you need
> +more than one mux controller, a shared mux controller or if you need a
> +specific idle-state, use the more flexible binding with the mux controller
> +in its own node.
> +
> +Example:
> +
> +	adc-mux {
> +		compatible = "io-channel-mux";
> +		io-channels = <&adc 0>;
> +		io-channel-names = "parent";
> +
> +		mux-gpios = <&pioA 0 GPIO_ACTIVE_HIGH>,
> +			    <&pioA 1 GPIO_ACTIVE_HIGH>;
> +
> +		channels = "sync-1", "in", "out", "sync-2";
> +	};
> 

^ permalink raw reply

* Re: [PATCH v7 05/12] mux: support simplified bindings for single-user gpio mux
From: Jonathan Cameron @ 2017-01-08 10:28 UTC (permalink / raw)
  To: Peter Rosin, linux-kernel
  Cc: Wolfram Sang, Rob Herring, Mark Rutland, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Jonathan Corbet,
	Arnd Bergmann, Greg Kroah-Hartman, linux-i2c, devicetree,
	linux-iio, linux-doc
In-Reply-To: <d89179f5-6ad6-3c40-cdb8-f49cf324e9ee@axentia.se>

On 05/01/17 16:21, Peter Rosin wrote:
> On 2017-01-04 13:16, Peter Rosin wrote:
>> Signed-off-by: Peter Rosin <peda@axentia.se>
>> ---
>>  drivers/mux/mux-core.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++--
>>  drivers/mux/mux-gpio.c | 56 ++--------------------------------
>>  include/linux/mux.h    |  7 +++++
>>  3 files changed, 89 insertions(+), 55 deletions(-)
>>
>> diff --git a/drivers/mux/mux-core.c b/drivers/mux/mux-core.c
>> index 21da15a264ad..d887ae1c0e55 100644
>> --- a/drivers/mux/mux-core.c
>> +++ b/drivers/mux/mux-core.c
>> @@ -15,6 +15,7 @@
>>  #include <linux/device.h>
>>  #include <linux/err.h>
>>  #include <linux/idr.h>
>> +#include <linux/gpio/consumer.h>
>>  #include <linux/module.h>
>>  #include <linux/mux.h>
>>  #include <linux/of.h>
>> @@ -288,6 +289,63 @@ static struct mux_chip *of_find_mux_chip_by_node(struct device_node *np)
>>  	return dev ? to_mux_chip(dev) : NULL;
>>  }
>>  
>> +#ifdef CONFIG_MUX_GPIO
>> +
>> +static int mux_gpio_set(struct mux_control *mux, int state)
>> +{
>> +	struct mux_gpio *mux_gpio = mux_chip_priv(mux->chip);
>> +	int i;
>> +
>> +	for (i = 0; i < mux_gpio->gpios->ndescs; i++)
>> +		mux_gpio->val[i] = (state >> i) & 1;
>> +
>> +	gpiod_set_array_value_cansleep(mux_gpio->gpios->ndescs,
>> +				       mux_gpio->gpios->desc,
>> +				       mux_gpio->val);
>> +
>> +	return 0;
>> +}
>> +
>> +static const struct mux_control_ops mux_gpio_ops = {
>> +	.set = mux_gpio_set,
>> +};
>> +
>> +struct mux_chip *mux_gpio_alloc(struct device *dev)
>> +{
>> +	struct mux_chip *mux_chip;
>> +	struct mux_gpio *mux_gpio;
>> +	int pins;
>> +	int ret;
>> +
>> +	pins = gpiod_count(dev, "mux");
>> +	if (pins < 0)
>> +		return ERR_PTR(pins);
>> +
>> +	mux_chip = devm_mux_chip_alloc(dev, 1, sizeof(*mux_gpio) +
>> +				       pins * sizeof(*mux_gpio->val));
>> +	if (!mux_chip)
>> +		return ERR_PTR(-ENOMEM);
>> +
>> +	mux_gpio = mux_chip_priv(mux_chip);
>> +	mux_gpio->val = (int *)(mux_gpio + 1);
>> +	mux_chip->ops = &mux_gpio_ops;
>> +
>> +	mux_gpio->gpios = devm_gpiod_get_array(dev, "mux", GPIOD_OUT_LOW);
>> +	if (IS_ERR(mux_gpio->gpios)) {
>> +		ret = PTR_ERR(mux_gpio->gpios);
>> +		if (ret != -EPROBE_DEFER)
>> +			dev_err(dev, "failed to get gpios\n");
>> +		return ERR_PTR(ret);
>> +	}
>> +	WARN_ON(pins != mux_gpio->gpios->ndescs);
>> +	mux_chip->mux->states = 1 << pins;
>> +
>> +	return mux_chip;
>> +}
>> +EXPORT_SYMBOL_GPL(mux_gpio_alloc);
>> +
>> +#endif /* CONFIG_MUX_GPIO */
>> +
>>  struct mux_control *mux_control_get(struct device *dev, const char *mux_name)
>>  {
>>  	struct device_node *np = dev->of_node;
>> @@ -307,9 +365,28 @@ struct mux_control *mux_control_get(struct device *dev, const char *mux_name)
>>  	ret = of_parse_phandle_with_args(np,
>>  					 "mux-controls", "#mux-control-cells",
>>  					 index, &args);
>> +
>> +#ifdef CONFIG_MUX_GPIO
>> +	if (ret == -ENOENT && !mux_name && gpiod_count(dev, "mux") > 0) {
>> +		mux_chip = mux_gpio_alloc(dev);
>> +		if (!IS_ERR(mux_chip)) {
>> +			ret = devm_mux_chip_register(dev, mux_chip);
>> +			if (ret < 0) {
>> +				dev_err(dev, "failed to register mux-chip\n");
>> +				return ERR_PTR(ret);
>> +			}
>> +			get_device(&mux_chip->dev);
>> +			return mux_chip->mux;
>> +		}
>> +
>> +		ret = PTR_ERR(mux_chip);
>> +	}
>> +#endif
>> +
>>  	if (ret) {
>> -		dev_err(dev, "%s: failed to get mux-control %s(%i)\n",
>> -			np->full_name, mux_name ?: "", index);
>> +		if (ret != -EPROBE_DEFER)
>> +			dev_err(dev, "%s: failed to get mux-control %s(%i)\n",
>> +				np->full_name, mux_name ?: "", index);
>>  		return ERR_PTR(ret);
>>  	}
>>  
>> diff --git a/drivers/mux/mux-gpio.c b/drivers/mux/mux-gpio.c
>> index 76b52bc63470..8a7bfbc0c4bb 100644
>> --- a/drivers/mux/mux-gpio.c
>> +++ b/drivers/mux/mux-gpio.c
>> @@ -11,37 +11,12 @@
>>   */
>>  
>>  #include <linux/err.h>
>> -#include <linux/gpio/consumer.h>
>>  #include <linux/module.h>
>>  #include <linux/mux.h>
>>  #include <linux/of_platform.h>
>>  #include <linux/platform_device.h>
>>  #include <linux/property.h>
> 
> Instead of moving the mux-gpio guts from mux-gpio.c to mux-core.c, I
> will instead make CONFIG_MUX_GPIO a bool option (no module possible)
> and call it from the mux-core. That will be cleaner and less of a
> break of abstractions in my opinion.
Hmm. I wonder if the balance is right here or whether we should just not have the
simplified binding at all as it breaks the assumption that all muxes are of the
same level...

I like the binding, but it is causing significant complexity in here.
> 
> Cheers,
> Peter
> 
>> -struct mux_gpio {
>> -	struct gpio_descs *gpios;
>> -	int *val;
>> -};
>> -
>> -static int mux_gpio_set(struct mux_control *mux, int state)
>> -{
>> -	struct mux_gpio *mux_gpio = mux_chip_priv(mux->chip);
>> -	int i;
>> -
>> -	for (i = 0; i < mux_gpio->gpios->ndescs; i++)
>> -		mux_gpio->val[i] = (state >> i) & 1;
>> -
>> -	gpiod_set_array_value_cansleep(mux_gpio->gpios->ndescs,
>> -				       mux_gpio->gpios->desc,
>> -				       mux_gpio->val);
>> -
>> -	return 0;
>> -}
>> -
>> -static const struct mux_control_ops mux_gpio_ops = {
>> -	.set = mux_gpio_set,
>> -};
>> -
>>  static const struct of_device_id mux_gpio_dt_ids[] = {
>>  	{ .compatible = "mux-gpio", },
>>  	{ /* sentinel */ }
>> @@ -51,38 +26,13 @@ MODULE_DEVICE_TABLE(of, mux_gpio_dt_ids);
>>  static int mux_gpio_probe(struct platform_device *pdev)
>>  {
>>  	struct device *dev = &pdev->dev;
>> -	struct device_node *np = dev->of_node;
>>  	struct mux_chip *mux_chip;
>> -	struct mux_gpio *mux_gpio;
>> -	int pins;
>>  	u32 idle_state;
>>  	int ret;
>>  
>> -	if (!np)
>> -		return -ENODEV;
>> -
>> -	pins = gpiod_count(dev, "mux");
>> -	if (pins < 0)
>> -		return pins;
>> -
>> -	mux_chip = devm_mux_chip_alloc(dev, 1, sizeof(*mux_gpio) +
>> -				       pins * sizeof(*mux_gpio->val));
>> -	if (!mux_chip)
>> -		return -ENOMEM;
>> -
>> -	mux_gpio = mux_chip_priv(mux_chip);
>> -	mux_gpio->val = (int *)(mux_gpio + 1);
>> -	mux_chip->ops = &mux_gpio_ops;
>> -
>> -	mux_gpio->gpios = devm_gpiod_get_array(dev, "mux", GPIOD_OUT_LOW);
>> -	if (IS_ERR(mux_gpio->gpios)) {
>> -		ret = PTR_ERR(mux_gpio->gpios);
>> -		if (ret != -EPROBE_DEFER)
>> -			dev_err(dev, "failed to get gpios\n");
>> -		return ret;
>> -	}
>> -	WARN_ON(pins != mux_gpio->gpios->ndescs);
>> -	mux_chip->mux->states = 1 << pins;
>> +	mux_chip = mux_gpio_alloc(dev);
>> +	if (IS_ERR(mux_chip))
>> +		return PTR_ERR(mux_chip);
>>  
>>  	ret = device_property_read_u32(dev, "idle-state", &idle_state);
>>  	if (ret >= 0) {
>> diff --git a/include/linux/mux.h b/include/linux/mux.h
>> index 3b9439927f11..3bfee23cfb8c 100644
>> --- a/include/linux/mux.h
>> +++ b/include/linux/mux.h
>> @@ -241,4 +241,11 @@ struct mux_control *devm_mux_control_get(struct device *dev,
>>   */
>>  void devm_mux_control_put(struct device *dev, struct mux_control *mux);
>>  
>> +struct mux_gpio {
>> +	struct gpio_descs *gpios;
>> +	int *val;
>> +};
>> +
>> +struct mux_chip *mux_gpio_alloc(struct device *dev);
>> +
>>  #endif /* _LINUX_MUX_H */
>>
> 

^ permalink raw reply

* Re: [PATCH v7 07/12] dt-bindings: iio: iio-mux: document iio-mux bindings
From: Jonathan Cameron @ 2017-01-08 10:29 UTC (permalink / raw)
  To: Peter Rosin, linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Wolfram Sang, Rob Herring, Mark Rutland, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Jonathan Corbet,
	Arnd Bergmann, Greg Kroah-Hartman,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-iio-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1483532187-28494-8-git-send-email-peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>

On 04/01/17 12:16, Peter Rosin wrote:
> Signed-off-by: Peter Rosin <peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>
Acked-by: Jonathan Cameron <jic23-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> ---
>  .../bindings/iio/multiplexer/io-channel-mux.txt    | 39 ++++++++++++++++++++++
>  MAINTAINERS                                        |  6 ++++
>  2 files changed, 45 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt
> 
> diff --git a/Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt b/Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt
> new file mode 100644
> index 000000000000..c82794002595
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt
> @@ -0,0 +1,39 @@
> +I/O channel multiplexer bindings
> +
> +If a multiplexer is used to select which hardware signal is fed to
> +e.g. an ADC channel, these bindings describe that situation.
> +
> +Required properties:
> +- compatible : "io-channel-mux"
> +- io-channels : Channel node of the parent channel that has multiplexed
> +		input.
> +- io-channel-names : Should be "parent".
> +- #address-cells = <1>;
> +- #size-cells = <0>;
> +- mux-controls : Mux controller node to use for operating the mux
> +- channels : List of strings, labeling the mux controller states.
> +
> +For each non-empty string in the channels property, an io-channel will
> +be created. The number of this io-channel is the same as the index into
> +the list of strings in the channels property, and also matches the mux
> +controller state. The mux controller state is described in
> +../mux/mux-controller.txt
> +
> +Example:
> +	mux: mux-controller {
> +		compatible = "mux-gpio";
> +		#mux-control-cells = <0>;
> +
> +		mux-gpios = <&pioA 0 GPIO_ACTIVE_HIGH>,
> +			    <&pioA 1 GPIO_ACTIVE_HIGH>;
> +	};
> +
> +	adc-mux {
> +		compatible = "io-channel-mux";
> +		io-channels = <&adc 0>;
> +		io-channel-names = "parent";
> +
> +		mux-controls = <&mux>;
> +
> +		channels = "sync", "in", "system-regulator";
> +	};
> diff --git a/MAINTAINERS b/MAINTAINERS
> index ebe96f3e25a0..91775f2be209 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -6274,6 +6274,12 @@ F:	Documentation/ABI/testing/sysfs-bus-iio-adc-envelope-detector
>  F:	Documentation/devicetree/bindings/iio/adc/envelope-detector.txt
>  F:	drivers/iio/adc/envelope-detector.c
>  
> +IIO MULTIPLEXER
> +M:	Peter Rosin <peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>
> +L:	linux-iio-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> +S:	Maintained
> +F:	Documentation/devicetree/bindings/iio/multiplexer/iio-mux.txt
> +
>  IIO SUBSYSTEM AND DRIVERS
>  M:	Jonathan Cameron <jic23-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
>  R:	Hartmut Knaack <knaack.h-Mmb7MZpHnFY@public.gmane.org>
> 

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

^ permalink raw reply

* Re: [PATCH v7 11/12] dt-bindings: mux-adg792a: document devicetree bindings for ADG792A/G mux
From: Jonathan Cameron @ 2017-01-08 10:31 UTC (permalink / raw)
  To: Peter Rosin, linux-kernel
  Cc: Wolfram Sang, Rob Herring, Mark Rutland, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Jonathan Corbet,
	Arnd Bergmann, Greg Kroah-Hartman, linux-i2c, devicetree,
	linux-iio, linux-doc
In-Reply-To: <1483532187-28494-12-git-send-email-peda@axentia.se>

On 04/01/17 12:16, Peter Rosin wrote:
> Analog Devices ADG792A/G is a triple 4:1 mux.
> 
> Signed-off-by: Peter Rosin <peda@axentia.se>
I think this is about as neat as we can make it.

Acked-by: Jonathan Cameron <jic23@kernel.org>
> ---
>  .../devicetree/bindings/mux/mux-adg792a.txt        | 79 ++++++++++++++++++++++
>  1 file changed, 79 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mux/mux-adg792a.txt
> 
> diff --git a/Documentation/devicetree/bindings/mux/mux-adg792a.txt b/Documentation/devicetree/bindings/mux/mux-adg792a.txt
> new file mode 100644
> index 000000000000..0b26dd11f070
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mux/mux-adg792a.txt
> @@ -0,0 +1,79 @@
> +Bindings for Analog Devices ADG792A/G Triple 4:1 Multiplexers
> +
> +Required properties:
> +- compatible : "adi,adg792a" or "adi,adg792g"
> +- #mux-control-cells : <0> if parallel, or <1> if not.
> +* Standard mux-controller bindings as decribed in mux-controller.txt
> +
> +Optional properties for ADG792G:
> +- gpio-controller : if present, #gpio-cells below is required.
> +- #gpio-cells : should be <2>
> +			  - First cell is the GPO line number, i.e. 0 or 1
> +			  - Second cell is used to specify active high (0)
> +			    or active low (1)
> +
> +Optional properties:
> +- adi,parallel : if present, the three muxes are bound together with a single
> +  mux controller, controlling all three muxes in parallel.
> +- adi,idle-state : if present, array of 2-tuples with mux controller number
> +  and state that mux controllers will have when idle. States 0 through 3
> +  correspond to signals A through D in the datasheet.
> +- adi,idle-high-impedance : if present, array of mux controller numbers that
> +  should be in the disconnected high-impedance state when idle.
> +
> +Mux controller states 0 through 3 correspond to signals A through D in the
> +datasheet. If a mux controller is mentioned in neither adi,idle-state nor
> +adi,idle-high-impedance it is left in its previously selected state when idle.
> +
> +Example:
> +
> +	/*
> +	 * Three independent mux controllers (of which one is used).
> +	 * Mux 0 is disconnected when idle, mux 1 idles with signal C
> +	 * and mux 2 idles with signal A.
> +	 */
> +	&i2c0 {
> +		mux: adg792a@50 {
> +			compatible = "adi,adg792a";
> +			reg = <0x50>;
> +			#mux-control-cells = <1>;
> +
> +			adi,idle-high-impedance = <0>;
> +			adi,idle-state = <1 2>, <2 0>;
> +		};
> +	};
> +
> +	adc-mux {
> +		compatible = "io-channel-mux";
> +		io-channels = <&adc 0>;
> +		io-channel-names = "parent";
> +
> +		mux-controls = <&mux 1>;
> +
> +		channels = "sync-1", "", "out";
> +	};
> +
> +
> +	/*
> +	 * Three parallel muxes with one mux controller, useful e.g. if
> +	 * the adc is differential, thus needing two signals to be muxed
> +	 * simultaneously for correct operation.
> +	 */
> +	&i2c0 {
> +		pmux: adg792a@50 {
> +			compatible = "adi,adg792a";
> +			reg = <0x50>;
> +			#mux-control-cells = <0>;
> +			adi,parallel;
> +		};
> +	};
> +
> +	diff-adc-mux {
> +		compatible = "io-channel-mux";
> +		io-channels = <&adc 0>;
> +		io-channel-names = "parent";
> +
> +		mux-controls = <&pmux>;
> +
> +		channels = "sync-1", "", "out";
> +	};
> 

^ permalink raw reply

* Re: [PATCH v7 12/12] mux: adg792a: add mux controller driver for ADG792A/G
From: Jonathan Cameron @ 2017-01-08 10:32 UTC (permalink / raw)
  To: Peter Rosin, linux-kernel
  Cc: Wolfram Sang, Rob Herring, Mark Rutland, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Jonathan Corbet,
	Arnd Bergmann, Greg Kroah-Hartman, linux-i2c, devicetree,
	linux-iio, linux-doc
In-Reply-To: <1483532187-28494-13-git-send-email-peda@axentia.se>

On 04/01/17 12:16, Peter Rosin wrote:
> Analog Devices ADG792A/G is a triple 4:1 mux.
> 
> Signed-off-by: Peter Rosin <peda@axentia.se>
Reviewed-by: Jonathan Cameron <jic23@kernel.org>

A nice little driver.  Hopefully this example will do the job of
convincing people a subsystem makes sense!

Jonathan
> ---
>  drivers/mux/Kconfig       |  12 ++++
>  drivers/mux/Makefile      |   1 +
>  drivers/mux/mux-adg792a.c | 169 ++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 182 insertions(+)
>  create mode 100644 drivers/mux/mux-adg792a.c
> 
> diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig
> index de5a35ffe7af..39b06e19aa96 100644
> --- a/drivers/mux/Kconfig
> +++ b/drivers/mux/Kconfig
> @@ -16,6 +16,18 @@ menuconfig MULTIPLEXER
>  
>  if MULTIPLEXER
>  
> +config MUX_ADG792A
> +	tristate "Analog Devices ADG792A/ADG792G Multiplexers"
> +	depends on I2C
> +	help
> +	  ADG792A and ADG792G Wide Bandwidth Triple 4:1 Multiplexers
> +
> +	  The driver supports both operating the three multiplexers in
> +	  parallel and operating them independently.
> +
> +	  To compile the driver as a module, choose M here: the module will
> +	  be called mux-adg792a.
> +
>  config MUX_GPIO
>  	tristate "GPIO-controlled Multiplexer"
>  	depends on OF && GPIOLIB
> diff --git a/drivers/mux/Makefile b/drivers/mux/Makefile
> index facc43da3648..fddbb073fc77 100644
> --- a/drivers/mux/Makefile
> +++ b/drivers/mux/Makefile
> @@ -3,4 +3,5 @@
>  #
>  
>  obj-$(CONFIG_MULTIPLEXER)      	+= mux-core.o
> +obj-$(CONFIG_MUX_ADG792A)	+= mux-adg792a.o
>  obj-$(CONFIG_MUX_GPIO)		+= mux-gpio.o
> diff --git a/drivers/mux/mux-adg792a.c b/drivers/mux/mux-adg792a.c
> new file mode 100644
> index 000000000000..c6d5c4571e7c
> --- /dev/null
> +++ b/drivers/mux/mux-adg792a.c
> @@ -0,0 +1,169 @@
> +/*
> + * Multiplexer driver for Analog Devices ADG792A/G Triple 4:1 mux
> + *
> + * Copyright (C) 2016 Axentia Technologies AB
> + *
> + * Author: Peter Rosin <peda@axentia.se>
> + *
> + * 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/err.h>
> +#include <linux/i2c.h>
> +#include <linux/module.h>
> +#include <linux/mux.h>
> +
> +#define ADG792A_LDSW		BIT(0)
> +#define ADG792A_RESET		BIT(1)
> +#define ADG792A_DISABLE(mux)	(0x50 | (mux))
> +#define ADG792A_DISABLE_ALL	(0x5f)
> +#define ADG792A_MUX(mux, state)	(0xc0 | (((mux) + 1) << 2) | (state))
> +#define ADG792A_MUX_ALL(state)	(0xc0 | (state))
> +
> +#define ADG792A_DISABLE_STATE	(4)
> +
> +static int adg792a_set(struct mux_control *mux, int state)
> +{
> +	struct i2c_client *i2c = to_i2c_client(mux->chip->dev.parent);
> +	u8 cmd;
> +
> +	if (mux->chip->controllers == 1) {
> +		/* parallel mux controller operation */
> +		if (state == ADG792A_DISABLE_STATE)
> +			cmd = ADG792A_DISABLE_ALL;
> +		else
> +			cmd = ADG792A_MUX_ALL(state);
> +	} else {
> +		unsigned int controller = mux_control_get_index(mux);
> +
> +		if (state == ADG792A_DISABLE_STATE)
> +			cmd = ADG792A_DISABLE(controller);
> +		else
> +			cmd = ADG792A_MUX(controller, state);
> +	}
> +
> +	return i2c_smbus_write_byte_data(i2c, cmd, ADG792A_LDSW);
> +}
> +
> +static const struct mux_control_ops adg792a_ops = {
> +	.set = adg792a_set,
> +};
> +
> +static int adg792a_probe(struct i2c_client *i2c,
> +			 const struct i2c_device_id *id)
> +{
> +	struct device *dev = &i2c->dev;
> +	struct mux_chip *mux_chip;
> +	bool parallel;
> +	int count;
> +	int ret;
> +	int i;
> +
> +	parallel = of_property_read_bool(i2c->dev.of_node, "adi,parallel");
> +
> +	mux_chip = devm_mux_chip_alloc(dev, parallel ? 1 : 3, 0);
> +	if (!mux_chip)
> +		return -ENOMEM;
> +
> +	mux_chip->ops = &adg792a_ops;
> +
> +	ret = i2c_smbus_write_byte_data(i2c, ADG792A_DISABLE_ALL,
> +					ADG792A_RESET | ADG792A_LDSW);
> +	if (ret < 0)
> +		return ret;
> +
> +	for (i = 0; i < mux_chip->controllers; ++i) {
> +		struct mux_control *mux = &mux_chip->mux[i];
> +
> +		mux->states = 4;
> +	}
> +
> +	count = of_property_count_u32_elems(dev->of_node, "adi,idle-state");
> +	for (i = 0; i < count; i += 2) {
> +		u32 index;
> +		u32 idle_state;
> +
> +		ret = of_property_read_u32_index(dev->of_node,
> +						 "adi,idle-state", i,
> +						 &index);
> +		if (ret < 0)
> +			return ret;
> +		if (index >= mux_chip->controllers) {
> +			dev_err(dev, "invalid mux %u\n", index);
> +			return -EINVAL;
> +		}
> +
> +		ret = of_property_read_u32_index(dev->of_node,
> +						 "adi,idle-state", i + 1,
> +						 &idle_state);
> +		if (ret < 0)
> +			return ret;
> +		if (idle_state >= ADG792A_DISABLE_STATE) {
> +			dev_err(dev, "invalid idle-state %u for mux %u\n",
> +				idle_state, index);
> +			return -EINVAL;
> +		}
> +		mux_chip->mux[index].idle_state = idle_state;
> +	}
> +
> +	count = of_property_count_u32_elems(dev->of_node,
> +					    "adi,idle-high-impedance");
> +	for (i = 0; i < count; ++i) {
> +		u32 index;
> +
> +		ret = of_property_read_u32_index(dev->of_node,
> +						 "adi,idle-high-impedance", i,
> +						 &index);
> +		if (ret < 0)
> +			return ret;
> +		if (index >= mux_chip->controllers) {
> +			dev_err(dev, "invalid mux %u\n", index);
> +			return -EINVAL;
> +		}
> +
> +		mux_chip->mux[index].idle_state = ADG792A_DISABLE_STATE;
> +	}
> +
> +	ret = devm_mux_chip_register(dev, mux_chip);
> +	if (ret < 0) {
> +		dev_err(dev, "failed to register mux-chip\n");
> +		return ret;
> +	}
> +
> +	if (parallel)
> +		dev_info(dev, "triple pole quadruple throw mux registered\n");
> +	else
> +		dev_info(dev, "3x single pole quadruple throw muxes registered\n");
> +
> +	return 0;
> +}
> +
> +static const struct i2c_device_id adg792a_id[] = {
> +	{ .name = "adg792a", },
> +	{ .name = "adg792g", },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(i2c, adg792a_id);
> +
> +static const struct of_device_id adg792a_of_match[] = {
> +	{ .compatible = "adi,adg792a", },
> +	{ .compatible = "adi,adg792g", },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(of, adg792a_of_match);
> +
> +static struct i2c_driver adg792a_driver = {
> +	.driver		= {
> +		.name		= "adg792a",
> +		.of_match_table = of_match_ptr(adg792a_of_match),
> +	},
> +	.probe		= adg792a_probe,
> +	.id_table	= adg792a_id,
> +};
> +module_i2c_driver(adg792a_driver);
> +
> +MODULE_DESCRIPTION("Analog Devices ADG792A/G Triple 4:1 mux driver");
> +MODULE_AUTHOR("Peter Rosin <peda@axentia.se");
> +MODULE_LICENSE("GPL v2");
> 

^ permalink raw reply

* Re: [PATCH 08/22] power: supply: add AC power supply driver for AXP20X and AXP22X PMICs
From: Quentin Schulz @ 2017-01-08 10:41 UTC (permalink / raw)
  To: Jonathan Cameron, knaack.h, lars, pmeerw, robh+dt, mark.rutland,
	wens, sre, linux, maxime.ripard, lee.jones
  Cc: thomas.petazzoni, devicetree, linux-pm, linux-iio, linux-kernel,
	bonbons, icenowy, linux-arm-kernel
In-Reply-To: <d6661ff6-442c-5535-aec2-35066577f119@kernel.org>

Hi Jonathan,

On 07/01/2017 20:31, Jonathan Cameron wrote:
> On 02/01/17 11:37, Quentin Schulz wrote:
[...]
>> +		/*
>> +		 * IIO framework gives mV but Power Supply framework gives µV.
>> +		 */
> single line comment syntax throughout or we'll have to face a patch 'fixing' it.

I actually had to make it a multiple lines comment to make checkpatch
happy. Maybe there is something with the encoding of the µ symbol? I'll
retry with a u instead and let you know.

[...]

Thanks,
Quentin

-- 
Quentin Schulz, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH v7 10/12] i2c: i2c-mux-simple: new driver
From: Wolfram Sang @ 2017-01-08 10:44 UTC (permalink / raw)
  To: Peter Rosin
  Cc: linux-kernel, Rob Herring, Mark Rutland, Jonathan Cameron,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Jonathan Corbet, Arnd Bergmann, Greg Kroah-Hartman, linux-i2c,
	devicetree, linux-iio, linux-doc
In-Reply-To: <1483532187-28494-11-git-send-email-peda@axentia.se>

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

On Wed, Jan 04, 2017 at 01:16:25PM +0100, Peter Rosin wrote:
> This is a generic simple i2c mux that uses the generic multiplexer
> subsystem to do the muxing.
> 
> The user can select if the mux is to be mux-locked and parent-locked
> as described in Documentation/i2c/i2c-topology.
> 
> Acked-by: Jonathan Cameron <jic23@kernel.org>
> Signed-off-by: Peter Rosin <peda@axentia.se>

Acked-by: Wolfram Sang <wsa@the-dreams.de>


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

^ permalink raw reply

* Re: [PATCH 14/22] dt-bindings: power: supply: add AXP20X/AXP22X battery DT binding
From: Quentin Schulz @ 2017-01-08 10:48 UTC (permalink / raw)
  To: Jonathan Cameron, Rob Herring
  Cc: mark.rutland, devicetree, lars, linux-pm, linux-iio, linux-kernel,
	sre, linux, wens, icenowy, pmeerw, knaack.h, maxime.ripard,
	bonbons, lee.jones, thomas.petazzoni, linux-arm-kernel
In-Reply-To: <3155ba16-b51a-9306-6be4-0bdf4482a679@kernel.org>

Hi Jonathan,

On 07/01/2017 20:33, Jonathan Cameron wrote:
> On 04/01/17 08:21, Rob Herring wrote:
>> On Mon, Jan 02, 2017 at 05:37:14PM +0100, Quentin Schulz wrote:
>>> The X-Powers AXP20X and AXP22X PMICs can have a battery as power supply.
>>>
>>> This patch adds the DT binding documentation for the battery power
>>> supply which gets various data from the PMIC, such as the battery status
>>> (charging, discharging, full, dead), current max limit, current current,
>>> battery capacity (in percentage), voltage max and min limits, current
>>> voltage and battery capacity (in Ah).
>>>
>>> Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
>>> ---
>>>  .../bindings/power/supply/axp20x_battery.txt       | 27 ++++++++++++++++++++++
>>>  1 file changed, 27 insertions(+)
>>>  create mode 100644 Documentation/devicetree/bindings/power/supply/axp20x_battery.txt
>>>
>>> diff --git a/Documentation/devicetree/bindings/power/supply/axp20x_battery.txt b/Documentation/devicetree/bindings/power/supply/axp20x_battery.txt
>>> new file mode 100644
>>> index 0000000..5489d0d
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/power/supply/axp20x_battery.txt
>>> @@ -0,0 +1,27 @@
>>> +AXP20x and AXP22x battery power supply
>>> +
>>> +Required Properties:
>>> + - compatible, one of:
>>> +			"x-powers,axp209-battery-power-supply"
>>> +			"x-powers,axp221-battery-power-supply"
>>> + - io-channels: phandles to battery voltage, charge and discharge
>>> + currents ADC channels
>>> + - io-channel-names = "batt_v", "batt_chrg_i", "batt_dischrg_i";
>>> +
>>> +This node is a subnode of the axp20x/axp22x PMIC.
>>> +
>>> +The AXP20X and AXP22X can read the battery voltage, charge and discharge
>>> +currents of the battery by reading ADC channels from the AXP20X/AXP22X
>>> +ADC.
>>> +
>>> +Example:
>>> +
>>> +&axp209 {
>>> +	battery_power_supply: battery_power_supply {
>>
>> Humm, I guess you power-supply is not sufficient, so 
>> 'battery-power-supply' and similar for ac.
>>
>>> +		compatible = "x-powers,axp209-battery-power-supply";
>>> +		io-channels = <&axp209_adc 7>, <&axp209_adc 8>,
>>> +			<&axp209_adc 9>;
>>> +		io-channel-names = "batt_v", "batt_chrg_i",
>>> +			"batt_dischrg_i";
> Is this stuff fixed for the device?

If we don't mix the IIO channels order, it is. This driver only requires
batt_v, batt_chrg_i and batt_dischrg_i so we've to keep them at that
place in the list of IIO channels. Or as suggested by Rob and Chen-Yu, I
can move all this inside the driver with iio_map and don't care anymore
about the order.

Thanks,
Quentin

-- 
Quentin Schulz, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

^ permalink raw reply

* Re: [PATCH v7 00/12] mux controller abstraction and iio/i2c muxes
From: Wolfram Sang @ 2017-01-08 10:51 UTC (permalink / raw)
  To: Peter Rosin
  Cc: linux-kernel, Rob Herring, Mark Rutland, Jonathan Cameron,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Jonathan Corbet, Arnd Bergmann, Greg Kroah-Hartman, linux-i2c,
	devicetree, linux-iio, linux-doc
In-Reply-To: <1483532187-28494-1-git-send-email-peda@axentia.se>

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

Hi peda,

> One thing that I would like to do, but don't see a solution
> for, is to move the mux control code that is present in
> various drivers in drivers/i2c/muxes to this new minimalistic
> muxing subsystem, thus converting all present i2c muxes (but
> perhaps not gates and arbitrators) to be i2c-mux-simple muxes.

In a few lines, what is preventing that?

> I'm using an rwsem to lock a mux, but that isn't really a
> perfect fit. Is there a better locking primitive that I don't
> know about that fits better? I had a mutex at one point, but
> that didn't allow any concurrent accesses at all. At least
> the rwsem allows concurrent access as long as all users
> agree on the mux state, but I suspect that the rwsem will
> degrade to the mutex situation pretty quickly if there is
> any contention.

Maybe ask this question in a seperate email thread on lkml cc-ing the
locking gurus (with a pointer to this thread)?

> Also, the "mux" name feels a bit ambitious, there are many muxes
> in the world, and this tiny bit of code is probably not good
> enough to be a nice fit for all...

"... and it probably never will support anything other than
AT-harddisks, as that's all I have..." ;))

Thanks for this work!

   Wolfram


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

^ permalink raw reply

* Re: [PATCH v3] iio:temperature: Add support for TI TMP007 sensor
From: Jonathan Cameron @ 2017-01-08 10:56 UTC (permalink / raw)
  To: Mani Sadhasivam, pmeerw-jW+XmwGofnusTnJN9+BGXg
  Cc: linux-iio-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20170106025006.GA9832-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

On 06/01/17 02:50, Mani Sadhasivam wrote:
> This patch adds support for TI TMP007 - 16 bit IR thermopile sensor with integrated Math engine.
> Sensor takes care of calculating the object temperature with the help of calibrated constants stored in non-volatile memory,
> thereby reducing the calculation overhead.
> 
> Signed-off-by: Manivannan Sadhasivam <manivannanece23-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Pretty good.  A few minor comments inline.  It 'might' be worth using
regmap for this part to avoid hand rolling masked partial register writes
and caching of register values.  Perhaps it's not worth it for such a
simple interface however.

Jonathan
> ---
> 
> Changes in v3 (based on suggestions from Peter):
> 
> 1. Added data validity check for TObj
> 2. Modified the comment style
> 3. Added powerdown function
> 4. Some code cleanups
> 
>  .../devicetree/bindings/iio/temperature/tmp007.txt |  16 +
>  drivers/iio/temperature/Kconfig                    |  10 +
>  drivers/iio/temperature/Makefile                   |   1 +
>  drivers/iio/temperature/tmp007.c                   | 345 +++++++++++++++++++++
>  4 files changed, 372 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/iio/temperature/tmp007.txt
>  create mode 100644 drivers/iio/temperature/tmp007.c
> 
> diff --git a/Documentation/devicetree/bindings/iio/temperature/tmp007.txt b/Documentation/devicetree/bindings/iio/temperature/tmp007.txt
> new file mode 100644
> index 0000000..9ae0519
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/iio/temperature/tmp007.txt
> @@ -0,0 +1,16 @@
> +* TI TMP007 - IR thermopile sensor with integrated math engine
> +
> +Link to datasheet: http://www.ti.com/lit/ds/symlink/tmp007.pdf
> +
> +Required properties:
> +
> +  - compatible: should be "ti,tmp007"
> +  - reg: the I2C address of the sensor (changeable via ADR pins)
Perhaps list the options that are possible?
> +
> +Example:
> +
> +tmp007@40 {
> +        compatible = "ti,tmp007";
> +        reg = <0x40>;
> +};
> +
> diff --git a/drivers/iio/temperature/Kconfig b/drivers/iio/temperature/Kconfig
> index c4664e5..538ce9e 100644
> --- a/drivers/iio/temperature/Kconfig
> +++ b/drivers/iio/temperature/Kconfig
> @@ -23,6 +23,16 @@ config TMP006
>  	  This driver can also be built as a module. If so, the module will
>  	  be called tmp006.
>  
> +config TMP007
> +        tristate "TMP007 infrared thermopile sensor with Integrated Math Engine"
> +        depends on I2C
> +        help
> +          If you say yes here you get support for the Texas Instruments
> +          TMP007 infrared thermopile sensor with Integrated Math Engine.
> +
> +          This driver can also be built as a module. If so, the module will
> +          be called tmp007.
> +
>  config TSYS01
>  	tristate "Measurement Specialties TSYS01 temperature sensor using I2C bus connection"
>  	depends on I2C
> diff --git a/drivers/iio/temperature/Makefile b/drivers/iio/temperature/Makefile
> index 02bc79d..f0cf5c5 100644
> --- a/drivers/iio/temperature/Makefile
> +++ b/drivers/iio/temperature/Makefile
> @@ -4,5 +4,6 @@
>  
>  obj-$(CONFIG_MLX90614) += mlx90614.o
>  obj-$(CONFIG_TMP006) += tmp006.o
> +obj-$(CONFIG_TMP007) += tmp007.o
>  obj-$(CONFIG_TSYS01) += tsys01.o
>  obj-$(CONFIG_TSYS02D) += tsys02d.o
> diff --git a/drivers/iio/temperature/tmp007.c b/drivers/iio/temperature/tmp007.c
> new file mode 100644
> index 0000000..a385ef5
> --- /dev/null
> +++ b/drivers/iio/temperature/tmp007.c
> @@ -0,0 +1,345 @@
> +/*
> + * tmp007.c - Support for TI TMP007 IR thermopile sensor with integrated math engine
> + *
> + * Copyright (c) 2017 Manivannan Sadhasivam <manivannanece23-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> + *
> + * This file is subject to the terms and conditions of version 2 of
> + * the GNU General Public License.  See the file COPYING in the main
> + * directory of this archive for more details.
> + *
> + * Driver for the Texas Instruments I2C 16-bit IR thermopile sensor
> + *
> + * (7-bit I2C slave address (0x40 - 0x47), changeable via ADR pins)
> + *
> + * Note: This driver assumes that the sensor has been calibrated beforehand
> + *
> + * TODO: ALERT irq, limit threshold events
> + *
> + */
> +
> +#include <linux/err.h>
> +#include <linux/i2c.h>
> +#include <linux/delay.h>
> +#include <linux/module.h>
> +#include <linux/pm.h>
> +#include <linux/bitops.h>
> +#include <linux/of.h>
> +
> +#include <linux/iio/iio.h>
> +#include <linux/iio/sysfs.h>
> +
> +#define TMP007_TDIE 0x01
> +#define TMP007_CONFIG 0x02
> +#define TMP007_TOBJECT 0x03
> +#define TMP007_STATUS 0x04
> +#define TMP007_STATUS_MASK 0x05
> +#define TMP007_MANUFACTURER_ID 0x1e
> +#define TMP007_DEVICE_ID 0x1f
> +
> +#define TMP007_CONFIG_CONV_EN BIT(12)
> +#define TMP007_CONFIG_COMP_EN BIT(5)
> +#define TMP007_CONFIG_TC_EN BIT(6)
> +#define TMP007_CONFIG_CR_MASK GENMASK(11, 9)
> +#define TMP007_CONFIG_CR_SHIFT 9
> +
> +#define TMP007_STATUS_CONV_READY BIT(14)
> +#define TMP007_STATUS_DATA_VALID BIT(9)
> +
> +#define TMP007_MANUFACTURER_MAGIC 0x5449
> +#define TMP007_DEVICE_MAGIC 0x0078
> +
> +#define TMP007_TEMP_SHIFT 2
> +
> +struct tmp007_data {
> +	struct i2c_client *client;

The fact you are caching values here and that everything is register
based suggests to me that it might make sense to use regmap and take
advantage of it's built in caching and masked write functions.

If you pefer to stick to direct smbus calls that is fine.

> +	u16 config;

> +	u16 status_mask;
Why cache this register?  It is directly read then written
whenever used.

> +};
> +
> +static const int tmp007_avgs[5][2] = { {4, 0}, {2, 0}, {1, 0},
> +					{0, 500000}, {0, 250000} };
> +
> +static int tmp007_read_temperature(struct tmp007_data *data, u8 reg)
> +{
> +	s32 ret;
> +	int tries = 50;
> +
> +	while (tries-- > 0) {
> +		ret = i2c_smbus_read_word_swapped(data->client,
> +			TMP007_STATUS);
> +		if (ret < 0)
> +			return ret;
> +		if ((ret & TMP007_STATUS_CONV_READY) &&
> +			!(ret & TMP007_STATUS_DATA_VALID))
> +				break;
> +		msleep(100);
> +	}
> +
> +	if (tries < 0)
> +		return -EIO;
> +
> +	return i2c_smbus_read_word_swapped(data->client, reg);
> +}
> +
> +static int tmp007_powerdown(struct tmp007_data *data)
> +{
> +	return i2c_smbus_write_word_swapped(data->client, TMP007_CONFIG,
> +			data->config & ~TMP007_CONFIG_CONV_EN);
> +}
> +
> +static int tmp007_read_raw(struct iio_dev *indio_dev,
> +		struct iio_chan_spec const *channel, int *val,
> +		int *val2, long mask)
> +{
> +	struct tmp007_data *data = iio_priv(indio_dev);
> +	s32 ret;
> +	int conv_rate;
> +
> +	switch (mask) {
> +	case IIO_CHAN_INFO_RAW:
> +		switch (channel->channel2) {
> +		case IIO_MOD_TEMP_AMBIENT: /* LSB: 0.03125 degree Celsius */
> +			ret = i2c_smbus_read_word_swapped(data->client, TMP007_TDIE);
> +			if (ret < 0)
> +				return ret;
> +			break;
> +		case IIO_MOD_TEMP_OBJECT:
> +			ret = tmp007_read_temperature(data, TMP007_TOBJECT);
> +			if (ret < 0)
> +				return ret;
> +			break;
> +		default:
> +			return -EINVAL;
> +		}
> +
> +		*val = sign_extend32(ret, 15) >> TMP007_TEMP_SHIFT;
> +
> +		return IIO_VAL_INT;
> +	case IIO_CHAN_INFO_SCALE:
> +		*val = 31;
> +		*val2 = 250000;
> +
> +		return IIO_VAL_INT_PLUS_MICRO;
> +	case IIO_CHAN_INFO_SAMP_FREQ:
> +		conv_rate = (data->config & TMP007_CONFIG_CR_MASK)
> +				>> TMP007_CONFIG_CR_SHIFT;
> +		*val = tmp007_avgs[conv_rate][0];
> +		*val2 = tmp007_avgs[conv_rate][1];
> +
> +		return IIO_VAL_INT_PLUS_MICRO;
> +	default:
> +		return -EINVAL;
> +	}
> +}
> +
> +static int tmp007_write_raw(struct iio_dev *indio_dev,
> +		struct iio_chan_spec const *channel, int val,
> +		int val2, long mask)
> +{
> +	struct tmp007_data *data = iio_priv(indio_dev);
> +	int i;
> +	u16 tmp;
> +
> +	if (mask == IIO_CHAN_INFO_SAMP_FREQ) {
> +		for (i = 0; i < ARRAY_SIZE(tmp007_avgs); i++) {
> +			if ((val == tmp007_avgs[i][0]) &&
> +			(val2 == tmp007_avgs[i][1])) {
> +				tmp = data->config & ~TMP007_CONFIG_CR_MASK;
> +				tmp |= (i << TMP007_CONFIG_CR_SHIFT);
> +
> +				return i2c_smbus_write_word_swapped(data->client,
> +								TMP007_CONFIG,
> +								data->config = tmp);
> +			}
> +		}
> +	}
> +
> +	return -EINVAL;
> +}
> +
> +static IIO_CONST_ATTR(sampling_frequency_available, "4 2 1 0.5 0.25");
> +
> +static struct attribute *tmp007_attributes[] = {
> +	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
> +	NULL
> +};
> +
> +static const struct attribute_group tmp007_attribute_group = {
> +	.attrs = tmp007_attributes,
> +};
> +
> +static const struct iio_chan_spec tmp007_channels[] = {
> +	{
> +		.type = IIO_TEMP,
> +		.modified = 1,
> +		.channel2 = IIO_MOD_TEMP_AMBIENT,
> +		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
> +				BIT(IIO_CHAN_INFO_SCALE),
> +		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
> +	},
> +	{
> +		.type = IIO_TEMP,
> +		.modified = 1,
> +		.channel2 = IIO_MOD_TEMP_OBJECT,
> +		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
> +				BIT(IIO_CHAN_INFO_SCALE),
> +		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
> +	}
> +};
> +
> +static const struct iio_info tmp007_info = {
> +	.read_raw = tmp007_read_raw,
> +	.write_raw = tmp007_write_raw,
> +	.attrs = &tmp007_attribute_group,
> +	.driver_module = THIS_MODULE,
> +};
> +
> +static bool tmp007_identify(struct i2c_client *client)
> +{
> +	int manf_id, dev_id;
> +
> +	manf_id = i2c_smbus_read_word_swapped(client, TMP007_MANUFACTURER_ID);
> +	if (manf_id < 0)
> +		return false;
> +
> +	dev_id = i2c_smbus_read_word_swapped(client, TMP007_DEVICE_ID);
> +	if (dev_id < 0)
> +		return false;
> +
> +	return (manf_id == TMP007_MANUFACTURER_MAGIC && dev_id == TMP007_DEVICE_MAGIC);
> +}
> +
> +static int tmp007_probe(struct i2c_client *client,
> +			const struct i2c_device_id *tmp007_id)
> +{
> +	struct tmp007_data *data;
> +	struct iio_dev *indio_dev;
> +	int ret;
> +
> +	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
> +		return -EOPNOTSUPP;
> +
> +	if (!tmp007_identify(client)) {
> +		dev_err(&client->dev, "TMP007 not found\n");
> +		return -ENODEV;
> +	}
> +
> +	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
> +	if (!indio_dev)
> +		return -ENOMEM;
> +
> +	data = iio_priv(indio_dev);
> +	i2c_set_clientdata(client, indio_dev);
> +	data->client = client;
> +
> +	indio_dev->dev.parent = &client->dev;
> +	indio_dev->name = dev_name(&client->dev);
> +	indio_dev->modes = INDIO_DIRECT_MODE;
> +	indio_dev->info = &tmp007_info;
> +
> +	indio_dev->channels = tmp007_channels;
> +	indio_dev->num_channels = ARRAY_SIZE(tmp007_channels);
> +
> +	/*
> +	 * Set Configuration register:
> +	 * 1. Conversion ON
> +	 * 2. Comparator mode
> +	 * 3. Transient correction enable
> +	 */
> +
> +	ret = i2c_smbus_read_word_swapped(data->client, TMP007_CONFIG);
> +	if (ret < 0)
> +		return ret;
> +
> +	data->config = ret;
> +	data->config |= (TMP007_CONFIG_CONV_EN | TMP007_CONFIG_COMP_EN | TMP007_CONFIG_TC_EN);
> +
> +	ret = i2c_smbus_write_word_swapped(data->client, TMP007_CONFIG,
> +					data->config);
> +	if (ret < 0)
> +		return ret;
> +
> +	/*
> +	 * Set Status Mask register:
> +	 * 1. Conversion ready enable
2. Data valid?
> +	 */
> +
> +	ret = i2c_smbus_read_word_swapped(data->client, TMP007_STATUS_MASK);
> +	if (ret < 0)
> +		goto error_powerdown;
> +
> +	data->status_mask = ret;
> +	data->status_mask |= (TMP007_STATUS_CONV_READY | TMP007_STATUS_DATA_VALID);
> +
> +	ret = i2c_smbus_write_word_swapped(data->client, TMP007_STATUS_MASK,
> +					data->status_mask);
> +	if (ret < 0)
> +		goto error_powerdown;
> +
> +	return iio_device_register(indio_dev);
> +
> +error_powerdown:
> +	tmp007_powerdown(data);
> +
> +	return ret;
> +}
> +
> +static int tmp007_remove(struct i2c_client *client)
> +{
> +	struct iio_dev *indio_dev = i2c_get_clientdata(client);
> +	struct tmp007_data *data = iio_priv(indio_dev);
> +
> +	iio_device_unregister(indio_dev);
> +	tmp007_powerdown(data);
> +
> +	return 0;
> +}
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int tmp007_suspend(struct device *dev)
> +{
> +	struct tmp007_data *data = iio_priv(i2c_get_clientdata(
> +			to_i2c_client(dev)));
> +
> +	return tmp007_powerdown(data);
> +}
> +
> +static int tmp007_resume(struct device *dev)
> +{
> +	struct tmp007_data *data = iio_priv(i2c_get_clientdata(
> +			to_i2c_client(dev)));
> +
> +	return i2c_smbus_write_word_swapped(data->client, TMP007_CONFIG,
> +			data->config | TMP007_CONFIG_CONV_EN);
> +}
> +#endif
> +
> +static SIMPLE_DEV_PM_OPS(tmp007_pm_ops, tmp007_suspend, tmp007_resume);
> +
> +static const struct of_device_id tmp007_of_match[] = {
> +	{ .compatible = "ti,tmp007", },
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, tmp007_of_match);
> +
> +static const struct i2c_device_id tmp007_id[] = {
> +	{ "tmp007", 0 },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(i2c, tmp007_id);
> +
> +static struct i2c_driver tmp007_driver = {
> +	.driver = {
> +		.name	= "tmp007",
> +		.of_match_table = of_match_ptr(tmp007_of_match),
> +		.pm	= &tmp007_pm_ops,
> +	},
> +	.probe		= tmp007_probe,
> +	.remove		= tmp007_remove,
> +	.id_table	= tmp007_id,
> +};
> +module_i2c_driver(tmp007_driver);
> +
> +MODULE_AUTHOR("Manivannan Sadhasivam <manivannanece23-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>");
> +MODULE_DESCRIPTION("TI TMP007 IR thermopile sensor driver");
> +MODULE_LICENSE("GPL");
> 

--
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 14/22] dt-bindings: power: supply: add AXP20X/AXP22X battery DT binding
From: Jonathan Cameron @ 2017-01-08 10:59 UTC (permalink / raw)
  To: Quentin Schulz, Rob Herring
  Cc: mark.rutland, devicetree, lars, linux-pm, linux-iio, linux-kernel,
	sre, linux, wens, icenowy, pmeerw, knaack.h, maxime.ripard,
	bonbons, lee.jones, thomas.petazzoni, linux-arm-kernel
In-Reply-To: <4a8456e6-c6e9-73ac-0f5c-29e9faceb13c@free-electrons.com>

On 08/01/17 10:48, Quentin Schulz wrote:
> Hi Jonathan,
> 
> On 07/01/2017 20:33, Jonathan Cameron wrote:
>> On 04/01/17 08:21, Rob Herring wrote:
>>> On Mon, Jan 02, 2017 at 05:37:14PM +0100, Quentin Schulz wrote:
>>>> The X-Powers AXP20X and AXP22X PMICs can have a battery as power supply.
>>>>
>>>> This patch adds the DT binding documentation for the battery power
>>>> supply which gets various data from the PMIC, such as the battery status
>>>> (charging, discharging, full, dead), current max limit, current current,
>>>> battery capacity (in percentage), voltage max and min limits, current
>>>> voltage and battery capacity (in Ah).
>>>>
>>>> Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
>>>> ---
>>>>  .../bindings/power/supply/axp20x_battery.txt       | 27 ++++++++++++++++++++++
>>>>  1 file changed, 27 insertions(+)
>>>>  create mode 100644 Documentation/devicetree/bindings/power/supply/axp20x_battery.txt
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/power/supply/axp20x_battery.txt b/Documentation/devicetree/bindings/power/supply/axp20x_battery.txt
>>>> new file mode 100644
>>>> index 0000000..5489d0d
>>>> --- /dev/null
>>>> +++ b/Documentation/devicetree/bindings/power/supply/axp20x_battery.txt
>>>> @@ -0,0 +1,27 @@
>>>> +AXP20x and AXP22x battery power supply
>>>> +
>>>> +Required Properties:
>>>> + - compatible, one of:
>>>> +			"x-powers,axp209-battery-power-supply"
>>>> +			"x-powers,axp221-battery-power-supply"
>>>> + - io-channels: phandles to battery voltage, charge and discharge
>>>> + currents ADC channels
>>>> + - io-channel-names = "batt_v", "batt_chrg_i", "batt_dischrg_i";
>>>> +
>>>> +This node is a subnode of the axp20x/axp22x PMIC.
>>>> +
>>>> +The AXP20X and AXP22X can read the battery voltage, charge and discharge
>>>> +currents of the battery by reading ADC channels from the AXP20X/AXP22X
>>>> +ADC.
>>>> +
>>>> +Example:
>>>> +
>>>> +&axp209 {
>>>> +	battery_power_supply: battery_power_supply {
>>>
>>> Humm, I guess you power-supply is not sufficient, so 
>>> 'battery-power-supply' and similar for ac.
>>>
>>>> +		compatible = "x-powers,axp209-battery-power-supply";
>>>> +		io-channels = <&axp209_adc 7>, <&axp209_adc 8>,
>>>> +			<&axp209_adc 9>;
>>>> +		io-channel-names = "batt_v", "batt_chrg_i",
>>>> +			"batt_dischrg_i";
>> Is this stuff fixed for the device?
> 
> If we don't mix the IIO channels order, it is. This driver only requires
> batt_v, batt_chrg_i and batt_dischrg_i so we've to keep them at that
> place in the list of IIO channels. Or as suggested by Rob and Chen-Yu, I
> can move all this inside the driver with iio_map and don't care anymore
> about the order.
> 
I'd do that. Makes life easier to represented fixed things as fixed!
> Thanks,
> Quentin
> 

^ 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