Devicetree
 help / color / mirror / Atom feed
* Re: [PATCH 0/4] Drop drivers for Exynos4415
From: Kukjin Kim @ 2017-01-15  2:00 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Sylwester Nawrocki, Tomasz Figa, Chanwoo Choi, Michael Turquette,
	Stephen Boyd, Rob Herring, Mark Rutland, Kukjin Kim,
	Javier Martinez Canillas, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Kyungmin Park, Linus Walleij, linux-samsung-soc, linux-clk,
	devicetree, linux-arm-kernel, linux-kernel, dri-devel, linux-gpio
In-Reply-To: <20170114123642.15581-1-krzk@kernel.org>

Hi Krzk,

2017. 1. 14. PM 8:36 Krzysztof Kozlowski <krzk@kernel.org> wrote:

> Hi,
> 
> Support for Exynos4415 is being removed because:
> 1. There are no upstream users,
> 2. There are no known downstream users,
> 3. Except compile testing, you cannot build working kernel
>   for Exynos4415 anymore.
> 
> Patches are rebased on current next and are independent.
> Please pick up as you wish.
> 
> Best regards,
> Krzysztof

Agreed,

Acked-by: Kukjin Kim <kgene@kernel.org>

k-gene
> 
> Krzysztof Kozlowski (4):
>  ARM: EXYNOS: Remove Exynos4415 driver (SoC not supported anymore)
>  clk: samsung: Remove Exynos4415 driver (SoC not supported anymore)
>  pinctrl: samsung: Remove support for Exynos4415 (SoC not supported
>    anymore)
>  drm: exynos: Remove support for Exynos4415 (SoC not supported anymore)
> 
> .../devicetree/bindings/clock/exynos4415-clock.txt |   38 -
> .../bindings/display/exynos/exynos_dsim.txt        |    1 -
> .../bindings/display/exynos/samsung-fimd.txt       |    1 -
> arch/arm/mach-exynos/Kconfig                       |    5 -
> arch/arm/mach-exynos/exynos.c                      |    1 -
> arch/arm/mach-exynos/suspend.c                     |    1 -
> drivers/clk/samsung/Makefile                       |    1 -
> drivers/clk/samsung/clk-exynos4415.c               | 1022 --------------------
> drivers/gpu/drm/exynos/exynos_drm_dsi.c            |   15 +-
> drivers/gpu/drm/exynos/exynos_drm_fimd.c           |   18 +-
> drivers/pinctrl/samsung/pinctrl-exynos.c           |   75 --
> drivers/pinctrl/samsung/pinctrl-samsung.c          |    2 -
> drivers/pinctrl/samsung/pinctrl-samsung.h          |    1 -
> include/dt-bindings/clock/exynos4415.h             |  360 -------
> 14 files changed, 3 insertions(+), 1538 deletions(-)
> delete mode 100644 Documentation/devicetree/bindings/clock/exynos4415-clock.txt
> delete mode 100644 drivers/clk/samsung/clk-exynos4415.c
> delete mode 100644 include/dt-bindings/clock/exynos4415.h
> 
> -- 
> 2.9.3
> 

^ permalink raw reply

* Re: [PATCH RFC v2 4/4] ARM: dts: imx6*-hummingboard2: convert to more conventional vmmc-supply
From: Fabio Estevam @ 2017-01-15  2:11 UTC (permalink / raw)
  To: Russell King
  Cc: Fabio Estevam, Sascha Hauer, Shawn Guo, Jon Nettleton,
	Mark Rutland, devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Rob Herring,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
In-Reply-To: <E1cS36q-0002wW-C3-eh5Bv4kxaXIk46pC+1QYvQNdhmdF6hFW@public.gmane.org>

On Fri, Jan 13, 2017 at 12:45 PM, Russell King
<rmk+kernel-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.org> wrote:

> +       reg_usdhc2_vmmc: reg-usdhc2-vmmc {
> +               compatible = "regulator-fixed";
> +               gpio = <&gpio4 30 GPIO_ACTIVE_HIGH>;
> +               pinctrl-names = "default";
> +               pinctrl-0 = <&pinctrl_hummingboard2_vmmc>;
> +               regulator-boot-on;
> +               regulator-max-microvolt = <3300000>;
> +               regulator-min-microvolt = <3300000>;
> +               regulator-name = "usdhc2_vmmc";
> +               startup-delay-us = <1000>;
> +       };
> +
>         sound-sgtl5000 {
>                 audio-codec = <&sgtl5000>;
>                 audio-routing =
> @@ -393,7 +400,6 @@
>
>                 pinctrl_hummingboard2_usdhc2_aux: hummingboard2-usdhc2-aux {
>                         fsl,pins = <
> -                               MX6QDL_PAD_GPIO_4__GPIO1_IO04    0x1f071
>                                 MX6QDL_PAD_KEY_ROW1__SD2_VSELECT 0x1b071
>                                 MX6QDL_PAD_DISP0_DAT9__GPIO4_IO30 0x1b0b0
>                         >;
> @@ -432,6 +438,12 @@
>                         >;
>                 };
>
> +               pinctrl_hummingboard2_vmmc: hummingboard2-vmmc {
> +                       fsl,pins = <
> +                               MX6QDL_PAD_GPIO_4__GPIO1_IO04    0x1f071

Shouldn't this be gpio4 30 instead?

> +                       >;
> +               };
> +
>                 pinctrl_hummingboard2_usdhc3: hummingboard2-usdhc3 {
>                         fsl,pins = <
>                                 MX6QDL_PAD_SD3_CMD__SD3_CMD    0x17059
> @@ -519,7 +531,7 @@
>                 &pinctrl_hummingboard2_usdhc2_aux
>                 &pinctrl_hummingboard2_usdhc2_200mhz
>         >;
> -       mmc-pwrseq = <&usdhc2_pwrseq>;
> +       vmmc-supply = <&reg_usdhc2_vmmc>;
>         cd-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;

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

^ permalink raw reply

* [PATCH 1/2] ARM: BCM5301X: Add DT for Luxul XAP-1410
From: Dan Haab @ 2017-01-15  2:29 UTC (permalink / raw)
  To: Florian Fainelli
  Cc: Mark Rutland, devicetree, Hauke Mehrtens, Rafał Miłecki,
	Russell King, Rob Herring, bcm-kernel-feedback-list, Dan Haab,
	linux-arm-kernel

Luxul XAP-1410 in a dual-band access point device based on BCM47081 with
serial flash. It has 3 LEDs and just one (reset) button.

Signed-off-by: Dan Haab <dhaab@luxul.com>
---
 arch/arm/boot/dts/Makefile                    |    1 +
 arch/arm/boot/dts/bcm47081-luxul-xap-1410.dts |   60 +++++++++++++++++++++++++
 2 files changed, 61 insertions(+)
 create mode 100644 arch/arm/boot/dts/bcm47081-luxul-xap-1410.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index cccdbcb..04fd8f0 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -83,6 +83,7 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \
 	bcm47081-asus-rt-n18u.dtb \
 	bcm47081-buffalo-wzr-600dhp2.dtb \
 	bcm47081-buffalo-wzr-900dhp.dtb \
+	bcm47081-luxul-xap-1410.dtb \
 	bcm4709-asus-rt-ac87u.dtb \
 	bcm4709-buffalo-wxr-1900dhp.dtb \
 	bcm4709-netgear-r7000.dtb \
diff --git a/arch/arm/boot/dts/bcm47081-luxul-xap-1410.dts b/arch/arm/boot/dts/bcm47081-luxul-xap-1410.dts
new file mode 100644
index 0000000..9b57598
--- /dev/null
+++ b/arch/arm/boot/dts/bcm47081-luxul-xap-1410.dts
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2017 Luxul Inc.
+ *
+ * Licensed under the ISC license.
+ */
+
+/dts-v1/;
+
+#include "bcm47081.dtsi"
+
+/ {
+	compatible = "luxul,xap-1410v1", "brcm,bcm47081", "brcm,bcm4708";
+	model = "Luxul XAP-1410 V1";
+
+	chosen {
+		bootargs = "console=ttyS0,115200";
+	};
+
+	memory {
+		reg = <0x00000000 0x08000000>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		5ghz {
+			label = "bcm53xx:blue:5ghz";
+			gpios = <&chipcommon 13 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "none";
+		};
+
+		2ghz {
+			label = "bcm53xx:blue:2ghz";
+			gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "none";
+		};
+
+		status {
+			label = "bcm53xx:green:status";
+			gpios = <&chipcommon 15 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "timer";
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		restart {
+			label = "Reset";
+			linux,code = <KEY_RESTART>;
+			gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>;
+		};
+	};
+};
+
+&spi_nor {
+	status = "okay";
+};
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH 2/2] ARM: BCM5301X: Add DT for Luxul XWR-1200
From: Dan Haab @ 2017-01-15  2:29 UTC (permalink / raw)
  To: Florian Fainelli
  Cc: Mark Rutland, devicetree, Hauke Mehrtens, Rafał Miłecki,
	Russell King, Rob Herring, bcm-kernel-feedback-list, Dan Haab,
	linux-arm-kernel
In-Reply-To: <1484447368-7622-1-git-send-email-dhaab@luxul.com>

Luxul XWR-1200 in a dual-band router based on BCM47081. It uses serial
flash (for bootloader and NVRAM) and NAND flash (for firmware).

Signed-off-by: Dan Haab <dhaab@luxul.com>
---
 arch/arm/boot/dts/Makefile                    |    1 +
 arch/arm/boot/dts/bcm47081-luxul-xwr-1200.dts |  107 +++++++++++++++++++++++++
 2 files changed, 108 insertions(+)
 create mode 100644 arch/arm/boot/dts/bcm47081-luxul-xwr-1200.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 04fd8f0..8a403a2 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -84,6 +84,7 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \
 	bcm47081-buffalo-wzr-600dhp2.dtb \
 	bcm47081-buffalo-wzr-900dhp.dtb \
 	bcm47081-luxul-xap-1410.dtb \
+	bcm47081-luxul-xwr-1200.dtb \
 	bcm4709-asus-rt-ac87u.dtb \
 	bcm4709-buffalo-wxr-1900dhp.dtb \
 	bcm4709-netgear-r7000.dtb \
diff --git a/arch/arm/boot/dts/bcm47081-luxul-xwr-1200.dts b/arch/arm/boot/dts/bcm47081-luxul-xwr-1200.dts
new file mode 100644
index 0000000..c544ab3
--- /dev/null
+++ b/arch/arm/boot/dts/bcm47081-luxul-xwr-1200.dts
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2017 Luxul Inc.
+ *
+ * Licensed under the ISC license.
+ */
+
+/dts-v1/;
+
+#include "bcm47081.dtsi"
+#include "bcm5301x-nand-cs0-bch4.dtsi"
+
+/ {
+	compatible = "luxul,xwr-1200v1", "brcm,bcm47081", "brcm,bcm4708";
+	model = "Luxul XWR-1200 V1";
+
+	chosen {
+		bootargs = "console=ttyS0,115200";
+	};
+
+	memory {
+		reg = <0x00000000 0x08000000>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		power {
+			label = "bcm53xx:green:power";
+			gpios = <&chipcommon 0 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "default-on";
+		};
+
+		lan3 {
+			label = "bcm53xx:green:lan3";
+			gpios = <&chipcommon 1 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "none";
+		};
+
+		lan4 {
+			label = "bcm53xx:green:lan4";
+			gpios = <&chipcommon 2 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "none";
+		};
+
+		wan {
+			label = "bcm53xx:green:wan";
+			gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "none";
+		};
+
+		lan2 {
+			label = "bcm53xx:green:lan2";
+			gpios = <&chipcommon 6 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "none";
+		};
+
+		usb {
+			label = "bcm53xx:green:usb";
+			gpios = <&chipcommon 8 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "none";
+		};
+
+		status {
+			label = "bcm53xx:green:status";
+			gpios = <&chipcommon 10 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "timer";
+		};
+
+		2ghz {
+			label = "bcm53xx:green:2ghz";
+			gpios = <&chipcommon 13 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "none";
+		};
+
+		5ghz {
+			label = "bcm53xx:green:5ghz";
+			gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "none";
+		};
+
+		lan1 {
+			label = "bcm53xx:green:lan1";
+			gpios = <&chipcommon 15 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "none";
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		restart {
+			label = "Reset";
+			linux,code = <KEY_RESTART>;
+			gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>;
+		};
+	};
+};
+
+&usb2 {
+	vcc-gpio = <&chipcommon 9 GPIO_ACTIVE_HIGH>;
+};
+
+&spi_nor {
+	status = "okay";
+};
-- 
1.7.9.5

^ permalink raw reply related

* Re: [alsa-devel] [PATCH 1/4] ASoC: es8328-i2c: Add compatible for ES8388
From: kbuild test robot @ 2017-01-15  2:56 UTC (permalink / raw)
  Cc: kbuild-all-JC7UmRfGjtg, Jaroslav Kysela, Takashi Iwai,
	alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw, Heiko Stuebner, Mark Rutland,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Pawel Moll, Ian Campbell,
	linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Sjoerd Simons,
	Rob Herring, Kumar Gala, Romain Perier
In-Reply-To: <20170113161452.14313-2-romain.perier-ZGY8ohtN/8qB+jHODAdFcQ@public.gmane.org>

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

Hi Romain,

[auto build test WARNING on rockchip/for-next]
[also build test WARNING on v4.10-rc3 next-20170113]
[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/Romain-Perier/Add-support-for-es8388-on-the-rock2/20170115-095611
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git for-next
config: alpha-allyesconfig (attached as .config)
compiler: alpha-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=alpha 

All warnings (new ones prefixed by >>):

>> sound/soc/codecs/es8328-i2c.c:22:14: warning: initialization makes integer from pointer without a cast [-Wint-conversion]
     { "es8328", "es8388", 0 },
                 ^~~~~~~~
   sound/soc/codecs/es8328-i2c.c:22:14: note: (near initialization for 'es8328_id[0].driver_data')
>> sound/soc/codecs/es8328-i2c.c:22:24: warning: excess elements in struct initializer
     { "es8328", "es8388", 0 },
                           ^
   sound/soc/codecs/es8328-i2c.c:22:24: note: (near initialization for 'es8328_id[0]')

vim +22 sound/soc/codecs/es8328-i2c.c

     6	 * Author: Sean Cross <xobs-nXMMniAx+RbQT0dZR+AlfA@public.gmane.org>
     7	 *
     8	 * This program is free software; you can redistribute it and/or modify
     9	 * it under the terms of the GNU General Public License version 2 as
    10	 * published by the Free Software Foundation.
    11	 */
    12	
    13	#include <linux/module.h>
    14	#include <linux/i2c.h>
    15	#include <linux/regmap.h>
    16	
    17	#include <sound/soc.h>
    18	
    19	#include "es8328.h"
    20	
    21	static const struct i2c_device_id es8328_id[] = {
  > 22		{ "es8328", "es8388", 0 },
    23		{ }
    24	};
    25	MODULE_DEVICE_TABLE(i2c, es8328_id);
    26	
    27	static const struct of_device_id es8328_of_match[] = {
    28		{ .compatible = "everest,es8328", },
    29		{ .compatible = "everest,es8388", },
    30		{ }

---
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: 48654 bytes --]

^ permalink raw reply

* Re: [alsa-devel] [PATCH 3/4] ASoC: rockchip: Add machine driver for ES8388 codecs
From: kbuild test robot @ 2017-01-15  5:21 UTC (permalink / raw)
  Cc: kbuild-all-JC7UmRfGjtg, Jaroslav Kysela, Takashi Iwai,
	alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw, Heiko Stuebner, Mark Rutland,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Pawel Moll, Ian Campbell,
	linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Sjoerd Simons,
	Rob Herring, Kumar Gala, Romain Perier
In-Reply-To: <20170113161452.14313-4-romain.perier-ZGY8ohtN/8qB+jHODAdFcQ@public.gmane.org>

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

Hi Romain,

[auto build test WARNING on rockchip/for-next]
[also build test WARNING on v4.10-rc3 next-20170113]
[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/Romain-Perier/Add-support-for-es8388-on-the-rock2/20170115-095611
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git for-next
config: sparc64-allyesconfig (attached as .config)
compiler: sparc64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=sparc64 

All warnings (new ones prefixed by >>):

warning: (SND_SOC_ROCKCHIP_ES8388) selects SND_SOC_ROCKCHIP_I2S which has unmet direct dependencies (SOUND && !M68K && !UML && SND && SND_SOC && CLKDEV_LOOKUP && SND_SOC_ROCKCHIP)

---
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: 48885 bytes --]

^ permalink raw reply

* Re: [PATCH v6 2/3] input: tm2-touchkey: Add touchkey driver support for TM2
From: Dmitry Torokhov @ 2017-01-15  7:11 UTC (permalink / raw)
  To: Jaechul Lee
  Cc: Rob Herring, Mark Rutland, Catalin Marinas, Will Deacon,
	Kukjin Kim, Krzysztof Kozlowski, Javier Martinez Canillas,
	Andi Shyti, Chanwoo Choi, beomho.seo, galaxyra, linux-arm-kernel,
	linux-input, devicetree, linux-kernel, linux-samsung-soc
In-Reply-To: <1483946535-4703-3-git-send-email-jcsing.lee@samsung.com>

Hi Jaechul,

On Mon, Jan 09, 2017 at 04:22:14PM +0900, Jaechul Lee wrote:
> +static irqreturn_t tm2_touchkey_irq_handler(int irq, void *devid)
> +{
> +	struct tm2_touchkey_data *touchkey = devid;
> +	u32 data;
> +
> +	data = i2c_smbus_read_byte_data(touchkey->client,
> +					TM2_TOUCHKEY_KEYCODE_REG);
> +
> +	if (data < 0) {

You declared data as u32 so it will never be negative.

> +		dev_err(&touchkey->client->dev, "Failed to read i2c data\n");
> +		return IRQ_HANDLED;
> +	}
> +
> +	touchkey->keycode_type = data & TM2_TOUCHKEY_BIT_KEYCODE;
> +	touchkey->pressed = !(data & TM2_TOUCHKEY_BIT_PRESS_EV);

There is no need to store this in touchkey structure as you are not
going to use it past this function.

Does the version of the patch below work for you?

Thanks.

-- 
Dmitry


Input: tm2-touchkey - add touchkey driver support for TM2

From: Jaechul Lee <jcsing.lee@samsung.com>

This patch adds support for the TM2 touch key and led functionality.

The driver interfaces with userspace through an input device and
reports KEY_PHONE and KEY_BACK event types. LED brightness can be
controlled by "/sys/class/leds/tm2-touchkey/brightness".

Signed-off-by: Beomho Seo <beomho.seo@samsung.com>
Signed-off-by: Jaechul Lee <jcsing.lee@samsung.com>
Reviewed-by: Javier Martinez Canillas <javier@osg.samsung.com>
Reviewed-by: Andi Shyti <andi.shyti@samsung.com>
Acked-by: Krzysztof Kozlowski <krzk@kernel.org>
Patchwork-Id: 9504149
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
 drivers/input/keyboard/Kconfig        |   11 +
 drivers/input/keyboard/Makefile       |    1 
 drivers/input/keyboard/tm2-touchkey.c |  286 +++++++++++++++++++++++++++++++++
 3 files changed, 298 insertions(+)
 create mode 100644 drivers/input/keyboard/tm2-touchkey.c

diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index cbd75cf44739..97acd6524ad7 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -666,6 +666,17 @@ config KEYBOARD_TC3589X
 	  To compile this driver as a module, choose M here: the
 	  module will be called tc3589x-keypad.
 
+config KEYBOARD_TM2_TOUCHKEY
+	tristate "TM2 touchkey support"
+	depends on I2C
+	depends on LEDS_CLASS
+	help
+	  Say Y here to enable device driver for tm2-touchkey with
+	  LED control for the Exynos5433 TM2 board.
+
+	  To compile this driver as a module, choose M here.
+	  module will be called tm2-touchkey.
+
 config KEYBOARD_TWL4030
 	tristate "TI TWL4030/TWL5030/TPS659x0 keypad support"
 	depends on TWL4030_CORE
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index d9f4cfcf3410..7d9acff819a7 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -61,6 +61,7 @@ obj-$(CONFIG_KEYBOARD_SUN4I_LRADC)	+= sun4i-lradc-keys.o
 obj-$(CONFIG_KEYBOARD_SUNKBD)		+= sunkbd.o
 obj-$(CONFIG_KEYBOARD_TC3589X)		+= tc3589x-keypad.o
 obj-$(CONFIG_KEYBOARD_TEGRA)		+= tegra-kbc.o
+obj-$(CONFIG_KEYBOARD_TM2_TOUCHKEY)	+= tm2-touchkey.o
 obj-$(CONFIG_KEYBOARD_TWL4030)		+= twl4030_keypad.o
 obj-$(CONFIG_KEYBOARD_XTKBD)		+= xtkbd.o
 obj-$(CONFIG_KEYBOARD_W90P910)		+= w90p910_keypad.o
diff --git a/drivers/input/keyboard/tm2-touchkey.c b/drivers/input/keyboard/tm2-touchkey.c
new file mode 100644
index 000000000000..79bc2d2bd4b9
--- /dev/null
+++ b/drivers/input/keyboard/tm2-touchkey.c
@@ -0,0 +1,286 @@
+/*
+ * TM2 touchkey device driver
+ *
+ * Copyright 2005 Phil Blundell
+ * Copyright 2016 Samsung Electronics Co., Ltd.
+ *
+ * Author: Beomho Seo <beomho.seo@samsung.com>
+ * Author: Jaechul Lee <jcsing.lee@samsung.com>
+ *
+ * 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/bitops.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/leds.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/pm.h>
+#include <linux/regulator/consumer.h>
+
+#define TM2_TOUCHKEY_DEV_NAME		"tm2-touchkey"
+#define TM2_TOUCHKEY_KEYCODE_REG	0x03
+#define TM2_TOUCHKEY_BASE_REG		0x00
+#define TM2_TOUCHKEY_CMD_LED_ON		0x10
+#define TM2_TOUCHKEY_CMD_LED_OFF	0x20
+#define TM2_TOUCHKEY_BIT_PRESS_EV	BIT(3)
+#define TM2_TOUCHKEY_BIT_KEYCODE	GENMASK(2, 0)
+#define TM2_TOUCHKEY_LED_VOLTAGE_MIN	2500000
+#define TM2_TOUCHKEY_LED_VOLTAGE_MAX	3300000
+
+enum {
+	TM2_TOUCHKEY_KEY_MENU = 0x1,
+	TM2_TOUCHKEY_KEY_BACK,
+};
+
+struct tm2_touchkey_data {
+	struct i2c_client *client;
+	struct input_dev *input_dev;
+	struct led_classdev led_dev;
+	struct regulator *vdd;
+	struct regulator_bulk_data regulators[2];
+};
+
+static void tm2_touchkey_led_brightness_set(struct led_classdev *led_dev,
+					    enum led_brightness brightness)
+{
+	struct tm2_touchkey_data *touchkey =
+		container_of(led_dev, struct tm2_touchkey_data, led_dev);
+	u32 volt;
+	u8 data;
+
+	if (brightness == LED_OFF) {
+		volt = TM2_TOUCHKEY_LED_VOLTAGE_MIN;
+		data = TM2_TOUCHKEY_CMD_LED_OFF;
+	} else {
+		volt = TM2_TOUCHKEY_LED_VOLTAGE_MAX;
+		data = TM2_TOUCHKEY_CMD_LED_ON;
+	}
+
+	regulator_set_voltage(touchkey->vdd, volt, volt);
+	i2c_smbus_write_byte_data(touchkey->client,
+				  TM2_TOUCHKEY_BASE_REG, data);
+}
+
+static int tm2_touchkey_power_enable(struct tm2_touchkey_data *touchkey)
+{
+	int error;
+
+	error = regulator_bulk_enable(ARRAY_SIZE(touchkey->regulators),
+				      touchkey->regulators);
+	if (error)
+		return error;
+
+	/* waiting for device initialization, at least 150ms */
+	msleep(150);
+
+	return 0;
+}
+
+static void tm2_touchkey_power_disable(void *data)
+{
+	struct tm2_touchkey_data *touchkey = data;
+
+	regulator_bulk_disable(ARRAY_SIZE(touchkey->regulators),
+			       touchkey->regulators);
+}
+
+static irqreturn_t tm2_touchkey_irq_handler(int irq, void *devid)
+{
+	struct tm2_touchkey_data *touchkey = devid;
+	int data;
+	int key;
+
+	data = i2c_smbus_read_byte_data(touchkey->client,
+					TM2_TOUCHKEY_KEYCODE_REG);
+	if (data < 0) {
+		dev_err(&touchkey->client->dev,
+			"failed to read i2c data: %d\n", data);
+		goto out;
+	}
+
+	switch (data & TM2_TOUCHKEY_BIT_KEYCODE) {
+	case TM2_TOUCHKEY_KEY_MENU:
+		key = KEY_PHONE;
+		break;
+
+	case TM2_TOUCHKEY_KEY_BACK:
+		key = KEY_BACK;
+		break;
+
+	default:
+		dev_warn(&touchkey->client->dev,
+			 "unhandled keycode, data %#02x\n", data);
+		goto out;
+	}
+
+	if (data & TM2_TOUCHKEY_BIT_PRESS_EV) {
+		input_report_key(touchkey->input_dev, key, 1);
+	} else {
+		input_report_key(touchkey->input_dev, KEY_PHONE, 0);
+		input_report_key(touchkey->input_dev, KEY_BACK, 0);
+	}
+
+	input_sync(touchkey->input_dev);
+
+out:
+	return IRQ_HANDLED;
+}
+
+static int tm2_touchkey_probe(struct i2c_client *client,
+			      const struct i2c_device_id *id)
+{
+	struct tm2_touchkey_data *touchkey;
+	int error;
+
+	if (!i2c_check_functionality(client->adapter,
+			I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA)) {
+		dev_err(&client->dev, "incompatible I2C adapter\n");
+		return -EIO;
+	}
+
+	touchkey = devm_kzalloc(&client->dev, sizeof(*touchkey), GFP_KERNEL);
+	if (!touchkey)
+		return -ENOMEM;
+
+	touchkey->client = client;
+	i2c_set_clientdata(client, touchkey);
+
+	touchkey->regulators[0].supply = "vcc";
+	touchkey->regulators[1].supply = "vdd";
+	error = devm_regulator_bulk_get(&client->dev,
+					ARRAY_SIZE(touchkey->regulators),
+					touchkey->regulators);
+	if (error) {
+		dev_err(&client->dev, "failed to get regulators: %d\n", error);
+		return error;
+	}
+
+	/* Save VDD for easy access */
+	touchkey->vdd = touchkey->regulators[1].consumer;
+
+	error = tm2_touchkey_power_enable(touchkey);
+	if (error) {
+		dev_err(&client->dev, "failed to power up device: %d\n", error);
+		return error;
+	}
+
+	error = devm_add_action_or_reset(&client->dev,
+					 tm2_touchkey_power_disable, touchkey);
+	if (error) {
+		dev_err(&client->dev,
+			"failed to install poweroff handler: %d\n", error);
+		return error;
+	}
+
+	/* input device */
+	touchkey->input_dev = devm_input_allocate_device(&client->dev);
+	if (!touchkey->input_dev) {
+		dev_err(&client->dev, "failed to allocate input device\n");
+		return -ENOMEM;
+	}
+
+	touchkey->input_dev->name = TM2_TOUCHKEY_DEV_NAME;
+	touchkey->input_dev->id.bustype = BUS_I2C;
+
+	input_set_capability(touchkey->input_dev, EV_KEY, KEY_PHONE);
+	input_set_capability(touchkey->input_dev, EV_KEY, KEY_BACK);
+
+	input_set_drvdata(touchkey->input_dev, touchkey);
+
+	error = input_register_device(touchkey->input_dev);
+	if (error) {
+		dev_err(&client->dev,
+			"failed to register input device: %d\n", error);
+		return error;
+	}
+
+	error = devm_request_threaded_irq(&client->dev, client->irq,
+					  NULL, tm2_touchkey_irq_handler,
+					  IRQF_ONESHOT,
+					  TM2_TOUCHKEY_DEV_NAME, touchkey);
+	if (error) {
+		dev_err(&client->dev,
+			"failed to request threaded irq: %d\n", error);
+		return error;
+	}
+
+	/* led device */
+	touchkey->led_dev.name = TM2_TOUCHKEY_DEV_NAME;
+	touchkey->led_dev.brightness = LED_FULL;
+	touchkey->led_dev.max_brightness = LED_FULL;
+	touchkey->led_dev.brightness_set = tm2_touchkey_led_brightness_set;
+
+	error = devm_led_classdev_register(&client->dev, &touchkey->led_dev);
+	if (error) {
+		dev_err(&client->dev,
+			"failed to register touchkey led: %d\n", error);
+		return error;
+	}
+
+	return 0;
+}
+
+static int __maybe_unused tm2_touchkey_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct tm2_touchkey_data *touchkey = i2c_get_clientdata(client);
+
+	disable_irq(client->irq);
+	tm2_touchkey_power_disable(touchkey);
+
+	return 0;
+}
+
+static int __maybe_unused tm2_touchkey_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct tm2_touchkey_data *touchkey = i2c_get_clientdata(client);
+	int ret;
+
+	enable_irq(client->irq);
+
+	ret = tm2_touchkey_power_enable(touchkey);
+	if (ret)
+		dev_err(dev, "failed to enable power: %d\n", ret);
+
+	return ret;
+}
+
+static SIMPLE_DEV_PM_OPS(tm2_touchkey_pm_ops,
+			 tm2_touchkey_suspend, tm2_touchkey_resume);
+
+static const struct i2c_device_id tm2_touchkey_id_table[] = {
+	{ TM2_TOUCHKEY_DEV_NAME, 0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(i2c, tm2_touchkey_id_table);
+
+static const struct of_device_id tm2_touchkey_of_match[] = {
+	{ .compatible = "cypress,tm2-touchkey", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, tm2_touchkey_of_match);
+
+static struct i2c_driver tm2_touchkey_driver = {
+	.driver = {
+		.name = TM2_TOUCHKEY_DEV_NAME,
+		.pm = &tm2_touchkey_pm_ops,
+		.of_match_table = of_match_ptr(tm2_touchkey_of_match),
+	},
+	.probe = tm2_touchkey_probe,
+	.id_table = tm2_touchkey_id_table,
+};
+module_i2c_driver(tm2_touchkey_driver);
+
+MODULE_AUTHOR("Beomho Seo <beomho.seo@samsung.com>");
+MODULE_AUTHOR("Jaechul Lee <jcsing.lee@samsung.com>");
+MODULE_DESCRIPTION("Samsung touchkey driver");
+MODULE_LICENSE("GPL v2");

^ permalink raw reply related

* [PATCH] fbdev: ssd1307fb: allow reset-gpios is missing
From: Icenowy Zheng @ 2017-01-15 11:21 UTC (permalink / raw)
  To: Rob Herring, David Airlie, Maxime Ripard
  Cc: devicetree, linux-kernel, linux-fbdev, Icenowy Zheng

Currently some SSD1306 OLED modules are sold without a reset pin (only
VCC, GND, SCK, SDA four pins).

Add support for missing reset-gpios property.

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
 .../devicetree/bindings/display/ssd1307fb.txt      |  2 +-
 drivers/video/fbdev/ssd1307fb.c                    | 34 ++++++++++++----------
 2 files changed, 20 insertions(+), 16 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/ssd1307fb.txt b/Documentation/devicetree/bindings/display/ssd1307fb.txt
index eb31ed47a283..a4541b13b706 100644
--- a/Documentation/devicetree/bindings/display/ssd1307fb.txt
+++ b/Documentation/devicetree/bindings/display/ssd1307fb.txt
@@ -8,13 +8,13 @@ Required properties:
          0x3c or 0x3d
   - pwm: Should contain the pwm to use according to the OF device tree PWM
          specification [0]. Only required for the ssd1307.
-  - reset-gpios: Should contain the GPIO used to reset the OLED display
   - solomon,height: Height in pixel of the screen driven by the controller
   - solomon,width: Width in pixel of the screen driven by the controller
   - solomon,page-offset: Offset of pages (band of 8 pixels) that the screen is
     mapped to.
 
 Optional properties:
+  - reset-gpios: Should contain the GPIO used to reset the OLED display
   - reset-active-low: Is the reset gpio is active on physical low?
   - solomon,segment-no-remap: Display needs normal (non-inverted) data column
                               to segment mapping
diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 2925d5ce8d3e..e2b51a091ed4 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -563,8 +563,8 @@ static int ssd1307fb_probe(struct i2c_client *client,
 
 	par->reset = of_get_named_gpio(client->dev.of_node,
 					 "reset-gpios", 0);
-	if (!gpio_is_valid(par->reset)) {
-		ret = -EINVAL;
+	if (!gpio_is_valid(par->reset) && par->reset != -ENOENT) {
+		ret = par->reset;
 		goto fb_alloc_error;
 	}
 
@@ -642,23 +642,27 @@ static int ssd1307fb_probe(struct i2c_client *client,
 
 	fb_deferred_io_init(info);
 
-	ret = devm_gpio_request_one(&client->dev, par->reset,
-				    GPIOF_OUT_INIT_HIGH,
-				    "oled-reset");
-	if (ret) {
-		dev_err(&client->dev,
-			"failed to request gpio %d: %d\n",
-			par->reset, ret);
-		goto reset_oled_error;
+	if (par->reset != -ENOENT) {
+		ret = devm_gpio_request_one(&client->dev, par->reset,
+					    GPIOF_OUT_INIT_HIGH,
+					    "oled-reset");
+		if (ret) {
+			dev_err(&client->dev,
+				"failed to request gpio %d: %d\n",
+				par->reset, ret);
+			goto reset_oled_error;
+		}
 	}
 
 	i2c_set_clientdata(client, info);
 
-	/* Reset the screen */
-	gpio_set_value(par->reset, 0);
-	udelay(4);
-	gpio_set_value(par->reset, 1);
-	udelay(4);
+	if (par->reset != -ENOENT) {
+		/* Reset the screen */
+		gpio_set_value(par->reset, 0);
+		udelay(4);
+		gpio_set_value(par->reset, 1);
+		udelay(4);
+	}
 
 	ret = ssd1307fb_init(par);
 	if (ret)
-- 
2.11.0

^ permalink raw reply related

* [PATCH] Documentation: usb: fix wrong documentation paths
From: Yegor Yefremov @ 2017-01-15 12:04 UTC (permalink / raw)
  To: devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, linux-usb-u79uwXL29TY76Z2rM5mHXA,
	Yegor Yefremov

Signed-off-by: Yegor Yefremov <yegorslists-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
---
 Documentation/devicetree/bindings/usb/dwc3-st.txt     | 4 ++--
 Documentation/devicetree/bindings/usb/ehci-st.txt     | 2 +-
 Documentation/devicetree/bindings/usb/mt8173-mtu3.txt | 2 +-
 Documentation/devicetree/bindings/usb/mt8173-xhci.txt | 4 ++--
 Documentation/devicetree/bindings/usb/qcom,dwc3.txt   | 2 +-
 5 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/Documentation/devicetree/bindings/usb/dwc3-st.txt b/Documentation/devicetree/bindings/usb/dwc3-st.txt
index 01c71b1..50dee3b 100644
--- a/Documentation/devicetree/bindings/usb/dwc3-st.txt
+++ b/Documentation/devicetree/bindings/usb/dwc3-st.txt
@@ -20,10 +20,10 @@ See: Documentation/devicetree/bindings/reset/reset.txt
    with 'reg' property
 
  - pinctl-names	: A pinctrl state named "default" must be defined
-See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
+See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
 
  - pinctrl-0	: Pin control group
-See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
+See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
 
  - ranges	: allows valid 1:1 translation between child's address space and
 		  parent's address space
diff --git a/Documentation/devicetree/bindings/usb/ehci-st.txt b/Documentation/devicetree/bindings/usb/ehci-st.txt
index fb45fa5..410d922 100644
--- a/Documentation/devicetree/bindings/usb/ehci-st.txt
+++ b/Documentation/devicetree/bindings/usb/ehci-st.txt
@@ -7,7 +7,7 @@ Required properties:
  - interrupts		: one EHCI interrupt should be described here
  - pinctrl-names	: a pinctrl state named "default" must be defined
  - pinctrl-0		: phandle referencing pin configuration of the USB controller
-See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
+See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
  - clocks		: phandle list of usb clocks
  - clock-names		: should be "ic" for interconnect clock and "clk48"
 See: Documentation/devicetree/bindings/clock/clock-bindings.txt
diff --git a/Documentation/devicetree/bindings/usb/mt8173-mtu3.txt b/Documentation/devicetree/bindings/usb/mt8173-mtu3.txt
index e049d19..718386a 100644
--- a/Documentation/devicetree/bindings/usb/mt8173-mtu3.txt
+++ b/Documentation/devicetree/bindings/usb/mt8173-mtu3.txt
@@ -30,7 +30,7 @@ Optional properties:
 	"id_float" and "id_ground" are optinal which depends on
 	"mediatek,enable-manual-drd"
  - pinctrl-0 : pin control group
-	See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
+	See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
 
  - maximum-speed : valid arguments are "super-speed", "high-speed" and
 	"full-speed"; refer to usb/generic.txt
diff --git a/Documentation/devicetree/bindings/usb/mt8173-xhci.txt b/Documentation/devicetree/bindings/usb/mt8173-xhci.txt
index 2a930bd..7ea3971 100644
--- a/Documentation/devicetree/bindings/usb/mt8173-xhci.txt
+++ b/Documentation/devicetree/bindings/usb/mt8173-xhci.txt
@@ -37,7 +37,7 @@ Optional properties:
  - usb3-lpm-capable : supports USB3.0 LPM
  - pinctrl-names : a pinctrl state named "default" must be defined
  - pinctrl-0 : pin control group
-	See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
+	See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
 
 Example:
 usb30: usb@11270000 {
@@ -67,7 +67,7 @@ usb30: usb@11270000 {
 
 In the case, xhci is added as subnode to mtu3. An example and the DT binding
 details of mtu3 can be found in:
-Documentation/devicetree/bindings/usb/mtu3.txt
+Documentation/devicetree/bindings/usb/mt8173-mtu3.txt
 
 Required properties:
  - compatible : should contain "mediatek,mt8173-xhci"
diff --git a/Documentation/devicetree/bindings/usb/qcom,dwc3.txt b/Documentation/devicetree/bindings/usb/qcom,dwc3.txt
index 39acb08..73cc096 100644
--- a/Documentation/devicetree/bindings/usb/qcom,dwc3.txt
+++ b/Documentation/devicetree/bindings/usb/qcom,dwc3.txt
@@ -18,7 +18,7 @@ A child node must exist to represent the core DWC3 IP block. The name of
 the node is not important. The content of the node is defined in dwc3.txt.
 
 Phy documentation is provided in the following places:
-Documentation/devicetree/bindings/phy/qcom,dwc3-usb-phy.txt
+Documentation/devicetree/bindings/phy/qcom-dwc3-usb-phy.txt
 
 Example device nodes:
 
-- 
2.9.3

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

^ permalink raw reply related

* Re: [PATCH] Documentation: usb: fix wrong documentation paths
From: Greg KH @ 2017-01-15 12:07 UTC (permalink / raw)
  To: Yegor Yefremov
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	linux-usb-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20170115120456.2942-1-yegorslists-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>

On Sun, Jan 15, 2017 at 01:04:56PM +0100, Yegor Yefremov wrote:
> Signed-off-by: Yegor Yefremov <yegorslists-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>

I never take patches without any changelog text, and I doubt that other
maintainers do either :(

thanks,

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

^ permalink raw reply

* [PATCH v2] Documentation: usb: fix wrong documentation paths
From: Yegor Yefremov @ 2017-01-15 12:14 UTC (permalink / raw)
  To: devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, linux-usb-u79uwXL29TY76Z2rM5mHXA,
	Yegor Yefremov

Fixes wrong spelled "pinctrl-bindings.txt" and "qcom-dwc3-usb-phy.txt"
file names as also wrong specified "mt8173-mtu3.txt" file name.

Signed-off-by: Yegor Yefremov <yegorslists-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
---
Changes:
	v1 -> v2: add changelog text (Greg Kroah-Hartman)

 Documentation/devicetree/bindings/usb/dwc3-st.txt     | 4 ++--
 Documentation/devicetree/bindings/usb/ehci-st.txt     | 2 +-
 Documentation/devicetree/bindings/usb/mt8173-mtu3.txt | 2 +-
 Documentation/devicetree/bindings/usb/mt8173-xhci.txt | 4 ++--
 Documentation/devicetree/bindings/usb/qcom,dwc3.txt   | 2 +-
 5 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/Documentation/devicetree/bindings/usb/dwc3-st.txt b/Documentation/devicetree/bindings/usb/dwc3-st.txt
index 01c71b1..50dee3b 100644
--- a/Documentation/devicetree/bindings/usb/dwc3-st.txt
+++ b/Documentation/devicetree/bindings/usb/dwc3-st.txt
@@ -20,10 +20,10 @@ See: Documentation/devicetree/bindings/reset/reset.txt
    with 'reg' property
 
  - pinctl-names	: A pinctrl state named "default" must be defined
-See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
+See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
 
  - pinctrl-0	: Pin control group
-See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
+See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
 
  - ranges	: allows valid 1:1 translation between child's address space and
 		  parent's address space
diff --git a/Documentation/devicetree/bindings/usb/ehci-st.txt b/Documentation/devicetree/bindings/usb/ehci-st.txt
index fb45fa5..410d922 100644
--- a/Documentation/devicetree/bindings/usb/ehci-st.txt
+++ b/Documentation/devicetree/bindings/usb/ehci-st.txt
@@ -7,7 +7,7 @@ Required properties:
  - interrupts		: one EHCI interrupt should be described here
  - pinctrl-names	: a pinctrl state named "default" must be defined
  - pinctrl-0		: phandle referencing pin configuration of the USB controller
-See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
+See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
  - clocks		: phandle list of usb clocks
  - clock-names		: should be "ic" for interconnect clock and "clk48"
 See: Documentation/devicetree/bindings/clock/clock-bindings.txt
diff --git a/Documentation/devicetree/bindings/usb/mt8173-mtu3.txt b/Documentation/devicetree/bindings/usb/mt8173-mtu3.txt
index e049d19..718386a 100644
--- a/Documentation/devicetree/bindings/usb/mt8173-mtu3.txt
+++ b/Documentation/devicetree/bindings/usb/mt8173-mtu3.txt
@@ -30,7 +30,7 @@ Optional properties:
 	"id_float" and "id_ground" are optinal which depends on
 	"mediatek,enable-manual-drd"
  - pinctrl-0 : pin control group
-	See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
+	See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
 
  - maximum-speed : valid arguments are "super-speed", "high-speed" and
 	"full-speed"; refer to usb/generic.txt
diff --git a/Documentation/devicetree/bindings/usb/mt8173-xhci.txt b/Documentation/devicetree/bindings/usb/mt8173-xhci.txt
index 2a930bd..7ea3971 100644
--- a/Documentation/devicetree/bindings/usb/mt8173-xhci.txt
+++ b/Documentation/devicetree/bindings/usb/mt8173-xhci.txt
@@ -37,7 +37,7 @@ Optional properties:
  - usb3-lpm-capable : supports USB3.0 LPM
  - pinctrl-names : a pinctrl state named "default" must be defined
  - pinctrl-0 : pin control group
-	See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
+	See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
 
 Example:
 usb30: usb@11270000 {
@@ -67,7 +67,7 @@ usb30: usb@11270000 {
 
 In the case, xhci is added as subnode to mtu3. An example and the DT binding
 details of mtu3 can be found in:
-Documentation/devicetree/bindings/usb/mtu3.txt
+Documentation/devicetree/bindings/usb/mt8173-mtu3.txt
 
 Required properties:
  - compatible : should contain "mediatek,mt8173-xhci"
diff --git a/Documentation/devicetree/bindings/usb/qcom,dwc3.txt b/Documentation/devicetree/bindings/usb/qcom,dwc3.txt
index 39acb08..73cc096 100644
--- a/Documentation/devicetree/bindings/usb/qcom,dwc3.txt
+++ b/Documentation/devicetree/bindings/usb/qcom,dwc3.txt
@@ -18,7 +18,7 @@ A child node must exist to represent the core DWC3 IP block. The name of
 the node is not important. The content of the node is defined in dwc3.txt.
 
 Phy documentation is provided in the following places:
-Documentation/devicetree/bindings/phy/qcom,dwc3-usb-phy.txt
+Documentation/devicetree/bindings/phy/qcom-dwc3-usb-phy.txt
 
 Example device nodes:
 
-- 
2.9.3

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

^ permalink raw reply related

* Re: [PATCH v4 1/2] iio: adc: Add Maxim MAX11100 driver
From: Lars-Peter Clausen @ 2017-01-15 12:18 UTC (permalink / raw)
  To: Jacopo Mondi, wsa+renesas-jBu1N2QxHDJrcw3mvpCnnVaTQe2KTcn/,
	magnus.damm-Re5JQEeQqe8AvxtiuMwx3w, jic23-DgEjT+Ai2ygdnm+yROfE0A,
	knaack.h-Mmb7MZpHnFY, pmeerw-jW+XmwGofnusTnJN9+BGXg,
	marek.vasut-Re5JQEeQqe8AvxtiuMwx3w, geert-Td1EMuHUCqxL1ZNQvxDV9g,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8
  Cc: linux-iio-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1484301038-16386-2-git-send-email-jacopo+renesas-AW8dsiIh9cEdnm+yROfE0A@public.gmane.org>

On 01/13/2017 10:50 AM, Jacopo Mondi wrote:
> From: Jacopo Mondi <jacopo-AW8dsiIh9cEdnm+yROfE0A@public.gmane.org>
> 
> Add iio driver for Maxim MAX11100 single-channel ADC.
> 
> Signed-off-by: Jacopo Mondi <jacopo+renesas-AW8dsiIh9cEdnm+yROfE0A@public.gmane.org>
> Tested-by: Marek Vasut <marek.vasut-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> 
> ---
>  drivers/iio/adc/Kconfig    |   9 +++
>  drivers/iio/adc/Makefile   |   1 +
>  drivers/iio/adc/max11100.c | 187 +++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 197 insertions(+)
>  create mode 100644 drivers/iio/adc/max11100.c
> 
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index 38bc319..c32bc7a 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -307,6 +307,15 @@ config MAX1027
>  	  To compile this driver as a module, choose M here: the module will be
>  	  called max1027.
>  
> +config MAX11100
> +	tristate "Maxim max11100 ADC driver"
> +	depends on SPI_MASTER
> +	help
> +	  Say yes here to build support for Maxim max11100 SPI ADC
> +
> +	  To compile this driver as a module, choose M here: the module will be
> +	  called max11100.
> +
>  config MAX1363
>  	tristate "Maxim max1363 ADC driver"
>  	depends on I2C
> diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
> index d36c4be..5684369 100644
> --- a/drivers/iio/adc/Makefile
> +++ b/drivers/iio/adc/Makefile
> @@ -31,6 +31,7 @@ obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
>  obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o
>  obj-$(CONFIG_LTC2485) += ltc2485.o
>  obj-$(CONFIG_MAX1027) += max1027.o
> +obj-$(CONFIG_MAX11100) += max11100.o
>  obj-$(CONFIG_MAX1363) += max1363.o
>  obj-$(CONFIG_MCP320X) += mcp320x.o
>  obj-$(CONFIG_MCP3422) += mcp3422.o
> diff --git a/drivers/iio/adc/max11100.c b/drivers/iio/adc/max11100.c
> new file mode 100644
> index 0000000..78e2a45
> --- /dev/null
> +++ b/drivers/iio/adc/max11100.c
> @@ -0,0 +1,187 @@
> +/*
> + * iio/adc/max11100.c
> + * Maxim max11100 ADC Driver with IIO interface
> + *
> + * Copyright (C) 2016 Renesas Electronics Corporation
> + * Copyright (C) 2016 Jacopo Mondi
> + *
> + * 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/delay.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/spi/spi.h>
> +
> +#include <linux/iio/iio.h>
> +#include <linux/iio/buffer.h>
> +#include <linux/iio/driver.h>
> +
> +/*
> + * LSB is the ADC single digital step
> + * 1 LSB = (vref_mv / 2 ^ 16)
> + *
> + * LSB is used to calculate analog voltage value
> + * from the number of ADC steps count
> + *
> + * Ain = (count * LSB)
> + */
> +#define MAX11100_LSB_DIV		(1 << 16)
> +
> +struct max11100_state {
> +	const struct max11100_chip_desc *desc;
> +	struct regulator *vref_reg;
> +	struct spi_device *spi;
> +};
> +
> +static struct iio_chan_spec max11100_channels[] = {
> +	{ /* [0] */
> +		.type = IIO_VOLTAGE,
> +		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
> +				      BIT(IIO_CHAN_INFO_SCALE),
> +	},
> +};
> +
> +static struct max11100_chip_desc {
> +	unsigned int num_chan;
> +	const struct iio_chan_spec *channels;
> +} max11100_desc = {
> +	.num_chan = ARRAY_SIZE(max11100_channels),
> +	.channels = max11100_channels,
> +};
> +
> +static int max11100_read_single(struct iio_dev *indio_dev, int *val)
> +{
> +	int ret;
> +	struct max11100_state *state = iio_priv(indio_dev);
> +	uint8_t buffer[3];
> +
> +	ret = spi_read(state->spi, buffer, sizeof(buffer));
> +	if (ret) {
> +		dev_err(&indio_dev->dev, "SPI transfer failed\n");
> +		return ret;
> +	}
> +
> +	/* the first 8 bits sent out from ADC must be 0s */
> +	if (buffer[0]) {
> +		dev_err(&indio_dev->dev, "Invalid value: buffer[0] != 0\n");
> +		return -EINVAL;
> +	}
> +
> +	*val = (buffer[1] << 8) | buffer[2];
> +
> +	return 0;
> +}
> +
> +static int max11100_read_raw(struct iio_dev *indio_dev,
> +			     struct iio_chan_spec const *chan,
> +			     int *val, int *val2, long info)
> +{
> +	int ret, vref_uv;
> +	struct max11100_state *state = iio_priv(indio_dev);
> +
> +	switch (info) {
> +	case IIO_CHAN_INFO_RAW:
> +		ret = max11100_read_single(indio_dev, val);
> +		if (ret)
> +			return ret;
> +
> +		return IIO_VAL_INT;
> +
> +	case IIO_CHAN_INFO_SCALE:
> +		vref_uv = regulator_get_voltage(state->vref_reg);
> +		if (vref_uv < 0)
> +			/* dummy regulator "get_voltage" returns -EINVAL */
> +			return -EINVAL;
> +
> +		*val =  vref_uv / 1000;
> +		*val2 = MAX11100_LSB_DIV;
> +		return IIO_VAL_FRACTIONAL;
> +	}
> +
> +	return -EINVAL;
> +}
> +
> +static const struct iio_info max11100_info = {
> +	.driver_module = THIS_MODULE,
> +	.read_raw = max11100_read_raw,
> +};
> +
> +static int max11100_probe(struct spi_device *spi)
> +{
> +	int ret;
> +	struct iio_dev *indio_dev;
> +	struct max11100_state *state;
> +
> +	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*state));
> +	if (!indio_dev)
> +		return -ENOMEM;
> +
> +	spi_set_drvdata(spi, indio_dev);
> +
> +	state = iio_priv(indio_dev);
> +	state->spi = spi;
> +	state->desc = &max11100_desc;
> +
> +	indio_dev->dev.parent = &spi->dev;
> +	indio_dev->dev.of_node = spi->dev.of_node;
> +	indio_dev->info = &max11100_info;
> +	indio_dev->modes = INDIO_DIRECT_MODE;
> +	indio_dev->channels = state->desc->channels;
> +	indio_dev->num_channels = state->desc->num_chan;

Consider setting indio_dev->name= "max11100"; so userspace can identify the
type of the device.

^ permalink raw reply

* Re: [PATCH v2 2/2] iio: distance: srf08: add IIO driver for us ranger
From: Lars-Peter Clausen @ 2017-01-15 12:24 UTC (permalink / raw)
  To: Andreas Klinger, jic23-DgEjT+Ai2ygdnm+yROfE0A,
	knaack.h-Mmb7MZpHnFY, pmeerw-jW+XmwGofnusTnJN9+BGXg,
	linux-iio-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, ktsai-GubuWUlQtMwciDkP5Hr2oA,
	wsa-z923LK4zBo2bacvFa/9K2g, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	pawel.moll-5wv7dgnIgG8, mark.rutland-5wv7dgnIgG8,
	ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg,
	galak-sgV2jX0FEOL9JmXXK+q4OQ, trivial-DgEjT+Ai2ygdnm+yROfE0A,
	mranostay-Re5JQEeQqe8AvxtiuMwx3w,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20170110184815.GA15532@andreas>

On 01/10/2017 07:48 PM, Andreas Klinger wrote:
[...]
> +	indio_dev->name = dev_name(&client->dev);

The name is supposed to be the type of the device, e.g. part name, not the
name of parent device instance. E.g. "srf08" in this case.

^ permalink raw reply

* Re: [PATCH 3/4] iio: adc: add a driver for the SAR ADC found in Amlogic Meson SoCs
From: Lars-Peter Clausen @ 2017-01-15 12:26 UTC (permalink / raw)
  To: Martin Blumenstingl, jic23-DgEjT+Ai2ygdnm+yROfE0A,
	knaack.h-Mmb7MZpHnFY, pmeerw-jW+XmwGofnusTnJN9+BGXg,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	khilman-rdvid1DuHRBWk0Htik3J/w, linux-iio-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-clk-u79uwXL29TY76Z2rM5mHXA
  Cc: carlo-KA+7E9HrN00dnm+yROfE0A, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, mturquette-rdvid1DuHRBWk0Htik3J/w,
	sboyd-sgV2jX0FEOL9JmXXK+q4OQ, narmstrong-rdvid1DuHRBWk0Htik3J/w,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <20170111174334.24343-4-martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>

On 01/11/2017 06:43 PM, Martin Blumenstingl wrote:
> +	indio_dev->name = dev_name(&pdev->dev);

The name is supposed to be the type of the device, e.g. part name, not the
name of parent device instance. E.g. meson-gxbb-saradc or meson-gxl-saradc
in this case.

^ permalink raw reply

* Re: [PATCH 3/4] iio: adc: add a driver for the SAR ADC found in Amlogic Meson SoCs
From: Jonathan Cameron @ 2017-01-15 13:08 UTC (permalink / raw)
  To: Martin Blumenstingl
  Cc: knaack.h, lars, pmeerw, robh+dt, mark.rutland, khilman, linux-iio,
	devicetree, linux-amlogic, linux-clk, carlo, catalin.marinas,
	will.deacon, mturquette, sboyd, narmstrong, linux-arm-kernel,
	Russell King
In-Reply-To: <CAFBinCB75JG+F-ZgeO4+q-S9AvrYKYn6AVEdgaDa1yv=cE=Ujw@mail.gmail.com>

On 14/01/17 17:44, Martin Blumenstingl wrote:
> Hi Jonathan,
> 
> thank you for the review!
> (further comments from me inline)
> I think I'll send an updated version on Monday.
> 
> On Sat, Jan 14, 2017 at 3:46 PM, Jonathan Cameron <jic23@kernel.org> wrote:
>> On 11/01/17 17:43, Martin Blumenstingl wrote:
>>> This adds support for the SAR (Successive Approximation Register) ADC
>>> on the Amlogic Meson SoCs.
>>>
>>> The code is based on the public S805 (Meson8b) and S905 (GXBB)
>>> datasheets, as well as by reading (various versions of) the vendor
>>> driver and by inspecting the registers on the vendor kernels of my
>>> testing-hardware.
>>>
>>> Currently the GXBB, GXL and GXM SoCs are supported. GXBB hardware has
>>> 10-bit ADC resolution, while GXL and GXM have 12-bit ADC resolution.
>>> The code was written to support older SoCs (Meson8 and Meson8b) as well,
>>> but due to lack of actual testing-hardware no of_device_id was added for
>>> these.
>>>
>>> Two "features" from the vendor driver are currently missing:
>>> - the vendor driver uses channel #7 for calibration (this improves the
>>>   accuracy of the results - in my tests the results were less than 3%
>>>   off without calibration compared to the vendor driver). Adding support
>>>   for this should be easy, but is not required for most applications.
>>> - channel #6 is connected to the SoCs internal temperature sensor.
>>>   Adding support for this is probably not so easy since (based on the
>>>   u-boot sources) most SoC versions are using different registers and
>>>   algorithms for the conversion from "ADC value" to temperature.
>>>
>>> Supported by the hardware but currently not supported by the driver:
>>> - reading multiple channels at the same time (the hardware has a FIFO
>>>   buffer which stores multiple results)
>>> - continuous sampling (this would require a way to enable this
>>>   individually because otherwise the ADC would be drawing power
>>>   constantly)
>>> - interrupt support (similar to the vendor driver this new driver is
>>>   polling the results. It is unclear if the IRQ-mode is supported on
>>>   older (Meson6 or Meson8) hardware as well or if there are any errata)
>>>
>> Russell Cc'd for a quick question on the clk api.
> a quick side-note the clk API: my driver is a clock consumer and
> provider at the same time. This seems to be a recurring pattern in
> Amlogic hardware designs (as the MMC and DWMAC glue drivers are doing
> this also), see [0]
> 
>> Ideally include a source for datasheets if available. Saves time googling and
>> perhaps getting the wrong thing!
> OK, will do this in v2
> 
>> A few other minor comments inline. Pretty good V1.
> thanks :-)
> 
>> Jonathan
>>> Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
>>> ---
>>>  drivers/iio/adc/Kconfig        |  12 +
>>>  drivers/iio/adc/Makefile       |   1 +
>>>  drivers/iio/adc/meson_saradc.c | 860 +++++++++++++++++++++++++++++++++++++++++
>>>  3 files changed, 873 insertions(+)
>>>  create mode 100644 drivers/iio/adc/meson_saradc.c
>>>
>>> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
>>> index 9c8b558ba19e..86059b9b91bf 100644
>>> --- a/drivers/iio/adc/Kconfig
>>> +++ b/drivers/iio/adc/Kconfig
>>> @@ -371,6 +371,18 @@ config MEN_Z188_ADC
>>>         This driver can also be built as a module. If so, the module will be
>>>         called men_z188_adc.
>>>
>>> +config MESON_SARADC
>>> +     tristate "Amlogic Meson SAR ADC driver"
>>> +     default ARCH_MESON
>>> +     depends on OF && COMMON_CLK && (ARCH_MESON || COMPILE_TEST)
>>> +     select REGMAP_MMIO
>>> +     help
>>> +       Say yes here to build support for the SAR ADC found in Amlogic Meson
>>> +       SoCs.
>>> +
>>> +       To compile this driver as a module, choose M here: the
>>> +       module will be called meson_saradc.
>>> +
>>>  config MXS_LRADC
>>>          tristate "Freescale i.MX23/i.MX28 LRADC"
>>>          depends on (ARCH_MXS || COMPILE_TEST) && HAS_IOMEM
>>> diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
>>> index d36c4be8d1fc..de05b9e75f8f 100644
>>> --- a/drivers/iio/adc/Makefile
>>> +++ b/drivers/iio/adc/Makefile
>>> @@ -36,6 +36,7 @@ obj-$(CONFIG_MCP320X) += mcp320x.o
>>>  obj-$(CONFIG_MCP3422) += mcp3422.o
>>>  obj-$(CONFIG_MEDIATEK_MT6577_AUXADC) += mt6577_auxadc.o
>>>  obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o
>>> +obj-$(CONFIG_MESON_SARADC) += meson_saradc.o
>>>  obj-$(CONFIG_MXS_LRADC) += mxs-lradc.o
>>>  obj-$(CONFIG_NAU7802) += nau7802.o
>>>  obj-$(CONFIG_PALMAS_GPADC) += palmas_gpadc.o
>>> diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c
>>> new file mode 100644
>>> index 000000000000..06e8ac620385
>>> --- /dev/null
>>> +++ b/drivers/iio/adc/meson_saradc.c
>>> @@ -0,0 +1,860 @@
>>> +/*
>>> + * Amlogic Meson Successive Approximation Register (SAR) A/D Converter
>>> + *
>>> + * Copyright (C) 2017 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
>>> + *
>>> + * 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.
>>> + *
>>> + * You should have received a copy of the GNU General Public License
>>> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
>>> + */
>>> +
>>> +#include <linux/bitfield.h>
>>> +#include <linux/clk-provider.h>
>>> +#include <linux/module.h>
>>> +#include <linux/platform_device.h>
>>> +#include <linux/interrupt.h>
>>> +#include <linux/io.h>
>>> +#include <linux/iio/iio.h>
>>> +#include <linux/of.h>
>>> +#include <linux/of_device.h>
>>> +#include <linux/clk.h>
>>> +#include <linux/completion.h>
>>> +#include <linux/delay.h>
>>> +#include <linux/reset.h>
>>> +#include <linux/regmap.h>
>>> +#include <linux/regulator/consumer.h>
>>> +
>>> +#define SAR_ADC_REG0                                         0x00
>>> +     #define SAR_ADC_REG0_PANEL_DETECT                       BIT(31)
>>> +     #define SAR_ADC_REG0_BUSY_MASK                          GENMASK(30, 28)
>>> +     #define SAR_ADC_REG0_DELTA_BUSY                         BIT(30)
>>> +     #define SAR_ADC_REG0_AVG_BUSY                           BIT(29)
>>> +     #define SAR_ADC_REG0_SAMPLE_BUSY                        BIT(28)
>>> +     #define SAR_ADC_REG0_FIFO_FULL                          BIT(27)
>>> +     #define SAR_ADC_REG0_FIFO_EMPTY                         BIT(26)
>>> +     #define SAR_ADC_REG0_FIFO_COUNT_MASK                    GENMASK(25, 21)
>>> +     #define SAR_ADC_REG0_ADC_BIAS_CTRL_MASK                 GENMASK(20, 19)
>>> +     #define SAR_ADC_REG0_CURR_CHAN_ID_MASK                  GENMASK(18, 16)
>>> +     #define SAR_ADC_REG0_ADC_TEMP_SEN_SEL                   BIT(15)
>>> +     #define SAR_ADC_REG0_SAMPLING_STOP                      BIT(14)
>>> +     #define SAR_ADC_REG0_CHAN_DELTA_EN_MASK                 GENMASK(13, 12)
>>> +     #define SAR_ADC_REG0_DETECT_IRQ_POL                     BIT(10)
>>> +     #define SAR_ADC_REG0_DETECT_IRQ_EN                      BIT(9)
>>> +     #define SAR_ADC_REG0_FIFO_CNT_IRQ_MASK                  GENMASK(8, 4)
>>> +     #define SAR_ADC_REG0_FIFO_IRQ_EN                        BIT(3)
>>> +     #define SAR_ADC_REG0_SAMPLING_START                     BIT(2)
>>> +     #define SAR_ADC_REG0_CONTINUOUS_EN                      BIT(1)
>>> +     #define SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE               BIT(0)
>>> +
>>> +#define SAR_ADC_CHAN_LIST                                    0x04
>>> +     #define SAR_ADC_CHAN_LIST_MAX_INDEX_MASK                GENMASK(26, 24)
>>> +     #define SAR_ADC_CHAN_CHAN_ENTRY_MASK(_chan)             \
>>> +                                     (GENMASK(2, 0) << (_chan * 3))
>>> +
>>> +#define SAR_ADC_AVG_CNTL                                     0x08
>>> +     #define SAR_ADC_AVG_CNTL_AVG_MODE_SHIFT(_chan)          \
>>> +                                     (16 + (_chan * 2))
>>> +     #define SAR_ADC_AVG_CNTL_AVG_MODE_MASK(_chan)           \
>>> +                                     (GENMASK(17, 16) << (_chan * 2))
>>> +     #define SAR_ADC_AVG_CNTL_NUM_SAMPLES_SHIFT(_chan)       \
>>> +                                     (0 + (_chan * 2))
>>> +     #define SAR_ADC_AVG_CNTL_NUM_SAMPLES_MASK(_chan)        \
>>> +                                     (GENMASK(1, 0) << (_chan * 2))
>>> +
>>> +#define SAR_ADC_REG3                                         0x0c
>>> +     #define SAR_ADC_REG3_CNTL_USE_SC_DLY                    BIT(31)
>>> +     #define SAR_ADC_REG3_CLK_EN                             BIT(30)
>>> +     #define SAR_ADC_REG3_BL30_INITIALIZED                   BIT(28)
>>> +     #define SAR_ADC_REG3_CTRL_CONT_RING_COUNTER_EN          BIT(27)
>>> +     #define SAR_ADC_REG3_CTRL_SAMPLING_CLOCK_PHASE          BIT(26)
>>> +     #define SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK            GENMASK(25, 23)
>>> +     #define SAR_ADC_REG3_DETECT_EN                          BIT(22)
>>> +     #define SAR_ADC_REG3_ADC_EN                             BIT(21)
>>> +     #define SAR_ADC_REG3_PANEL_DETECT_COUNT_MASK            GENMASK(20, 18)
>>> +     #define SAR_ADC_REG3_PANEL_DETECT_FILTER_TB_MASK        GENMASK(17, 16)
>>> +     #define SAR_ADC_REG3_ADC_CLK_DIV_SHIFT                  10
>>> +     #define SAR_ADC_REG3_ADC_CLK_DIV_WIDTH                  5
>>> +     #define SAR_ADC_REG3_ADC_CLK_DIV_MASK                   GENMASK(15, 10)
>>> +     #define SAR_ADC_REG3_BLOCK_DLY_SEL_MASK                 GENMASK(9, 8)
>>> +     #define SAR_ADC_REG3_BLOCK_DLY_MASK                     GENMASK(7, 0)
>>> +
>>> +#define SAR_ADC_DELAY                                                0x10
>>> +     #define SAR_ADC_DELAY_INPUT_DLY_SEL_MASK                GENMASK(25, 24)
>>> +     #define SAR_ADC_DELAY_BL30_BUSY                         BIT(15)
>>> +     #define SAR_ADC_DELAY_KERNEL_BUSY                       BIT(14)
>>> +     #define SAR_ADC_DELAY_INPUT_DLY_CNT_MASK                GENMASK(23, 16)
>>> +     #define SAR_ADC_DELAY_SAMPLE_DLY_SEL_MASK               GENMASK(9, 8)
>>> +     #define SAR_ADC_DELAY_SAMPLE_DLY_CNT_MASK               GENMASK(7, 0)
>>> +
>>> +#define SAR_ADC_LAST_RD                                              0x14
>>> +     #define SAR_ADC_LAST_RD_LAST_CHANNEL1_MASK              GENMASK(23, 16)
>>> +     #define SAR_ADC_LAST_RD_LAST_CHANNEL0_MASK              GENMASK(9, 0)
>>> +
>>> +#define SAR_ADC_FIFO_RD                                              0x18
>>> +     #define SAR_ADC_FIFO_RD_CHAN_ID_MASK                    GENMASK(14, 12)
>>> +     #define SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK               GENMASK(11, 0)
>>> +
>>> +#define SAR_ADC_AUX_SW                                               0x1c
>>> +     #define SAR_ADC_AUX_SW_MUX_SEL_CHAN_MASK(_chan)         \
>>> +                                     (GENMASK(10, 8) << ((_chan - 2) * 2))
>>> +     #define SAR_ADC_AUX_SW_VREF_P_MUX                       BIT(6)
>>> +     #define SAR_ADC_AUX_SW_VREF_N_MUX                       BIT(5)
>>> +     #define SAR_ADC_AUX_SW_MODE_SEL                         BIT(4)
>>> +     #define SAR_ADC_AUX_SW_YP_DRIVE_SW                      BIT(3)
>>> +     #define SAR_ADC_AUX_SW_XP_DRIVE_SW                      BIT(2)
>>> +     #define SAR_ADC_AUX_SW_YM_DRIVE_SW                      BIT(1)
>>> +     #define SAR_ADC_AUX_SW_XM_DRIVE_SW                      BIT(0)
>>> +
>>> +#define SAR_ADC_CHAN_10_SW                                   0x20
>>> +     #define SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK           GENMASK(25, 23)
>>> +     #define SAR_ADC_CHAN_10_SW_CHAN1_VREF_P_MUX             BIT(22)
>>> +     #define SAR_ADC_CHAN_10_SW_CHAN1_VREF_N_MUX             BIT(21)
>>> +     #define SAR_ADC_CHAN_10_SW_CHAN1_MODE_SEL               BIT(20)
>>> +     #define SAR_ADC_CHAN_10_SW_CHAN1_YP_DRIVE_SW            BIT(19)
>>> +     #define SAR_ADC_CHAN_10_SW_CHAN1_XP_DRIVE_SW            BIT(18)
>>> +     #define SAR_ADC_CHAN_10_SW_CHAN1_YM_DRIVE_SW            BIT(17)
>>> +     #define SAR_ADC_CHAN_10_SW_CHAN1_XM_DRIVE_SW            BIT(16)
>>> +     #define SAR_ADC_CHAN_10_SW_CHAN0_MUX_SEL_MASK           GENMASK(9, 7)
>>> +     #define SAR_ADC_CHAN_10_SW_CHAN0_VREF_P_MUX             BIT(6)
>>> +     #define SAR_ADC_CHAN_10_SW_CHAN0_VREF_N_MUX             BIT(5)
>>> +     #define SAR_ADC_CHAN_10_SW_CHAN0_MODE_SEL               BIT(4)
>>> +     #define SAR_ADC_CHAN_10_SW_CHAN0_YP_DRIVE_SW            BIT(3)
>>> +     #define SAR_ADC_CHAN_10_SW_CHAN0_XP_DRIVE_SW            BIT(2)
>>> +     #define SAR_ADC_CHAN_10_SW_CHAN0_YM_DRIVE_SW            BIT(1)
>>> +     #define SAR_ADC_CHAN_10_SW_CHAN0_XM_DRIVE_SW            BIT(0)
>>> +
>>> +#define SAR_ADC_DETECT_IDLE_SW                                       0x24
>>> +     #define SAR_ADC_DETECT_IDLE_SW_DETECT_SW_EN             BIT(26)
>>> +     #define SAR_ADC_DETECT_IDLE_SW_DETECT_MODE_MUX_MASK     GENMASK(25, 23)
>>> +     #define SAR_ADC_DETECT_IDLE_SW_DETECT_MODE_VREF_P_MUX   BIT(22)
>>> +     #define SAR_ADC_DETECT_IDLE_SW_DETECT_MODE_VREF_N_MUX   BIT(21)
>>> +     #define SAR_ADC_DETECT_IDLE_SW_DETECT_MODE_SEL          BIT(20)
>>> +     #define SAR_ADC_DETECT_IDLE_SW_DETECT_MODE_YP_DRIVE_SW  BIT(19)
>>> +     #define SAR_ADC_DETECT_IDLE_SW_DETECT_MODE_XP_DRIVE_SW  BIT(18)
>>> +     #define SAR_ADC_DETECT_IDLE_SW_DETECT_MODE_YM_DRIVE_SW  BIT(17)
>>> +     #define SAR_ADC_DETECT_IDLE_SW_DETECT_MODE_XM_DRIVE_SW  BIT(16)
>>> +     #define SAR_ADC_DETECT_IDLE_SW_IDLE_MODE_MUX_SEL_MASK   GENMASK(9, 7)
>>> +     #define SAR_ADC_DETECT_IDLE_SW_IDLE_MODE_VREF_P_MUX     BIT(6)
>>> +     #define SAR_ADC_DETECT_IDLE_SW_IDLE_MODE_VREF_N_MUX     BIT(5)
>>> +     #define SAR_ADC_DETECT_IDLE_SW_IDLE_MODE_SEL            BIT(4)
>>> +     #define SAR_ADC_DETECT_IDLE_SW_IDLE_MODE_YP_DRIVE_SW    BIT(3)
>>> +     #define SAR_ADC_DETECT_IDLE_SW_IDLE_MODE_XP_DRIVE_SW    BIT(2)
>>> +     #define SAR_ADC_DETECT_IDLE_SW_IDLE_MODE_YM_DRIVE_SW    BIT(1)
>>> +     #define SAR_ADC_DETECT_IDLE_SW_IDLE_MODE_XM_DRIVE_SW    BIT(0)
>>> +
>>> +#define SAR_ADC_DELTA_10                                     0x28
>>> +     #define SAR_ADC_DELTA_10_TEMP_SEL                       BIT(27)
>>> +     #define SAR_ADC_DELTA_10_TS_REVE1                       BIT(26)
>>> +     #define SAR_ADC_DELTA_10_CHAN1_DELTA_VALUE_SHIFT        16
>>> +     #define SAR_ADC_DELTA_10_CHAN1_DELTA_VALUE_MASK         GENMASK(25, 16)
>>> +     #define SAR_ADC_DELTA_10_TS_REVE0                       BIT(15)
>>> +     #define SAR_ADC_DELTA_10_TS_C_SHIFT                     11
>>> +     #define SAR_ADC_DELTA_10_TS_C_MASK                      GENMASK(14, 11)
>>> +     #define SAR_ADC_DELTA_10_TS_VBG_EN                      BIT(10)
>>> +     #define SAR_ADC_DELTA_10_CHAN0_DELTA_VALUE_SHIFT        0
>>> +     #define SAR_ADC_DELTA_10_CHAN0_DELTA_VALUE_MASK         GENMASK(9, 0)
>>> +
>>> +/* NOTE: registers from here are undocumented (the vendor Linux kernel driver
>>> + * and u-boot source served as reference). These only seem to be relevant on
>>> + * GXBB and newer.
>>> + */
>>> +#define SAR_ADC_REG11                                                0x2c
>>> +     #define SAR_ADC_REG11_BANDGAP_EN                        BIT(13)
>>> +
>>> +#define SAR_ADC_REG13                                                0x34
>>> +     #define SAR_ADC_REG13_12BIT_CALIBRATION_MASK            GENMASK(13, 8)
>>> +
>>> +#define SAR_ADC_MAX_FIFO_SIZE                32
>>> +#define SAR_ADC_NUM_CHANNELS         ARRAY_SIZE(meson_saradc_iio_channels)
>>> +#define SAR_ADC_VALUE_MASK(_priv)    (BIT(_priv->resolution) - 1)
>>> +
>>> +#define MESON_SAR_ADC_CHAN(_chan, _type) {                           \
>>> +     .type = _type,                                                  \
>>> +     .indexed = true,                                                \
>>> +     .channel = _chan,                                               \
>>> +     .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |                  \
>>> +                             BIT(IIO_CHAN_INFO_AVERAGE_RAW),         \
>>> +     .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),           \
>>> +     .datasheet_name = "SAR_ADC_CH"#_chan,                           \
>>> +}
>>> +
>>> +/* TODO: the hardware supports IIO_TEMP for channel 6 as well which is
>> Multline comment syntax.
> I got this wrong in 2 other places as well. will be fixed in v2, thanks!
> 
>>> + * currently not supported by this driver.
>>> + */
>>> +static const struct iio_chan_spec meson_saradc_iio_channels[] = {
>>> +     MESON_SAR_ADC_CHAN(0, IIO_VOLTAGE),
>>> +     MESON_SAR_ADC_CHAN(1, IIO_VOLTAGE),
>>> +     MESON_SAR_ADC_CHAN(2, IIO_VOLTAGE),
>>> +     MESON_SAR_ADC_CHAN(3, IIO_VOLTAGE),
>>> +     MESON_SAR_ADC_CHAN(4, IIO_VOLTAGE),
>>> +     MESON_SAR_ADC_CHAN(5, IIO_VOLTAGE),
>>> +     MESON_SAR_ADC_CHAN(6, IIO_VOLTAGE),
>>> +     MESON_SAR_ADC_CHAN(7, IIO_VOLTAGE),
>>> +     IIO_CHAN_SOFT_TIMESTAMP(8),
>>> +};
>>> +
>>> +enum meson_saradc_avg_mode {
>>> +     NO_AVERAGING = 0x0,
>>> +     MEAN_AVERAGING = 0x1,
>>> +     MEDIAN_AVERAGING = 0x2,
>>> +};
>>> +
>>> +enum meson_saradc_num_samples {
>>> +     ONE_SAMPLE = 0x0,
>>> +     TWO_SAMPLES = 0x1,
>>> +     FOUR_SAMPLES = 0x2,
>>> +     EIGHT_SAMPLES = 0x3,
>>> +};
>>> +
>>> +enum meson_saradc_chan7_mux_sel {
>>> +     CHAN7_MUX_VSS = 0x0,
>>> +     CHAN7_MUX_VDD_DIV4 = 0x1,
>>> +     CHAN7_MUX_VDD_DIV2 = 0x2,
>>> +     CHAN7_MUX_VDD_MUL3_DIV4 = 0x3,
>>> +     CHAN7_MUX_VDD = 0x4,
>>> +     CHAN7_MUX_CH7_INPUT = 0x7,
>>> +};
>>> +
>>> +struct meson_saradc_priv {
>>> +     struct regmap                   *regmap;
>>> +     struct clk                      *clkin;
>>> +     struct clk                      *core_clk;
>>> +     struct clk                      *sana_clk;
>>> +     struct clk                      *adc_sel_clk;
>>> +     struct clk                      *adc_clk;
>>> +     struct clk_gate                 clk_gate;
>>> +     struct clk                      *adc_div_clk;
>>> +     struct clk_divider              clk_div;
>>> +     struct regulator                *vref;
>>> +     struct completion               completion;
>>> +     u8                              resolution;
>>> +};
>>> +
>>> +static const struct regmap_config meson_saradc_regmap_config = {
>>> +     .reg_bits = 8,
>>> +     .val_bits = 32,
>>> +     .reg_stride = 4,
>>> +     .max_register = SAR_ADC_REG13,
>>> +};
>>> +
>>> +static unsigned int meson_saradc_get_fifo_count(struct iio_dev *indio_dev)
>>> +{
>>> +     struct meson_saradc_priv *priv = iio_priv(indio_dev);
>>> +     u32 regval;
>>> +
>>> +     regmap_read(priv->regmap, SAR_ADC_REG0, &regval);
>>> +
>>> +     return FIELD_GET(SAR_ADC_REG0_FIFO_COUNT_MASK, regval);
>>> +}
>>> +
>>> +static int meson_saradc_wait_busy_clear(struct iio_dev *indio_dev)
>>> +{
>>> +     struct meson_saradc_priv *priv = iio_priv(indio_dev);
>>> +     int regval, timeout = 10000;
>>> +
>>> +     do {
>>> +             udelay(1);
>>> +             regmap_read(priv->regmap, SAR_ADC_REG0, &regval);
>>> +     } while (FIELD_GET(SAR_ADC_REG0_BUSY_MASK, regval) && timeout--);
>>> +
>>> +     if (timeout < 0)
>>> +             return -ETIMEDOUT;
>>> +
>>> +     return 0;
>>> +}
>>> +
>>> +static int meson_saradc_read_raw_sample(struct iio_dev *indio_dev,
>>> +                                     const struct iio_chan_spec *chan,
>>> +                                     int *val)
>>> +{
>>> +     struct meson_saradc_priv *priv = iio_priv(indio_dev);
>>> +     int ret, regval, fifo_chan, fifo_val, sum = 0, count = 0;
>>> +
>>> +     ret = meson_saradc_wait_busy_clear(indio_dev);
>>> +     if (ret)
>>> +             return ret;
>>> +
>>> +     regmap_read(priv->regmap, SAR_ADC_REG0, &regval);
>>> +
>>> +     while (meson_saradc_get_fifo_count(indio_dev) > 0 &&
>>> +            count < SAR_ADC_MAX_FIFO_SIZE) {
>>> +             regmap_read(priv->regmap, SAR_ADC_FIFO_RD, &regval);
>>> +
>>> +             fifo_chan = FIELD_GET(SAR_ADC_FIFO_RD_CHAN_ID_MASK, regval);
>>> +             if (fifo_chan == chan->channel) {
>>> +                     fifo_val = FIELD_GET(SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK,
>>> +                                          regval) & SAR_ADC_VALUE_MASK(priv);
>>> +                     sum += fifo_val;
>>> +                     count++;
>>> +             }
>>> +     }
>>> +
>>> +     if (!count)
>>> +             return -ENOENT;
>>> +
>>> +     *val = sum / count;
>>> +
>>> +     return 0;
>>> +}
>>> +
>>> +static void meson_saradc_set_averaging(struct iio_dev *indio_dev,
>>> +                                    const struct iio_chan_spec *chan,
>>> +                                    enum meson_saradc_avg_mode mode,
>>> +                                    enum meson_saradc_num_samples samples)
>>> +{
>>> +     struct meson_saradc_priv *priv = iio_priv(indio_dev);
>>> +     u32 val;
>>> +
>>> +     val = samples << SAR_ADC_AVG_CNTL_NUM_SAMPLES_SHIFT(chan->channel);
>>> +     regmap_update_bits(priv->regmap, SAR_ADC_AVG_CNTL,
>>> +                        SAR_ADC_AVG_CNTL_NUM_SAMPLES_MASK(chan->channel),
>>> +                        val);
>>> +
>>> +     val = mode << SAR_ADC_AVG_CNTL_AVG_MODE_SHIFT(chan->channel);
>>> +     regmap_update_bits(priv->regmap, SAR_ADC_AVG_CNTL,
>>> +                        SAR_ADC_AVG_CNTL_AVG_MODE_MASK(chan->channel), val);
>>> +}
>>> +
>>> +static void meson_saradc_enable_channel(struct iio_dev *indio_dev,
>>> +                                     const struct iio_chan_spec *chan)
>>> +{
>>> +     struct meson_saradc_priv *priv = iio_priv(indio_dev);
>>> +     u32 regval;
>>> +
>>> +     /* the SAR ADC engine allows sampling multiple channels at the same
>>> +      * time. to keep it simple we're only working with one *internal*
>>> +      * channel, which starts counting at index 0 (which means: count = 1).
>>> +      */
>>> +     regval = FIELD_PREP(SAR_ADC_CHAN_LIST_MAX_INDEX_MASK, 0);
>>> +     regmap_update_bits(priv->regmap, SAR_ADC_CHAN_LIST,
>>> +                        SAR_ADC_CHAN_LIST_MAX_INDEX_MASK, regval);
>>> +
>>> +     /* map channel index 0 to the channel which we want to read */
>>> +     regval = FIELD_PREP(SAR_ADC_CHAN_CHAN_ENTRY_MASK(0), chan->channel);
>>> +     regmap_update_bits(priv->regmap, SAR_ADC_CHAN_LIST,
>>> +                        SAR_ADC_CHAN_CHAN_ENTRY_MASK(0), regval);
>>> +
>>> +     regval = FIELD_PREP(SAR_ADC_DETECT_IDLE_SW_DETECT_MODE_MUX_MASK,
>>> +                         chan->channel);
>>> +     regmap_update_bits(priv->regmap, SAR_ADC_DETECT_IDLE_SW,
>>> +                        SAR_ADC_DETECT_IDLE_SW_DETECT_MODE_MUX_MASK,
>>> +                        regval);
>>> +
>>> +     regval = FIELD_PREP(SAR_ADC_DETECT_IDLE_SW_IDLE_MODE_MUX_SEL_MASK,
>>> +                         chan->channel);
>>> +     regmap_update_bits(priv->regmap, SAR_ADC_DETECT_IDLE_SW,
>>> +                        SAR_ADC_DETECT_IDLE_SW_IDLE_MODE_MUX_SEL_MASK,
>>> +                        regval);
>>> +
>>> +     if (chan->channel == 6)
>>> +             regmap_update_bits(priv->regmap, SAR_ADC_DELTA_10,
>>> +                                SAR_ADC_DELTA_10_TEMP_SEL, 0);
>>> +}
>>> +
>>> +static void meson_saradc_set_channel7_mux(struct iio_dev *indio_dev,
>>> +                                       enum meson_saradc_chan7_mux_sel sel)
>>> +{
>>> +     struct meson_saradc_priv *priv = iio_priv(indio_dev);
>>> +     u32 regval;
>>> +
>>> +     regval = FIELD_PREP(SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK, sel);
>>> +     regmap_update_bits(priv->regmap, SAR_ADC_REG3,
>>> +                        SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK, regval);
>>> +
>>> +     usleep_range(10, 20);
>>> +}
>>> +
>>> +static void meson_saradc_start_sample_engine(struct iio_dev *indio_dev)
>>> +{
>>> +     struct meson_saradc_priv *priv = iio_priv(indio_dev);
>>> +
>>> +     regmap_update_bits(priv->regmap, SAR_ADC_REG0,
>>> +                        SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE,
>>> +                        SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE);
>>> +
>>> +     regmap_update_bits(priv->regmap, SAR_ADC_REG0,
>>> +                        SAR_ADC_REG0_SAMPLING_START,
>>> +                        SAR_ADC_REG0_SAMPLING_START);
>>> +}
>>> +
>>> +static void meson_saradc_stop_sample_engine(struct iio_dev *indio_dev)
>>> +{
>>> +     struct meson_saradc_priv *priv = iio_priv(indio_dev);
>>> +
>>> +     regmap_update_bits(priv->regmap, SAR_ADC_REG0,
>>> +                        SAR_ADC_REG0_SAMPLING_STOP,
>>> +                        SAR_ADC_REG0_SAMPLING_STOP);
>>> +
>>> +     /* wait until all modules are stopped */
>>> +     meson_saradc_wait_busy_clear(indio_dev);
>>> +
>>> +     regmap_update_bits(priv->regmap, SAR_ADC_REG0,
>>> +                        SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE, 0);
>>> +}
>>> +
>>> +static void meson_saradc_lock(struct iio_dev *indio_dev)
>>> +{
>>> +     struct meson_saradc_priv *priv = iio_priv(indio_dev);
>>> +     int val;
>>> +
>>> +     mutex_lock(&indio_dev->mlock);
>>> +
>>> +     /* prevent BL30 from using the SAR ADC while we are using it */
>>> +     regmap_update_bits(priv->regmap, SAR_ADC_DELAY,
>>> +                        SAR_ADC_DELAY_KERNEL_BUSY,
>>> +                        SAR_ADC_DELAY_KERNEL_BUSY);
>>> +
>>> +     /* wait until BL30 releases it's lock (so we can use the SAR ADC) */
>>> +     do {
>>> +             udelay(1);
>>> +             regmap_read(priv->regmap, SAR_ADC_DELAY, &val);
>>> +     } while (val & SAR_ADC_DELAY_BL30_BUSY);
>>> +}
>>> +
>>> +static void meson_saradc_unlock(struct iio_dev *indio_dev)
>>> +{
>>> +     struct meson_saradc_priv *priv = iio_priv(indio_dev);
>>> +
>>> +     /* allow BL30 to use the SAR ADC again */
>>> +     regmap_update_bits(priv->regmap, SAR_ADC_DELAY,
>>> +                        SAR_ADC_DELAY_KERNEL_BUSY, 0);
>>> +
>>> +     mutex_unlock(&indio_dev->mlock);
>>> +}
>>> +
>>> +static int meson_saradc_get_sample(struct iio_dev *indio_dev,
>>> +                                const struct iio_chan_spec *chan,
>>> +                                enum meson_saradc_avg_mode avg_mode,
>>> +                                enum meson_saradc_num_samples avg_samples,
>>> +                                int *val)
>>> +{
>>> +     int ret, tmp;
>>> +
>>> +     meson_saradc_lock(indio_dev);
>>> +
>>> +     /* clear old values from the FIFO buffer, ignoring errors */
>>> +     meson_saradc_read_raw_sample(indio_dev, chan, &tmp);
>>> +
>>> +     meson_saradc_set_averaging(indio_dev, chan, avg_mode, avg_samples);
>>> +
>>> +     meson_saradc_enable_channel(indio_dev, chan);
>>> +
>>> +     meson_saradc_start_sample_engine(indio_dev);
>>> +     ret = meson_saradc_read_raw_sample(indio_dev, chan, val);
>>> +     meson_saradc_stop_sample_engine(indio_dev);
>>> +
>>> +     meson_saradc_unlock(indio_dev);
>>> +
>>> +     if (ret) {
>>> +             dev_warn(&indio_dev->dev,
>>> +                      "failed to read sample for channel %d: %d\n",
>>> +                      chan->channel, ret);
>>> +             return ret;
>>> +     }
>>> +
>>> +     return IIO_VAL_INT;
>>> +}
>>> +
>>> +static int meson_saradc_iio_info_read_raw(struct iio_dev *indio_dev,
>>> +                                       const struct iio_chan_spec *chan,
>>> +                                       int *val, int *val2, long mask)
>>> +{
>>> +     struct meson_saradc_priv *priv = iio_priv(indio_dev);
>>> +     int ret;
>>> +
>>> +     switch (mask) {
>>> +     case IIO_CHAN_INFO_RAW:
>>> +             return meson_saradc_get_sample(indio_dev, chan, NO_AVERAGING,
>>> +                                            ONE_SAMPLE, val);
>>> +             break;
>>> +
>>> +     case IIO_CHAN_INFO_AVERAGE_RAW:
>>> +             return meson_saradc_get_sample(indio_dev, chan, MEAN_AVERAGING,
>>> +                                            EIGHT_SAMPLES, val);
>>> +             break;
>>> +
>>> +     case IIO_CHAN_INFO_SCALE:
>>> +             ret = regulator_get_voltage(priv->vref);
>>> +             if (ret < 0) {
>>> +                     dev_err(&indio_dev->dev,
>>> +                             "failed to get vref voltage: %d\n", ret);
>>> +                     return ret;
>>> +             }
>>> +
>>> +             *val = ret / 1000;
>>> +             *val2 = priv->resolution;
>>> +             return IIO_VAL_FRACTIONAL_LOG2;
>>> +
>>> +     default:
>>> +             return -EINVAL;
>>> +     }
>>> +}
>>> +
>>> +static int meson_saradc_clk_init(struct iio_dev *indio_dev, void __iomem *base)
>>> +{
>>> +     struct meson_saradc_priv *priv = iio_priv(indio_dev);
>>> +     struct clk_init_data init;
>>> +     char clk_name[32];
>>> +     const char *clk_parents[1];
>>> +
>>> +     snprintf(clk_name, sizeof(clk_name), "%s#adc_div",
>>> +              of_node_full_name(indio_dev->dev.of_node));
>>> +     init.name = devm_kstrdup(&indio_dev->dev, clk_name, GFP_KERNEL);
>>> +     init.flags = 0;
>>> +     init.ops = &clk_divider_ops;
>>> +     clk_parents[0] = __clk_get_name(priv->clkin);
>>> +     init.parent_names = clk_parents;
>>> +     init.num_parents = 1;
>>> +
>>> +     priv->clk_div.reg = base + SAR_ADC_REG3;
>>> +     priv->clk_div.shift = SAR_ADC_REG3_ADC_CLK_DIV_SHIFT;
>>> +     priv->clk_div.width = SAR_ADC_REG3_ADC_CLK_DIV_WIDTH;
>>> +     priv->clk_div.hw.init = &init;
>>> +     priv->clk_div.flags = 0;
>>> +
>>> +     priv->adc_div_clk = devm_clk_register(&indio_dev->dev,
>>> +                                           &priv->clk_div.hw);
>>> +     if (WARN_ON(IS_ERR(priv->adc_div_clk)))
>>> +             return PTR_ERR(priv->adc_div_clk);
>>> +
>>> +     snprintf(clk_name, sizeof(clk_name), "%s#adc_en",
>>> +              of_node_full_name(indio_dev->dev.of_node));
>>> +     init.name = devm_kstrdup(&indio_dev->dev, clk_name, GFP_KERNEL);
>>> +     init.flags = CLK_SET_RATE_PARENT;
>>> +     init.ops = &clk_gate_ops;
>>> +     clk_parents[0] = __clk_get_name(priv->adc_div_clk);
>>> +     init.parent_names = clk_parents;
>>> +     init.num_parents = 1;
>>> +
>>> +     priv->clk_gate.reg = base + SAR_ADC_REG3;
>>> +     priv->clk_gate.bit_idx = fls(SAR_ADC_REG3_CLK_EN);
>>> +     priv->clk_gate.hw.init = &init;
>>> +
>>> +     priv->adc_clk = devm_clk_register(&indio_dev->dev, &priv->clk_gate.hw);
>>> +     if (WARN_ON(IS_ERR(priv->adc_clk)))
>>> +             return PTR_ERR(priv->adc_clk);
>>> +
>>> +     return 0;
>>> +}
>>> +
>>> +static int meson_saradc_init(struct iio_dev *indio_dev)
>>> +{
>>> +     struct meson_saradc_priv *priv = iio_priv(indio_dev);
>>> +     int regval, ret;
>>> +
>>> +     /* make sure we start at CH7 input */
>> why?  Seems like a little more detail would be good here ;)
> I'll change this to "make sure we start at CH7 input since the other
> muxes are only used for internal calibration." in v2
> 
>>> +     meson_saradc_set_channel7_mux(indio_dev, CHAN7_MUX_CH7_INPUT);
>>> +
>>> +     regmap_read(priv->regmap, SAR_ADC_REG3, &regval);
>>> +     if (regval & SAR_ADC_REG3_BL30_INITIALIZED) {
>>> +             dev_info(&indio_dev->dev, "already initialized by BL30\n");
>>> +             return 0;
>>> +     }
>>> +
>>> +     dev_info(&indio_dev->dev, "initializing SAR ADC\n");
>> I'd argue this provides no useful info so should be dropped.
>> Useful for debugging no doubt, but just noise going forward.
> do you want me to remove them or should I turn them into dev_dbg() (so
> they can be enabled for debugging purposes)?
Drop it entirely.
> 
>>> +
>>> +     meson_saradc_stop_sample_engine(indio_dev);
>>> +
>>> +     /* update the channel 6 MUX to select the temperature sensor */
>>> +     regmap_update_bits(priv->regmap, SAR_ADC_REG0,
>>> +                     SAR_ADC_REG0_ADC_TEMP_SEN_SEL,
>>> +                     SAR_ADC_REG0_ADC_TEMP_SEN_SEL);
>>> +
>>> +     /* disable all channels by default */
>>> +     regmap_write(priv->regmap, SAR_ADC_CHAN_LIST, 0x0);
>>> +
>>> +     regmap_update_bits(priv->regmap, SAR_ADC_REG3,
>>> +                        SAR_ADC_REG3_CTRL_SAMPLING_CLOCK_PHASE, 0);
>>> +     regmap_update_bits(priv->regmap, SAR_ADC_REG3,
>>> +                        SAR_ADC_REG3_CNTL_USE_SC_DLY,
>>> +                        SAR_ADC_REG3_CNTL_USE_SC_DLY);
>>> +
>>> +     /* delay between two samples = (10+1) * 1uS */
>>> +     regmap_update_bits(priv->regmap, SAR_ADC_DELAY,
>>> +                        SAR_ADC_DELAY_INPUT_DLY_CNT_MASK,
>>> +                        FIELD_PREP(SAR_ADC_DELAY_SAMPLE_DLY_CNT_MASK, 10));
>>> +     regmap_update_bits(priv->regmap, SAR_ADC_DELAY,
>>> +                        SAR_ADC_DELAY_SAMPLE_DLY_SEL_MASK,
>>> +                        FIELD_PREP(SAR_ADC_DELAY_SAMPLE_DLY_SEL_MASK, 0));
>>> +
>>> +     /* delay between two samples = (10+1) * 1uS */
>>> +     regmap_update_bits(priv->regmap, SAR_ADC_DELAY,
>>> +                        SAR_ADC_DELAY_INPUT_DLY_CNT_MASK,
>>> +                        FIELD_PREP(SAR_ADC_DELAY_INPUT_DLY_CNT_MASK, 10));
>>> +     regmap_update_bits(priv->regmap, SAR_ADC_DELAY,
>>> +                        SAR_ADC_DELAY_INPUT_DLY_SEL_MASK,
>>> +                        FIELD_PREP(SAR_ADC_DELAY_INPUT_DLY_SEL_MASK, 1));
>>> +
>> Cool. I hadn't come across FIELD_PREP before. Neater and tidier than having
>> a shift and a mask for at least some usecases.
> I think these were introduced with v4.9. I like them because I tend
> use GENMASK() incorrectly and with those macros I get an error at
> compile-time (without having to debug my code at all)
> 
>>> +     ret = clk_set_parent(priv->adc_sel_clk, priv->clkin);
>>> +     if (ret) {
>>> +             dev_err(&indio_dev->dev,
>>> +                     "failed to set adc parent to clkin\n");
>>> +             return ret;
>>> +     }
>>> +
>>> +     ret = clk_set_rate(priv->adc_clk, 1200000);
>>> +     if (ret) {
>>> +             dev_err(&indio_dev->dev, "failed to set adc clock rate\n");
>>> +             return ret;
>>> +     }
>>> +
>>> +     return 0;
>>> +}
>>> +
>>> +static int meson_saradc_hw_enable(struct iio_dev *indio_dev)
>>> +{
>>> +     struct meson_saradc_priv *priv = iio_priv(indio_dev);
>>> +     int ret;
>>> +
>>> +     meson_saradc_lock(indio_dev);
>>> +
>>> +     ret = regulator_enable(priv->vref);
>>> +     if (ret < 0) {
>>> +             dev_err(&indio_dev->dev, "failed to enable vref regulator\n");
>>> +             goto err_vref;
>>> +     }
>>> +
>>> +     ret = clk_prepare_enable(priv->core_clk);
>>> +     if (ret) {
>>> +             dev_err(&indio_dev->dev, "failed to enable core clk\n");
>>> +             goto err_core_clk;
>>> +     }
>>> +
>>> +     ret = clk_prepare_enable(priv->sana_clk);
>>> +     if (ret) {
>>> +             dev_err(&indio_dev->dev, "failed to enable sana clk\n");
>>> +             goto err_sana_clk;
>>> +     }
>>> +
>>> +     regmap_update_bits(priv->regmap, SAR_ADC_REG11,
>>> +                        SAR_ADC_REG11_BANDGAP_EN, SAR_ADC_REG11_BANDGAP_EN);
>> Is this controlling an offset for a bandgap or some actual electronics?
>> Not sure if it should be disabled on error and the datasheets I've found are
>> far from great!  You disable it in the disable, so I'd expect it to be
>> unwound on error in here too.
> actually the bandgap is not documented at all :(
> 
>>> +     regmap_update_bits(priv->regmap, SAR_ADC_REG3, SAR_ADC_REG3_ADC_EN,
>>> +                        SAR_ADC_REG3_ADC_EN);
>> The fact you turn this of in the disable suggests to me that on error
>> you should be doing it in here too.
> I will disable this along with SAR_ADC_REG11_BANDGAP_EN in the
> err_adc_clk label, thanks for spotting this.
> 
>>> +
>>> +     udelay(5);
>>> +
>>> +     ret = clk_prepare_enable(priv->adc_clk);
>>> +     if (ret) {
>>> +             dev_err(&indio_dev->dev, "failed to enable adc_en clk\n");
>>> +             goto err_adc_clk;
>>> +     }
>>> +
>>> +     meson_saradc_unlock(indio_dev);
>>> +
>>> +     return 0;
>>> +
>>> +err_adc_clk:
>>> +     clk_disable_unprepare(priv->sana_clk);
>>> +err_sana_clk:
>>> +     clk_disable_unprepare(priv->core_clk);
>>> +err_core_clk:
>>> +     regulator_disable(priv->vref);
>>> +err_vref:
>>> +     meson_saradc_unlock(indio_dev);
>>> +     return ret;
>>> +}
>>> +
>>> +static void meson_saradc_hw_disable(struct iio_dev *indio_dev)
>>> +{
>>> +     struct meson_saradc_priv *priv = iio_priv(indio_dev);
>>> +
>>> +     meson_saradc_lock(indio_dev);
>>> +
>>> +     clk_disable_unprepare(priv->adc_clk);
>>> +
>>> +     regmap_update_bits(priv->regmap, SAR_ADC_REG3, SAR_ADC_REG3_ADC_EN, 0);
>>> +     regmap_update_bits(priv->regmap, SAR_ADC_REG11,
>>> +                        SAR_ADC_REG11_BANDGAP_EN, 0);
>>> +
>>> +     clk_disable_unprepare(priv->sana_clk);
>>> +     clk_disable_unprepare(priv->core_clk);
>>> +
>>> +     regulator_disable(priv->vref);
>>> +
>>> +     meson_saradc_unlock(indio_dev);
>>> +}
>>> +
>>> +static const struct iio_info meson_saradc_iio_info = {
>>> +     .read_raw = meson_saradc_iio_info_read_raw,
>>> +     .driver_module = THIS_MODULE,
>>> +};
>>> +
>>> +static const struct of_device_id meson_saradc_of_match[] = {
>>> +     {
>>> +             .compatible = "amlogic,meson-gxbb-saradc",
>>> +             .data = (void *)10,
>> Might have been worth having a structure array indexed from an enum.
>> For now it is overkill, but seems likely there are a few other differences
>> that aren't supported yet?
> what do you mean with "structure array indexed from an enum"? I can
> introduce some match-specific struct if you want (just like it's done
> in rockchip_saradc.c with "struct rockchip_saradc_data").
That works, or data can be an enum indexing an array of similar structures.
It doesn't really matter.
> 
>>> +     }, {
>>> +             .compatible = "amlogic,meson-gxl-saradc",
>>> +             .data = (void *)12,
>>> +     },
>>> +     {},
>>> +};
>>> +MODULE_DEVICE_TABLE(of, meson_saradc_of_match);
>>> +
>>> +static int meson_saradc_probe(struct platform_device *pdev)
>>> +{
>>> +     struct meson_saradc_priv *priv;
>>> +     struct iio_dev *indio_dev;
>>> +     struct resource *res;
>>> +     void __iomem *base;
>>> +     const struct of_device_id *match;
>>> +     int ret;
>>> +
>>> +     indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
>>> +     if (!indio_dev) {
>>> +             dev_err(&pdev->dev, "failed allocating iio device\n");
>>> +             return -ENOMEM;
>>> +     }
>>> +
>>> +     priv = iio_priv(indio_dev);
>>> +
>>> +     match = of_match_device(meson_saradc_of_match, &pdev->dev);
>>> +     priv->resolution = (unsigned long)match->data;
>>> +
>>> +     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>> +     base = devm_ioremap_resource(&pdev->dev, res);
>>> +     if (IS_ERR(base))
>>> +             return PTR_ERR(base);
>>> +
>>> +     priv->regmap = devm_regmap_init_mmio(&pdev->dev, base,
>>> +                                          &meson_saradc_regmap_config);
>>> +     if (IS_ERR(priv->regmap))
>>> +             return PTR_ERR(priv->regmap);
>>> +
>>> +     init_completion(&priv->completion);
>>> +
>>> +     priv->clkin = devm_clk_get(&pdev->dev, "clkin");
>>> +     if (IS_ERR(priv->clkin)) {
>>> +             dev_err(&pdev->dev, "failed to get clkin\n");
>>> +             return PTR_ERR(priv->clkin);
>>> +     }
>>> +
>>> +     priv->core_clk = devm_clk_get(&pdev->dev, "core");
>>> +     if (IS_ERR(priv->core_clk)) {
>>> +             dev_err(&pdev->dev, "failed to get core clk\n");
>>> +             return PTR_ERR(priv->core_clk);
>>> +     }
>>> +
>>> +     priv->sana_clk = devm_clk_get(&pdev->dev, "sana");
>> Oh for a devm_clk_get_optional to handle this boiler plate neatly.
>> It's been suggested before, but nothing seems to have come of it.
> I guess quite a few drivers would benefit from that. maybe we should
> take this to the linux-clk list again?
Perhaps. I guess this has been proposed before but gone nowhere.
I haven't digged into why though.
> 
>> Some array clk get functions might also clean this up a touch.
> yes, unfortunately in this case it's not that easy as it would have to
> allow a mix of mandatory and optional clocks. Additionally I cannot
> bulk-enable them unconditionally since some of these are simple gates,
> others need to be reparented and for some the rate has to be set.
> 
>>> +     if (IS_ERR(priv->sana_clk)) {
>>> +             if (PTR_ERR(priv->sana_clk) == -ENOENT) {
>>> +                     priv->sana_clk = NULL;
>>> +             } else {
>>> +                     dev_err(&pdev->dev, "failed to get sana clk\n");
>>> +                     return PTR_ERR(priv->sana_clk);
>>> +             }
>>> +     }
>>> +
>>> +     priv->adc_clk = devm_clk_get(&pdev->dev, "adc_clk");
>>> +     if (IS_ERR(priv->adc_clk)) {
>>> +             if (PTR_ERR(priv->adc_clk) == -ENOENT) {
>>> +                     priv->adc_clk = NULL;
>>> +             } else {
>>> +                     dev_err(&pdev->dev, "failed to get adc clk\n");
>>> +                     return PTR_ERR(priv->adc_clk);
>>> +             }
>>> +     }
>>> +
>>> +     priv->adc_sel_clk = devm_clk_get(&pdev->dev, "adc_sel");
>>> +     if (IS_ERR(priv->adc_sel_clk)) {
>>> +             if (PTR_ERR(priv->adc_sel_clk) == -ENOENT) {
>>> +                     priv->adc_sel_clk = NULL;
>>> +             } else {
>>> +                     dev_err(&pdev->dev, "failed to get adc_sel clk\n");
>>> +                     return PTR_ERR(priv->adc_sel_clk);
>>> +             }
>>> +     }
>>> +
>>> +     /* on pre-GXBB SoCs the SAR ADC itself provides the ADC clock: */
>>> +     if (!priv->adc_clk) {
>>> +             ret = meson_saradc_clk_init(indio_dev, base);
>>> +             if (ret)
>>> +                     return ret;
>>> +     }
>>> +
>>> +     priv->vref = devm_regulator_get(&pdev->dev, "vref");
>>> +     if (IS_ERR(priv->vref)) {
>>> +             dev_err(&pdev->dev, "failed to get vref regulator\n");
>>> +             return PTR_ERR(priv->vref);
>>> +     }
>>> +
>>> +     ret = meson_saradc_init(indio_dev);
>>> +     if (ret)
>>> +             goto err;
>>> +
>>> +     ret = meson_saradc_hw_enable(indio_dev);
>>> +     if (ret)
>>> +             goto err;
>>> +
>>> +     platform_set_drvdata(pdev, indio_dev);
>>> +
>>> +     indio_dev->name = dev_name(&pdev->dev);
>>> +     indio_dev->dev.parent = &pdev->dev;
>>> +     indio_dev->dev.of_node = pdev->dev.of_node;
>>> +     indio_dev->modes = INDIO_DIRECT_MODE;
>>> +     indio_dev->info = &meson_saradc_iio_info;
>>> +
>>> +     indio_dev->channels = meson_saradc_iio_channels;
>>> +     indio_dev->num_channels = SAR_ADC_NUM_CHANNELS;
>>> +
>>> +     ret = iio_device_register(indio_dev);
>>> +     if (ret)
>>> +             goto err_hw;
>>> +
>>> +     return 0;
>>> +
>>> +err_hw:
>>> +     meson_saradc_hw_disable(indio_dev);
>>> +err:
>>> +     return ret;
>>> +}
>>> +
>>> +static int meson_saradc_remove(struct platform_device *pdev)
>>> +{
>>> +     struct iio_dev *indio_dev = platform_get_drvdata(pdev);
>>> +
>>> +     meson_saradc_hw_disable(indio_dev);
>>> +     iio_device_unregister(indio_dev);
>>> +
>>> +     return 0;
>>> +}
>>> +
>>> +#ifdef CONFIG_PM_SLEEP
>>> +static int meson_saradc_suspend(struct device *dev)
>>> +{
>>> +     struct iio_dev *indio_dev = dev_get_drvdata(dev);
>>> +
>>> +     meson_saradc_hw_disable(indio_dev);
>>> +
>>> +     return 0;
>>> +}
>>> +
>>> +static int meson_saradc_resume(struct device *dev)
>>> +{
>>> +     struct iio_dev *indio_dev = dev_get_drvdata(dev);
>>> +
>>> +     return meson_saradc_hw_enable(indio_dev);
>>> +}
>>> +#endif /* CONFIG_PM_SLEEP */
>>> +
>>> +static SIMPLE_DEV_PM_OPS(meson_saradc_pm_ops,
>>> +                      meson_saradc_suspend, meson_saradc_resume);
>>> +
>>> +static struct platform_driver meson_saradc_driver = {
>>> +     .probe          = meson_saradc_probe,
>>> +     .remove         = meson_saradc_remove,
>>> +     .driver         = {
>>> +             .name   = "meson-saradc",
>>> +             .of_match_table = meson_saradc_of_match,
>>> +             .pm = &meson_saradc_pm_ops,
>>> +     },
>>> +};
>>> +
>>> +module_platform_driver(meson_saradc_driver);
>>> +
>>> +MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
>>> +MODULE_DESCRIPTION("Amlogic Meson SAR ADC driver");
>>> +MODULE_LICENSE("GPL v2");
>>>
>>
> 
> 
> Regards,
> Martin
> 
> [0] http://lists.infradead.org/pipermail/linux-amlogic/2016-August/000986.html
> 


^ permalink raw reply

* Re: [PATCH 3/4] iio: adc: add a driver for the SAR ADC found in Amlogic Meson SoCs
From: Jonathan Cameron @ 2017-01-15 13:09 UTC (permalink / raw)
  To: Lars-Peter Clausen, Martin Blumenstingl, knaack.h, pmeerw,
	robh+dt, mark.rutland, khilman, linux-iio, devicetree,
	linux-amlogic, linux-clk
  Cc: carlo, catalin.marinas, will.deacon, mturquette, sboyd,
	narmstrong, linux-arm-kernel
In-Reply-To: <0bfa97d1-2ee3-9dd9-dce3-593e93771f03@metafoo.de>

On 15/01/17 12:26, Lars-Peter Clausen wrote:
> On 01/11/2017 06:43 PM, Martin Blumenstingl wrote:
>> +	indio_dev->name = dev_name(&pdev->dev);
> 
> The name is supposed to be the type of the device, e.g. part name, not the
> name of parent device instance. E.g. meson-gxbb-saradc or meson-gxl-saradc
> in this case.
Drat. I've been missing these again.  Somehow, never manage to get them
onto those things my eyes pick up whilst reviewing.

Thanks Lars,

Jonathan
> 
> --
> 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 v2 2/2] iio: distance: srf08: add IIO driver for us ranger
From: Jonathan Cameron @ 2017-01-15 13:12 UTC (permalink / raw)
  To: Andreas Klinger
  Cc: knaack.h-Mmb7MZpHnFY, lars-Qo5EllUWu/uELgA04lAiVw,
	pmeerw-jW+XmwGofnusTnJN9+BGXg, linux-iio-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, ktsai-GubuWUlQtMwciDkP5Hr2oA,
	wsa-z923LK4zBo2bacvFa/9K2g, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	pawel.moll-5wv7dgnIgG8, mark.rutland-5wv7dgnIgG8,
	ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg,
	galak-sgV2jX0FEOL9JmXXK+q4OQ, trivial-DgEjT+Ai2ygdnm+yROfE0A,
	mranostay-Re5JQEeQqe8AvxtiuMwx3w,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20170114174856.GA2351@andreas>

On 14/01/17 17:48, Andreas Klinger wrote:
> Hi Jonathan,
> 
> see comments below.
> 
> Andreas
> 
> 
> Jonathan Cameron <jic23-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> schrieb am Sat, 14. Jan 12:17:
>> On 10/01/17 18:48, Andreas Klinger wrote:
>>> This is the IIO driver for devantech srf08 ultrasonic ranger which can be
>>> used to measure the distances to an object.
>>>
>>> The sensor supports I2C with some registers.
>>>
>>> Supported Features include:
>>> - read the distance in ranging mode in centimeters
>>> - output of the driver is directly the read value
>>> - together with the scale the driver delivers the distance in meters
>>> - only the first echo of the nearest object is delivered
>>> - set max gain register; userspace enters analogue value
>>> - set range registers; userspace enters range in millimeters in 43 mm steps
>>>
>>> Features not supported by this driver:
>>> - ranging mode in inches or in microseconds
>>> - ANN mode
>>> - change I2C address through this driver
>>> - light sensor
>>>
>>> The driver was added in the directory "proximity" of the iio subsystem
>>> in absence of another directory named "distance".
>>> There is also a new submenu "distance"
>> Hi Andreas,
>>
>> Sorry it took me a while to get to this!
>>
>> I'd not bother with the new submenu.  Perhaps we should rename the
>> proximity menu to proximity/distance.
>>
>> We already the lightening detector in there which is definitely not
>> measuring proximity in the convetional sense!
>>
>> Anyhow, the actual code is fine, but we need to think about how the
>> userspace ABI fits within the wider IIO ABI.  Naming and approaches
>> that make sense in a single class of drivers can end up meaining
>> very different things for other drivers.  Various suggestions inline.
>>
>> Jonathan
>>>
>>> Signed-off-by: Andreas Klinger <ak-n176/SwNRljddJNmlsFzeA@public.gmane.org>
>>> ---
>>>  drivers/iio/proximity/Kconfig  |  15 ++
>>>  drivers/iio/proximity/Makefile |   1 +
>>>  drivers/iio/proximity/srf08.c  | 362 +++++++++++++++++++++++++++++++++++++++++
>>>  3 files changed, 378 insertions(+)
>>>  create mode 100644 drivers/iio/proximity/srf08.c
>>>
>>> diff --git a/drivers/iio/proximity/Kconfig b/drivers/iio/proximity/Kconfig
>>> index ef4c73db5b53..7b10a137702b 100644
>>> --- a/drivers/iio/proximity/Kconfig
>>> +++ b/drivers/iio/proximity/Kconfig
>>> @@ -46,3 +46,18 @@ config SX9500
>>>  	  module will be called sx9500.
>>>  
>>>  endmenu
>>> +
>>> +menu "Distance sensors"
>>> +
>>> +config SRF08
>>> +	tristate "Devantech SRF08 ultrasonic ranger sensor"
>>> +	depends on I2C
>>> +	help
>>> +	  Say Y here to build a driver for Devantech SRF08 ultrasonic
>>> +	  ranger sensor. This driver can be used to measure the distance
>>> +	  of objects.
>>> +
>>> +	  To compile this driver as a module, choose M here: the
>>> +	  module will be called srf08.
>>> +
>>> +endmenu
>>> diff --git a/drivers/iio/proximity/Makefile b/drivers/iio/proximity/Makefile
>>> index 9aadd9a8ee99..e914c2a5dd49 100644
>>> --- a/drivers/iio/proximity/Makefile
>>> +++ b/drivers/iio/proximity/Makefile
>>> @@ -5,4 +5,5 @@
>>>  # When adding new entries keep the list in alphabetical order
>>>  obj-$(CONFIG_AS3935)		+= as3935.o
>>>  obj-$(CONFIG_LIDAR_LITE_V2)	+= pulsedlight-lidar-lite-v2.o
>>> +obj-$(CONFIG_SRF08)		+= srf08.o
>>>  obj-$(CONFIG_SX9500)		+= sx9500.o
>>> diff --git a/drivers/iio/proximity/srf08.c b/drivers/iio/proximity/srf08.c
>>> new file mode 100644
>>> index 000000000000..f38c74ed0933
>>> --- /dev/null
>>> +++ b/drivers/iio/proximity/srf08.c
>>> @@ -0,0 +1,362 @@
>>> +/*
>>> + * srf08.c - Support for Devantech SRF08 ultrasonic ranger
>>> + *
>>> + * Copyright (c) 2016 Andreas Klinger <ak-n176/SwNRljddJNmlsFzeA@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.
>>> + *
>>> + * For details about the device see:
>>> + * http://www.robot-electronics.co.uk/htm/srf08tech.html
>>> + */
>>> +
>>> +#include <linux/err.h>
>>> +#include <linux/i2c.h>
>>> +#include <linux/delay.h>
>>> +#include <linux/module.h>
>>> +#include <linux/bitops.h>
>>> +#include <linux/iio/iio.h>
>>> +#include <linux/iio/sysfs.h>
>>> +
>>> +/* registers of SRF08 device */
>>> +#define SRF08_WRITE_COMMAND	0x00	/* Command Register */
>>> +#define SRF08_WRITE_MAX_GAIN	0x01	/* Max Gain Register: 0 .. 31 */
>>> +#define SRF08_WRITE_RANGE	0x02	/* Range Register: 0 .. 255 */
>>> +#define SRF08_READ_SW_REVISION	0x00	/* Software Revision */
>>> +#define SRF08_READ_LIGHT	0x01	/* Light Sensor during last echo */
>>> +#define SRF08_READ_ECHO_1_HIGH	0x02	/* Range of first echo received */
>>> +#define SRF08_READ_ECHO_1_LOW	0x03	/* Range of first echo received */
>>> +
>>> +#define SRF08_CMD_RANGING_CM	0x51	/* Ranging Mode - Result in cm */
>>> +
>>> +#define SRF08_DEFAULT_GAIN	1025	/* max. analogue value of Gain */
>>> +#define SRF08_DEFAULT_RANGE	11008	/* max. value of Range in mm */
>>> +
>>> +struct srf08_data {
>>> +	struct i2c_client	*client;
>>> +	int			gain;			/* Max Gain */
>>> +	int			range_mm;		/* Range in mm */
>>> +	struct mutex		lock;
>>> +};
>>> +
>>> +static const int srf08_gain[] = {
>>> +	 94,  97, 100, 103, 107, 110, 114, 118,
>>> +	123, 128, 133, 139, 145, 152, 159, 168,
>>> +	177, 187, 199, 212, 227, 245, 265, 288,
>>> +	317, 352, 395, 450, 524, 626, 777, 1025 };
>>> +
>>> +static int srf08_read_ranging(struct srf08_data *data)
>>> +{
>>> +	struct i2c_client *client = data->client;
>>> +	int ret, i;
>>> +
>>> +	mutex_lock(&data->lock);
>>> +
>>> +	ret = i2c_smbus_write_byte_data(data->client,
>>> +			SRF08_WRITE_COMMAND, SRF08_CMD_RANGING_CM);
>>> +	if (ret < 0) {
>>> +		dev_err(&client->dev, "write command - err: %d\n", ret);
>>> +		mutex_unlock(&data->lock);
>>> +		return ret;
>>> +	}
>>> +
>>> +	/*
>>> +	 * normally after 65 ms the device should have the read value
>>> +	 * we round it up to 100 ms
>> I'd suggest this should be adapted so that it takes advantage of knowing
>> roughly how long it is going to take as the 'range' maximum is changed.
>> So perhaps in the basic case, sleep for 65 msecs, then poll at 5msec
>> intervals.  If we know it's going to be a lot faster, then poll it from
>> an earlier time.
>>> +	 *
>>> +	 * we read here until a correct version number shows up as
>>> +	 * suggested by the documentation
>>> +	 */
>>> +	for (i = 0; i < 5; i++) {
>>> +		ret = i2c_smbus_read_byte_data(data->client,
>>> +						SRF08_READ_SW_REVISION);
>>> +
>>> +		/* check if a valid version number is read */
>>> +		if (ret < 255 && ret > 0)
>>> +			break;
>>> +		msleep(20);
>>> +	}
>>> +
>>> +	if (ret >= 255 || ret <= 0) {
>>> +		dev_err(&client->dev, "device not ready\n");
>>> +		mutex_unlock(&data->lock);
>>> +		return -EIO;
>>> +	}
>>> +
>>> +	ret = i2c_smbus_read_word_swapped(data->client,
>>> +						SRF08_READ_ECHO_1_HIGH);
>>> +	if (ret < 0) {
>>> +		dev_err(&client->dev, "cannot read distance: ret=%d\n", ret);
>>> +		mutex_unlock(&data->lock);
>>> +		return ret;
>>> +	}
>>> +
>>> +	mutex_unlock(&data->lock);
>>> +
>>> +	return ret;
>>> +}
>>> +
>>> +static int srf08_read_raw(struct iio_dev *indio_dev,
>>> +			    struct iio_chan_spec const *channel, int *val,
>>> +			    int *val2, long mask)
>>> +{
>>> +	struct srf08_data *data = iio_priv(indio_dev);
>>> +	int ret;
>>> +
>>> +	if (channel->type != IIO_DISTANCE)
>>> +		return -EINVAL;
>>> +
>>> +	switch (mask) {
>>> +	case IIO_CHAN_INFO_RAW:
>>> +		ret = srf08_read_ranging(data);
>>> +		if (ret < 0)
>>> +			return ret;
>>> +		*val = ret;
>>> +		return IIO_VAL_INT;
>>> +	case IIO_CHAN_INFO_SCALE:
>>> +		/* 1 LSB is 1 cm */
>>> +		*val = 0;
>>> +		*val2 = 10000;
>>> +		return IIO_VAL_INT_PLUS_MICRO;
>>> +	default:
>>> +		return -EINVAL;
>>> +	}
>>> +}
>>> +
>>> +static ssize_t srf08_show_range_mm_available(struct device *dev,
>>> +				struct device_attribute *attr, char *buf)
>>> +{
>>> +	int i, len = 0;
>>> +
>>> +	for (i = 0; i < 256; i++)
>>> +		len += scnprintf(buf + len, PAGE_SIZE - len,
>>> +							"%d ", (i + 1) * 43);
>>> +
>>> +	buf[len - 1] = '\n';
>>> +
>>> +	return len;
>>> +}
>>> +
>>> +static IIO_DEVICE_ATTR(range_mm_available, S_IRUGO,
>>> +				srf08_show_range_mm_available, NULL, 0);
>>> +
>>> +static ssize_t srf08_show_range_mm(struct device *dev,
>>> +				struct device_attribute *attr, char *buf)
>>> +{
>>> +	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
>>> +	struct srf08_data *data = iio_priv(indio_dev);
>>> +
>>> +	return sprintf(buf, "%d\n", data->range_mm);
>>> +}
>>> +
>>> +/*
>>> + * set the range of the sensor to an even multiple of 43 mm
>>> + * which corresponds to 1 LSB in the register
>>> + *
>>> + * register value    corresponding range
>>> + *         0x00             43 mm
>>> + *         0x01             86 mm
>>> + *         0x02            129 mm
>>> + *         ...
>>> + *         0xFF          11008 mm
>>> + */
>>> +static ssize_t srf08_write_range_mm(struct device *dev,
>>> +					struct device_attribute *attr,
>>> +					const char *buf, size_t len)
>>> +{
>>> +	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
>>> +	struct srf08_data *data = iio_priv(indio_dev);
>>> +	struct i2c_client *client = data->client;
>>> +	int ret;
>>> +	unsigned int val, mod;
>>> +	u8 regval;
>>> +
>>> +	ret = kstrtouint(buf, 10, &val);
>>> +	if (ret)
>>> +		return ret;
>>> +
>>> +	ret = val / 43 - 1;
>>> +	mod = val % 43;
>>> +
>>> +	if (mod || (ret < 0) || (ret > 255))
>>> +		return -EINVAL;
>>> +
>>> +	regval = ret;
>>> +
>>> +	mutex_lock(&data->lock);
>>> +
>>> +	ret = i2c_smbus_write_byte_data(data->client,
>>> +						SRF08_WRITE_RANGE, regval);
>>> +	if (ret < 0) {
>>> +		dev_err(&client->dev, "write_range - err: %d\n", ret);
>>> +		mutex_unlock(&data->lock);
>>> +		return ret;
>>> +	}
>>> +
>>> +	data->range_mm = val;
>>> +
>>> +	mutex_unlock(&data->lock);
>>> +
>>> +	return len;
>>> +}
>>> +
>>> +static IIO_DEVICE_ATTR(range_mm, S_IRUGO | S_IWUSR,
>>> +			srf08_show_range_mm, srf08_write_range_mm, 0);
>>> +
>>> +static ssize_t srf08_show_gain_available(struct device *dev,
>>> +				struct device_attribute *attr, char *buf)
>>> +{
>>> +	int i, len = 0;
>>> +
>>> +	for (i = 0; i < ARRAY_SIZE(srf08_gain); i++)
>>> +		len += sprintf(buf + len, "%d ", srf08_gain[i]);
>>> +
>>> +	len += sprintf(buf + len, "\n");
>>> +
>>> +	return len;
>>> +}
>>> +
>>> +static IIO_DEVICE_ATTR(gain_available, S_IRUGO,
>>> +				srf08_show_gain_available, NULL, 0);
>>> +
>>> +static ssize_t srf08_show_gain(struct device *dev,
>>> +				struct device_attribute *attr, char *buf)
>>> +{
>>> +	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
>>> +	struct srf08_data *data = iio_priv(indio_dev);
>>> +	int len;
>>> +
>>> +	len = sprintf(buf, "%d\n", data->gain);
>>> +
>>> +	return len;
>>> +}
>>> +
>>> +static ssize_t srf08_write_gain(struct device *dev,
>>> +						struct device_attribute *attr,
>>> +						const char *buf, size_t len)
>>> +{
>>> +	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
>>> +	struct srf08_data *data = iio_priv(indio_dev);
>>> +	struct i2c_client *client = data->client;
>>> +	int ret, i;
>>> +	unsigned int val;
>>> +	u8 regval;
>>> +
>>> +	ret = kstrtouint(buf, 10, &val);
>>> +	if (ret)
>>> +		return ret;
>>> +
>>> +	for (i = 0; i < ARRAY_SIZE(srf08_gain); i++)
>>> +		if (val == srf08_gain[i]) {
>>> +			regval = i;
>>> +			break;
>>> +		}
>>> +
>>> +	if (i >= ARRAY_SIZE(srf08_gain))
>>> +		return -EINVAL;
>>> +
>>> +	mutex_lock(&data->lock);
>>> +
>>> +	ret = i2c_smbus_write_byte_data(data->client,
>>> +						SRF08_WRITE_MAX_GAIN, regval);
>>> +	if (ret < 0) {
>>> +		dev_err(&client->dev, "write_gain - err: %d\n", ret);
>>> +		mutex_unlock(&data->lock);
>>> +		return ret;
>>> +	}
>>> +
>>> +	data->gain = val;
>>> +
>>> +	mutex_unlock(&data->lock);
>>> +
>>> +	return len;
>>> +}
>>> +
>>> +static IIO_DEVICE_ATTR(gain, S_IRUGO | S_IWUSR,
>>> +					srf08_show_gain, srf08_write_gain, 0);
>>> +
>>> +static struct attribute *srf08_attributes[] = {
>>> +	&iio_dev_attr_range_mm.dev_attr.attr,
>>> +	&iio_dev_attr_range_mm_available.dev_attr.attr,
>>> +	&iio_dev_attr_gain.dev_attr.attr,
>>> +	&iio_dev_attr_gain_available.dev_attr.attr,
>> Hmm. Custom attributes always give us issues. The primary point of IIO
>> is to enforce (more or less) standard interfaces.
>>
>> If you do need to add something new then that is fine (and I do think
>> you need to here!).
>>
>> They need to be formally proposed as an addition to the ABI with
>> docs in /Documentation/ABI/testing/sysfs-bus-iio*
>>
>> Once we take one driver using it it becomes part of our ABI that
>> userspace will need to handle, hence we consider these very
>> carefully.
>>
>> My gut feeling would be that gain needs to be more specific as it's
>> a term that can mean very different things.. Here we are talking
>> about an amplifier on a signal that we are then looking at the timing
>> of.   It might otherwise be interpretted as another term for what
>> we term 'scale' in IIO.
>>
>> So what to call it... Perhaps afegain for Analog front end gain?
>> We might want to add this to the core supported attrs, but lets
>> not do so until we see if we have this on a number of devices.
>>
> 
> In /Documentation/ABI/testing/sysfs-bus-iio-proximity-as3935 there is also a
> gain used in a similar situation and it's called there "sensor_sensitivity"
> 
> What it we also use this name here?
It's not ideal as it's not linked to a particular channel or anything,
but lets go with that as at least we will be consistent between drivers.
> 
>> The description would need to make it explicit that this gain is
>> for cases where we aren't measuring the magnitude of what is
>> being amplified.
>>
>> For the range, it's an interesting one.  Again the term range could
>> mean too many things within the wider ABI. We need to make it more
>> specific.
>>
>> Actually reading the datasheet, I think this is fundamentally about the
>> maximum sampling frequency rather than directly about the range.
>> The only reason you'd reduce the range is to speed that up. It doesn't
>> improve the resolution, the device simply answers quicker.
>>
>> So I'd support this as sampling_frequency.  You could then use
>> the the iio_info_mask_*_available and relevant callback to provide
>> info on what it then restricts the possible output values to
>> (rather than controlling it directly).
>>
> 
> By changing the range one cannot influence the sampling frequency directly. I
> have seen on the oszilloscope that the telegrams arrive almost at the same time
> with different settings of range and the same gain.
> 
> Only if the gain is also adjusted the sensor works faster and a higher frequency
> can be used. But the gain is also used to adjust the sensitivity of the sensor. 
That's rather weird and not what the datasheet suggests. Ah well.
> 
> What about calling it "sensor_domain" or "sensor_max_range"?
hmm. Not sure - propose that with appropriate Docs and we can think more on it.
> 
> 
>>> +	NULL,
>>> +};
>>> +
>>> +static const struct attribute_group srf08_attribute_group = {
>>> +	.attrs = srf08_attributes,
>>> +};
>>> +
>>> +static const struct iio_chan_spec srf08_channels[] = {
>>> +	{
>>> +		.type = IIO_DISTANCE,
>>> +		.info_mask_separate =
>>> +				BIT(IIO_CHAN_INFO_RAW) |
>>> +				BIT(IIO_CHAN_INFO_SCALE),
>>> +	},
>>> +};
>>> +
>>> +static const struct iio_info srf08_info = {
>>> +	.read_raw = srf08_read_raw,
>>> +	.attrs = &srf08_attribute_group,
>>> +	.driver_module = THIS_MODULE,
>>> +};
>>> +
>>> +static int srf08_probe(struct i2c_client *client,
>>> +					 const struct i2c_device_id *id)
>>> +{
>>> +	struct iio_dev *indio_dev;
>>> +	struct srf08_data *data;
>>> +
>>> +	if (!i2c_check_functionality(client->adapter,
>>> +					I2C_FUNC_SMBUS_READ_BYTE_DATA |
>>> +					I2C_FUNC_SMBUS_WRITE_BYTE_DATA |
>>> +					I2C_FUNC_SMBUS_READ_WORD_DATA))
>>> +		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;
>>> +
>>> +	/*
>>> +	 * set default values of device here
>>> +	 * these values are already set on the hardware after power on
>>> +	 */
>>> +	data->gain = SRF08_DEFAULT_GAIN;
>>> +	data->range_mm = SRF08_DEFAULT_RANGE;
>> We should be a little careful with assumptions about the device having
>> just been powered on.  The driver might simply have been removed and
>> reprobed.  So I'd sugest rewriting them whatever to be sure we have
>> what we expect.  Either that or if they can be read back, then just
>> always retrieve them from the device.
> 
> You are right. 
> Then i'll set the default value at the sensor, because it cannot be read.
> 
>>> +
>>> +	indio_dev->name = dev_name(&client->dev);
>>> +	indio_dev->dev.parent = &client->dev;
>>> +	indio_dev->modes = INDIO_DIRECT_MODE;
>>> +	indio_dev->info = &srf08_info;
>>> +	indio_dev->channels = srf08_channels;
>>> +	indio_dev->num_channels = ARRAY_SIZE(srf08_channels);
>>> +
>>> +	mutex_init(&data->lock);
>>> +
>>> +	return devm_iio_device_register(&client->dev, indio_dev);
>>> +}
>>> +
>>> +static const struct i2c_device_id srf08_id[] = {
>>> +	{ "srf08", 0 },
>>> +	{ }
>>> +};
>>> +MODULE_DEVICE_TABLE(i2c, srf08_id);
>>> +
>>> +static struct i2c_driver srf08_driver = {
>>> +	.driver = {
>>> +		.name	= "srf08",
>>> +	},
>>> +	.probe = srf08_probe,
>>> +	.id_table = srf08_id,
>>> +};
>>> +module_i2c_driver(srf08_driver);
>>> +
>>> +MODULE_AUTHOR("Andreas Klinger <ak-n176/SwNRljddJNmlsFzeA@public.gmane.org>");
>>> +MODULE_DESCRIPTION("Devantech SRF08 ultrasonic ranger driver");
>>> +MODULE_LICENSE("GPL");
>>>
>>
> 

^ permalink raw reply

* [PATCH v2 0/5] nput: mpr121 - switch to use device tree probe
From: Akinobu Mita @ 2017-01-15 13:15 UTC (permalink / raw)
  To: linux-input, devicetree; +Cc: Akinobu Mita, Dmitry Torokhov, Rob Herring

This driver currently only supports legacy platform data probe.  This
change adds device tree support and gets rid of platform data probe code
since no one is actually using mpr121 platform data in the mainline.

This series also contains miscellaneous cleanup and bug fixes that
mostly I found while playing with this driver.

* Changes since v1 (All changes are suggested by Dmitry Torokhov)
- Add patch 'annotate PM methods as __maybe_unused'
- Use for_each_set_bit() to search changed bit
- Use linux,keycodes property instead of using matrix keymap API
- Get rid of platform data

Akinobu Mita (5):
  Input: mpr121 - annotate PM methods as __maybe_unused
  Input: mpr121 - remove unused field in struct mpr121_touchkey
  Input: mpr121 - set missing event capability
  Input: mpr121 - handle multiple bits change of status register
  Input: mpr121 - switch to device tree probe

 .../devicetree/bindings/input/mpr121-touchkey.txt  |  30 +++++
 drivers/input/keyboard/mpr121_touchkey.c           | 141 ++++++++++++++-------
 include/linux/i2c/mpr121_touchkey.h                |  20 ---
 3 files changed, 127 insertions(+), 64 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/input/mpr121-touchkey.txt
 delete mode 100644 include/linux/i2c/mpr121_touchkey.h

Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Rob Herring <robh@kernel.org>
-- 
2.7.4


^ permalink raw reply

* [PATCH v2 1/5] Input: mpr121 - annotate PM methods as __maybe_unused
From: Akinobu Mita @ 2017-01-15 13:15 UTC (permalink / raw)
  To: linux-input-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: Akinobu Mita, Dmitry Torokhov
In-Reply-To: <1484486144-27947-1-git-send-email-akinobu.mita-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

Instead of using #ifdef, let's mark suspend and resume methods as
__maybe_unused to provide better compile coverage.

Cc: Dmitry Torokhov <dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Suggested-by: Dmitry Torokhov <dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Akinobu Mita <akinobu.mita-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
* Newly added patch from v2

 drivers/input/keyboard/mpr121_touchkey.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/input/keyboard/mpr121_touchkey.c b/drivers/input/keyboard/mpr121_touchkey.c
index 0fd612d..a3fd6e5 100644
--- a/drivers/input/keyboard/mpr121_touchkey.c
+++ b/drivers/input/keyboard/mpr121_touchkey.c
@@ -266,8 +266,7 @@ static int mpr_touchkey_probe(struct i2c_client *client,
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int mpr_suspend(struct device *dev)
+static int __maybe_unused mpr_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 
@@ -279,7 +278,7 @@ static int mpr_suspend(struct device *dev)
 	return 0;
 }
 
-static int mpr_resume(struct device *dev)
+static int __maybe_unused mpr_resume(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct mpr121_touchkey *mpr121 = i2c_get_clientdata(client);
@@ -292,7 +291,6 @@ static int mpr_resume(struct device *dev)
 
 	return 0;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(mpr121_touchkey_pm_ops, mpr_suspend, mpr_resume);
 
-- 
2.7.4

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

^ permalink raw reply related

* [PATCH v2 2/5] Input: mpr121 - remove unused field in struct mpr121_touchkey
From: Akinobu Mita @ 2017-01-15 13:15 UTC (permalink / raw)
  To: linux-input-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: Akinobu Mita, Dmitry Torokhov
In-Reply-To: <1484486144-27947-1-git-send-email-akinobu.mita-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

Remove unused key_val field in struct mpr121_touchkey.

Cc: Dmitry Torokhov <dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Akinobu Mita <akinobu.mita-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
* No changes from v1

 drivers/input/keyboard/mpr121_touchkey.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/input/keyboard/mpr121_touchkey.c b/drivers/input/keyboard/mpr121_touchkey.c
index a3fd6e5..90be99d 100644
--- a/drivers/input/keyboard/mpr121_touchkey.c
+++ b/drivers/input/keyboard/mpr121_touchkey.c
@@ -59,7 +59,6 @@
 struct mpr121_touchkey {
 	struct i2c_client	*client;
 	struct input_dev	*input_dev;
-	unsigned int		key_val;
 	unsigned int		statusbits;
 	unsigned int		keycount;
 	u16			keycodes[MPR121_MAX_KEY_COUNT];
-- 
2.7.4

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

^ permalink raw reply related

* [PATCH v2 3/5] Input: mpr121 - set missing event capability
From: Akinobu Mita @ 2017-01-15 13:15 UTC (permalink / raw)
  To: linux-input-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: Akinobu Mita, Dmitry Torokhov
In-Reply-To: <1484486144-27947-1-git-send-email-akinobu.mita-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

This driver reports misc scan input events on the sensor's status
register changes.  But the event capability for them was not set in the
device initialization, so these events were ignored.

This change adds the missing event capability.

Cc: Dmitry Torokhov <dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Akinobu Mita <akinobu.mita-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
* No changes from v1

 drivers/input/keyboard/mpr121_touchkey.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/input/keyboard/mpr121_touchkey.c b/drivers/input/keyboard/mpr121_touchkey.c
index 90be99d..2558c60 100644
--- a/drivers/input/keyboard/mpr121_touchkey.c
+++ b/drivers/input/keyboard/mpr121_touchkey.c
@@ -230,6 +230,7 @@ static int mpr_touchkey_probe(struct i2c_client *client,
 	input_dev->id.bustype = BUS_I2C;
 	input_dev->dev.parent = &client->dev;
 	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
+	input_set_capability(input_dev, EV_MSC, MSC_SCAN);
 
 	input_dev->keycode = mpr121->keycodes;
 	input_dev->keycodesize = sizeof(mpr121->keycodes[0]);
-- 
2.7.4

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

^ permalink raw reply related

* [PATCH v2 4/5] Input: mpr121 - handle multiple bits change of status register
From: Akinobu Mita @ 2017-01-15 13:15 UTC (permalink / raw)
  To: linux-input-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: Akinobu Mita, Dmitry Torokhov
In-Reply-To: <1484486144-27947-1-git-send-email-akinobu.mita-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

This driver reports input events on their interrupts which are triggered
by the sensor's status register changes.  But only single bit change is
reported in the interrupt handler.  So if there are multiple bits are
changed at almost the same time, other press or release events are ignored.

This fixes it by detecting all changed bits in the status register.

Cc: Dmitry Torokhov <dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Akinobu Mita <akinobu.mita-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
* Use for_each_set_bit() to search changed bit

 drivers/input/keyboard/mpr121_touchkey.c | 23 ++++++++++++++---------
 1 file changed, 14 insertions(+), 9 deletions(-)

diff --git a/drivers/input/keyboard/mpr121_touchkey.c b/drivers/input/keyboard/mpr121_touchkey.c
index 2558c60..a0210ae 100644
--- a/drivers/input/keyboard/mpr121_touchkey.c
+++ b/drivers/input/keyboard/mpr121_touchkey.c
@@ -86,7 +86,8 @@ static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id)
 	struct mpr121_touchkey *mpr121 = dev_id;
 	struct i2c_client *client = mpr121->client;
 	struct input_dev *input = mpr121->input_dev;
-	unsigned int key_num, key_val, pressed;
+	unsigned long bit_changed;
+	unsigned int key_num;
 	int reg;
 
 	reg = i2c_smbus_read_byte_data(client, ELE_TOUCH_STATUS_1_ADDR);
@@ -104,18 +105,22 @@ static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id)
 
 	reg &= TOUCH_STATUS_MASK;
 	/* use old press bit to figure out which bit changed */
-	key_num = ffs(reg ^ mpr121->statusbits) - 1;
-	pressed = reg & (1 << key_num);
+	bit_changed = reg ^ mpr121->statusbits;
 	mpr121->statusbits = reg;
+	for_each_set_bit(key_num, &bit_changed, mpr121->keycount) {
+		unsigned int key_val, pressed;
 
-	key_val = mpr121->keycodes[key_num];
+		pressed = reg & (1 << key_num);
+		key_val = mpr121->keycodes[key_num];
 
-	input_event(input, EV_MSC, MSC_SCAN, key_num);
-	input_report_key(input, key_val, pressed);
-	input_sync(input);
+		input_event(input, EV_MSC, MSC_SCAN, key_num);
+		input_report_key(input, key_val, pressed);
+
+		dev_dbg(&client->dev, "key %d %d %s\n", key_num, key_val,
+			pressed ? "pressed" : "released");
 
-	dev_dbg(&client->dev, "key %d %d %s\n", key_num, key_val,
-		pressed ? "pressed" : "released");
+	}
+	input_sync(input);
 
 out:
 	return IRQ_HANDLED;
-- 
2.7.4

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

^ permalink raw reply related

* [PATCH v2 5/5] Input: mpr121 - switch to device tree probe
From: Akinobu Mita @ 2017-01-15 13:15 UTC (permalink / raw)
  To: linux-input-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: Akinobu Mita, Dmitry Torokhov, Rob Herring
In-Reply-To: <1484486144-27947-1-git-send-email-akinobu.mita-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

This driver currently only supports legacy platform data probe.  This
change adds device tree support and gets rid of platform data probe code
since no one is actually using mpr121 platform data in the mainline.

The device tree property parsing code is based on the work of
atmel_captouch driver.

Cc: Dmitry Torokhov <dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Cc: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Signed-off-by: Akinobu Mita <akinobu.mita-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
* Newly added patch from v2

 .../devicetree/bindings/input/mpr121-touchkey.txt  |  30 ++++++
 drivers/input/keyboard/mpr121_touchkey.c           | 110 +++++++++++++++------
 include/linux/i2c/mpr121_touchkey.h                |  20 ----
 3 files changed, 110 insertions(+), 50 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/input/mpr121-touchkey.txt
 delete mode 100644 include/linux/i2c/mpr121_touchkey.h

diff --git a/Documentation/devicetree/bindings/input/mpr121-touchkey.txt b/Documentation/devicetree/bindings/input/mpr121-touchkey.txt
new file mode 100644
index 0000000..b7c61ee
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/mpr121-touchkey.txt
@@ -0,0 +1,30 @@
+* Freescale MPR121 Controllor
+
+Required Properties:
+- compatible:		Should be "fsl,mpr121-touchkey"
+- reg:			The I2C slave address of the device.
+- interrupts:		The interrupt number to the cpu.
+- vdd-supply:		Phandle to the Vdd power supply.
+- linux,keycodes:	Specifies an array of numeric keycode values to
+			be used for reporting button presses. The array can
+			contain up to 12 entries.
+
+Optional Properties:
+- wakeup-source:	Use any event on keypad as wakeup event.
+- autorepeat:		Enable autorepeat feature.
+
+Example:
+
+#include "dt-bindings/input/input.h"
+
+	touchkey: mpr121@5a {
+		compatible = "fsl,mpr121-touchkey";
+		reg = <0x5a>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <28 2>;
+		autorepeat;
+		vdd-supply = <&ldo4_reg>;
+		linux,keycodes = <KEY_0>, <KEY_1>, <KEY_2>, <KEY_3>,
+				<KEY_4> <KEY_5>, <KEY_6>, <KEY_7>,
+				<KEY_8>, <KEY_9>, <KEY_A>, <KEY_B>;
+	};
diff --git a/drivers/input/keyboard/mpr121_touchkey.c b/drivers/input/keyboard/mpr121_touchkey.c
index a0210ae..ebb401f 100644
--- a/drivers/input/keyboard/mpr121_touchkey.c
+++ b/drivers/input/keyboard/mpr121_touchkey.c
@@ -19,7 +19,7 @@
 #include <linux/delay.h>
 #include <linux/bitops.h>
 #include <linux/interrupt.h>
-#include <linux/i2c/mpr121_touchkey.h>
+#include <linux/regulator/consumer.h>
 
 /* Register definitions */
 #define ELE_TOUCH_STATUS_0_ADDR	0x0
@@ -61,7 +61,7 @@ struct mpr121_touchkey {
 	struct input_dev	*input_dev;
 	unsigned int		statusbits;
 	unsigned int		keycount;
-	u16			keycodes[MPR121_MAX_KEY_COUNT];
+	u32			keycodes[MPR121_MAX_KEY_COUNT];
 };
 
 struct mpr121_init_register {
@@ -81,6 +81,42 @@ static const struct mpr121_init_register init_reg_table[] = {
 	{ AUTO_CONFIG_CTRL_ADDR, 0x0b },
 };
 
+static void mpr121_vdd_supply_disable(void *data)
+{
+	struct regulator *vdd_supply = data;
+
+	regulator_disable(vdd_supply);
+}
+
+static struct regulator *mpr121_vdd_supply_init(struct device *dev)
+{
+	struct regulator *vdd_supply;
+	int err;
+
+	vdd_supply = devm_regulator_get(dev, "vdd");
+	if (IS_ERR(vdd_supply)) {
+		dev_err(dev, "failed to get vdd regulator: %ld\n",
+			PTR_ERR(vdd_supply));
+		return vdd_supply;
+	}
+
+	err = regulator_enable(vdd_supply);
+	if (err) {
+		dev_err(dev, "failed to enable vdd regulator: %d\n", err);
+		return ERR_PTR(err);
+	}
+
+	err = devm_add_action(dev, mpr121_vdd_supply_disable, vdd_supply);
+	if (err) {
+		regulator_disable(vdd_supply);
+		dev_err(dev, "failed to add disable regulator action: %d\n",
+			err);
+		return ERR_PTR(err);
+	}
+
+	return vdd_supply;
+}
+
 static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id)
 {
 	struct mpr121_touchkey *mpr121 = dev_id;
@@ -126,9 +162,8 @@ static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static int mpr121_phys_init(const struct mpr121_platform_data *pdata,
-				      struct mpr121_touchkey *mpr121,
-				      struct i2c_client *client)
+static int mpr121_phys_init(struct mpr121_touchkey *mpr121,
+			    struct i2c_client *client, int vdd_uv)
 {
 	const struct mpr121_init_register *reg;
 	unsigned char usl, lsl, tl, eleconf;
@@ -158,9 +193,9 @@ static int mpr121_phys_init(const struct mpr121_platform_data *pdata,
 	/*
 	 * Capacitance on sensing input varies and needs to be compensated.
 	 * The internal MPR121-auto-configuration can do this if it's
-	 * registers are set properly (based on pdata->vdd_uv).
+	 * registers are set properly (based on vdd_uv).
 	 */
-	vdd = pdata->vdd_uv / 1000;
+	vdd = vdd_uv / 1000;
 	usl = ((vdd - 700) * 256) / vdd;
 	lsl = (usl * 65) / 100;
 	tl = (usl * 90) / 100;
@@ -191,27 +226,19 @@ static int mpr121_phys_init(const struct mpr121_platform_data *pdata,
 static int mpr_touchkey_probe(struct i2c_client *client,
 			      const struct i2c_device_id *id)
 {
-	const struct mpr121_platform_data *pdata =
-			dev_get_platdata(&client->dev);
+	struct device *dev = &client->dev;
+	struct regulator *vdd_supply;
+	int vdd_uv;
 	struct mpr121_touchkey *mpr121;
 	struct input_dev *input_dev;
 	int error;
 	int i;
 
-	if (!pdata) {
-		dev_err(&client->dev, "no platform data defined\n");
-		return -EINVAL;
-	}
+	vdd_supply = mpr121_vdd_supply_init(dev);
+	if (IS_ERR(vdd_supply))
+		return PTR_ERR(vdd_supply);
 
-	if (!pdata->keymap || !pdata->keymap_size) {
-		dev_err(&client->dev, "missing keymap data\n");
-		return -EINVAL;
-	}
-
-	if (pdata->keymap_size > MPR121_MAX_KEY_COUNT) {
-		dev_err(&client->dev, "too many keys defined\n");
-		return -EINVAL;
-	}
+	vdd_uv = regulator_get_voltage(vdd_supply);
 
 	if (!client->irq) {
 		dev_err(&client->dev, "irq number should not be zero\n");
@@ -229,24 +256,37 @@ static int mpr_touchkey_probe(struct i2c_client *client,
 
 	mpr121->client = client;
 	mpr121->input_dev = input_dev;
-	mpr121->keycount = pdata->keymap_size;
+	mpr121->keycount = device_property_read_u32_array(dev, "linux,keycodes",
+							NULL, 0);
+	if (mpr121->keycount > MPR121_MAX_KEY_COUNT) {
+		dev_err(dev, "too many keys defined\n");
+		return -EINVAL;
+	}
+
+	error = device_property_read_u32_array(dev, "linux,keycodes",
+						mpr121->keycodes,
+						mpr121->keycount);
+	if (error) {
+		dev_err(dev,
+			"failed to read linux,keycode property: %d\n", error);
+		return error;
+	}
 
 	input_dev->name = "Freescale MPR121 Touchkey";
 	input_dev->id.bustype = BUS_I2C;
 	input_dev->dev.parent = &client->dev;
-	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
+	if (device_property_present(dev, "autorepeat"))
+		__set_bit(EV_REP, input_dev->evbit);
 	input_set_capability(input_dev, EV_MSC, MSC_SCAN);
 
 	input_dev->keycode = mpr121->keycodes;
 	input_dev->keycodesize = sizeof(mpr121->keycodes[0]);
 	input_dev->keycodemax = mpr121->keycount;
 
-	for (i = 0; i < pdata->keymap_size; i++) {
-		input_set_capability(input_dev, EV_KEY, pdata->keymap[i]);
-		mpr121->keycodes[i] = pdata->keymap[i];
-	}
+	for (i = 0; i < mpr121->keycount; i++)
+		input_set_capability(input_dev, EV_KEY, mpr121->keycodes[i]);
 
-	error = mpr121_phys_init(pdata, mpr121, client);
+	error = mpr121_phys_init(mpr121, client, vdd_uv);
 	if (error) {
 		dev_err(&client->dev, "Failed to init register\n");
 		return error;
@@ -266,7 +306,8 @@ static int mpr_touchkey_probe(struct i2c_client *client,
 		return error;
 
 	i2c_set_clientdata(client, mpr121);
-	device_init_wakeup(&client->dev, pdata->wakeup);
+	device_init_wakeup(dev,
+			device_property_read_bool(dev, "wakeup-source"));
 
 	return 0;
 }
@@ -305,10 +346,19 @@ static const struct i2c_device_id mpr121_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, mpr121_id);
 
+#ifdef CONFIG_OF
+static const struct of_device_id mpr121_touchkey_dt_match_table[] = {
+	{ .compatible = "fsl,mpr121-touchkey" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, mpr121_touchkey_dt_match_table);
+#endif
+
 static struct i2c_driver mpr_touchkey_driver = {
 	.driver = {
 		.name	= "mpr121",
 		.pm	= &mpr121_touchkey_pm_ops,
+		.of_match_table = of_match_ptr(mpr121_touchkey_dt_match_table),
 	},
 	.id_table	= mpr121_id,
 	.probe		= mpr_touchkey_probe,
diff --git a/include/linux/i2c/mpr121_touchkey.h b/include/linux/i2c/mpr121_touchkey.h
deleted file mode 100644
index f0bcc38..0000000
--- a/include/linux/i2c/mpr121_touchkey.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* Header file for Freescale MPR121 Capacitive Touch Sensor */
-
-#ifndef _MPR121_TOUCHKEY_H
-#define _MPR121_TOUCHKEY_H
-
-/**
- * struct mpr121_platform_data - platform data for mpr121 sensor
- * @keymap: pointer to array of KEY_* values representing keymap
- * @keymap_size: size of the keymap
- * @wakeup: configure the button as a wake-up source
- * @vdd_uv: VDD voltage in uV
- */
-struct mpr121_platform_data {
-	const unsigned short *keymap;
-	unsigned int keymap_size;
-	bool wakeup;
-	int vdd_uv;
-};
-
-#endif /* _MPR121_TOUCHKEY_H */
-- 
2.7.4

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

^ permalink raw reply related

* [PATCH] pcie: ti: Provide patch to force GEN1 PCIe operation
From: Lukasz Majewski @ 2017-01-15 13:19 UTC (permalink / raw)
  To: Kishon Vijay Abraham I, Bjorn Helgaas
  Cc: Rob Herring, Mark Rutland, Jingoo Han, Joao Pinto,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Lukasz Majewski

Some devices (due to e.g. bad PCIe signal integrity) require to run
with forced GEN1 speed on PCIe bus.

This patch changes the speed explicitly on dra7 based devices when
proper device tree attribute is defined for the PCIe controller.

Signed-off-by: Lukasz Majewski <lukma-ynQEQJNshbs@public.gmane.org>
---

Patch applies on newest origin/master
SHA1: f4d3935e4f4884ba80561db5549394afb8eef8f7

Tested at AM5728

---
 Documentation/devicetree/bindings/pci/ti-pci.txt |  1 +
 drivers/pci/host/pci-dra7xx.c                    | 23 +++++++++++++++++++++++
 drivers/pci/host/pcie-designware.h               |  1 +
 3 files changed, 25 insertions(+)

diff --git a/Documentation/devicetree/bindings/pci/ti-pci.txt b/Documentation/devicetree/bindings/pci/ti-pci.txt
index 60e2516..9f97409 100644
--- a/Documentation/devicetree/bindings/pci/ti-pci.txt
+++ b/Documentation/devicetree/bindings/pci/ti-pci.txt
@@ -25,6 +25,7 @@ PCIe Designware Controller
 
 Optional Property:
  - gpios : Should be added if a gpio line is required to drive PERST# line
+ - to,pcie-is-gen1: Indicates that forced gen1 port operation is needed.
 
 Example:
 axi {
diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-dra7xx.c
index 9595fad..eec5fae 100644
--- a/drivers/pci/host/pci-dra7xx.c
+++ b/drivers/pci/host/pci-dra7xx.c
@@ -63,6 +63,13 @@
 #define	LINK_UP						BIT(16)
 #define	DRA7XX_CPU_TO_BUS_ADDR				0x0FFFFFFF
 
+#define         PCIECTRL_EP_DBICS_LNK_CAP                       0x007C
+#define         MAX_LINK_SPEEDS_MASK				GENMASK(3, 0)
+#define         MAX_LINK_SPEEDS_GEN1                            BIT(0)
+
+#define         PCIECTRL_PL_WIDTH_SPEED_CTL                     0x080C
+#define         CFG_DIRECTED_SPEED_CHANGE                       BIT(17)
+
 struct dra7xx_pcie {
 	struct pcie_port	pp;
 	void __iomem		*base;		/* DT ti_conf */
@@ -270,6 +277,7 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx,
 	struct pcie_port *pp = &dra7xx->pp;
 	struct device *dev = pp->dev;
 	struct resource *res;
+	u32 val;
 
 	pp->irq = platform_get_irq(pdev, 1);
 	if (pp->irq < 0) {
@@ -296,6 +304,18 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx,
 	if (!pp->dbi_base)
 		return -ENOMEM;
 
+	if (pp->is_gen1) {
+		dev_info(dev, "GEN1 forced\n");
+
+		val = readl(pp->dbi_base + PCIECTRL_EP_DBICS_LNK_CAP);
+		set_mask_bits(&val, MAX_LINK_SPEEDS_MASK, MAX_LINK_SPEEDS_GEN1);
+		writel(val, pp->dbi_base + PCIECTRL_EP_DBICS_LNK_CAP);
+
+		val = readl(pp->dbi_base + PCIECTRL_PL_WIDTH_SPEED_CTL);
+		val &= ~CFG_DIRECTED_SPEED_CHANGE;
+		writel(val, pp->dbi_base + PCIECTRL_PL_WIDTH_SPEED_CTL);
+	}
+
 	ret = dw_pcie_host_init(pp);
 	if (ret) {
 		dev_err(dev, "failed to initialize host\n");
@@ -404,6 +424,9 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev)
 		goto err_gpio;
 	}
 
+	if (of_property_read_bool(np, "ti,pcie-is-gen1"))
+		pp->is_gen1 = true;
+
 	reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD);
 	reg &= ~LTSSM_EN;
 	dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD, reg);
diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h
index a567ea2..2fb0b18 100644
--- a/drivers/pci/host/pcie-designware.h
+++ b/drivers/pci/host/pcie-designware.h
@@ -50,6 +50,7 @@ struct pcie_port {
 	struct irq_domain	*irq_domain;
 	unsigned long		msi_data;
 	u8			iatu_unroll_enabled;
+	u8                      is_gen1;
 	DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS);
 };
 
-- 
2.1.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 1/3] DT/bindings: Add bindings for TI ADS7950 A/DC chips
From: Jonathan Cameron @ 2017-01-15 13:52 UTC (permalink / raw)
  To: David Lechner, devicetree, linux-iio
  Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Rob Herring, Mark Rutland, linux-kernel
In-Reply-To: <662a48e1-39fc-4fb7-a3b9-b671d2e40029@lechnology.com>

On 14/01/17 18:00, David Lechner wrote:
> On 01/14/2017 06:53 AM, Jonathan Cameron wrote:
>> On 11/01/17 17:52, David Lechner wrote:
>>> This adds device tree bindings for the TI ADS7950 family of A/DC chips.
>>>
>>> Signed-off-by: David Lechner <david@lechnology.com>
>> This is in of itself good, but we may need to have some deprecated
>> elements to continue supporting what was implicitly happening with
>> the missnaming so as to avoid accidentally breaking someone's device
>> tree.
>>
> 
> As I mentioned in my cover letter, this driver, as far as I can tell,
> only exists in your testing branch, so I find it highly unlikely that
> we would be breaking anyone. It is not in mainline and it is not even
> in linux-next.

Oops, I not only have a memory like a goldfish, I clearly didn't read your
cover letter either.

Applied to the togreg branch of iio.git and pushed out as testing.

The driver will hit next before this does but will get into mainline
in the same ultimate pull request unless something weird happens so that's
all fine.

Jonathan
>> Jonathan
>>> ---
>>>  .../devicetree/bindings/iio/adc/ti-ads7950.txt     | 23 ++++++++++++++++++++++
>>>  1 file changed, 23 insertions(+)
>>>  create mode 100644 Documentation/devicetree/bindings/iio/adc/ti-ads7950.txt
>>>
>>> diff --git a/Documentation/devicetree/bindings/iio/adc/ti-ads7950.txt b/Documentation/devicetree/bindings/iio/adc/ti-ads7950.txt
>>> new file mode 100644
>>> index 0000000..e77a6f7
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/iio/adc/ti-ads7950.txt
>>> @@ -0,0 +1,23 @@
>>> +* Texas Instruments ADS7950 family of A/DC chips
>>> +
>>> +Required properties:
>>> + - compatible: Must be one of "ti,ads7950", "ti,ads7951", "ti,ads7952",
>>> +   "ti,ads7953", "ti,ads7954", "ti,ads7955", "ti,ads7956", "ti,ads7957",
>>> +   "ti,ads7958", "ti,ads7959", "ti,ads7960", or "ti,ads7961"
>>> + - reg: SPI chip select number for the device
>>> + - #io-channel-cells: Must be 1 as per ../iio-bindings.txt
>>> + - vref-supply: phandle to a regulator node that supplies the 2.5V or 5V
>>> +   reference voltage
>>> +
>>> +Recommended properties:
>>> + - spi-max-frequency: Definition as per
>>> +        Documentation/devicetree/bindings/spi/spi-bus.txt
>>> +
>>> +Example:
>>> +adc@0 {
>>> +    compatible = "ti,ads7957";
>>> +    reg = <0>;
>>> +    #io-channel-cells = <1>;
>>> +    vref-supply = <&refin_supply>;
>>> +    spi-max-frequency = <10000000>;
>>> +};
>>>
>>
> 
> -- 
> 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


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