Devicetree
 help / color / mirror / Atom feed
* [PATCH v2 01/19] ARM: dts: armada-xp-matrix: Fix the location of the pcie-controller node
From: Gregory CLEMENT @ 2016-11-13 21:23 UTC (permalink / raw)
  To: Jason Cooper, Andrew Lunn, Sebastian Hesselbarth, Gregory CLEMENT
  Cc: Thomas Petazzoni,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Rob Herring,
	devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20161113212402.3060-1-gregory.clement-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>

In the dts for the Marvell Armada XP Matrix board the pcie-controller was
located under the internal-regs node whereas it belongs to the soc node.

It means that, until this fix, the pcie could not work for this board
because it didn't match the definition of the pcie-controller node in the
dtsi file. If we had a look on the decompiled dtb file we saw two
different instances of the pcie-controller node: one with the all the
resource set but disabled and the other without any resource but enabled.

Signed-off-by: Gregory CLEMENT <gregory.clement-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
---
 arch/arm/boot/dts/armada-xp-matrix.dts | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/arch/arm/boot/dts/armada-xp-matrix.dts b/arch/arm/boot/dts/armada-xp-matrix.dts
index 6522b04f4a8e..e1509f4c5114 100644
--- a/arch/arm/boot/dts/armada-xp-matrix.dts
+++ b/arch/arm/boot/dts/armada-xp-matrix.dts
@@ -71,6 +71,15 @@
 			  MBUS_ID(0x09, 0x09) 0 0 0xf1100000 0x10000
 			  MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000>;
 
+		pcie-controller {
+			status = "okay";
+
+			pcie@1,0 {
+				/* Port 0, Lane 0 */
+				status = "okay";
+			};
+		};
+
 		internal-regs {
 			serial@12000 {
 				status = "okay";
@@ -99,15 +108,6 @@
 				};
 			};
 
-			pcie-controller {
-				status = "okay";
-
-				pcie@1,0 {
-					/* Port 0, Lane 0 */
-					status = "okay";
-				};
-			};
-
 			usb@50000 {
 				status = "okay";
 			};
-- 
2.10.2

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

^ permalink raw reply related

* [PATCH v2 00/19] Various Armada 370/XP DT warning fixup
From: Gregory CLEMENT @ 2016-11-13 21:23 UTC (permalink / raw)
  To: Jason Cooper, Andrew Lunn, Sebastian Hesselbarth, Gregory CLEMENT
  Cc: Thomas Petazzoni,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Rob Herring,
	devicetree-u79uwXL29TY76Z2rM5mHXA

As it was done a few months ago for kirkwood, this patchset fixes up
various warning from the DT compiler when using the flag W=1 with
make.

In this second version I used the target and attributes property of
the memory windows when MBUS_ID. Indeed by adding this information to
the unit-address is really uniq as required bu the epar as explained
in this email:
http://lists.infradead.org/pipermail/linux-arm-kernel/2016-November/466941.html.

As for the first version, the only remaining warnings are the following:
  DTC     arch/arm/boot/dts/armada-370-db.dtb
Warning (unit_address_vs_reg): Node /sound/simple-audio-card,dai-link@0 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound/simple-audio-card,dai-link@1 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound/simple-audio-card,dai-link@2 has a unit name, but no reg property

However it seems a false positive as here the '@' is part of the name
of the node and is not a reference of an address. Moreover the node
name is directly used by the driver so it must not be modified.

Gregory

Gregory CLEMENT (19):
  ARM: dts: armada-xp-matrix: Fix the location of the pcie-controller
    node
  ARM: dts: armada-370-xp: move the cpurst node in the common file
  ARM: dts: armada-370-xp: add node labels
  ARM: dts: armada-370-xp: Use the node labels
  ARM: dts: armada-370-xp: Fixup mdio DT warning
  ARM: dts: armada-370-xp: Fixup bootrom DT warning
  ARM: dts: armada-370-xp: Fixup devbus DT warning
  ARM: dts: armada-370-xp: Fixup bm-bppi DT warning
  ARM: dts: armada-370-xp: Fixup sa-ram DT warning
  ARM: dts: armada-xp: Fixup pcie DT warnings
  ARM: dts: armada-370: Fixup pcie DT warnings
  ARM: dts: armada-370-xp: Remove skeleton.dtsi
  ARM: dts: armada-370-xp: Fixup l2-cache DT warning
  ARM: dts: armada-370-xp: Fixup internal-regs DT warning
  ARM: dts: armada-370-xp: Fixup soc DT warning
  ARM: dts: armada-370-xp: Fixup memory DT warning
  ARM: dts: armada-370-xp: Remove address from dsa unit name
  ARM: dts: armada-370-xp: Remove button address and fixup names
  ARM: dts: armada-370-xp: Fixup regulator DT warning

 arch/arm/boot/dts/armada-370-db.dts                |  67 ++++----
 arch/arm/boot/dts/armada-370-dlink-dns327l.dts     |  34 ++---
 arch/arm/boot/dts/armada-370-mirabox.dts           |  61 ++++----
 arch/arm/boot/dts/armada-370-netgear-rn102.dts     |  54 +++----
 arch/arm/boot/dts/armada-370-netgear-rn104.dts     |  62 ++++----
 arch/arm/boot/dts/armada-370-rd.dts                |  61 ++++----
 arch/arm/boot/dts/armada-370-seagate-nas-4bay.dts  |  31 ++--
 arch/arm/boot/dts/armada-370-seagate-nas-xbay.dtsi |  49 +++---
 .../dts/armada-370-seagate-personal-cloud-2bay.dts |   4 +-
 .../boot/dts/armada-370-seagate-personal-cloud.dts |   4 +-
 .../dts/armada-370-seagate-personal-cloud.dtsi     |  48 +++---
 arch/arm/boot/dts/armada-370-synology-ds213j.dts   |  22 +--
 arch/arm/boot/dts/armada-370-xp.dtsi               |  43 +++---
 arch/arm/boot/dts/armada-370.dtsi                  | 144 +++++++++--------
 arch/arm/boot/dts/armada-xp-axpwifiap.dts          |  72 ++++-----
 arch/arm/boot/dts/armada-xp-db.dts                 | 170 ++++++++++-----------
 arch/arm/boot/dts/armada-xp-gp.dts                 | 146 +++++++++---------
 arch/arm/boot/dts/armada-xp-lenovo-ix4-300d.dts    |  57 ++++---
 arch/arm/boot/dts/armada-xp-linksys-mamba.dts      |  56 +++----
 arch/arm/boot/dts/armada-xp-matrix.dts             |  24 +--
 arch/arm/boot/dts/armada-xp-mv78230.dtsi           |  16 +-
 arch/arm/boot/dts/armada-xp-mv78260.dtsi           |  24 +--
 arch/arm/boot/dts/armada-xp-mv78460.dtsi           |  26 ++--
 arch/arm/boot/dts/armada-xp-netgear-rn2120.dts     |  71 ++++-----
 arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts   | 124 +++++++--------
 arch/arm/boot/dts/armada-xp-synology-ds414.dts     |  79 +++++-----
 arch/arm/boot/dts/armada-xp.dtsi                   | 106 ++++++-------
 27 files changed, 832 insertions(+), 823 deletions(-)

-- 
2.10.2

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

^ permalink raw reply

* [PATCH 2/2] ARM: dts: sun8i: reference-design-tablet: ldo_io1 is vcc-touchscreen
From: Hans de Goede @ 2016-11-13 19:22 UTC (permalink / raw)
  To: Maxime Ripard, Chen-Yu Tsai
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree,
	Hans de Goede
In-Reply-To: <20161113192203.7101-1-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>

On some Q8 and other tablets ldo_io1 is used as vcc-touchscreen,
config at as such in sun8i-reference-design-tablet.dtsi.

Note that it will only be enabled when it us actually referenced by
a foo-supply property in the touchscreen node, so for tablets which
do not use ldo_io1 as vcc-touchscreen, it will be disabled.

Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 arch/arm/boot/dts/sun8i-a23-polaroid-mid2407pxe03.dts | 7 -------
 arch/arm/boot/dts/sun8i-reference-design-tablet.dtsi  | 7 +++++++
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/arch/arm/boot/dts/sun8i-a23-polaroid-mid2407pxe03.dts b/arch/arm/boot/dts/sun8i-a23-polaroid-mid2407pxe03.dts
index a86cbed..21bb291 100644
--- a/arch/arm/boot/dts/sun8i-a23-polaroid-mid2407pxe03.dts
+++ b/arch/arm/boot/dts/sun8i-a23-polaroid-mid2407pxe03.dts
@@ -98,13 +98,6 @@
 	};
 };
 
-&reg_ldo_io1 {
-	regulator-min-microvolt = <3300000>;
-	regulator-max-microvolt = <3300000>;
-	regulator-name = "vcc-touchscreen";
-	status = "okay";
-};
-
 &touchscreen {
 	reg = <0x40>;
 	compatible = "silead,gsl1680";
diff --git a/arch/arm/boot/dts/sun8i-reference-design-tablet.dtsi b/arch/arm/boot/dts/sun8i-reference-design-tablet.dtsi
index 08cd001..69bc0cd 100644
--- a/arch/arm/boot/dts/sun8i-reference-design-tablet.dtsi
+++ b/arch/arm/boot/dts/sun8i-reference-design-tablet.dtsi
@@ -209,6 +209,13 @@
 	status = "okay";
 };
 
+&reg_ldo_io1 {
+	regulator-min-microvolt = <3300000>;
+	regulator-max-microvolt = <3300000>;
+	regulator-name = "vcc-touchscreen";
+	status = "okay";
+};
+
 &reg_rtc_ldo {
 	regulator-name = "vcc-rtc";
 };
-- 
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

* [PATCH 1/2] ARM: dts: sun5i: Add touchscreen node to reference-design-tablet.dtsi
From: Hans de Goede @ 2016-11-13 19:22 UTC (permalink / raw)
  To: Maxime Ripard, Chen-Yu Tsai
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree,
	Hans de Goede

Just like on sun8i all sun5i tablets use the same interrupt and power
gpios for their touchscreens. I've checked all known a13 fex files and
only the UTOO P66 uses a different gpio for the interrupt.

Add a touchscreen node to sun5i-reference-design-tablet.dtsi, which
fills in the necessary gpios to avoid duplication in the tablet dts files,
just like we do in sun8i-reference-design-tablet.dtsi.

This will make future patches adding touchscreen nodes to a13 tablets
simpler.

Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 arch/arm/boot/dts/sun5i-a13-utoo-p66.dts           | 38 ++++++++--------------
 .../boot/dts/sun5i-reference-design-tablet.dtsi    | 25 ++++++++++++++
 2 files changed, 39 insertions(+), 24 deletions(-)

diff --git a/arch/arm/boot/dts/sun5i-a13-utoo-p66.dts b/arch/arm/boot/dts/sun5i-a13-utoo-p66.dts
index a8b0bcc..3d7ff10 100644
--- a/arch/arm/boot/dts/sun5i-a13-utoo-p66.dts
+++ b/arch/arm/boot/dts/sun5i-a13-utoo-p66.dts
@@ -83,22 +83,6 @@
 	allwinner,pins = "PG3";
 };
 
-&i2c1 {
-	icn8318: touchscreen@40 {
-		compatible = "chipone,icn8318";
-		reg = <0x40>;
-		interrupt-parent = <&pio>;
-		interrupts = <6 9 IRQ_TYPE_EDGE_FALLING>; /* EINT9 (PG9) */
-		pinctrl-names = "default";
-		pinctrl-0 = <&ts_wake_pin_p66>;
-		wake-gpios = <&pio 1 3 GPIO_ACTIVE_HIGH>; /* PB3 */
-		touchscreen-size-x = <800>;
-		touchscreen-size-y = <480>;
-		touchscreen-inverted-x;
-		touchscreen-swapped-x-y;
-	};
-};
-
 &mmc2 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&mmc2_pins_a>;
@@ -121,20 +105,26 @@
 		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
 		allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
 	};
-
-	ts_wake_pin_p66: ts_wake_pin@0 {
-		allwinner,pins = "PB3";
-		allwinner,function = "gpio_out";
-		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-	};
-
 };
 
 &reg_usb0_vbus {
 	gpio = <&pio 1 4 GPIO_ACTIVE_HIGH>; /* PB4 */
 };
 
+&touchscreen {
+	compatible = "chipone,icn8318";
+	reg = <0x40>;
+	/* The P66 uses a different EINT then the reference design */
+	interrupts = <6 9 IRQ_TYPE_EDGE_FALLING>; /* EINT9 (PG9) */
+	/* The icn8318 binding expects wake-gpios instead of power-gpios */
+	wake-gpios = <&pio 1 3 GPIO_ACTIVE_HIGH>; /* PB3 */
+	touchscreen-size-x = <800>;
+	touchscreen-size-y = <480>;
+	touchscreen-inverted-x;
+	touchscreen-swapped-x-y;
+	status = "okay";
+};
+
 &uart1 {
 	/* The P66 uses the uart pins as gpios */
 	status = "disabled";
diff --git a/arch/arm/boot/dts/sun5i-reference-design-tablet.dtsi b/arch/arm/boot/dts/sun5i-reference-design-tablet.dtsi
index 20cc940..7af488a 100644
--- a/arch/arm/boot/dts/sun5i-reference-design-tablet.dtsi
+++ b/arch/arm/boot/dts/sun5i-reference-design-tablet.dtsi
@@ -41,6 +41,7 @@
  */
 #include "sunxi-reference-design-tablet.dtsi"
 
+#include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/pwm/pwm.h>
 
 / {
@@ -84,6 +85,23 @@
 };
 
 &i2c1 {
+	/*
+	 * The gsl1680 is rated at 400KHz and it will not work reliable at
+	 * 100KHz, this has been confirmed on multiple different q8 tablets.
+	 * All other devices on this bus are also rated for 400KHz.
+	 */
+	clock-frequency = <400000>;
+
+	touchscreen: touchscreen {
+		interrupt-parent = <&pio>;
+		interrupts = <6 11 IRQ_TYPE_EDGE_FALLING>; /* EINT11 (PG11) */
+		pinctrl-names = "default";
+		pinctrl-0 = <&ts_power_pin>;
+		power-gpios = <&pio 1 3 GPIO_ACTIVE_HIGH>; /* PB3 */
+		/* Tablet dts must provide reg and compatible */
+		status = "disabled";
+	};
+
 	pcf8563: rtc@51 {
 		compatible = "nxp,pcf8563";
 		reg = <0x51>;
@@ -125,6 +143,13 @@
 		allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
 	};
 
+	ts_power_pin: ts_power_pin {
+		allwinner,pins = "PB3";
+		allwinner,function = "gpio_out";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+
 	usb0_vbus_detect_pin: usb0_vbus_detect_pin@0 {
 		allwinner,pins = "PG1";
 		allwinner,function = "gpio_in";
-- 
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 1/3] ARM: sunxi: add support for H2+ SoC
From: Hans de Goede @ 2016-11-13 18:59 UTC (permalink / raw)
  To: icenowy-ymACFijhrKM, Jonathan Corbet, Maxime Ripard, Chen-Yu Tsai,
	Rob Herring
  Cc: Mark Rutland, Russell King, linux-doc-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
In-Reply-To: <20161111164654.15273-1-icenowy-ymACFijhrKM@public.gmane.org>

Hi,

On 11-11-16 17:46, Icenowy Zheng wrote:
> Allwinner H2+ is a quad-core Cortex-A7 SoC.
>
> It is very like H3, that they share the same SoC ID (0x1680), and H3
> memory maps as well as drivers works well on the SoC.
>
> Signed-off-by: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>

I agree that given that the chip-id is 1680 for both
this does seem to be the same die as the H3, and given
that we do not have any datasheets, I agree that just
treating the H2+ as a H3 is best for now, we can always
change h2.dtsi to actually differentiate things later.

This entire series LGTM and is:

Reviewed-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>

Regards,

Hans

> ---
>  Documentation/arm/sunxi/README                  | 4 ++++
>  Documentation/devicetree/bindings/arm/sunxi.txt | 1 +
>  arch/arm/mach-sunxi/sunxi.c                     | 1 +
>  3 files changed, 6 insertions(+)
>
> diff --git a/Documentation/arm/sunxi/README b/Documentation/arm/sunxi/README
> index cd02433..1fe4d99c 100644
> --- a/Documentation/arm/sunxi/README
> +++ b/Documentation/arm/sunxi/README
> @@ -63,6 +63,10 @@ SunXi family
>          + User Manual
>            http://dl.linux-sunxi.org/A33/A33%20user%20manual%20release%201.1.pdf
>
> +      - Allwinner H2+ (sun8i)
> +        + No document available now, but is known to be working properly with
> +          H3 drivers and memory map.
> +
>        - Allwinner H3 (sun8i)
>          + Datasheet
>            http://dl.linux-sunxi.org/H3/Allwinner_H3_Datasheet_V1.0.pdf
> diff --git a/Documentation/devicetree/bindings/arm/sunxi.txt b/Documentation/devicetree/bindings/arm/sunxi.txt
> index 3975d0a..0c0f277 100644
> --- a/Documentation/devicetree/bindings/arm/sunxi.txt
> +++ b/Documentation/devicetree/bindings/arm/sunxi.txt
> @@ -13,5 +13,6 @@ using one of the following compatible strings:
>    allwinner,sun8i-a33
>    allwinner,sun8i-a83t
>    allwinner,sun8i-h3
> +  allwinner,sun8i-h2plus
>    allwinner,sun9i-a80
>    nextthing,gr8
> diff --git a/arch/arm/mach-sunxi/sunxi.c b/arch/arm/mach-sunxi/sunxi.c
> index 2e2bde2..3647ad7 100644
> --- a/arch/arm/mach-sunxi/sunxi.c
> +++ b/arch/arm/mach-sunxi/sunxi.c
> @@ -63,6 +63,7 @@ static const char * const sun8i_board_dt_compat[] = {
>  	"allwinner,sun8i-a23",
>  	"allwinner,sun8i-a33",
>  	"allwinner,sun8i-a83t",
> +	"allwinner,sun8i-h2plus",
>  	"allwinner,sun8i-h3",
>  	NULL,
>  };
>

^ permalink raw reply

* Re: [PATCH v2 1/6] Documentation: dt-bindings: Document STM32 ADC DT bindings
From: Jonathan Cameron @ 2016-11-13 11:38 UTC (permalink / raw)
  To: Fabrice Gasnier, linux-iio, linux-arm-kernel, devicetree,
	linux-kernel
  Cc: lee.jones, linux, robh+dt, mark.rutland, mcoquelin.stm32,
	alexandre.torgue, lars, knaack.h, pmeerw
In-Reply-To: <1478794738-28933-2-git-send-email-fabrice.gasnier@st.com>

On 10/11/16 16:18, Fabrice Gasnier wrote:
> This patch adds documentation of device tree bindings for the STM32 ADC.
> 
> Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
> ---
>  .../devicetree/bindings/iio/adc/st,stm32-adc.txt   | 85 ++++++++++++++++++++++
>  1 file changed, 85 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt
> 
> diff --git a/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt b/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt
> new file mode 100644
> index 0000000..8b20c23
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt
> @@ -0,0 +1,85 @@
> +STMicroelectronics STM32 ADC device driver
> +
> +STM32 ADC is a successive approximation analog-to-digital converter.
> +It has several multiplexed input channels. Conversions can be performed
> +in single, continuous, scan or discontinuous mode. Result of the ADC is
> +stored in a left-aligned or right-aligned 32-bit data register.
> +Conversions can be launched in software or using hardware triggers.
> +
> +The analog watchdog feature allows the application to detect if the input
> +voltage goes beyond the user-defined, higher or lower thresholds.
> +
> +Each STM32 ADC block can have up to 3 ADC instances.
> +
> +Each instance supports two contexts to manage conversions, each one has its
> +own configurable sequence and trigger:
> +- regular conversion can be done in sequence, running in background
> +- injected conversions have higher priority, and so have the ability to
> +  interrupt regular conversion sequence (either triggered in SW or HW).
> +  Regular sequence is resumed, in case it has been interrupted.
> +
> +Contents of a stm32 adc root node:
> +-----------------------------------
> +Required properties:
> +- compatible: Should be "st,stm32f4-adc-core".
> +- reg: Offset and length of the ADC block register set.
> +- interrupts: Must contain the interrupt for ADC block.
> +- clocks: Clock for the analog circuitry (common to all ADCs).
> +- clock-names: Must be "adc".
> +- interrupt-controller: Identifies the controller node as interrupt-parent
> +- vref-supply: Phandle to the vref input analog reference voltage.
> +- #interrupt-cells = <1>;
> +- #address-cells = <1>;
> +- #size-cells = <0>;
> +
> +Optional properties:
> +- A pinctrl state named "default" for each ADC channel may be defined to set
> +  inX ADC pins in mode of operation for analog input on external pin.
> +
> +Contents of a stm32 adc child node:
> +-----------------------------------
> +An ADC block node should contain at least one subnode, representing an
> +ADC instance available on the machine.
> +
> +Required properties:
> +- compatible: Should be "st,stm32f4-adc".
> +- reg: Offset of ADC instance in ADC block (e.g. may be 0x0, 0x100, 0x200).
> +- st,adc-channels: List of single-ended channels muxed for this ADC.
> +  It can have up to 16 channels, numbered from 0 to 15 (resp. for in0..in15).
> +- interrupt-parent: Phandle to the parent interrupt controller.
> +- interrupts: IRQ Line for the ADC (e.g. may be 0 for adc@0, 1 for adc@100 or
> +  2 for adc@200).
> +- #io-channel-cells = <1>: See the IIO bindings section "IIO consumers" in
> +  Documentation/devicetree/bindings/iio/iio-bindings.txt
> +
> +Optional properties:
> +- clocks: Input clock private to this ADC instance.
I'm a little surprised this is optional.  Perhaps some text here explaining why?
> +
> +Example:
> +	adc: adc@40012000 {
> +		compatible = "st,stm32f4-adc-core";
> +		reg = <0x40012000 0x400>;
> +		interrupts = <18>;
> +		clocks = <&rcc 0 168>;
> +		clock-names = "adc";
> +		vref-supply = <&reg_vref>;
> +		interrupt-controller;
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&adc3_in8_pin>;
> +
> +		#interrupt-cells = <1>;
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		adc@0 {
> +			compatible = "st,stm32f4-adc";
> +			#io-channel-cells = <1>;
> +			reg = <0x0>;
> +			clocks = <&rcc 0 168>;
> +			interrupt-parent = <&adc>;
> +			interrupts = <0>;
> +			st,adc-channels = <8>;
> +		};
> +		...
> +		other adc child nodes follow...
> +	};
> 

^ permalink raw reply

* [PATCH devicetree/next] ARM: BCM5301X: Add DT for TP-LINK Archer C9 V1
From: Rafał Miłecki @ 2016-11-13 10:12 UTC (permalink / raw)
  To: Florian Fainelli
  Cc: Rob Herring, Mark Rutland, Russell King, Hauke Mehrtens,
	bcm-kernel-feedback-list-dY08KVG/lbpWk0Htik3J/w,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Rafał Miłecki

From: Rafał Miłecki <rafal-g1n6cQUeyibVItvQsEIGlw@public.gmane.org>

It's BCM4709A0 based device with 16 MiB flash, 128 MiB of RAM and two
PCIe based on-PCB BCM4360 chipsets.

Signed-off-by: Rafał Miłecki <rafal-g1n6cQUeyibVItvQsEIGlw@public.gmane.org>
---
 arch/arm/boot/dts/Makefile                        |   1 +
 arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts | 114 ++++++++++++++++++++++
 2 files changed, 115 insertions(+)
 create mode 100644 arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 837703a..7a52a9f 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -87,6 +87,7 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \
 	bcm4709-buffalo-wxr-1900dhp.dtb \
 	bcm4709-netgear-r7000.dtb \
 	bcm4709-netgear-r8000.dtb \
+	bcm4709-tplink-archer-c9-v1.dtb \
 	bcm47094-dlink-dir-885l.dtb \
 	bcm47094-luxul-xwr-3100.dtb \
 	bcm47094-netgear-r8500.dtb \
diff --git a/arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts b/arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts
new file mode 100644
index 0000000..9a92c24
--- /dev/null
+++ b/arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2016 Rafał Miłecki <rafal-g1n6cQUeyibVItvQsEIGlw@public.gmane.org>
+ *
+ * Licensed under the ISC license.
+ */
+
+/dts-v1/;
+
+#include "bcm4709.dtsi"
+
+/ {
+	compatible = "tplink,archer-c9-v1", "brcm,bcm4709", "brcm,bcm4708";
+	model = "TP-LINK Archer C9 V1";
+
+	chosen {
+		bootargs = "console=ttyS0,115200 earlycon";
+	};
+
+	memory {
+		reg = <0x00000000 0x08000000>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		lan {
+			label = "bcm53xx:blue:lan";
+			gpios = <&chipcommon 1 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "default-off";
+		};
+
+		wps {
+			label = "bcm53xx:blue:wps";
+			gpios = <&chipcommon 2 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "default-off";
+		};
+
+		2ghz {
+			label = "bcm53xx:blue:2ghz";
+			gpios = <&chipcommon 4 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "default-off";
+		};
+
+		5ghz {
+			label = "bcm53xx:blue:5ghz";
+			gpios = <&chipcommon 5 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "default-off";
+		};
+
+		usb3 {
+			label = "bcm53xx:blue:usb3";
+			gpios = <&chipcommon 6 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "default-off";
+		};
+
+		usb2 {
+			label = "bcm53xx:blue:usb2";
+			gpios = <&chipcommon 7 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "default-off";
+		};
+
+		wan-blue {
+			label = "bcm53xx:blue:wan";
+			gpios = <&chipcommon 14 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "default-off";
+		};
+
+		wan-amber {
+			label = "bcm53xx:amber:wan";
+			gpios = <&chipcommon 15 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "default-off";
+		};
+
+		power {
+			label = "bcm53xx:blue:power";
+			gpios = <&chipcommon 18 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "default-on";
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		wps {
+			label = "WPS";
+			linux,code = <KEY_WPS_BUTTON>;
+			gpios = <&chipcommon 0 GPIO_ACTIVE_LOW>;
+		};
+
+		restart {
+			label = "Reset";
+			linux,code = <KEY_RESTART>;
+			gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
+		};
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&usb2 {
+	vcc-gpio = <&chipcommon 13 GPIO_ACTIVE_HIGH>;
+};
+
+&usb3 {
+	vcc-gpio = <&chipcommon 12 GPIO_ACTIVE_HIGH>;
+};
+
+&spi_nor {
+	status = "okay";
+};
-- 
2.10.1

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

^ permalink raw reply related

* Re: [PATCH v2 2/2] of: changesets: Introduce changeset helper methods
From: Hans de Goede @ 2016-11-13  8:14 UTC (permalink / raw)
  To: Frank Rowand, Rob Herring, Pantelis Antoniou
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <5827CCC3.90003-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

Hi,

On 13-11-16 03:15, Frank Rowand wrote:
> On 11/04/16 07:42, Hans de Goede wrote:
>> From: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
>>
>> Changesets are very powerful, but the lack of a helper API
>> makes using them cumbersome. Introduce a simple copy based
>> API that makes things considerably easier.
>>
>> To wit, adding a property using the raw API.
>>
>> 	struct property *prop;
>> 	prop = kzalloc(sizeof(*prop)), GFP_KERNEL);
>> 	prop->name = kstrdup("compatible");
>> 	prop->value = kstrdup("foo,bar");
>> 	prop->length = strlen(prop->value) + 1;
>> 	of_changeset_add_property(ocs, np, prop);
>>
>> while using the helper API
>>
>> 	of_changeset_add_property_string(ocs, np, "compatible",
>> 			"foo,bar");
>>
>> Signed-off-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
>> Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
>> ---
>> Changes in v2 (hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org):
>> -Address review comments from:
>>  https://www.spinics.net/lists/kernel/msg2252845.html
>
> That points to the May 9 version 1 patches from Pantelis (as expected),
> but containing 4, not 2, patches.  Patch 1/4 was applied.  Patch 4/4
> seems to have disappeared?

Ah, I cherry picked this into my tree a long time ago, hoping
Pantelis himself would upstream them, so I only cherry picked
the bare minimum and I did not pick-up the unit tests.

> Pantelis then sent a version 2 set of the patches on May 16.

Hmm, I never found this in google.

> Your version is a modification of the May 9 patches (as would be expected
> of a version 2).  It is confusing to have two different version 2 patch
> sets.  I don't have any brilliant ideas on how this patch set could have
> been named differently to avoid that confusion.

Actually my patches were cherry picked from Pantelis' beaglebone
capemanager tree, which I hope contained the last version.

> The point of this little side-track is simply to note the existence of two
> different version 2 series so I won't be confused when I revisit this
> thread in the future.

Ack, sorry about that.

Regards,

Hans


>
>>  -Simplify (and fix) __of_changeset_add_update_property_copy OOM handling
>>  -Remove (by manual inlining) these 2 static helpers:
>>   __of_changeset_add_update_property_u32
>>   __of_changeset_add_update_property_bool
>>  -Remove the following exported helper method:
>>   of_changeset_node_move_to
>
> Not all comments were addressed.
>
> There are some other changes made that are not noted in the changelog.
>
> I am still reading through the patches. I will reply again either with
> a reviewed-by or specific comments when I finish.
>
> -Frank
>
>> ---
>>  drivers/of/dynamic.c | 428 +++++++++++++++++++++++++++++++++++++++++++++++++++
>>  include/linux/of.h   | 135 ++++++++++++++++
>>  2 files changed, 563 insertions(+)
>
> < snip >
>
--
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 v5 3/3] clocksource: Add clockevent support to NPS400 driver
From: Noam Camus @ 2016-11-13  7:24 UTC (permalink / raw)
  To: robh+dt, mark.rutland, daniel.lezcano
  Cc: tglx, devicetree, linux-kernel, Noam Camus
In-Reply-To: <1479021872-14237-1-git-send-email-noamca@mellanox.com>

From: Noam Camus <noamca@mellanox.com>

Till now we used clockevent from generic ARC driver.
This was enough as long as we worked with simple multicore SoC.
When we are working with multithread SoC each HW thread can be
scheduled to receive timer interrupt using timer mask register.
This patch will provide a way to control clock events per HW thread.

The design idea is that for each core there is dedicated regirtser
(TSI) serving all 16 HW threads.
The register is a bitmask with one bit for each HW thread.
When HW thread wants that next expiration of timer interrupt will
hit it then the proper bit should be set in this dedicated register.
When timer expires all HW threads within this core which their bit
is set at the TSI register will be interrupted.

Driver can be used from device tree by:
compatible = "ezchip,nps400-timer0" <-- for clocksource
compatible = "ezchip,nps400-timer1" <-- for clockevent

Note that name convention for timer0/timer1 was taken from legacy
ARC design. This design is our base before adding HW threads.
For backward compatibility we keep "ezchip,nps400-timer" for clocksource

Signed-off-by: Noam Camus <noamca@mellanox.com>
---
 .../bindings/timer/ezchip,nps400-timer.txt         |   15 --
 .../bindings/timer/ezchip,nps400-timer0.txt        |   17 ++
 .../bindings/timer/ezchip,nps400-timer1.txt        |   15 ++
 drivers/clocksource/timer-nps.c                    |  213 ++++++++++++++++++++
 4 files changed, 245 insertions(+), 15 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
 create mode 100644 Documentation/devicetree/bindings/timer/ezchip,nps400-timer0.txt
 create mode 100644 Documentation/devicetree/bindings/timer/ezchip,nps400-timer1.txt

diff --git a/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt b/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
deleted file mode 100644
index c8c03d7..0000000
--- a/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-NPS Network Processor
-
-Required properties:
-
-- compatible :	should be "ezchip,nps400-timer"
-
-Clocks required for compatible = "ezchip,nps400-timer":
-- clocks : Must contain a single entry describing the clock input
-
-Example:
-
-timer {
-	compatible = "ezchip,nps400-timer";
-	clocks = <&sysclk>;
-};
diff --git a/Documentation/devicetree/bindings/timer/ezchip,nps400-timer0.txt b/Documentation/devicetree/bindings/timer/ezchip,nps400-timer0.txt
new file mode 100644
index 0000000..e3cfce8
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/ezchip,nps400-timer0.txt
@@ -0,0 +1,17 @@
+NPS Network Processor
+
+Required properties:
+
+- compatible :	should be "ezchip,nps400-timer0"
+
+Clocks required for compatible = "ezchip,nps400-timer0":
+- interrupts : The interrupt of the first timer
+- clocks : Must contain a single entry describing the clock input
+
+Example:
+
+timer {
+	compatible = "ezchip,nps400-timer0";
+	interrupts = <3>;
+	clocks = <&sysclk>;
+};
diff --git a/Documentation/devicetree/bindings/timer/ezchip,nps400-timer1.txt b/Documentation/devicetree/bindings/timer/ezchip,nps400-timer1.txt
new file mode 100644
index 0000000..c0ab419
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/ezchip,nps400-timer1.txt
@@ -0,0 +1,15 @@
+NPS Network Processor
+
+Required properties:
+
+- compatible :	should be "ezchip,nps400-timer1"
+
+Clocks required for compatible = "ezchip,nps400-timer1":
+- clocks : Must contain a single entry describing the clock input
+
+Example:
+
+timer {
+	compatible = "ezchip,nps400-timer1";
+	clocks = <&sysclk>;
+};
diff --git a/drivers/clocksource/timer-nps.c b/drivers/clocksource/timer-nps.c
index eeef9e9..ed4bce4 100644
--- a/drivers/clocksource/timer-nps.c
+++ b/drivers/clocksource/timer-nps.c
@@ -109,3 +109,216 @@ static int __init nps_setup_clocksource(struct device_node *node)
 
 CLOCKSOURCE_OF_DECLARE(ezchip_nps400_clksrc, "ezchip,nps400-timer",
 		       nps_setup_clocksource);
+CLOCKSOURCE_OF_DECLARE(ezchip_nps400_clk_src, "ezchip,nps400-timer1",
+		       nps_setup_clocksource);
+
+#ifdef CONFIG_EZNPS_MTM_EXT
+#include <soc/nps/mtm.h>
+
+/* Timer related Aux registers */
+#define NPS_REG_TIMER0_TSI	0xFFFFF850
+#define NPS_REG_TIMER0_LIMIT	0x23
+#define NPS_REG_TIMER0_CTRL	0x22
+#define NPS_REG_TIMER0_CNT	0x21
+
+/*
+ * Interrupt Enabled (IE) - re-arm the timer
+ * Not Halted (NH) - is cleared when working with JTAG (for debug)
+ */
+#define TIMER0_CTRL_IE		BIT(0)
+#define TIMER0_CTRL_NH		BIT(1)
+
+static unsigned long nps_timer0_freq;
+static unsigned long nps_timer0_irq;
+
+/*
+ * Arm the timer to interrupt after @cycles
+ */
+static void nps_clkevent_timer_event_setup(unsigned int cycles)
+{
+	write_aux_reg(NPS_REG_TIMER0_LIMIT, cycles);
+	write_aux_reg(NPS_REG_TIMER0_CNT, 0);
+
+	write_aux_reg(NPS_REG_TIMER0_CTRL, TIMER0_CTRL_IE | TIMER0_CTRL_NH);
+}
+
+/*
+ * Clear from TSI the bit for this thread (if not in periodic mode)
+ * If still there are pending HW treads set next timer event
+ */
+static void nps_clkevent_rm_thread(bool remove_thread)
+{
+	unsigned int cflags;
+	unsigned int enabled_threads = 0;
+	int thread;
+
+	hw_schd_save(&cflags);
+
+	enabled_threads = read_aux_reg(NPS_REG_TIMER0_TSI);
+
+	/* remove thread from TSI1 */
+	if (remove_thread) {
+		thread = read_aux_reg(CTOP_AUX_THREAD_ID);
+		enabled_threads &= ~(1 << thread);
+		write_aux_reg(NPS_REG_TIMER0_TSI, enabled_threads);
+	}
+
+	/* Re-arm the timer if needed */
+	if (!enabled_threads)
+		write_aux_reg(NPS_REG_TIMER0_CTRL, TIMER0_CTRL_NH);
+	else
+		write_aux_reg(NPS_REG_TIMER0_CTRL,
+			      TIMER0_CTRL_IE | TIMER0_CTRL_NH);
+
+	hw_schd_restore(cflags);
+}
+
+static void nps_clkevent_add_thread(bool set_event)
+{
+	int thread;
+	unsigned int cflags, enabled_threads;
+
+	hw_schd_save(&cflags);
+
+	/* add thread to TSI1 */
+	thread = read_aux_reg(CTOP_AUX_THREAD_ID);
+	enabled_threads = read_aux_reg(NPS_REG_TIMER0_TSI);
+	enabled_threads |= (1 << thread);
+	write_aux_reg(NPS_REG_TIMER0_TSI, enabled_threads);
+
+	/* set next timer event */
+	if (set_event)
+		write_aux_reg(NPS_REG_TIMER0_CTRL,
+			      TIMER0_CTRL_IE | TIMER0_CTRL_NH);
+
+	hw_schd_restore(cflags);
+}
+
+static int nps_clkevent_set_next_event(unsigned long delta,
+				       struct clock_event_device *dev)
+{
+	nps_clkevent_add_thread(true);
+	enable_percpu_irq(nps_timer0_irq, IRQ_TYPE_NONE);
+
+	return 0;
+}
+
+/*
+ * Whenever anyone tries to change modes, we just mask interrupts
+ * and wait for the next event to get set.
+ */
+static int nps_clkevent_timer_shutdown(struct clock_event_device *dev)
+{
+	disable_percpu_irq(nps_timer0_irq);
+
+	return 0;
+}
+
+/*
+ * For each HW thread set its relevant bit at the TSI register
+ * To arm the timer only thread 0 is needed since it is shared
+ * by all HW threads within same core.
+ */
+static int nps_clkevent_set_periodic(struct clock_event_device *dev)
+{
+	nps_clkevent_add_thread(false);
+	if (read_aux_reg(CTOP_AUX_THREAD_ID) == 0)
+		nps_clkevent_timer_event_setup(nps_timer0_freq / HZ);
+
+	return 0;
+}
+
+static int nps_clkevent_set_oneshot(struct clock_event_device *dev)
+{
+	nps_clkevent_rm_thread(true);
+	nps_clkevent_timer_shutdown(dev);
+
+	return 0;
+}
+
+static DEFINE_PER_CPU(struct clock_event_device, nps_clockevent_device) = {
+	.name				=	"NPS Timer0",
+	.features			=	CLOCK_EVT_FEAT_ONESHOT |
+						CLOCK_EVT_FEAT_PERIODIC,
+	.rating				=	300,
+	.set_next_event			=	nps_clkevent_set_next_event,
+	.set_state_periodic		=	nps_clkevent_set_periodic,
+	.set_state_oneshot		=	nps_clkevent_set_oneshot,
+	.set_state_oneshot_stopped	=	nps_clkevent_timer_shutdown,
+	.set_state_shutdown		=	nps_clkevent_timer_shutdown,
+	.tick_resume			=	nps_clkevent_timer_shutdown,
+};
+
+static irqreturn_t timer_irq_handler(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = dev_id;
+	int irq_reenable = clockevent_state_periodic(evt);
+
+	/* Remove HW thread from TSI only if NOT in periodic state */
+	nps_clkevent_rm_thread(!irq_reenable);
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static int nps_timer_starting_cpu(unsigned int cpu)
+{
+	struct clock_event_device *evt = this_cpu_ptr(&nps_clockevent_device);
+
+	evt->cpumask = cpumask_of(smp_processor_id());
+
+	clockevents_config_and_register(evt, nps_timer0_freq, 0, ULONG_MAX);
+	enable_percpu_irq(nps_timer0_irq, IRQ_TYPE_NONE);
+
+	return 0;
+}
+
+static int nps_timer_dying_cpu(unsigned int cpu)
+{
+	disable_percpu_irq(nps_timer0_irq);
+	return 0;
+}
+
+static int __init nps_setup_clockevent(struct device_node *node)
+{
+	struct clk *clk;
+	int ret;
+
+	nps_timer0_irq = irq_of_parse_and_map(node, 0);
+	if (nps_timer0_irq <= 0) {
+		pr_err("clockevent: missing irq");
+		return -EINVAL;
+	}
+
+	ret = nps_get_timer_clk(node, &nps_timer0_freq, &clk);
+	if (ret)
+		return ret;
+
+	/* Needs apriori irq_set_percpu_devid() done in intc map function */
+	ret = request_percpu_irq(nps_timer0_irq, timer_irq_handler,
+				 "Timer0 (per-cpu-tick)",
+				 &nps_clockevent_device);
+	if (ret) {
+		pr_err("Couldn't request irq\n");
+		clk_disable_unprepare(clk);
+		return ret;
+	}
+
+	ret = cpuhp_setup_state(CPUHP_AP_ARC_TIMER_STARTING,
+				"clockevents/nps:starting",
+				nps_timer_starting_cpu,
+				nps_timer_dying_cpu);
+	if (ret) {
+		pr_err("Failed to setup hotplug state");
+		clk_disable_unprepare(clk);
+		free_percpu_irq(nps_timer0_irq, &nps_clockevent_device);
+		return ret;
+	}
+
+	return 0;
+}
+
+CLOCKSOURCE_OF_DECLARE(ezchip_nps400_clk_evt, "ezchip,nps400-timer0",
+		       nps_setup_clockevent);
+#endif /* CONFIG_EZNPS_MTM_EXT */
-- 
1.7.1

^ permalink raw reply related

* [PATCH v5 2/3] clocksource: update "fn" at CLOCKSOURCE_OF_DECLARE() of nps400 timer
From: Noam Camus @ 2016-11-13  7:24 UTC (permalink / raw)
  To: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	daniel.lezcano-QSEj5FYQhm4dnm+yROfE0A
  Cc: tglx-hfZtesqFncYOwBW4kG4KsQ, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Noam Camus
In-Reply-To: <1479021872-14237-1-git-send-email-noamca-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>

From: Noam Camus <noamca-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>

nps_setup_clocksource() should take node as only argument i.e.:
replace
int __init nps_setup_clocksource(struct device_node *node, struct clk *clk)
with
int __init nps_setup_clocksource(struct device_node *node)

This is also serve as preperation for next patch which adds support
for clockevents to nps400.
Specifically we add new function nps_get_timer_clk() to serve clocksource
and later clockevent registration.

Signed-off-by: Noam Camus <noamca-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
---
 drivers/clocksource/timer-nps.c |   63 +++++++++++++++++++++++----------------
 1 files changed, 37 insertions(+), 26 deletions(-)

diff --git a/drivers/clocksource/timer-nps.c b/drivers/clocksource/timer-nps.c
index 70c149a..eeef9e9 100644
--- a/drivers/clocksource/timer-nps.c
+++ b/drivers/clocksource/timer-nps.c
@@ -46,7 +46,33 @@
 /* This array is per cluster of CPUs (Each NPS400 cluster got 256 CPUs) */
 static void *nps_msu_reg_low_addr[NPS_CLUSTER_NUM] __read_mostly;
 
-static unsigned long nps_timer_rate;
+static int __init nps_get_timer_clk(struct device_node *node,
+			     unsigned long *timer_freq,
+			     struct clk **clk)
+{
+	int ret;
+
+	*clk = of_clk_get(node, 0);
+	if (IS_ERR(*clk)) {
+		pr_err("timer missing clk");
+		return PTR_ERR(*clk);
+	}
+
+	ret = clk_prepare_enable(*clk);
+	if (ret) {
+		pr_err("Couldn't enable parent clk\n");
+		return ret;
+	}
+
+	*timer_freq = clk_get_rate(*clk);
+	if (!(*timer_freq)) {
+		pr_err("Couldn't get clk rate\n");
+		clk_disable_unprepare(*clk);
+		return 1;
+	}
+
+	return 0;
+}
 
 static cycle_t nps_clksrc_read(struct clocksource *clksrc)
 {
@@ -55,26 +81,24 @@ static cycle_t nps_clksrc_read(struct clocksource *clksrc)
 	return (cycle_t)ioread32be(nps_msu_reg_low_addr[cluster]);
 }
 
-static int __init nps_setup_clocksource(struct device_node *node,
-					struct clk *clk)
+static int __init nps_setup_clocksource(struct device_node *node)
 {
 	int ret, cluster;
+	struct clk *clk;
+	unsigned long nps_timer1_freq;
+
 
 	for (cluster = 0; cluster < NPS_CLUSTER_NUM; cluster++)
 		nps_msu_reg_low_addr[cluster] =
 			nps_host_reg((cluster << NPS_CLUSTER_OFFSET),
-				 NPS_MSU_BLKID, NPS_MSU_TICK_LOW);
+				     NPS_MSU_BLKID, NPS_MSU_TICK_LOW);
 
-	ret = clk_prepare_enable(clk);
-	if (ret) {
-		pr_err("Couldn't enable parent clock\n");
+	ret = nps_get_timer_clk(node, &nps_timer1_freq, &clk);
+	if (ret)
 		return ret;
-	}
 
-	nps_timer_rate = clk_get_rate(clk);
-
-	ret = clocksource_mmio_init(nps_msu_reg_low_addr, "EZnps-tick",
-				    nps_timer_rate, 301, 32, nps_clksrc_read);
+	ret = clocksource_mmio_init(nps_msu_reg_low_addr, "nps-tick",
+				    nps_timer1_freq, 300, 32, nps_clksrc_read);
 	if (ret) {
 		pr_err("Couldn't register clock source.\n");
 		clk_disable_unprepare(clk);
@@ -83,18 +107,5 @@ static int __init nps_setup_clocksource(struct device_node *node,
 	return ret;
 }
 
-static int __init nps_timer_init(struct device_node *node)
-{
-	struct clk *clk;
-
-	clk = of_clk_get(node, 0);
-	if (IS_ERR(clk)) {
-		pr_err("Can't get timer clock.\n");
-		return PTR_ERR(clk);
-	}
-
-	return nps_setup_clocksource(node, clk);
-}
-
 CLOCKSOURCE_OF_DECLARE(ezchip_nps400_clksrc, "ezchip,nps400-timer",
-		       nps_timer_init);
+		       nps_setup_clocksource);
-- 
1.7.1

--
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 v5 1/3] soc: Support for NPS HW scheduling
From: Noam Camus @ 2016-11-13  7:24 UTC (permalink / raw)
  To: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	daniel.lezcano-QSEj5FYQhm4dnm+yROfE0A
  Cc: tglx-hfZtesqFncYOwBW4kG4KsQ, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Noam Camus
In-Reply-To: <1479021872-14237-1-git-send-email-noamca-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>

From: Noam Camus <noamca-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>

This new header file is for NPS400 SoC (part of ARC architecture).
The header file includes macros for save/restore of HW scheduling.
The control of HW scheduling is achieved by writing core registers.
This code was moved from arc/plat-eznps so it can be used
from drivers/clocksource/, available only for CONFIG_EZNPS_MTM_EXT.

Signed-off-by: Noam Camus <noamca-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
---
 arch/arc/plat-eznps/include/plat/ctop.h |    2 -
 include/soc/nps/mtm.h                   |   59 +++++++++++++++++++++++++++++++
 2 files changed, 59 insertions(+), 2 deletions(-)
 create mode 100644 include/soc/nps/mtm.h

diff --git a/arch/arc/plat-eznps/include/plat/ctop.h b/arch/arc/plat-eznps/include/plat/ctop.h
index 9d6718c..ee2e32d 100644
--- a/arch/arc/plat-eznps/include/plat/ctop.h
+++ b/arch/arc/plat-eznps/include/plat/ctop.h
@@ -46,9 +46,7 @@
 #define CTOP_AUX_UDMC				(CTOP_AUX_BASE + 0x300)
 
 /* EZchip core instructions */
-#define CTOP_INST_HWSCHD_OFF_R3			0x3B6F00BF
 #define CTOP_INST_HWSCHD_OFF_R4			0x3C6F00BF
-#define CTOP_INST_HWSCHD_RESTORE_R3		0x3E6F70C3
 #define CTOP_INST_HWSCHD_RESTORE_R4		0x3E6F7103
 #define CTOP_INST_SCHD_RW			0x3E6F7004
 #define CTOP_INST_SCHD_RD			0x3E6F7084
diff --git a/include/soc/nps/mtm.h b/include/soc/nps/mtm.h
new file mode 100644
index 0000000..d2f5e7e
--- /dev/null
+++ b/include/soc/nps/mtm.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2016, Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef SOC_NPS_MTM_H
+#define SOC_NPS_MTM_H
+
+#define CTOP_INST_HWSCHD_OFF_R3                 0x3B6F00BF
+#define CTOP_INST_HWSCHD_RESTORE_R3             0x3E6F70C3
+
+static inline void hw_schd_save(unsigned int *flags)
+{
+	__asm__ __volatile__(
+	"       .word %1\n"
+	"       st r3,[%0]\n"
+	:
+	: "r"(flags), "i"(CTOP_INST_HWSCHD_OFF_R3)
+	: "r3", "memory");
+}
+
+static inline void hw_schd_restore(unsigned int flags)
+{
+	__asm__ __volatile__(
+	"       mov r3, %0\n"
+	"       .word %1\n"
+	:
+	: "r"(flags), "i"(CTOP_INST_HWSCHD_RESTORE_R3)
+	: "r3");
+}
+
+#endif /* SOC_NPS_MTM_H */
-- 
1.7.1

--
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 v5 0/3] Add clockevet for timer-nps driver to NPS400 SoC
From: Noam Camus @ 2016-11-13  7:24 UTC (permalink / raw)
  To: robh+dt, mark.rutland, daniel.lezcano
  Cc: tglx, devicetree, linux-kernel, Noam Camus

From: Noam Camus <noamca@mellanox.com>

Change log
---
V4 --> V5
Apply several comments made by Daneil Lezcano:
1) Add __init attribute to nps_get_timer_clk()
2) Fix return value of nps_get_timer_clk()
 when failing to get clk rate
3) Change clocksource rate from 301 -> 300

V3 --> V4
Main changes are [Thanks for the review]:
Fix many typos at log [Daniel]
Add handling for bad return values [Daniel and Thomas]
Replace use of internal irqchip pointers with existing IRQ API [Thomas]
Provide interrupt handler (percpu) with dev_id equal to evt [Thomas]
Fix passing *clk by reference to nps_get_timer_clk() [Daniel]

V2 --> V3
Apply Rob Herring comment about backword compatibility

V1 --> V2
Apply Daniel Lezcano comments:
	CLOCKSOURCE_OF_DECLARE return value
	update hotplug callbacks usage
	squash of 2 first commits.
In this version I created new commit to serve as preperation for adding clockevents.
This way the last patch is more readable with clockevent content.
---

In first version of this driver we supported clocksource for the NPS400.
The support for clockevent was taken from Synopsys ARC timer driver.
This was good for working with our simulator of NPS400.
However in NPS400 ASIC the timers behave differently than simulation.
The timers in ASIC are shared between all threads whithin a core
and hence need different driver to support this behaviour.

The idea of this design is that we got 16 HW threads per core
each represented at bimask in a shared register in this core.
So when thread wants that next clockevent expiration will produce
timer interrupt to itself the correspondance bit in this register
should be set.
So theoretically if all 16 bits are set then all HW threads will get
timer interrupt on next expiration of timer 0.

Note that we use Synopsys ARC design naming convention for the timers
where:
timer0 is used for clockevents
timer1 is used for clocksource.

Noam Camus (3):
  soc: Support for NPS HW scheduling
  clocksource: update "fn" at CLOCKSOURCE_OF_DECLARE() of nps400 timer
  clocksource: Add clockevent support to NPS400 driver

 .../bindings/timer/ezchip,nps400-timer.txt         |   15 --
 .../bindings/timer/ezchip,nps400-timer0.txt        |   17 ++
 .../bindings/timer/ezchip,nps400-timer1.txt        |   15 ++
 arch/arc/plat-eznps/include/plat/ctop.h            |    2 -
 drivers/clocksource/timer-nps.c                    |  264 ++++++++++++++++++--
 include/soc/nps/mtm.h                              |   59 +++++
 6 files changed, 335 insertions(+), 37 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
 create mode 100644 Documentation/devicetree/bindings/timer/ezchip,nps400-timer0.txt
 create mode 100644 Documentation/devicetree/bindings/timer/ezchip,nps400-timer1.txt
 create mode 100644 include/soc/nps/mtm.h

^ permalink raw reply

* [PATCH 2/2] PCI: rockchip: Add quirk to disable RC's ASPM L0s
From: Shawn Lin @ 2016-11-13  3:06 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Rob Herring, linux-pci-u79uwXL29TY76Z2rM5mHXA,
	linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Wenrui Li,
	Brian Norris, Jeffy Chen, devicetree-u79uwXL29TY76Z2rM5mHXA,
	Shawn Lin
In-Reply-To: <1479006374-192306-1-git-send-email-shawn.lin-TNX95d0MmH7DzftRWevZcw@public.gmane.org>

Rockchip's RC outputs 100MHz reference clock but there are
two methods for PHY to generate it.

(1)One of them is to use system PLL to generate 100MHz clock and
the PHY will relock it and filter signal noise then outputs the
reference clock.

(2)Another way is to share Soc's 24MHZ crystal oscillator with
PHY and force PHY's DLL to generate 100MHz internally.

When using case(2), the exit from L0s doesn't work fine occasionally
due to the broken design of RC receiver's logical circuit. So even if
we use extended-synch, it still fails for PHY to relock the bits from
FTS sometimes. This will hang the system.

Maybe we could argue that why not use case(1) to avoid it? The reason
is that as we could see the reference clock is derived from system PLL
and the path from it to PHY isn't so clean which means there are some
noise introduced by power-domain and other buses can't be filterd out
by PHY and we could see noise from the frequency spectrum by oscilloscope.
This makes the TX compatibility test a little difficult to pass the spec.
So case(1) and case(2) are both used indeed now. If using case(2), we
should disable RC's L0s support, and that is why we need this property to
indicate this quirk.

Also after checking quirk.c, I noticed there is already a quirk for
disabling L0s unconditionally, quirk_disable_aspm_l0s. But obviously we
shouldn't do that as mentioned above that case(1) could still works fine
with L0s.

Reported-by: Jeffy Chen <jeffy.chen-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
Cc: Brian Norris <briannorris-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
Signed-off-by: Shawn Lin <shawn.lin-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
---

 Documentation/devicetree/bindings/pci/rockchip-pcie.txt | 2 ++
 drivers/pci/host/pcie-rockchip.c                        | 9 +++++++++
 2 files changed, 11 insertions(+)

diff --git a/Documentation/devicetree/bindings/pci/rockchip-pcie.txt b/Documentation/devicetree/bindings/pci/rockchip-pcie.txt
index ba67b39..cfa44a7 100644
--- a/Documentation/devicetree/bindings/pci/rockchip-pcie.txt
+++ b/Documentation/devicetree/bindings/pci/rockchip-pcie.txt
@@ -42,6 +42,8 @@ Required properties:
 Optional Property:
 - ep-gpios: contain the entry for pre-reset gpio
 - num-lanes: number of lanes to use
+- quirk,aspm-no-l0s: RC won't support ASPM L0s. This property is needed if
+	using 24MHz OSC for RC's PHY.
 - vpcie3v3-supply: The phandle to the 3.3v regulator to use for PCIe.
 - vpcie1v8-supply: The phandle to the 1.8v regulator to use for PCIe.
 - vpcie0v9-supply: The phandle to the 0.9v regulator to use for PCIe.
diff --git a/drivers/pci/host/pcie-rockchip.c b/drivers/pci/host/pcie-rockchip.c
index 1dba698..e0d8055 100644
--- a/drivers/pci/host/pcie-rockchip.c
+++ b/drivers/pci/host/pcie-rockchip.c
@@ -140,6 +140,8 @@
 #define   PCIE_RC_CONFIG_DCR_CSPL_SHIFT		18
 #define   PCIE_RC_CONFIG_DCR_CSPL_LIMIT		0xff
 #define   PCIE_RC_CONFIG_DCR_CPLS_SHIFT		26
+#define PCIE_RC_CONFIG_LINK_CAP		(PCIE_RC_CONFIG_BASE + 0xcc)
+#define   PCIE_RC_CONFIG_LINK_CAP_L0S		BIT(10)
 #define PCIE_RC_CONFIG_LCS		(PCIE_RC_CONFIG_BASE + 0xd0)
 #define PCIE_RC_CONFIG_L1_SUBSTATE_CTRL2 (PCIE_RC_CONFIG_BASE + 0x90c)
 #define PCIE_RC_CONFIG_THP_CAP		(PCIE_RC_CONFIG_BASE + 0x274)
@@ -607,6 +609,13 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip)
 	status &= ~PCIE_RC_CONFIG_THP_CAP_NEXT_MASK;
 	rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_THP_CAP);
 
+	/* Clear L0s from RC's link cap */
+	if (of_property_read_bool(node, "quirk,apsm-no-l0s")) {
+		status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LINK_CAP);
+		status &= ~PCIE_RC_CONFIG_LINK_CAP_L0S;
+		rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LINK_CAP);
+	}
+
 	rockchip_pcie_write(rockchip, 0x0, PCIE_RC_BAR_CONF);
 
 	rockchip_pcie_write(rockchip,
-- 
1.9.1


--
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 1/2] PCI: rockchip: cleanup bit definition for PCIE_RC_CONFIG_LCS
From: Shawn Lin @ 2016-11-13  3:06 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Rob Herring, linux-pci-u79uwXL29TY76Z2rM5mHXA,
	linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Wenrui Li,
	Brian Norris, Jeffy Chen, devicetree-u79uwXL29TY76Z2rM5mHXA,
	Shawn Lin

PCIE_RC_CONFIG_LCS contains control and status bits specific
to the PCIe link. The layout for this register looks the same
as the existed PCI_EXP_LNKCTL and PCI_EXP_LNKSTA. So let's
reuse them.

Signed-off-by: Shawn Lin <shawn.lin-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
---

 drivers/pci/host/pcie-rockchip.c | 14 ++++----------
 1 file changed, 4 insertions(+), 10 deletions(-)

diff --git a/drivers/pci/host/pcie-rockchip.c b/drivers/pci/host/pcie-rockchip.c
index 7f238af..1dba698 100644
--- a/drivers/pci/host/pcie-rockchip.c
+++ b/drivers/pci/host/pcie-rockchip.c
@@ -141,12 +141,6 @@
 #define   PCIE_RC_CONFIG_DCR_CSPL_LIMIT		0xff
 #define   PCIE_RC_CONFIG_DCR_CPLS_SHIFT		26
 #define PCIE_RC_CONFIG_LCS		(PCIE_RC_CONFIG_BASE + 0xd0)
-#define   PCIE_RC_CONFIG_LCS_RETRAIN_LINK	BIT(5)
-#define   PCIE_RC_CONFIG_LCS_CCC		BIT(6)
-#define   PCIE_RC_CONFIG_LCS_LBMIE		BIT(10)
-#define   PCIE_RC_CONFIG_LCS_LABIE		BIT(11)
-#define   PCIE_RC_CONFIG_LCS_LBMS		BIT(30)
-#define   PCIE_RC_CONFIG_LCS_LAMS		BIT(31)
 #define PCIE_RC_CONFIG_L1_SUBSTATE_CTRL2 (PCIE_RC_CONFIG_BASE + 0x90c)
 #define PCIE_RC_CONFIG_THP_CAP		(PCIE_RC_CONFIG_BASE + 0x274)
 #define   PCIE_RC_CONFIG_THP_CAP_NEXT_MASK	GENMASK(31, 20)
@@ -229,7 +223,7 @@ static void rockchip_pcie_enable_bw_int(struct rockchip_pcie *rockchip)
 	u32 status;
 
 	status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LCS);
-	status |= (PCIE_RC_CONFIG_LCS_LBMIE | PCIE_RC_CONFIG_LCS_LABIE);
+	status |= (PCI_EXP_LNKCTL_LBMIE | PCI_EXP_LNKCTL_LABIE);
 	rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LCS);
 }
 
@@ -238,7 +232,7 @@ static void rockchip_pcie_clr_bw_int(struct rockchip_pcie *rockchip)
 	u32 status;
 
 	status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LCS);
-	status |= (PCIE_RC_CONFIG_LCS_LBMS | PCIE_RC_CONFIG_LCS_LAMS);
+	status |= (PCI_EXP_LNKSTA_LBMS | PCI_EXP_LNKSTA_LABS) << 16;
 	rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LCS);
 }
 
@@ -540,7 +534,7 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip)
 
 	/* Set RC's clock architecture as common clock */
 	status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LCS);
-	status |= PCIE_RC_CONFIG_LCS_CCC;
+	status |= PCI_EXP_LNKCTL_CCC;
 	rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LCS);
 
 	/* Enable Gen1 training */
@@ -575,7 +569,7 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip)
 		 * gen1 finished.
 		 */
 		status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LCS);
-		status |= PCIE_RC_CONFIG_LCS_RETRAIN_LINK;
+		status |= PCI_EXP_LNKCTL_RL;
 		rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LCS);
 
 		timeout = jiffies + msecs_to_jiffies(500);
-- 
1.9.1


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

^ permalink raw reply related

* Re: [PATCH v2 2/2] of: changesets: Introduce changeset helper methods
From: Frank Rowand @ 2016-11-13  2:15 UTC (permalink / raw)
  To: Hans de Goede, Rob Herring, Pantelis Antoniou
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20161104144241.18002-2-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>

On 11/04/16 07:42, Hans de Goede wrote:
> From: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
> 
> Changesets are very powerful, but the lack of a helper API
> makes using them cumbersome. Introduce a simple copy based
> API that makes things considerably easier.
> 
> To wit, adding a property using the raw API.
> 
> 	struct property *prop;
> 	prop = kzalloc(sizeof(*prop)), GFP_KERNEL);
> 	prop->name = kstrdup("compatible");
> 	prop->value = kstrdup("foo,bar");
> 	prop->length = strlen(prop->value) + 1;
> 	of_changeset_add_property(ocs, np, prop);
> 
> while using the helper API
> 
> 	of_changeset_add_property_string(ocs, np, "compatible",
> 			"foo,bar");
> 
> Signed-off-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
> Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> ---
> Changes in v2 (hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org):
> -Address review comments from:
>  https://www.spinics.net/lists/kernel/msg2252845.html

That points to the May 9 version 1 patches from Pantelis (as expected),
but containing 4, not 2, patches.  Patch 1/4 was applied.  Patch 4/4
seems to have disappeared?

Pantelis then sent a version 2 set of the patches on May 16.

Your version is a modification of the May 9 patches (as would be expected
of a version 2).  It is confusing to have two different version 2 patch
sets.  I don't have any brilliant ideas on how this patch set could have
been named differently to avoid that confusion.

The point of this little side-track is simply to note the existence of two
different version 2 series so I won't be confused when I revisit this
thread in the future.

>  -Simplify (and fix) __of_changeset_add_update_property_copy OOM handling
>  -Remove (by manual inlining) these 2 static helpers:
>   __of_changeset_add_update_property_u32
>   __of_changeset_add_update_property_bool
>  -Remove the following exported helper method:
>   of_changeset_node_move_to

Not all comments were addressed.

There are some other changes made that are not noted in the changelog.

I am still reading through the patches. I will reply again either with
a reviewed-by or specific comments when I finish.

-Frank

> ---
>  drivers/of/dynamic.c | 428 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/of.h   | 135 ++++++++++++++++
>  2 files changed, 563 insertions(+)

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

^ permalink raw reply

* Re: [PATCH v7 4/9] drivers:input:tsc2007: add iio interface to read external ADC input and temperature
From: H. Nikolaus Schaller @ 2016-11-12 19:22 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Sebastian Reichel, Dmitry Torokhov, Mark Rutland,
	Benoît Cousson, Tony Lindgren, Russell King, Arnd Bergmann,
	Michael Welling, Mika Penttilä, Javier Martinez Canillas,
	Igor Grinberg, Andrew F. Davis, Mark Brown, linux-input,
	devicetree, linux-kernel, linux-omap, letux-kernel, linux-iio,
	kernel
In-Reply-To: <b4d79a26-4353-9860-a884-49c751bbe617@kernel.org>

> Am 12.11.2016 um 15:19 schrieb Jonathan Cameron <jic23@kernel.org>:
> 
> On 12/11/16 14:04, Jonathan Cameron wrote:
>> On 11/11/16 19:02, H. Nikolaus Schaller wrote:
>>> The tsc2007 chip not only has a resistive touch screen controller but
>>> also an external AUX adc imput which can be used for an ambient
>>> light sensor, battery voltage monitoring or any general purpose.
>>> 
>>> Additionally it can measure the chip temperature.
>>> 
>>> This extension provides an iio interface for these adc channels.
>>> 
>>> Since it is not wasting much resources and is very straightforward,
>>> we simply provide all other adc channels as optional iio interfaces
>>> as weel. This can be used for debugging or special applications.
>>> 
>>> This patch also splits the tsc2007 driver in several source files:
>>> tsc2007.h -- constants, structs and stubs
>>> tsc2007_core.c -- functional parts of the original driver
>>> tsc2007_iio.c -- the optional iio stuff
>>> 
>>> Makefile magic allows to conditionally link the iio
>>> stuff if CONFIG_IIO=y in a way that it works with
>>> CONFIG_TOUCHSCREEN_TSC2007=m.
>>> 
>> 
>> I ran a quick build test and it blows up in a number of ways related to
>> the #ifdef CONFIG_IIO.
>> 
>> I'm not entirely sure why but
>> #if IS_ENABLED(CONFIG_IIO) works fine.
> Ah, I'm being sleepy today.  It's because I'm building IIO as a module
> and the symbol defined would therefore be CONFIG_IIO_MODULE.
> 
> The IS_ENABLED macro takes care of both cases.

Ah, yes. I wasn't aware that CONFIG_IIO is tristate at all.
We have it as "y" and therefore didn't notice.

I will collect this fix for V8.

>> 
>> Otherwise looks good to me
>>> Signed-off-by: H. Nikolaus Schaller <hns@goldelico.com>
>> Reviewed-by: Jonathan Cameron <jic23@kernel.org>

Will add this as well.

Thanks for the detailled review!

BR,
Nikolaus



^ permalink raw reply

* Re: [PATCH v4 8/8] iio: envelope-detector: ADC driver based on a DAC and a comparator
From: Jonathan Cameron @ 2016-11-12 17:29 UTC (permalink / raw)
  To: Peter Rosin, Thomas Gleixner
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Rob Herring,
	Mark Rutland, Daniel Baluta, Slawomir Stepien,
	linux-iio-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <9fa01d3d-74ba-a048-52bf-4df959153354-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>

On 11/11/16 11:37, Peter Rosin wrote:
> On 2016-11-09 16:06, Thomas Gleixner wrote:
>> On Wed, 9 Nov 2016, Peter Rosin wrote:
>>> On 2016-11-08 22:47, Thomas Gleixner wrote:
>>>> I don't think you need extra race handling with that, but I might be wrong
>>>> as usual.
>>>
>>> There's obviously no way to determine which of the timeout or the
>>> interrupt that happens first without some race handling, so I don't
>>> know what you mean? If the timeout happens first, there is also a
>>> need to handle late hits from the irq that might come in during the
>>> preparation for the next step in the binary search. It gets messy
>>> quickly compared to the simplicity of the current implementation.
>>
>> Gah, forgot about that timeout thingy. Fair enough.
>>
>> Feel free to add an 
>>
>> Acked-by: Thomas Gleixner <tglx-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
> 
> Thanks for looking!
Applied to the togreg branch of iio.git and pushed out
as testing for the autobuilders to play with.

Excellent patch set.

Thanks,

Jonathan
> 
> Cheers,
> Peter
> 

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

^ permalink raw reply

* Re: [PATCH v4 8/8] iio: envelope-detector: ADC driver based on a DAC and a comparator
From: Jonathan Cameron @ 2016-11-12 17:27 UTC (permalink / raw)
  To: Peter Rosin, Thomas Gleixner
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Rob Herring,
	Mark Rutland, Daniel Baluta, Slawomir Stepien,
	linux-iio-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <d8237286-d2ff-3146-d718-f54d05b0101d-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>

On 08/11/16 17:03, Peter Rosin wrote:
> On 2016-11-08 16:59, Thomas Gleixner wrote:
>> On Tue, 8 Nov 2016, Peter Rosin wrote:
>>> +/*
>>> + * The envelope_detector_comp_latch function works together with the compare
>>> + * interrupt service routine below (envelope_detector_comp_isr) as a latch
>>> + * (one-bit memory) for if the interrupt has triggered since last calling
>>> + * this function.
>>> + * The ..._comp_isr function disables the interrupt so that the cpu does not
>>> + * need to service a possible interrupt flood from the comparator when no-one
>>> + * cares anyway, and this ..._comp_latch function reenables them again if
>>> + * needed.
>>> + */
>>> +static int envelope_detector_comp_latch(struct envelope *env)
>>> +{
>>> +	int comp;
>>> +
>>> +	spin_lock_irq(&env->comp_lock);
>>> +	comp = env->comp;
>>> +	env->comp = 0;
>>> +	spin_unlock_irq(&env->comp_lock);
>>> +
>>> +	if (!comp)
>>> +		return 0;
>>> +
>>> +	/*
>>> +	 * The irq was disabled, and is reenabled just now.
>>> +	 * But there might have been a pending irq that
>>> +	 * happened while the irq was disabled that fires
>>> +	 * just as the irq is reenabled. That is not what
>>> +	 * is desired.
>>> +	 */
>>> +	enable_irq(env->comp_irq);
>>> +
>>> +	/* So, synchronize this possibly pending irq... */
>>> +	synchronize_irq(env->comp_irq);
>>> +
>>> +	/* ...and redo the whole dance. */
>>> +	spin_lock_irq(&env->comp_lock);
>>> +	comp = env->comp;
>>> +	env->comp = 0;
>>> +	spin_unlock_irq(&env->comp_lock);
>>> +
>>> +	if (comp)
>>> +		enable_irq(env->comp_irq);
>>
>> So you need that whole dance including the delayed work because you cannot
>> call iio_write_channel_raw() from hard interrupt context, right?
> 
> It's not the "cannot call from hard irq context" that made me do that, it's...
> 
>> So you might just register a threaded interrupt handler, which should make
>> this whole thing way simpler.
>>
>>      devm_request_threaded_irq(dev, irq, NULL, your_isr, IRQF_ONESHOT, ...);
>>
>> The core will mask the interrupt line until the threaded handler is
>> finished. The threaded handler is invoked with preemption enabled, so you
>> can sleep there as long as you want. So you can do everything in your
>> handler and the above dance is just not required.
> 
> ...that I couldn't work out how to reenable a oneshot irq once it had fired,
> short of freeing the irq and requesting it again. That seemed entirely
> bogus, the driver shouldn't risk losing a resource like that so I don't know
> what I didn't see? Or maybe it was that I had a hard time resolving the race
> between the irq and the timeout in a nice way. I honestly don't remember
> why exactly I abandoned oneshot irqs, but this enable/sync/enable dance
> was much nicer than what I came up with for the oneshot irq solution I
> originally worked on.
> 
> Or maybe I had problems with the possibly pending irq also when using a
> oneshot irq, but didn't realize it? That was something I discovered quite
> late in the process, some time after moving away from oneshot irqs. Are
> pending irqs cleared when requesting (or reenabling, however that is done)
> a oneshot irq?
> 
> Anyway, I do not want the interrupt to be serviced when no one is interested,
> since I'm afraid that nasty input might generate a flood of interrupts that
> might disturb other things that the cpu is doing. Which means that I need
> to enable/disable the interrupt as needed.
> 
> However, what *I* thought Jonathan wanted input on was the part where the
> interrupt edge/level is flipped when requesting "inverted" signals in
> envelope_store_invert(). That could perhaps be seen as unorthodox and in
> need of more eyes?
Nope, as far as I can recall it was precisely this dance that was 
I wanted Thomas to comment on :)  The inverted bit isn't as novel as
this ;)

Anyhow, thread ended up with a good conclusion so I'm happy.

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

^ permalink raw reply

* Re: [PATCH v4 7/8] dt-bindings: iio: document envelope-detector bindings
From: Jonathan Cameron @ 2016-11-12 17:25 UTC (permalink / raw)
  To: Peter Rosin, linux-kernel
  Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Rob Herring, Mark Rutland, Daniel Baluta, Slawomir Stepien,
	Thomas Gleixner, linux-iio, devicetree
In-Reply-To: <1478606339-31253-8-git-send-email-peda@axentia.se>

On 08/11/16 11:58, Peter Rosin wrote:
> Acked-by: Rob Herring <robh@kernel.org>
> Signed-off-by: Peter Rosin <peda@axentia.se>
Applied.
> ---
>  .../bindings/iio/adc/envelope-detector.txt         | 54 ++++++++++++++++++++++
>  MAINTAINERS                                        |  6 +++
>  2 files changed, 60 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/iio/adc/envelope-detector.txt
> 
> diff --git a/Documentation/devicetree/bindings/iio/adc/envelope-detector.txt b/Documentation/devicetree/bindings/iio/adc/envelope-detector.txt
> new file mode 100644
> index 000000000000..27544bdd4478
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/iio/adc/envelope-detector.txt
> @@ -0,0 +1,54 @@
> +Bindings for ADC envelope detector using a DAC and a comparator
> +
> +The DAC is used to find the peak level of an alternating voltage input
> +signal by a binary search using the output of a comparator wired to
> +an interrupt pin. Like so:
> +                          _
> +                         | \
> +    input +------>-------|+ \
> +                         |   \
> +           .-------.     |    }---.
> +           |       |     |   /    |
> +           |    dac|-->--|- /     |
> +           |       |     |_/      |
> +           |       |              |
> +           |       |              |
> +           |    irq|------<-------'
> +           |       |
> +           '-------'
> +
> +Required properties:
> +- compatible: Should be "axentia,tse850-envelope-detector"
> +- io-channels: Channel node of the dac to be used for comparator input.
> +- io-channel-names: Should be "dac".
> +- interrupt specification for one client interrupt,
> +  see ../../interrupt-controller/interrupts.txt for details.
> +- interrupt-names: Should be "comp".
> +
> +Example:
> +
> +	&i2c {
> +		dpot: mcp4651-104@28 {
> +			compatible = "microchip,mcp4651-104";
> +			reg = <0x28>;
> +			#io-channel-cells = <1>;
> +		};
> +	};
> +
> +	dac: dac {
> +		compatible = "dpot-dac";
> +		vref-supply = <&reg_3v3>;
> +		io-channels = <&dpot 0>;
> +		io-channel-names = "dpot";
> +		#io-channel-cells = <1>;
> +	};
> +
> +	envelope-detector {
> +		compatible = "axentia,tse850-envelope-detector";
> +		io-channels = <&dac 0>;
> +		io-channel-names = "dac";
> +
> +		interrupt-parent = <&gpio>;
> +		interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
> +		interrupt-names = "comp";
> +	};
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 583c6c93b6f3..0e13066ca3a2 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -6132,6 +6132,12 @@ F:	Documentation/ABI/testing/sysfs-bus-iio-dac-dpot-dac
>  F:	Documentation/devicetree/bindings/iio/dac/dpot-dac.txt
>  F:	drivers/iio/dac/dpot-dac.c
>  
> +IIO ENVELOPE DETECTOR
> +M:	Peter Rosin <peda@axentia.se>
> +L:	linux-iio@vger.kernel.org
> +S:	Maintained
> +F:	Documentation/devicetree/bindings/iio/adc/envelope-detector.txt
> +
>  IIO SUBSYSTEM AND DRIVERS
>  M:	Jonathan Cameron <jic23@kernel.org>
>  R:	Hartmut Knaack <knaack.h@gmx.de>
> 

^ permalink raw reply

* Re: [PATCH v4 6/8] iio: dpot-dac: DAC driver based on a digital potentiometer
From: Jonathan Cameron @ 2016-11-12 17:24 UTC (permalink / raw)
  To: Peter Rosin, linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Rob Herring, Mark Rutland, Daniel Baluta, Slawomir Stepien,
	Thomas Gleixner, linux-iio-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1478606339-31253-7-git-send-email-peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>

On 08/11/16 11:58, Peter Rosin wrote:
> It is assumed that the dpot is used as a voltage divider between the
> current dpot wiper setting and the maximum resistance of the dpot. The
> divided voltage is provided by a vref regulator.
> 
>                   .------.
>    .-----------.  |      |
>    | vref      |--'    .---.
>    | regulator |--.    |   |
>    '-----------'  |    | d |
>                   |    | p |
>                   |    | o |  wiper
>                   |    | t |<---------+
>                   |    |   |
>                   |    '---'       dac output voltage
>                   |      |
>                   '------+------------+
> 
> Signed-off-by: Peter Rosin <peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>
Applied to the togreg branch of iio.git - shortly to be pushed out as testing
for the autobuilders to play with it.

Thanks,

Jonathan
> ---
>  .../ABI/testing/sysfs-bus-iio-dac-dpot-dac         |   8 +
>  MAINTAINERS                                        |   2 +
>  drivers/iio/dac/Kconfig                            |  10 +
>  drivers/iio/dac/Makefile                           |   1 +
>  drivers/iio/dac/dpot-dac.c                         | 266 +++++++++++++++++++++
>  5 files changed, 287 insertions(+)
>  create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-dac-dpot-dac
>  create mode 100644 drivers/iio/dac/dpot-dac.c
> 
> diff --git a/Documentation/ABI/testing/sysfs-bus-iio-dac-dpot-dac b/Documentation/ABI/testing/sysfs-bus-iio-dac-dpot-dac
> new file mode 100644
> index 000000000000..580e93f373f6
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-bus-iio-dac-dpot-dac
> @@ -0,0 +1,8 @@
> +What:		/sys/bus/iio/devices/iio:deviceX/out_voltageY_raw_available
> +Date:		October 2016
> +KernelVersion:	4.9
> +Contact:	Peter Rosin <peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>
> +Description:
> +		The range of available values represented as the minimum value,
> +		the step and the maximum value, all enclosed in square brackets.
> +		Example: [0 1 256]
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 4ff9c12b1313..583c6c93b6f3 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -6128,7 +6128,9 @@ IIO DIGITAL POTENTIOMETER DAC
>  M:	Peter Rosin <peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>
>  L:	linux-iio-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
>  S:	Maintained
> +F:	Documentation/ABI/testing/sysfs-bus-iio-dac-dpot-dac
>  F:	Documentation/devicetree/bindings/iio/dac/dpot-dac.txt
> +F:	drivers/iio/dac/dpot-dac.c
>  
>  IIO SUBSYSTEM AND DRIVERS
>  M:	Jonathan Cameron <jic23-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig
> index 120b24478469..d3084028905b 100644
> --- a/drivers/iio/dac/Kconfig
> +++ b/drivers/iio/dac/Kconfig
> @@ -200,6 +200,16 @@ config AD8801
>  	  To compile this driver as a module choose M here: the module will be called
>  	  ad8801.
>  
> +config DPOT_DAC
> +	tristate "DAC emulation using a DPOT"
> +	depends on OF
> +	help
> +	  Say yes here to build support for DAC emulation using a digital
> +	  potentiometer.
> +
> +	  To compile this driver as a module, choose M here: the module will be
> +	  called dpot-dac.
> +
>  config LPC18XX_DAC
>  	tristate "NXP LPC18xx DAC driver"
>  	depends on ARCH_LPC18XX || COMPILE_TEST
> diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile
> index 27642bbf75f2..f01bf4a99867 100644
> --- a/drivers/iio/dac/Makefile
> +++ b/drivers/iio/dac/Makefile
> @@ -22,6 +22,7 @@ obj-$(CONFIG_AD5686) += ad5686.o
>  obj-$(CONFIG_AD7303) += ad7303.o
>  obj-$(CONFIG_AD8801) += ad8801.o
>  obj-$(CONFIG_CIO_DAC) += cio-dac.o
> +obj-$(CONFIG_DPOT_DAC) += dpot-dac.o
>  obj-$(CONFIG_LPC18XX_DAC) += lpc18xx_dac.o
>  obj-$(CONFIG_M62332) += m62332.o
>  obj-$(CONFIG_MAX517) += max517.o
> diff --git a/drivers/iio/dac/dpot-dac.c b/drivers/iio/dac/dpot-dac.c
> new file mode 100644
> index 000000000000..eb1f0509a3ec
> --- /dev/null
> +++ b/drivers/iio/dac/dpot-dac.c
> @@ -0,0 +1,266 @@
> +/*
> + * IIO DAC emulation driver using a digital potentiometer
> + *
> + * Copyright (C) 2016 Axentia Technologies AB
> + *
> + * Author: Peter Rosin <peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +/*
> + * It is assumed that the dpot is used as a voltage divider between the
> + * current dpot wiper setting and the maximum resistance of the dpot. The
> + * divided voltage is provided by a vref regulator.
> + *
> + *                   .------.
> + *    .-----------.  |      |
> + *    | vref      |--'    .---.
> + *    | regulator |--.    |   |
> + *    '-----------'  |    | d |
> + *                   |    | p |
> + *                   |    | o |  wiper
> + *                   |    | t |<---------+
> + *                   |    |   |
> + *                   |    '---'       dac output voltage
> + *                   |      |
> + *                   '------+------------+
> + */
> +
> +#include <linux/err.h>
> +#include <linux/iio/consumer.h>
> +#include <linux/iio/iio.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/regulator/consumer.h>
> +
> +struct dpot_dac {
> +	struct regulator *vref;
> +	struct iio_channel *dpot;
> +	u32 max_ohms;
> +};
> +
> +static const struct iio_chan_spec dpot_dac_iio_channel = {
> +	.type = IIO_VOLTAGE,
> +	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW)
> +			    | BIT(IIO_CHAN_INFO_SCALE),
> +	.info_mask_separate_available = BIT(IIO_CHAN_INFO_RAW),
> +	.output = 1,
> +	.indexed = 1,
> +};
> +
> +static int dpot_dac_read_raw(struct iio_dev *indio_dev,
> +			     struct iio_chan_spec const *chan,
> +			     int *val, int *val2, long mask)
> +{
> +	struct dpot_dac *dac = iio_priv(indio_dev);
> +	int ret;
> +	unsigned long long tmp;
> +
> +	switch (mask) {
> +	case IIO_CHAN_INFO_RAW:
> +		return iio_read_channel_raw(dac->dpot, val);
> +
> +	case IIO_CHAN_INFO_SCALE:
> +		ret = iio_read_channel_scale(dac->dpot, val, val2);
> +		switch (ret) {
> +		case IIO_VAL_FRACTIONAL_LOG2:
> +			tmp = *val * 1000000000LL;
> +			do_div(tmp, dac->max_ohms);
> +			tmp *= regulator_get_voltage(dac->vref) / 1000;
> +			do_div(tmp, 1000000000LL);
> +			*val = tmp;
> +			return ret;
> +		case IIO_VAL_INT:
> +			/*
> +			 * Convert integer scale to fractional scale by
> +			 * setting the denominator (val2) to one...
> +			 */
> +			*val2 = 1;
> +			ret = IIO_VAL_FRACTIONAL;
> +			/* ...and fall through. */
> +		case IIO_VAL_FRACTIONAL:
> +			*val *= regulator_get_voltage(dac->vref) / 1000;
> +			*val2 *= dac->max_ohms;
> +			break;
> +		}
> +
> +		return ret;
> +	}
> +
> +	return -EINVAL;
> +}
> +
> +static int dpot_dac_read_avail(struct iio_dev *indio_dev,
> +			       struct iio_chan_spec const *chan,
> +			       const int **vals, int *type, int *length,
> +			       long mask)
> +{
> +	struct dpot_dac *dac = iio_priv(indio_dev);
> +
> +	switch (mask) {
> +	case IIO_CHAN_INFO_RAW:
> +		*type = IIO_VAL_INT;
> +		return iio_read_avail_channel_raw(dac->dpot, vals, length);
> +	}
> +
> +	return -EINVAL;
> +}
> +
> +static int dpot_dac_write_raw(struct iio_dev *indio_dev,
> +			      struct iio_chan_spec const *chan,
> +			      int val, int val2, long mask)
> +{
> +	struct dpot_dac *dac = iio_priv(indio_dev);
> +
> +	switch (mask) {
> +	case IIO_CHAN_INFO_RAW:
> +		return iio_write_channel_raw(dac->dpot, val);
> +	}
> +
> +	return -EINVAL;
> +}
> +
> +static const struct iio_info dpot_dac_info = {
> +	.read_raw = dpot_dac_read_raw,
> +	.read_avail = dpot_dac_read_avail,
> +	.write_raw = dpot_dac_write_raw,
> +	.driver_module = THIS_MODULE,
> +};
> +
> +static int dpot_dac_channel_max_ohms(struct iio_dev *indio_dev)
> +{
> +	struct device *dev = &indio_dev->dev;
> +	struct dpot_dac *dac = iio_priv(indio_dev);
> +	unsigned long long tmp;
> +	int ret;
> +	int val;
> +	int val2;
> +	int max;
> +
> +	ret = iio_read_max_channel_raw(dac->dpot, &max);
> +	if (ret < 0) {
> +		dev_err(dev, "dpot does not indicate its raw maximum value\n");
> +		return ret;
> +	}
> +
> +	switch (iio_read_channel_scale(dac->dpot, &val, &val2)) {
> +	case IIO_VAL_INT:
> +		return max * val;
> +	case IIO_VAL_FRACTIONAL:
> +		tmp = (unsigned long long)max * val;
> +		do_div(tmp, val2);
> +		return tmp;
> +	case IIO_VAL_FRACTIONAL_LOG2:
> +		tmp = val * 1000000000LL * max >> val2;
> +		do_div(tmp, 1000000000LL);
> +		return tmp;
> +	default:
> +		dev_err(dev, "dpot has a scale that is too weird\n");
> +	}
> +
> +	return -EINVAL;
> +}
> +
> +static int dpot_dac_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct iio_dev *indio_dev;
> +	struct dpot_dac *dac;
> +	enum iio_chan_type type;
> +	int ret;
> +
> +	indio_dev = devm_iio_device_alloc(dev, sizeof(*dac));
> +	if (!indio_dev)
> +		return -ENOMEM;
> +
> +	platform_set_drvdata(pdev, indio_dev);
> +	dac = iio_priv(indio_dev);
> +
> +	indio_dev->name = dev_name(dev);
> +	indio_dev->dev.parent = dev;
> +	indio_dev->info = &dpot_dac_info;
> +	indio_dev->modes = INDIO_DIRECT_MODE;
> +	indio_dev->channels = &dpot_dac_iio_channel;
> +	indio_dev->num_channels = 1;
> +
> +	dac->vref = devm_regulator_get(dev, "vref");
> +	if (IS_ERR(dac->vref)) {
> +		if (PTR_ERR(dac->dpot) != -EPROBE_DEFER)
> +			dev_err(&pdev->dev, "failed to get vref regulator\n");
> +		return PTR_ERR(dac->vref);
> +	}
> +
> +	dac->dpot = devm_iio_channel_get(dev, "dpot");
> +	if (IS_ERR(dac->dpot)) {
> +		if (PTR_ERR(dac->dpot) != -EPROBE_DEFER)
> +			dev_err(dev, "failed to get dpot input channel\n");
> +		return PTR_ERR(dac->dpot);
> +	}
> +
> +	ret = iio_get_channel_type(dac->dpot, &type);
> +	if (ret < 0)
> +		return ret;
> +
> +	if (type != IIO_RESISTANCE) {
> +		dev_err(dev, "dpot is of the wrong type\n");
> +		return -EINVAL;
> +	}
> +
> +	ret = dpot_dac_channel_max_ohms(indio_dev);
> +	if (ret < 0)
> +		return ret;
> +	dac->max_ohms = ret;
> +
> +	ret = regulator_enable(dac->vref);
> +	if (ret) {
> +		dev_err(dev, "failed to enable the vref regulator\n");
> +		return ret;
> +	}
> +
> +	ret = iio_device_register(indio_dev);
> +	if (ret) {
> +		dev_err(dev, "failed to register iio device\n");
> +		goto disable_reg;
> +	}
> +
> +	return 0;
> +
> +disable_reg:
> +	regulator_disable(dac->vref);
> +	return ret;
> +}
> +
> +static int dpot_dac_remove(struct platform_device *pdev)
> +{
> +	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
> +	struct dpot_dac *dac = iio_priv(indio_dev);
> +
> +	iio_device_unregister(indio_dev);
> +	regulator_disable(dac->vref);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id dpot_dac_match[] = {
> +	{ .compatible = "dpot-dac" },
> +	{ /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(of, dpot_dac_match);
> +
> +static struct platform_driver dpot_dac_driver = {
> +	.probe = dpot_dac_probe,
> +	.remove = dpot_dac_remove,
> +	.driver = {
> +		.name = "iio-dpot-dac",
> +		.of_match_table = dpot_dac_match,
> +	},
> +};
> +module_platform_driver(dpot_dac_driver);
> +
> +MODULE_DESCRIPTION("DAC emulation driver using a digital potentiometer");
> +MODULE_AUTHOR("Peter Rosin <peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>");
> +MODULE_LICENSE("GPL v2");
> 

^ permalink raw reply

* Re: [PATCH v4 4/8] dt-bindings: add axentia to vendor-prefixes
From: Jonathan Cameron @ 2016-11-12 17:23 UTC (permalink / raw)
  To: Peter Rosin, linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Rob Herring, Mark Rutland, Daniel Baluta, Slawomir Stepien,
	Thomas Gleixner, linux-iio-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1478606339-31253-5-git-send-email-peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>

On 08/11/16 11:58, Peter Rosin wrote:
> Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> Signed-off-by: Peter Rosin <peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>
Applied.
> ---
>  Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
> index f0a48ea78659..a437120a7eee 100644
> --- a/Documentation/devicetree/bindings/vendor-prefixes.txt
> +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
> @@ -39,6 +39,7 @@ auo	AU Optronics Corporation
>  auvidea Auvidea GmbH
>  avago	Avago Technologies
>  avic	Shanghai AVIC Optoelectronics Co., Ltd.
> +axentia	Axentia Technologies AB
>  axis	Axis Communications AB
>  boe	BOE Technology Group Co., Ltd.
>  bosch	Bosch Sensortec GmbH
> 

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

^ permalink raw reply

* Re: [PATCH v4 3/8] iio: mcp4531: provide range of available raw values
From: Jonathan Cameron @ 2016-11-12 17:22 UTC (permalink / raw)
  To: Peter Rosin, linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Rob Herring, Mark Rutland, Daniel Baluta, Slawomir Stepien,
	Thomas Gleixner, linux-iio-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1478606339-31253-4-git-send-email-peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>

On 08/11/16 11:58, Peter Rosin wrote:
> Example:
> 
> $ cat '/sys/bus/iio/devices/iio:device0/out_resistance_raw_available'
> [0 1 256]
> 
> Meaning: min 0, step 1 and max 256.
> 
> Signed-off-by: Peter Rosin <peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>
Applied.
> ---
>  .../testing/sysfs-bus-iio-potentiometer-mcp4531    |   8 ++
>  MAINTAINERS                                        |   1 +
>  drivers/iio/potentiometer/mcp4531.c                | 104 ++++++++++++---------
>  3 files changed, 71 insertions(+), 42 deletions(-)
>  create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-potentiometer-mcp4531
> 
> diff --git a/Documentation/ABI/testing/sysfs-bus-iio-potentiometer-mcp4531 b/Documentation/ABI/testing/sysfs-bus-iio-potentiometer-mcp4531
> new file mode 100644
> index 000000000000..2a91fbe394fc
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-bus-iio-potentiometer-mcp4531
> @@ -0,0 +1,8 @@
> +What:		/sys/bus/iio/devices/iio:deviceX/out_resistance_raw_available
> +Date:		October 2016
> +KernelVersion:	4.9
> +Contact:	Peter Rosin <peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>
> +Description:
> +		The range of available values represented as the minimum value,
> +		the step and the maximum value, all enclosed in square brackets.
> +		Example: [0 1 256]
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 411e3b87b8c2..2409e1d79cb6 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -7707,6 +7707,7 @@ MCP4531 MICROCHIP DIGITAL POTENTIOMETER DRIVER
>  M:	Peter Rosin <peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>
>  L:	linux-iio-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
>  S:	Maintained
> +F:	Documentation/ABI/testing/sysfs-bus-iio-potentiometer-mcp4531
>  F:	drivers/iio/potentiometer/mcp4531.c
>  
>  MEASUREMENT COMPUTING CIO-DAC IIO DRIVER
> diff --git a/drivers/iio/potentiometer/mcp4531.c b/drivers/iio/potentiometer/mcp4531.c
> index 13b6ae2fcf7b..0d1bcf89ae17 100644
> --- a/drivers/iio/potentiometer/mcp4531.c
> +++ b/drivers/iio/potentiometer/mcp4531.c
> @@ -38,7 +38,7 @@
>  
>  struct mcp4531_cfg {
>  	int wipers;
> -	int max_pos;
> +	int avail[3];
>  	int kohms;
>  };
>  
> @@ -78,38 +78,38 @@ enum mcp4531_type {
>  };
>  
>  static const struct mcp4531_cfg mcp4531_cfg[] = {
> -	[MCP453x_502] = { .wipers = 1, .max_pos = 128, .kohms =   5, },
> -	[MCP453x_103] = { .wipers = 1, .max_pos = 128, .kohms =  10, },
> -	[MCP453x_503] = { .wipers = 1, .max_pos = 128, .kohms =  50, },
> -	[MCP453x_104] = { .wipers = 1, .max_pos = 128, .kohms = 100, },
> -	[MCP454x_502] = { .wipers = 1, .max_pos = 128, .kohms =   5, },
> -	[MCP454x_103] = { .wipers = 1, .max_pos = 128, .kohms =  10, },
> -	[MCP454x_503] = { .wipers = 1, .max_pos = 128, .kohms =  50, },
> -	[MCP454x_104] = { .wipers = 1, .max_pos = 128, .kohms = 100, },
> -	[MCP455x_502] = { .wipers = 1, .max_pos = 256, .kohms =   5, },
> -	[MCP455x_103] = { .wipers = 1, .max_pos = 256, .kohms =  10, },
> -	[MCP455x_503] = { .wipers = 1, .max_pos = 256, .kohms =  50, },
> -	[MCP455x_104] = { .wipers = 1, .max_pos = 256, .kohms = 100, },
> -	[MCP456x_502] = { .wipers = 1, .max_pos = 256, .kohms =   5, },
> -	[MCP456x_103] = { .wipers = 1, .max_pos = 256, .kohms =  10, },
> -	[MCP456x_503] = { .wipers = 1, .max_pos = 256, .kohms =  50, },
> -	[MCP456x_104] = { .wipers = 1, .max_pos = 256, .kohms = 100, },
> -	[MCP463x_502] = { .wipers = 2, .max_pos = 128, .kohms =   5, },
> -	[MCP463x_103] = { .wipers = 2, .max_pos = 128, .kohms =  10, },
> -	[MCP463x_503] = { .wipers = 2, .max_pos = 128, .kohms =  50, },
> -	[MCP463x_104] = { .wipers = 2, .max_pos = 128, .kohms = 100, },
> -	[MCP464x_502] = { .wipers = 2, .max_pos = 128, .kohms =   5, },
> -	[MCP464x_103] = { .wipers = 2, .max_pos = 128, .kohms =  10, },
> -	[MCP464x_503] = { .wipers = 2, .max_pos = 128, .kohms =  50, },
> -	[MCP464x_104] = { .wipers = 2, .max_pos = 128, .kohms = 100, },
> -	[MCP465x_502] = { .wipers = 2, .max_pos = 256, .kohms =   5, },
> -	[MCP465x_103] = { .wipers = 2, .max_pos = 256, .kohms =  10, },
> -	[MCP465x_503] = { .wipers = 2, .max_pos = 256, .kohms =  50, },
> -	[MCP465x_104] = { .wipers = 2, .max_pos = 256, .kohms = 100, },
> -	[MCP466x_502] = { .wipers = 2, .max_pos = 256, .kohms =   5, },
> -	[MCP466x_103] = { .wipers = 2, .max_pos = 256, .kohms =  10, },
> -	[MCP466x_503] = { .wipers = 2, .max_pos = 256, .kohms =  50, },
> -	[MCP466x_104] = { .wipers = 2, .max_pos = 256, .kohms = 100, },
> +	[MCP453x_502] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms =   5, },
> +	[MCP453x_103] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms =  10, },
> +	[MCP453x_503] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms =  50, },
> +	[MCP453x_104] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms = 100, },
> +	[MCP454x_502] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms =   5, },
> +	[MCP454x_103] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms =  10, },
> +	[MCP454x_503] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms =  50, },
> +	[MCP454x_104] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms = 100, },
> +	[MCP455x_502] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms =   5, },
> +	[MCP455x_103] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms =  10, },
> +	[MCP455x_503] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms =  50, },
> +	[MCP455x_104] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms = 100, },
> +	[MCP456x_502] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms =   5, },
> +	[MCP456x_103] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms =  10, },
> +	[MCP456x_503] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms =  50, },
> +	[MCP456x_104] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms = 100, },
> +	[MCP463x_502] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms =   5, },
> +	[MCP463x_103] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms =  10, },
> +	[MCP463x_503] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms =  50, },
> +	[MCP463x_104] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms = 100, },
> +	[MCP464x_502] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms =   5, },
> +	[MCP464x_103] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms =  10, },
> +	[MCP464x_503] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms =  50, },
> +	[MCP464x_104] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms = 100, },
> +	[MCP465x_502] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms =   5, },
> +	[MCP465x_103] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms =  10, },
> +	[MCP465x_503] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms =  50, },
> +	[MCP465x_104] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms = 100, },
> +	[MCP466x_502] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms =   5, },
> +	[MCP466x_103] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms =  10, },
> +	[MCP466x_503] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms =  50, },
> +	[MCP466x_104] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms = 100, },
>  };
>  
>  #define MCP4531_WRITE (0 << 2)
> @@ -124,13 +124,14 @@ struct mcp4531_data {
>  	const struct mcp4531_cfg *cfg;
>  };
>  
> -#define MCP4531_CHANNEL(ch) {					\
> -	.type = IIO_RESISTANCE,					\
> -	.indexed = 1,						\
> -	.output = 1,						\
> -	.channel = (ch),					\
> -	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
> -	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
> +#define MCP4531_CHANNEL(ch) {						\
> +	.type = IIO_RESISTANCE,						\
> +	.indexed = 1,							\
> +	.output = 1,							\
> +	.channel = (ch),						\
> +	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),			\
> +	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),		\
> +	.info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_RAW),	\
>  }
>  
>  static const struct iio_chan_spec mcp4531_channels[] = {
> @@ -156,13 +157,31 @@ static int mcp4531_read_raw(struct iio_dev *indio_dev,
>  		return IIO_VAL_INT;
>  	case IIO_CHAN_INFO_SCALE:
>  		*val = 1000 * data->cfg->kohms;
> -		*val2 = data->cfg->max_pos;
> +		*val2 = data->cfg->avail[2];
>  		return IIO_VAL_FRACTIONAL;
>  	}
>  
>  	return -EINVAL;
>  }
>  
> +static int mcp4531_read_avail(struct iio_dev *indio_dev,
> +			      struct iio_chan_spec const *chan,
> +			      const int **vals, int *type, int *length,
> +			      long mask)
> +{
> +	struct mcp4531_data *data = iio_priv(indio_dev);
> +
> +	switch (mask) {
> +	case IIO_CHAN_INFO_RAW:
> +		*length = ARRAY_SIZE(data->cfg->avail);
> +		*vals = data->cfg->avail;
> +		*type = IIO_VAL_INT;
> +		return IIO_AVAIL_RANGE;
> +	}
> +
> +	return -EINVAL;
> +}
> +
>  static int mcp4531_write_raw(struct iio_dev *indio_dev,
>  			     struct iio_chan_spec const *chan,
>  			     int val, int val2, long mask)
> @@ -172,7 +191,7 @@ static int mcp4531_write_raw(struct iio_dev *indio_dev,
>  
>  	switch (mask) {
>  	case IIO_CHAN_INFO_RAW:
> -		if (val > data->cfg->max_pos || val < 0)
> +		if (val > data->cfg->avail[2] || val < 0)
>  			return -EINVAL;
>  		break;
>  	default:
> @@ -186,6 +205,7 @@ static int mcp4531_write_raw(struct iio_dev *indio_dev,
>  
>  static const struct iio_info mcp4531_info = {
>  	.read_raw = mcp4531_read_raw,
> +	.read_avail = mcp4531_read_avail,
>  	.write_raw = mcp4531_write_raw,
>  	.driver_module = THIS_MODULE,
>  };
> 

^ permalink raw reply

* Re: [PATCH v4 2/8] iio: inkern: add helpers to query available values from channels
From: Jonathan Cameron @ 2016-11-12 17:17 UTC (permalink / raw)
  To: Peter Rosin, linux-kernel
  Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Rob Herring, Mark Rutland, Daniel Baluta, Slawomir Stepien,
	Thomas Gleixner, linux-iio, devicetree
In-Reply-To: <1478606339-31253-3-git-send-email-peda@axentia.se>

On 08/11/16 11:58, Peter Rosin wrote:
> Specifically a helper for reading the available maximum raw value of a
> channel and a helper for forwarding read_avail requests for raw values
> from one iio driver to an iio channel that is consumed.
> 
> These rather specific helpers are in turn built with generic helpers
> making it easy to build more helpers for available values as needed.
> 
> Signed-off-by: Peter Rosin <peda@axentia.se>
Applied.
> ---
>  drivers/iio/inkern.c         | 104 +++++++++++++++++++++++++++++++++++++++++++
>  include/linux/iio/consumer.h |  28 ++++++++++++
>  include/linux/iio/iio.h      |  17 +++++++
>  3 files changed, 149 insertions(+)
> 
> diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c
> index c4757e6367e7..cfca17ba2535 100644
> --- a/drivers/iio/inkern.c
> +++ b/drivers/iio/inkern.c
> @@ -703,6 +703,110 @@ int iio_read_channel_scale(struct iio_channel *chan, int *val, int *val2)
>  }
>  EXPORT_SYMBOL_GPL(iio_read_channel_scale);
>  
> +static int iio_channel_read_avail(struct iio_channel *chan,
> +				  const int **vals, int *type, int *length,
> +				  enum iio_chan_info_enum info)
> +{
> +	if (!iio_channel_has_available(chan->channel, info))
> +		return -EINVAL;
> +
> +	return chan->indio_dev->info->read_avail(chan->indio_dev, chan->channel,
> +						 vals, type, length, info);
> +}
> +
> +int iio_read_avail_channel_raw(struct iio_channel *chan,
> +			       const int **vals, int *length)
> +{
> +	int ret;
> +	int type;
> +
> +	mutex_lock(&chan->indio_dev->info_exist_lock);
> +	if (!chan->indio_dev->info) {
> +		ret = -ENODEV;
> +		goto err_unlock;
> +	}
> +
> +	ret = iio_channel_read_avail(chan,
> +				     vals, &type, length, IIO_CHAN_INFO_RAW);
> +err_unlock:
> +	mutex_unlock(&chan->indio_dev->info_exist_lock);
> +
> +	if (ret >= 0 && type != IIO_VAL_INT) {
> +		/* raw values are assumed to be IIO_VAL_INT */
> +		ret = -EINVAL;
> +		goto err_unlock;
> +	}
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(iio_read_avail_channel_raw);
> +
> +static int iio_channel_read_max(struct iio_channel *chan,
> +				int *val, int *val2, int *type,
> +				enum iio_chan_info_enum info)
> +{
> +	int unused;
> +	const int *vals;
> +	int length;
> +	int ret;
> +
> +	if (!val2)
> +		val2 = &unused;
> +
> +	ret = iio_channel_read_avail(chan, &vals, type, &length, info);
> +	switch (ret) {
> +	case IIO_AVAIL_RANGE:
> +		switch (*type) {
> +		case IIO_VAL_INT:
> +			*val = vals[2];
> +			break;
> +		default:
> +			*val = vals[4];
> +			*val2 = vals[5];
> +		}
> +		return 0;
> +
> +	case IIO_AVAIL_LIST:
> +		if (length <= 0)
> +			return -EINVAL;
> +		switch (*type) {
> +		case IIO_VAL_INT:
> +			*val = vals[--length];
> +			while (length) {
> +				if (vals[--length] > *val)
> +					*val = vals[length];
> +			}
> +			break;
> +		default:
> +			/* FIXME: learn about max for other iio values */
> +			return -EINVAL;
> +		}
> +		return 0;
> +
> +	default:
> +		return ret;
> +	}
> +}
> +
> +int iio_read_max_channel_raw(struct iio_channel *chan, int *val)
> +{
> +	int ret;
> +	int type;
> +
> +	mutex_lock(&chan->indio_dev->info_exist_lock);
> +	if (!chan->indio_dev->info) {
> +		ret = -ENODEV;
> +		goto err_unlock;
> +	}
> +
> +	ret = iio_channel_read_max(chan, val, NULL, &type, IIO_CHAN_INFO_RAW);
> +err_unlock:
> +	mutex_unlock(&chan->indio_dev->info_exist_lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(iio_read_max_channel_raw);
> +
>  int iio_get_channel_type(struct iio_channel *chan, enum iio_chan_type *type)
>  {
>  	int ret = 0;
> diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h
> index 9edccfba1ffb..9a4f336d8b4a 100644
> --- a/include/linux/iio/consumer.h
> +++ b/include/linux/iio/consumer.h
> @@ -226,6 +226,34 @@ int iio_read_channel_processed(struct iio_channel *chan, int *val);
>  int iio_write_channel_raw(struct iio_channel *chan, int val);
>  
>  /**
> + * iio_read_max_channel_raw() - read maximum available raw value from a given
> + *				channel, i.e. the maximum possible value.
> + * @chan:		The channel being queried.
> + * @val:		Value read back.
> + *
> + * Note raw reads from iio channels are in adc counts and hence
> + * scale will need to be applied if standard units are required.
> + */
> +int iio_read_max_channel_raw(struct iio_channel *chan, int *val);
> +
> +/**
> + * iio_read_avail_channel_raw() - read available raw values from a given channel
> + * @chan:		The channel being queried.
> + * @vals:		Available values read back.
> + * @length:		Number of entries in vals.
> + *
> + * Returns an error code, IIO_AVAIL_RANGE or IIO_AVAIL_LIST.
> + *
> + * For ranges, three vals are always returned; min, step and max.
> + * For lists, all the possible values are enumerated.
> + *
> + * Note raw available values from iio channels are in adc counts and
> + * hence scale will need to be applied if standard units are required.
> + */
> +int iio_read_avail_channel_raw(struct iio_channel *chan,
> +			       const int **vals, int *length);
> +
> +/**
>   * iio_get_channel_type() - get the type of a channel
>   * @channel:		The channel being queried.
>   * @type:		The type of the channel.
> diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h
> index 45b781084a4b..f9be8836ef23 100644
> --- a/include/linux/iio/iio.h
> +++ b/include/linux/iio/iio.h
> @@ -315,6 +315,23 @@ static inline bool iio_channel_has_info(const struct iio_chan_spec *chan,
>  		(chan->info_mask_shared_by_all & BIT(type));
>  }
>  
> +/**
> + * iio_channel_has_available() - Checks if a channel has an available attribute
> + * @chan: The channel to be queried
> + * @type: Type of the available attribute to be checked
> + *
> + * Returns true if the channel supports reporting available values for the
> + * given attribute type, false otherwise.
> + */
> +static inline bool iio_channel_has_available(const struct iio_chan_spec *chan,
> +					     enum iio_chan_info_enum type)
> +{
> +	return (chan->info_mask_separate_available & BIT(type)) |
> +		(chan->info_mask_shared_by_type_available & BIT(type)) |
> +		(chan->info_mask_shared_by_dir_available & BIT(type)) |
> +		(chan->info_mask_shared_by_all_available & BIT(type));
> +}
> +
>  #define IIO_CHAN_SOFT_TIMESTAMP(_si) {					\
>  	.type = IIO_TIMESTAMP,						\
>  	.channel = -1,							\
> 

^ permalink raw reply

* Re: [PATCH v4 1/8] iio:core: add a callback to allow drivers to provide _available attributes
From: Jonathan Cameron @ 2016-11-12 17:17 UTC (permalink / raw)
  To: Peter Rosin, linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Rob Herring, Mark Rutland, Daniel Baluta, Slawomir Stepien,
	Thomas Gleixner, linux-iio-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1478606339-31253-2-git-send-email-peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>

On 08/11/16 11:58, Peter Rosin wrote:
> From: Jonathan Cameron <jic23-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> 
> A large number of attributes can only take a limited range of values.
> Currently in IIO this is handled by directly registering additional
> *_available attributes thus providing this information to userspace.
> 
> It is desirable to provide this information via the core for much the same
> reason this was done for the actual channel information attributes in the
> first place.  If it isn't there, then it can only really be accessed from
> userspace.  Other in kernel IIO consumers have no access to what valid
> parameters are.
> 
> Two forms are currently supported:
> * list of values in one particular IIO_VAL_* format.
> 	e.g. 1.300000 1.500000 1.730000
> * range specification with a step size:
> 	e.g. [1.000000 0.500000 2.500000]
> 	equivalent to 1.000000 1.5000000 2.000000 2.500000
> 
> An addition set of masks are used to allow different sharing rules for the
> *_available attributes generated.
> 
> This allows for example:
> 
> in_accel_x_offset
> in_accel_y_offset
> in_accel_offset_available.
> 
> We could have gone with having a specification for each and every
> info_mask element but that would have meant changing the existing userspace
> ABI.  This approach does not.
> 
> Signed-off-by: Jonathan Cameron <jic23-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> [forward ported, added some docs and fixed buffer overflows /peda]
> Acked-by: Daniel Baluta <daniel.baluta-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
> Signed-off-by: Peter Rosin <peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>
Applied to the togreg branch of iio.git.

Lars, if you get a chance I'd still appreciate any feedback you have
in the ABI in particular.  We still have a window to modify it but that
will be running out fast. If you are happy with it then great!

Jonathan
> ---
>  drivers/iio/industrialio-core.c | 259 +++++++++++++++++++++++++++++++++++-----
>  include/linux/iio/iio.h         |  29 +++++
>  include/linux/iio/types.h       |   5 +
>  3 files changed, 260 insertions(+), 33 deletions(-)
> 
> diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
> index fc340ed3dca1..b35c61a31fa6 100644
> --- a/drivers/iio/industrialio-core.c
> +++ b/drivers/iio/industrialio-core.c
> @@ -575,66 +575,82 @@ int of_iio_read_mount_matrix(const struct device *dev,
>  #endif
>  EXPORT_SYMBOL(of_iio_read_mount_matrix);
>  
> -/**
> - * iio_format_value() - Formats a IIO value into its string representation
> - * @buf:	The buffer to which the formatted value gets written
> - * @type:	One of the IIO_VAL_... constants. This decides how the val
> - *		and val2 parameters are formatted.
> - * @size:	Number of IIO value entries contained in vals
> - * @vals:	Pointer to the values, exact meaning depends on the
> - *		type parameter.
> - *
> - * Return: 0 by default, a negative number on failure or the
> - *	   total number of characters written for a type that belongs
> - *	   to the IIO_VAL_... constant.
> - */
> -ssize_t iio_format_value(char *buf, unsigned int type, int size, int *vals)
> +static ssize_t __iio_format_value(char *buf, size_t len, unsigned int type,
> +				  int size, const int *vals)
>  {
>  	unsigned long long tmp;
> +	int tmp0, tmp1;
>  	bool scale_db = false;
>  
>  	switch (type) {
>  	case IIO_VAL_INT:
> -		return sprintf(buf, "%d\n", vals[0]);
> +		return snprintf(buf, len, "%d", vals[0]);
>  	case IIO_VAL_INT_PLUS_MICRO_DB:
>  		scale_db = true;
>  	case IIO_VAL_INT_PLUS_MICRO:
>  		if (vals[1] < 0)
> -			return sprintf(buf, "-%d.%06u%s\n", abs(vals[0]),
> -				       -vals[1], scale_db ? " dB" : "");
> +			return snprintf(buf, len, "-%d.%06u%s", abs(vals[0]),
> +					-vals[1], scale_db ? " dB" : "");
>  		else
> -			return sprintf(buf, "%d.%06u%s\n", vals[0], vals[1],
> -				scale_db ? " dB" : "");
> +			return snprintf(buf, len, "%d.%06u%s", vals[0], vals[1],
> +					scale_db ? " dB" : "");
>  	case IIO_VAL_INT_PLUS_NANO:
>  		if (vals[1] < 0)
> -			return sprintf(buf, "-%d.%09u\n", abs(vals[0]),
> -				       -vals[1]);
> +			return snprintf(buf, len, "-%d.%09u", abs(vals[0]),
> +					-vals[1]);
>  		else
> -			return sprintf(buf, "%d.%09u\n", vals[0], vals[1]);
> +			return snprintf(buf, len, "%d.%09u", vals[0], vals[1]);
>  	case IIO_VAL_FRACTIONAL:
>  		tmp = div_s64((s64)vals[0] * 1000000000LL, vals[1]);
> -		vals[0] = (int)div_s64_rem(tmp, 1000000000, &vals[1]);
> -		return sprintf(buf, "%d.%09u\n", vals[0], abs(vals[1]));
> +		tmp1 = vals[1];
> +		tmp0 = (int)div_s64_rem(tmp, 1000000000, &tmp1);
> +		return snprintf(buf, len, "%d.%09u", tmp0, abs(tmp1));
>  	case IIO_VAL_FRACTIONAL_LOG2:
>  		tmp = (s64)vals[0] * 1000000000LL >> vals[1];
> -		vals[1] = do_div(tmp, 1000000000LL);
> -		vals[0] = tmp;
> -		return sprintf(buf, "%d.%09u\n", vals[0], vals[1]);
> +		tmp1 = do_div(tmp, 1000000000LL);
> +		tmp0 = tmp;
> +		return snprintf(buf, len, "%d.%09u", tmp0, tmp1);
>  	case IIO_VAL_INT_MULTIPLE:
>  	{
>  		int i;
> -		int len = 0;
> +		int l = 0;
>  
> -		for (i = 0; i < size; ++i)
> -			len += snprintf(&buf[len], PAGE_SIZE - len, "%d ",
> -								vals[i]);
> -		len += snprintf(&buf[len], PAGE_SIZE - len, "\n");
> -		return len;
> +		for (i = 0; i < size; ++i) {
> +			l += snprintf(&buf[l], len - l, "%d ", vals[i]);
> +			if (l >= len)
> +				break;
> +		}
> +		return l;
>  	}
>  	default:
>  		return 0;
>  	}
>  }
> +
> +/**
> + * iio_format_value() - Formats a IIO value into its string representation
> + * @buf:	The buffer to which the formatted value gets written
> + *		which is assumed to be big enough (i.e. PAGE_SIZE).
> + * @type:	One of the IIO_VAL_... constants. This decides how the val
> + *		and val2 parameters are formatted.
> + * @size:	Number of IIO value entries contained in vals
> + * @vals:	Pointer to the values, exact meaning depends on the
> + *		type parameter.
> + *
> + * Return: 0 by default, a negative number on failure or the
> + *	   total number of characters written for a type that belongs
> + *	   to the IIO_VAL_... constant.
> + */
> +ssize_t iio_format_value(char *buf, unsigned int type, int size, int *vals)
> +{
> +	ssize_t len;
> +
> +	len = __iio_format_value(buf, PAGE_SIZE, type, size, vals);
> +	if (len >= PAGE_SIZE - 1)
> +		return -EFBIG;
> +
> +	return len + sprintf(buf + len, "\n");
> +}
>  EXPORT_SYMBOL_GPL(iio_format_value);
>  
>  static ssize_t iio_read_channel_info(struct device *dev,
> @@ -662,6 +678,119 @@ static ssize_t iio_read_channel_info(struct device *dev,
>  	return iio_format_value(buf, ret, val_len, vals);
>  }
>  
> +static ssize_t iio_format_avail_list(char *buf, const int *vals,
> +				     int type, int length)
> +{
> +	int i;
> +	ssize_t len = 0;
> +
> +	switch (type) {
> +	case IIO_VAL_INT:
> +		for (i = 0; i < length; i++) {
> +			len += __iio_format_value(buf + len, PAGE_SIZE - len,
> +						  type, 1, &vals[i]);
> +			if (len >= PAGE_SIZE)
> +				return -EFBIG;
> +			if (i < length - 1)
> +				len += snprintf(buf + len, PAGE_SIZE - len,
> +						" ");
> +			else
> +				len += snprintf(buf + len, PAGE_SIZE - len,
> +						"\n");
> +			if (len >= PAGE_SIZE)
> +				return -EFBIG;
> +		}
> +		break;
> +	default:
> +		for (i = 0; i < length / 2; i++) {
> +			len += __iio_format_value(buf + len, PAGE_SIZE - len,
> +						  type, 2, &vals[i * 2]);
> +			if (len >= PAGE_SIZE)
> +				return -EFBIG;
> +			if (i < length / 2 - 1)
> +				len += snprintf(buf + len, PAGE_SIZE - len,
> +						" ");
> +			else
> +				len += snprintf(buf + len, PAGE_SIZE - len,
> +						"\n");
> +			if (len >= PAGE_SIZE)
> +				return -EFBIG;
> +		}
> +	};
> +
> +	return len;
> +}
> +
> +static ssize_t iio_format_avail_range(char *buf, const int *vals, int type)
> +{
> +	int i;
> +	ssize_t len;
> +
> +	len = snprintf(buf, PAGE_SIZE, "[");
> +	switch (type) {
> +	case IIO_VAL_INT:
> +		for (i = 0; i < 3; i++) {
> +			len += __iio_format_value(buf + len, PAGE_SIZE - len,
> +						  type, 1, &vals[i]);
> +			if (len >= PAGE_SIZE)
> +				return -EFBIG;
> +			if (i < 2)
> +				len += snprintf(buf + len, PAGE_SIZE - len,
> +						" ");
> +			else
> +				len += snprintf(buf + len, PAGE_SIZE - len,
> +						"]\n");
> +			if (len >= PAGE_SIZE)
> +				return -EFBIG;
> +		}
> +		break;
> +	default:
> +		for (i = 0; i < 3; i++) {
> +			len += __iio_format_value(buf + len, PAGE_SIZE - len,
> +						  type, 2, &vals[i * 2]);
> +			if (len >= PAGE_SIZE)
> +				return -EFBIG;
> +			if (i < 2)
> +				len += snprintf(buf + len, PAGE_SIZE - len,
> +						" ");
> +			else
> +				len += snprintf(buf + len, PAGE_SIZE - len,
> +						"]\n");
> +			if (len >= PAGE_SIZE)
> +				return -EFBIG;
> +		}
> +	};
> +
> +	return len;
> +}
> +
> +static ssize_t iio_read_channel_info_avail(struct device *dev,
> +					   struct device_attribute *attr,
> +					   char *buf)
> +{
> +	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
> +	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
> +	const int *vals;
> +	int ret;
> +	int length;
> +	int type;
> +
> +	ret = indio_dev->info->read_avail(indio_dev, this_attr->c,
> +					  &vals, &type, &length,
> +					  this_attr->address);
> +
> +	if (ret < 0)
> +		return ret;
> +	switch (ret) {
> +	case IIO_AVAIL_LIST:
> +		return iio_format_avail_list(buf, vals, type, length);
> +	case IIO_AVAIL_RANGE:
> +		return iio_format_avail_range(buf, vals, type);
> +	default:
> +		return -EINVAL;
> +	}
> +}
> +
>  /**
>   * iio_str_to_fixpoint() - Parse a fixed-point number from a string
>   * @str: The string to parse
> @@ -978,6 +1107,40 @@ static int iio_device_add_info_mask_type(struct iio_dev *indio_dev,
>  	return attrcount;
>  }
>  
> +static int iio_device_add_info_mask_type_avail(struct iio_dev *indio_dev,
> +					       struct iio_chan_spec const *chan,
> +					       enum iio_shared_by shared_by,
> +					       const long *infomask)
> +{
> +	int i, ret, attrcount = 0;
> +	char *avail_postfix;
> +
> +	for_each_set_bit(i, infomask, sizeof(infomask) * 8) {
> +		avail_postfix = kasprintf(GFP_KERNEL,
> +					  "%s_available",
> +					  iio_chan_info_postfix[i]);
> +		if (!avail_postfix)
> +			return -ENOMEM;
> +
> +		ret = __iio_add_chan_devattr(avail_postfix,
> +					     chan,
> +					     &iio_read_channel_info_avail,
> +					     NULL,
> +					     i,
> +					     shared_by,
> +					     &indio_dev->dev,
> +					     &indio_dev->channel_attr_list);
> +		kfree(avail_postfix);
> +		if ((ret == -EBUSY) && (shared_by != IIO_SEPARATE))
> +			continue;
> +		else if (ret < 0)
> +			return ret;
> +		attrcount++;
> +	}
> +
> +	return attrcount;
> +}
> +
>  static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev,
>  					struct iio_chan_spec const *chan)
>  {
> @@ -993,6 +1156,14 @@ static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev,
>  		return ret;
>  	attrcount += ret;
>  
> +	ret = iio_device_add_info_mask_type_avail(indio_dev, chan,
> +						  IIO_SEPARATE,
> +						  &chan->
> +						  info_mask_separate_available);
> +	if (ret < 0)
> +		return ret;
> +	attrcount += ret;
> +
>  	ret = iio_device_add_info_mask_type(indio_dev, chan,
>  					    IIO_SHARED_BY_TYPE,
>  					    &chan->info_mask_shared_by_type);
> @@ -1000,6 +1171,14 @@ static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev,
>  		return ret;
>  	attrcount += ret;
>  
> +	ret = iio_device_add_info_mask_type_avail(indio_dev, chan,
> +						  IIO_SHARED_BY_TYPE,
> +						  &chan->
> +						  info_mask_shared_by_type_available);
> +	if (ret < 0)
> +		return ret;
> +	attrcount += ret;
> +
>  	ret = iio_device_add_info_mask_type(indio_dev, chan,
>  					    IIO_SHARED_BY_DIR,
>  					    &chan->info_mask_shared_by_dir);
> @@ -1007,6 +1186,13 @@ static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev,
>  		return ret;
>  	attrcount += ret;
>  
> +	ret = iio_device_add_info_mask_type_avail(indio_dev, chan,
> +						  IIO_SHARED_BY_DIR,
> +						  &chan->info_mask_shared_by_dir_available);
> +	if (ret < 0)
> +		return ret;
> +	attrcount += ret;
> +
>  	ret = iio_device_add_info_mask_type(indio_dev, chan,
>  					    IIO_SHARED_BY_ALL,
>  					    &chan->info_mask_shared_by_all);
> @@ -1014,6 +1200,13 @@ static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev,
>  		return ret;
>  	attrcount += ret;
>  
> +	ret = iio_device_add_info_mask_type_avail(indio_dev, chan,
> +						  IIO_SHARED_BY_ALL,
> +						  &chan->info_mask_shared_by_all_available);
> +	if (ret < 0)
> +		return ret;
> +	attrcount += ret;
> +
>  	if (chan->ext_info) {
>  		unsigned int i = 0;
>  		for (ext_info = chan->ext_info; ext_info->name; ext_info++) {
> diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h
> index b4a0679e4a49..45b781084a4b 100644
> --- a/include/linux/iio/iio.h
> +++ b/include/linux/iio/iio.h
> @@ -225,12 +225,22 @@ struct iio_event_spec {
>   *			endianness:	little or big endian
>   * @info_mask_separate: What information is to be exported that is specific to
>   *			this channel.
> + * @info_mask_separate_available: What availability information is to be
> + *			exported that is specific to this channel.
>   * @info_mask_shared_by_type: What information is to be exported that is shared
>   *			by all channels of the same type.
> + * @info_mask_shared_by_type_available: What availability information is to be
> + *			exported that is shared by all channels of the same
> + *			type.
>   * @info_mask_shared_by_dir: What information is to be exported that is shared
>   *			by all channels of the same direction.
> + * @info_mask_shared_by_dir_available: What availability information is to be
> + *			exported that is shared by all channels of the same
> + *			direction.
>   * @info_mask_shared_by_all: What information is to be exported that is shared
>   *			by all channels.
> + * @info_mask_shared_by_all_available: What availability information is to be
> + *			exported that is shared by all channels.
>   * @event_spec:		Array of events which should be registered for this
>   *			channel.
>   * @num_event_specs:	Size of the event_spec array.
> @@ -269,9 +279,13 @@ struct iio_chan_spec {
>  		enum iio_endian endianness;
>  	} scan_type;
>  	long			info_mask_separate;
> +	long			info_mask_separate_available;
>  	long			info_mask_shared_by_type;
> +	long			info_mask_shared_by_type_available;
>  	long			info_mask_shared_by_dir;
> +	long			info_mask_shared_by_dir_available;
>  	long			info_mask_shared_by_all;
> +	long			info_mask_shared_by_all_available;
>  	const struct iio_event_spec *event_spec;
>  	unsigned int		num_event_specs;
>  	const struct iio_chan_spec_ext_info *ext_info;
> @@ -349,6 +363,14 @@ struct iio_dev;
>   *			max_len specifies maximum number of elements
>   *			vals pointer can contain. val_len is used to return
>   *			length of valid elements in vals.
> + * @read_avail:		function to return the available values from the device.
> + *			mask specifies which value. Note 0 means the available
> + *			values for the channel in question.  Return value
> + *			specifies if a IIO_AVAIL_LIST or a IIO_AVAIL_RANGE is
> + *			returned in vals. The type of the vals are returned in
> + *			type and the number of vals is returned in length. For
> + *			ranges, there are always three vals returned; min, step
> + *			and max. For lists, all possible values are enumerated.
>   * @write_raw:		function to write a value to the device.
>   *			Parameters are the same as for read_raw.
>   * @write_raw_get_fmt:	callback function to query the expected
> @@ -397,6 +419,13 @@ struct iio_info {
>  			int *val_len,
>  			long mask);
>  
> +	int (*read_avail)(struct iio_dev *indio_dev,
> +			  struct iio_chan_spec const *chan,
> +			  const int **vals,
> +			  int *type,
> +			  int *length,
> +			  long mask);
> +
>  	int (*write_raw)(struct iio_dev *indio_dev,
>  			 struct iio_chan_spec const *chan,
>  			 int val,
> diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h
> index 32b579525004..2aa7b6384d64 100644
> --- a/include/linux/iio/types.h
> +++ b/include/linux/iio/types.h
> @@ -29,4 +29,9 @@ enum iio_event_info {
>  #define IIO_VAL_FRACTIONAL 10
>  #define IIO_VAL_FRACTIONAL_LOG2 11
>  
> +enum iio_available_type {
> +	IIO_AVAIL_LIST,
> +	IIO_AVAIL_RANGE,
> +};
> +
>  #endif /* _IIO_TYPES_H_ */
> 

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

^ permalink raw reply

* Re: [PATCH v4 0/8] IIO wrapper drivers, dpot-dac and envelope-detector
From: Jonathan Cameron @ 2016-11-12 17:15 UTC (permalink / raw)
  To: Peter Rosin, linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Rob Herring, Mark Rutland, Daniel Baluta, Slawomir Stepien,
	Thomas Gleixner, linux-iio-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1478606339-31253-1-git-send-email-peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>

On 08/11/16 11:58, Peter Rosin wrote:
> Hi!
> 
> This is a respin with a handful of nitpicks fixed from v3. No major
> changes. And a couple of acks was added too, thanks! I also added
> Thomas Gleixner as Cc, since Jonathan was hoping for some comments
> on the somewhat odd interrupt handling in patch 8/8 (but perhaps
> plumbers-week isn't the best week to hope for that).
> 
> 
> These two drivers share the fact that they wrap another iio channel,
> and I use the first in combination with the second, which is why I'm
> submitting them as a pair.
> 
> The first driver is a simple wrapper converting an iio dpot into an
> iio dac. It only changes the unit and scale. It also does not add any
> fancy iio buffer support that I don't need. I suppose that can be
> added. By someone else :-)
I'll probably get to it sooner or later if no one else jumps on it.
> 
> The second driver (the envelope detector) is more involved. It also
> explains why I need the dpot-dac driver. I wanted the envelope
> detector to be generic and work with any dac, but I had a dpot...
> 
> But before those two new drivers, there is some infrastructure added
> to provide available values for a channel.
> 
> One thing I still don't like is that the irq needs to be changed for cases
> where it is only ever interesting with the 'invert' variant, and it may not
> work to set up the irq the wrong way first. For the TSE-850, this does not
> matter, since we have a mux on the envelope detector input and can make use
> of both 'invert' and 'normal' for different signals (we could have gotten
> by with only 'invert' since the only signals we are measuring that are
> 'normal' are also DC signals and can thus be detected both from below and
> from above), but it is nice to have it both ways. The only way out of this
> is a devicetree thing. I suppose it will have to be added by whomever needs
> it whenever that is...
> 
> I also wonder if the "new" *_available ABI should perhaps be documented
> for all variants directly in sysfs-bus-iio instead of doing it in a driver
> specific maner that I did? But that can be fixed later by someone more
> capable than me :-)
You doubt yourself too much ;)  Some one with fewer inhibitions you mean!

Anyhow, just thought I'd add that I like this series very much.
It's a nice interesting use of the infrastructures.  Good to see people
are getting more adventurous all the time.

Also always nice when someone else picks up a patch I dropped years ago
and does the remaining hard work to get it in ;)

There is a limited window left obviously if we want to adjust that ABI
so shout soon or it'll be there for ever *muhahahaha*

Jonathan
> 
> v3 -> v4
> - gained acks from Rob for the three bindings patches
> - gained ack from Daniel for the core _available patch (1/8)
> - dropped the type argument from iio_read_avail_channel_raw(), since
>   raw values are assumed to be of type IIO_VAL_INT anyway
> - add some more words about what iio_read_avail_channel_raw() does
> - rebased onto v4.9-rc4
> 
> dpot-dac:
> - adjust to changed signature of iio_read_avail_channel_raw()
> - one instance of s/the channels supports/the channel supports/
> - drop surplus s64 cast in dpot_dac_channel_max_ohms()
> 
> envelope-detector
> - the envelope-detector module is called envelope-detector
> 
> 
> v2 -> v3
> - add some missing @foo comments in iio.h in the initial forward ported patch
> - killed some buffer overflow problems in the initial forward ported patch
> - add inkern.c helpers for the new available attributes to avoid viral
>   boilerplating in the future (also add support for finding max of
>   IIO_AVAIL_LISTs of IIO_VAL_INTs)
> - add ABI docs for new ABI of mcp4531 (out_resistance_raw_available)
>   and an example in the commit message
> 
> dpot-dac:
> - two more counts of s/assumed the that the/assumed that the/   *blush*
> - add ABI docs for new ABI (out_voltageY_raw_available)
> 
> envelope detector:
> - move device attributes 'compare_interval_ms' and 'invert' to extended
>   channel attributes (out_altvoltage0_compare_interval and
>   out_altvoltage0_invert) as they really are about the channel and not
>   the device
> - kill "dpot-dac,max-ohms = <100000>;" in the devicetree example
> 
> 
> v1 -> v2
> - provide out_resistanceX_raw_available channel attribute in mcp4531 dpot
> 
> dpot-dac:
> - change Vref to vref
> - the module will be called dpot-dac (in Kconfig help)
> - removed a 'the'
> - removed (s64) cast
> - make the channel indexed, makes libiio find the channel (tested with 0.5)
> - add a comment on how integer scale is converted to fractional scale
>   and clarify the code a bit
> - dig out max-ohms by looking at scale and maximum available raw value
>   from the dpot channel and drop the 'dpot-dac,max-ohms' devicetree property
> - provide out_voltageX_raw_available channel attribute
> 
> envelope-detector:
> - change compatible from envelope-detector to axentia,tse850-envelope-detector
> - remove envelope-detector,invert and envelope-detector,comp-interval-ms from
>   devicetree and add them as iio device attributes instead
> - make the channel indexed, makes libiio find the channel (tested with 0.5)
> - reorder struct envelope to better indicate what is covered by read_lock
> - add comment on interaction between envelope_detector_comp_latch (renamed
>   from envelope_detector_latch) and envelope_detector_comp_isr (renamed
>   from envelope_detector_isr)
> - fixup a problem in envelope_detector_comp_latch where interrupts pending
>   from when the interrupt has been disabled interferes with expected
>   operation
> - slight rewrite of the initial high/low assignments
> - use a better name when requesting the interrupt
> - dig out dac_max by looking at scale and maximum available raw value
>   from the dac channel and drop the 'envelope-detector,dac-max' devicetree
>   property
> 
> Cheers,
> Peter
> 
> Jonathan Cameron (1):
>   iio:core: add a callback to allow drivers to provide _available
>     attributes
> 
> Peter Rosin (7):
>   iio: inkern: add helpers to query available values from channels
>   iio: mcp4531: provide range of available raw values
>   dt-bindings: add axentia to vendor-prefixes
>   dt-bindings: iio: document dpot-dac bindings
>   iio: dpot-dac: DAC driver based on a digital potentiometer
>   dt-bindings: iio: document envelope-detector bindings
>   iio: envelope-detector: ADC driver based on a DAC and a comparator
> 
>  .../testing/sysfs-bus-iio-adc-envelope-detector    |  36 ++
>  .../ABI/testing/sysfs-bus-iio-dac-dpot-dac         |   8 +
>  .../testing/sysfs-bus-iio-potentiometer-mcp4531    |   8 +
>  .../bindings/iio/adc/envelope-detector.txt         |  54 +++
>  .../devicetree/bindings/iio/dac/dpot-dac.txt       |  41 ++
>  .../devicetree/bindings/vendor-prefixes.txt        |   1 +
>  MAINTAINERS                                        |  17 +
>  drivers/iio/adc/Kconfig                            |  10 +
>  drivers/iio/adc/Makefile                           |   1 +
>  drivers/iio/adc/envelope-detector.c                | 422 +++++++++++++++++++++
>  drivers/iio/dac/Kconfig                            |  10 +
>  drivers/iio/dac/Makefile                           |   1 +
>  drivers/iio/dac/dpot-dac.c                         | 266 +++++++++++++
>  drivers/iio/industrialio-core.c                    | 259 +++++++++++--
>  drivers/iio/inkern.c                               | 104 +++++
>  drivers/iio/potentiometer/mcp4531.c                | 104 +++--
>  include/linux/iio/consumer.h                       |  28 ++
>  include/linux/iio/iio.h                            |  46 +++
>  include/linux/iio/types.h                          |   5 +
>  19 files changed, 1346 insertions(+), 75 deletions(-)
>  create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-adc-envelope-detector
>  create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-dac-dpot-dac
>  create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-potentiometer-mcp4531
>  create mode 100644 Documentation/devicetree/bindings/iio/adc/envelope-detector.txt
>  create mode 100644 Documentation/devicetree/bindings/iio/dac/dpot-dac.txt
>  create mode 100644 drivers/iio/adc/envelope-detector.c
>  create mode 100644 drivers/iio/dac/dpot-dac.c
> 

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


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