Linux I2C development
 help / color / mirror / Atom feed
* [PATCH v4 02/14] ARM: dts: lager: use demuxer for IIC1/I2C1
From: Wolfram Sang @ 2016-11-06 20:20 UTC (permalink / raw)
  To: linux-renesas-soc, Simon Horman; +Cc: linux-i2c, Simon Horman, Wolfram Sang
In-Reply-To: <20161106202032.5227-1-wsa+renesas@sang-engineering.com>

From: Simon Horman <horms+renesas@verge.net.au>

Make it possible to select which I2C1 IP core you want to run on the
EXIO-A connector.

This is based on reference work for the I2C0 core of the lager board
by Wolfram Sang.

Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
[wsa: rebased and fixed aliases]
Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
---
 arch/arm/boot/dts/r8a7790-lager.dts | 39 +++++++++++++++++++++++++++++++++++--
 1 file changed, 37 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts
index dafa49f837118e..bd512c86e85222 100644
--- a/arch/arm/boot/dts/r8a7790-lager.dts
+++ b/arch/arm/boot/dts/r8a7790-lager.dts
@@ -50,7 +50,9 @@
 	aliases {
 		serial0 = &scif0;
 		serial1 = &scifa1;
+		i2c8 = &gpioi2c1;
 		i2c10 = &i2cexio0;
+		i2c11 = &i2cexio1;
 	};
 
 	chosen {
@@ -265,6 +267,17 @@
 		clock-frequency = <148500000>;
 	};
 
+	gpioi2c1: i2c-8 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "i2c-gpio";
+		status = "disabled";
+		gpios = <&gpio1 17 GPIO_ACTIVE_HIGH /* sda */
+			 &gpio1 16 GPIO_ACTIVE_HIGH /* scl */
+			>;
+		i2c-gpio,delay-us = <5>;
+	};
+
 	/*
 	 * IIC0/I2C0 is routed to EXIO connector A, pins 114 (SCL) + 116 (SDA) only.
 	 * We use the I2C demuxer, so the desired IP core can be selected at runtime
@@ -283,6 +296,19 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 	};
+
+	/*
+	 * IIC1/I2C1 is routed to EXIO connector A, pins 78 (SCL) + 80 (SDA).
+	 * This is similar to the arangement described for i2cexio0 (above)
+	 * with a fallback to GPIO also provided.
+	 */
+	i2cexio1: i2c-11 {
+		compatible = "i2c-demux-pinctrl";
+		i2c-parent = <&iic1>, <&i2c1>, <&gpioi2c1>;
+		i2c-bus-name = "i2c-exio1";
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
 };
 
 &du {
@@ -405,6 +431,11 @@
 		function = "iic0";
 	};
 
+	i2c1_pins: i2c1 {
+		groups = "i2c1";
+		function = "i2c1";
+	};
+
 	iic1_pins: iic1 {
 		groups = "iic1";
 		function = "iic1";
@@ -607,10 +638,14 @@
 	pinctrl-names = "i2c-exio0";
 };
 
+&i2c1	{
+	pinctrl-0 = <&i2c1_pins>;
+	pinctrl-names = "i2c-exio1";
+};
+
 &iic1	{
-	status = "okay";
 	pinctrl-0 = <&iic1_pins>;
-	pinctrl-names = "default";
+	pinctrl-names = "i2c-exio1";
 };
 
 &iic2	{
-- 
2.9.3

^ permalink raw reply related

* [PATCH v4 00/14] ARM: dts: r8a779x: use demuxer for I2C
From: Wolfram Sang @ 2016-11-06 20:20 UTC (permalink / raw)
  To: linux-renesas-soc, Simon Horman; +Cc: linux-i2c, Wolfram Sang

So, here is the newest series for using the I2C demuxer on Gen2 boards.
Initially done by Simon. The intention of this series is to extend use of the
demuxer for I2C on the lager, koelsch, porter, koelsch, alt and silk boards to
cover all I2C IP blocks that are either already used or exposed via an EXIO
connector.

I tested this on a Lager board where I could successfully switch between I2C,
IIC, and GPIO on I2C2.

Simon, can you test with your script on the other boards? If all works, I'll
pick up the i2c patch for 4.9, so the DTS changes should be fine for 4.10.

The branch is here:

git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git renesas/ip-switch-rework

Regards,

   Wolfram


Changes between v4 and v3
* rebased to latest renesas-drivers (double checked that the moved i2c clients
  were complete because they changed meanwhile)
* fixed the aliases to be proper phandles
* fixed some typos in comments and commit messages
* added a patch to ensure i2c-gpio works again

Changes between v2 and v3
* Group extra GPIO buses
* Add GPIO fallback for IIC1/I2C1 on Lager
* Add patches for koelsch, porter, alt and silk

Changes between v1 and v2
* Provide GPIO fallback for I2C2,
  this does not seem appropriate for other I2C blocks on the lager board



Simon Horman (13):
  ARM: dts: lager: rename and reindex i2cexio
  ARM: dts: lager: use demuxer for IIC1/I2C1
  ARM: dts: lager: use demuxer for IIC2/I2C2
  ARM: dts: lager: use demuxer for IIC3/I2C3
  ARM: dts: koelsch: use demuxer for I2C1
  ARM: dts: koelsch: use demuxer for I2C2
  ARM: dts: koelsch: use demuxer for I2C4
  ARM: dts: porter: use demuxer for I2C2
  ARM: dts: gose: use demuxer for I2C2
  ARM: dts: gose: use demuxer for I2C4
  ARM: dts: alt: use demuxer for I2C1
  ARM: dts: alt: use demuxer for I2C4
  ARM: dts: silk: use demuxer for I2C1

Wolfram Sang (1):
  i2c: mux: demux-pinctrl: make drivers with no pinctrl work again

 arch/arm/boot/dts/r8a7790-lager.dts   | 329 ++++++++++++++++++++++------------
 arch/arm/boot/dts/r8a7791-koelsch.dts | 263 ++++++++++++++++++---------
 arch/arm/boot/dts/r8a7791-porter.dts  | 129 +++++++------
 arch/arm/boot/dts/r8a7793-gose.dts    | 203 +++++++++++++--------
 arch/arm/boot/dts/r8a7794-alt.dts     |  86 +++++++--
 arch/arm/boot/dts/r8a7794-silk.dts    | 129 +++++++------
 drivers/i2c/muxes/i2c-demux-pinctrl.c |  22 ++-
 7 files changed, 765 insertions(+), 396 deletions(-)

-- 
2.9.3

^ permalink raw reply

* [PATCH v4 04/14] ARM: dts: lager: use demuxer for IIC3/I2C3
From: Wolfram Sang @ 2016-11-06 20:20 UTC (permalink / raw)
  To: linux-renesas-soc, Simon Horman; +Cc: linux-i2c, Simon Horman, Wolfram Sang
In-Reply-To: <20161106202032.5227-1-wsa+renesas@sang-engineering.com>

From: Simon Horman <horms+renesas@verge.net.au>

Create a separate bus for da9063 PMIC and da9210 regulator
related I2C slaves.

Based on similar work for HDMI by Wolfram Sang.

Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
[wsa: rebased, corrected chip name in commit msg, updated aliases]
Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
---
 arch/arm/boot/dts/r8a7790-lager.dts | 84 +++++++++++++++++++++++--------------
 1 file changed, 53 insertions(+), 31 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts
index 2659bf854b3bd5..e4ac480b0e229a 100644
--- a/arch/arm/boot/dts/r8a7790-lager.dts
+++ b/arch/arm/boot/dts/r8a7790-lager.dts
@@ -55,6 +55,7 @@
 		i2c10 = &i2cexio0;
 		i2c11 = &i2cexio1;
 		i2c12 = &i2chdmi;
+		i2c13 = &i2cpwr;
 	};
 
 	chosen {
@@ -412,6 +413,46 @@
 			};
 		};
 	};
+
+	/*
+	 * IIC3 and I2C3 may be switched using pinmux.
+	 * IIC3/I2C3 does not appear to support fallback to GPIO.
+	 */
+	i2cpwr: i2c-13 {
+		compatible = "i2c-demux-pinctrl";
+		i2c-parent = <&iic3>, <&i2c3>;
+		i2c-bus-name = "i2c-pwr";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		pmic@58 {
+			compatible = "dlg,da9063";
+			reg = <0x58>;
+			interrupt-parent = <&irqc0>;
+			interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+			interrupt-controller;
+
+			rtc {
+				compatible = "dlg,da9063-rtc";
+			};
+
+			wdt {
+				compatible = "dlg,da9063-watchdog";
+			};
+		};
+
+		vdd_dvfs: regulator@68 {
+			compatible = "dlg,da9210";
+			reg = <0x68>;
+			interrupt-parent = <&irqc0>;
+			interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+
+			regulator-min-microvolt = <1000000>;
+			regulator-max-microvolt = <1000000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+	};
 };
 
 &du {
@@ -554,6 +595,11 @@
 		function = "iic2";
 	};
 
+	i2c3_pins: i2c3 {
+		groups = "i2c3";
+		function = "i2c3";
+	};
+
 	iic3_pins: iic3 {
 		groups = "iic3";
 		function = "iic3";
@@ -770,38 +816,14 @@
 	clock-frequency = <100000>;
 };
 
-&iic3 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&iic3_pins>;
-	status = "okay";
-
-	pmic@58 {
-		compatible = "dlg,da9063";
-		reg = <0x58>;
-		interrupt-parent = <&irqc0>;
-		interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
-		interrupt-controller;
-
-		rtc {
-			compatible = "dlg,da9063-rtc";
-		};
-
-		wdt {
-			compatible = "dlg,da9063-watchdog";
-		};
-	};
-
-	vdd_dvfs: regulator@68 {
-		compatible = "dlg,da9210";
-		reg = <0x68>;
-		interrupt-parent = <&irqc0>;
-		interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+&i2c3	{
+	pinctrl-0 = <&i2c3_pins>;
+	pinctrl-names = "i2c-pwr";
+};
 
-		regulator-min-microvolt = <1000000>;
-		regulator-max-microvolt = <1000000>;
-		regulator-boot-on;
-		regulator-always-on;
-	};
+&iic3	{
+	pinctrl-0 = <&iic3_pins>;
+	pinctrl-names = "i2c-pwr";
 };
 
 &pci0 {
-- 
2.9.3

^ permalink raw reply related

* [PATCH v4 05/14] ARM: dts: koelsch: use demuxer for I2C1
From: Wolfram Sang @ 2016-11-06 20:20 UTC (permalink / raw)
  To: linux-renesas-soc, Simon Horman; +Cc: linux-i2c, Simon Horman, Wolfram Sang
In-Reply-To: <20161106202032.5227-1-wsa+renesas@sang-engineering.com>

From: Simon Horman <horms+renesas@verge.net.au>

Make it possible to fallback to GPIO for I2C1 on the EXIO-C connector.

This is based on reference work for the I2C0 core of the lager/r8a7790
by Wolfram Sang.

Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
[wsa: rebased and fixed aliases]
Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
---
 arch/arm/boot/dts/r8a7791-koelsch.dts | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/arch/arm/boot/dts/r8a7791-koelsch.dts b/arch/arm/boot/dts/r8a7791-koelsch.dts
index 57e69af6513619..5405d337d74486 100644
--- a/arch/arm/boot/dts/r8a7791-koelsch.dts
+++ b/arch/arm/boot/dts/r8a7791-koelsch.dts
@@ -50,6 +50,8 @@
 	aliases {
 		serial0 = &scif0;
 		serial1 = &scif1;
+		i2c9 = &gpioi2c1;
+		i2c12 = &i2cexio1;
 	};
 
 	chosen {
@@ -298,6 +300,29 @@
 		#clock-cells = <0>;
 		clock-frequency = <148500000>;
 	};
+
+	gpioi2c1: i2c-9 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "i2c-gpio";
+		status = "disabled";
+		gpios = <&gpio7 16 GPIO_ACTIVE_HIGH /* sda */
+			 &gpio7 15 GPIO_ACTIVE_HIGH /* scl */
+			>;
+		i2c-gpio,delay-us = <5>;
+	};
+
+	/*
+	 * I2C1 is routed to EXIO connector B, pins 64 (SCL) + 66 (SDA).
+	 * A fallback to GPIO is provided.
+	 */
+	i2cexio1: i2c-12 {
+		compatible = "i2c-demux-pinctrl";
+		i2c-parent = <&i2c1>, <&gpioi2c1>;
+		i2c-bus-name = "i2c-exio1";
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
 };
 
 &du {
@@ -333,6 +358,11 @@
 	pinctrl-0 = <&scif_clk_pins>;
 	pinctrl-names = "default";
 
+	i2c1_pins: i2c1 {
+		groups = "i2c1";
+		function = "i2c1";
+	};
+
 	i2c2_pins: i2c2 {
 		groups = "i2c2";
 		function = "i2c2";
@@ -582,6 +612,11 @@
 	};
 };
 
+&i2c1 {
+	pinctrl-0 = <&i2c1_pins>;
+	pinctrl-names = "i2c-exio1";
+};
+
 &i2c2 {
 	pinctrl-0 = <&i2c2_pins>;
 	pinctrl-names = "default";
-- 
2.9.3

^ permalink raw reply related

* [PATCH v4 08/14] ARM: dts: porter: use demuxer for I2C2
From: Wolfram Sang @ 2016-11-06 20:20 UTC (permalink / raw)
  To: linux-renesas-soc, Simon Horman; +Cc: linux-i2c, Simon Horman, Wolfram Sang
In-Reply-To: <20161106202032.5227-1-wsa+renesas@sang-engineering.com>

From: Simon Horman <horms+renesas@verge.net.au>

Create a separate bus for HDMI related I2C2 and provide fallback to GPIO.

Based on work for the r8a7790/lager by Wolfram Sang.

Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
[wsa: rebased and fixed aliases]
Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
---
 arch/arm/boot/dts/r8a7791-porter.dts | 129 +++++++++++++++++++++--------------
 1 file changed, 76 insertions(+), 53 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7791-porter.dts b/arch/arm/boot/dts/r8a7791-porter.dts
index 6761d11d3f9e13..f4d296e0f67cb5 100644
--- a/arch/arm/boot/dts/r8a7791-porter.dts
+++ b/arch/arm/boot/dts/r8a7791-porter.dts
@@ -29,6 +29,8 @@
 
 	aliases {
 		serial0 = &scif0;
+		i2c9 = &gpioi2c2;
+		i2c10 = &i2chdmi;
 	};
 
 	chosen {
@@ -135,6 +137,79 @@
 			clocks = <&x14_clk>;
 		};
 	};
+
+	gpioi2c2: i2c-9 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "i2c-gpio";
+		status = "disabled";
+		gpios = <&gpio2 7 GPIO_ACTIVE_HIGH /* sda */
+			 &gpio2 6 GPIO_ACTIVE_HIGH /* scl */
+			>;
+		i2c-gpio,delay-us = <5>;
+	};
+
+	/*
+	 * A fallback to GPIO is provided for I2C2.
+	 */
+	i2chdmi: i2c-10 {
+		compatible = "i2c-demux-pinctrl";
+		i2c-parent = <&i2c2>, <&gpioi2c2>;
+		i2c-bus-name = "i2c-hdmi";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ak4642: codec@12 {
+			compatible = "asahi-kasei,ak4642";
+			#sound-dai-cells = <0>;
+			reg = <0x12>;
+		};
+
+		composite-in@20 {
+			compatible = "adi,adv7180";
+			reg = <0x20>;
+			remote = <&vin0>;
+
+			port {
+				adv7180: endpoint {
+					bus-width = <8>;
+					remote-endpoint = <&vin0ep>;
+				};
+			};
+		};
+
+		hdmi@39 {
+			compatible = "adi,adv7511w";
+			reg = <0x39>;
+			interrupt-parent = <&gpio3>;
+			interrupts = <29 IRQ_TYPE_LEVEL_LOW>;
+
+			adi,input-depth = <8>;
+			adi,input-colorspace = "rgb";
+			adi,input-clock = "1x";
+			adi,input-style = <1>;
+			adi,input-justification = "evenly";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					adv7511_in: endpoint {
+						remote-endpoint = <&du_out_rgb>;
+					};
+				};
+
+				port@1 {
+					reg = <1>;
+					adv7511_out: endpoint {
+						remote-endpoint = <&hdmi_con>;
+					};
+				};
+			};
+		};
+	};
 };
 
 &extal_clk {
@@ -296,61 +371,9 @@
 
 &i2c2 {
 	pinctrl-0 = <&i2c2_pins>;
-	pinctrl-names = "default";
+	pinctrl-names = "i2c-hdmi";
 
-	status = "okay";
 	clock-frequency = <400000>;
-
-	ak4642: codec@12 {
-		compatible = "asahi-kasei,ak4642";
-		#sound-dai-cells = <0>;
-		reg = <0x12>;
-	};
-
-	composite-in@20 {
-		compatible = "adi,adv7180";
-		reg = <0x20>;
-		remote = <&vin0>;
-
-		port {
-			adv7180: endpoint {
-				bus-width = <8>;
-				remote-endpoint = <&vin0ep>;
-			};
-		};
-	};
-
-	hdmi@39 {
-		compatible = "adi,adv7511w";
-		reg = <0x39>;
-		interrupt-parent = <&gpio3>;
-		interrupts = <29 IRQ_TYPE_LEVEL_LOW>;
-
-		adi,input-depth = <8>;
-		adi,input-colorspace = "rgb";
-		adi,input-clock = "1x";
-		adi,input-style = <1>;
-		adi,input-justification = "evenly";
-
-		ports {
-			#address-cells = <1>;
-			#size-cells = <0>;
-
-			port@0 {
-				reg = <0>;
-				adv7511_in: endpoint {
-					remote-endpoint = <&du_out_rgb>;
-				};
-			};
-
-			port@1 {
-				reg = <1>;
-				adv7511_out: endpoint {
-					remote-endpoint = <&hdmi_con>;
-				};
-			};
-		};
-	};
 };
 
 &sata0 {
-- 
2.9.3

^ permalink raw reply related

* Re: [PATCHv6 00/11] i2c: Relax mandatory I2C ID table passing
From: Wolfram Sang @ 2016-11-07  0:07 UTC (permalink / raw)
  To: Kieran Bingham
  Cc: Lee Jones, linux-i2c, linux-kernel, Javier Martinez Canillas,
	sameo
In-Reply-To: <1477413715-22894-1-git-send-email-kieran@bingham.xyz>

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


> As such, in this series I have extended i2c_of_match_device_strip_vendor
> so that it will also perform a search against a full compatible string
> for the matching process. This was not done by the core OF framework as
> the sysfs interface does not create an of_node to match against. If so
> desired, this function could now be renamed to i2c_of_match_device_sysfs

Looks good from a glimpse. Now I want to test, but I can't apply to
v4.9-rc3. What is your base? Is there a branch available? Or could you
even resend, rebased with the sysfs_streq() change applied?


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

^ permalink raw reply

* Re: [PATCH v5 6/6] i2c: use an IRQ to report Host Notify events, not alert
From: Wolfram Sang @ 2016-11-07  0:20 UTC (permalink / raw)
  To: Benjamin Tissoires; +Cc: Dmitry Torokhov, linux-i2c, linux-kernel, Jean Delvare
In-Reply-To: <1476360640-12901-7-git-send-email-benjamin.tissoires@redhat.com>

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

On Thu, Oct 13, 2016 at 02:10:40PM +0200, Benjamin Tissoires wrote:
> The current SMBus Host Notify implementation relies on .alert() to
> relay its notifications. However, the use cases where SMBus Host
> Notify is needed currently is to signal data ready on touchpads.
> 
> This is closer to an IRQ than a custom API through .alert().
> Given that the 2 touchpad manufacturers (Synaptics and Elan) that
> use SMBus Host Notify don't put any data in the SMBus payload, the
> concept actually matches one to one.

I see the advantages. The only question I have: What if we encounter
devices in the future which do put data in the payload? Can this
mechanism be extended to handle that?

> 
> Benefits are multiple:
> - simpler code and API: the client will just have an IRQ, and
>   nothing needs to be added in the adapter beside internally
>   enabling it.
> - no more specific workqueue, the threading is handled by IRQ core
>   directly (when required)
> - no more races when removing the device (the drivers are already
>   required to disable irq on remove)
> - simpler handling for drivers: use plain regular IRQs
> - no more dependency on i2c-smbus for i2c-i801 (and any other adapter)
> - the IRQ domain is created automatically when the adapter exports
>   the Host Notify capability
> - the IRQ are assign only if ACPI, OF and the caller did not assign
>   one already
> - the domain is automatically destroyed on remove
> - fewer lines of code (minus 20, yeah!)
> 
> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>

Thanks for keeping at it!


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

^ permalink raw reply

* Re: [PATCH v4 0/7] i2c: bcm2835: Bring in changes from downstream
From: Wolfram Sang @ 2016-11-07  0:36 UTC (permalink / raw)
  To: Noralf Trønnes
  Cc: swarren, eric, linux-kernel, linux-i2c, linux-arm-kernel,
	linux-rpi-kernel
In-Reply-To: <1475525174-28604-1-git-send-email-noralf@tronnes.org>

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

On Mon, Oct 03, 2016 at 10:06:07PM +0200, Noralf Trønnes wrote:

> This patchset tries to bring in the lessons learned in the downstream
> driver i2c-bcm2708. The downstream clock stretcing timeout patch has
> been left out since clock stretching is broken/unreliable on this
> controller, so no point in setting it.
> 
> Changes since version 3:
> - Add comment about I2C_C_CLEAR on error

Looks like some serious hacking to get around HW limitations. Thanks for
upporting it.

Applied to for-next.


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

^ permalink raw reply

* Re: [patch v4 1/1] i2c: add master driver for mellanox systems
From: Vladimir Zapolskiy @ 2016-11-07  0:47 UTC (permalink / raw)
  To: vadimp, wsa; +Cc: linux-i2c, linux-kernel, jiri, Michael Shych
In-Reply-To: <1478250907-147450-1-git-send-email-vadimp@mellanox.com>

Hi Vadim,

please find below some more nitpickings.

On 11/04/2016 11:15 AM, vadimp@mellanox.com wrote:
> From: Vadim Pasternak <vadimp@mellanox.com>
>

[snip]

> diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
> index d252276..b9e1c4c 100644
> --- a/drivers/i2c/busses/Kconfig
> +++ b/drivers/i2c/busses/Kconfig
> @@ -1150,6 +1150,18 @@ config I2C_ELEKTOR
>  	  This support is also available as a module.  If so, the module
>  	  will be called i2c-elektor.
>
> +config I2C_MLXCPLD
> +	tristate "Mellanox I2C driver"
> +	depends on X86_64
> +	default n

Please just remove 'default n' line, unset default value in Kconfig
is the same as 'default n'.

[snip]

> +/* General defines */
> +#define MLXPLAT_CPLD_LPC_I2C_BASE_ADDR	0x2000
> +#define MLXCPLD_I2C_DEVICE_NAME		"i2c_mlxcpld"
> +#define MLXCPLD_I2C_VALID_FLAG		(I2C_M_RECV_LEN | I2C_M_RD)
> +#define MLXCPLD_I2C_BUS_NUM		1
> +#define MLXCPLD_I2C_DATA_REG_SZ		36
> +#define MLXCPLD_I2C_MAX_ADDR_LEN	4
> +#define MLXCPLD_I2C_RETR_NUM		2
> +#define MLXCPLD_I2C_XFER_TO		500000 /* msec */
> +#define MLXCPLD_I2C_POLL_TIME		2000   /* msec */

Two lines above define macro values with the microsecond unit, its
short form is denoted as "usec" and "msec" or "ms" is used to
denote milliseconds. Please correct it, transfer timeout of "500
seconds" is confusing.

[snip]

> +
> +static int mlxcpld_i2c_probe(struct platform_device *pdev)
> +{
> +	struct mlxcpld_i2c_priv *priv;
> +	int err;
> +
> +	priv = devm_kzalloc(&pdev->dev, sizeof(struct mlxcpld_i2c_priv),
> +			    GFP_KERNEL);
> +	if (!priv)
> +		return -ENOMEM;
> +
> +	mutex_init(&priv->lock);
> +	platform_set_drvdata(pdev, priv);
> +
> +	priv->dev = &pdev->dev;
> +
> +	/* Register with i2c layer */
> +	mlxcpld_i2c_adapter.timeout = usecs_to_jiffies(MLXCPLD_I2C_XFER_TO);
> +	priv->adap = mlxcpld_i2c_adapter;
> +	priv->adap.dev.parent = &pdev->dev;
> +	priv->base_addr = MLXPLAT_CPLD_LPC_I2C_BASE_ADDR;
> +	i2c_set_adapdata(&priv->adap, priv);
> +
> +	err = i2c_add_numbered_adapter(&priv->adap);
> +	if (err) {
> +		dev_err(&pdev->dev, "Failed to add %s adapter (%d)\n",
> +			MLXCPLD_I2C_DEVICE_NAME, err);
> +		goto fail_adapter;
> +	}
> +
> +	return 0;
> +
> +fail_adapter:
> +	mutex_destroy(&priv->lock);
> +	return err;

Here you can save some more lines of code by changing it to

	err = i2c_add_numbered_adapter(&priv->adap);
	if (err)
		mutex_destroy(&priv->lock);

	return err;

Note, dev_err() is not needed here, because printing of the error
message is delegated to the I2C core.

> +}
> +

Please feel free to add a tag to the next version:

Reviewed-by: Vladimir Zapolskiy <vz@mleia.com>

--
With best wishes,
Vladimir

^ permalink raw reply

* [patch v5 1/1] i2c: add master driver for mellanox systems
From: vadimp @ 2016-11-07  7:47 UTC (permalink / raw)
  To: wsa; +Cc: vz, linux-i2c, linux-kernel, jiri, Vadim Pasternak, Michael Shych

From: Vadim Pasternak <vadimp@mellanox.com>

Device driver for Mellanox I2C controller logic, implemented in Lattice
CPLD device.
Device supports:
 - Master mode
 - One physical bus
 - Polling mode

The Kconfig currently controlling compilation of this code is:
drivers/i2c/busses/Kconfig:config I2C_MLXCPLD

Signed-off-by: Michael Shych <michaelsh@mellanox.com>
Signed-off-by: Vadim Pasternak <vadimp@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
Reviewed-by: Vladimir Zapolskiy <vz@mleia.com>
---
v4->v5:
 Comments pointed out by Vladimir:
 - Remove "default n" from Kconfig;
 - Fix the comments for timeout and pool time;
 - Optimize error flow in mlxcpld_i2c_probe;
v3->v4:
 Comments pointed out by Vladimir:
 - Set default to no in Kconfig;
 - Make mlxcpld_i2c_plat_dev static and add empty line before the
   declaration;
 - In function mlxcpld_i2c_invalid_len remove (msg->len < 0), since len is
   unsigned;
 - Remove unused symbol mlxcpld_i2c_plat_dev;
 - Remove extra spaces in comments to mlxcpld_i2c_check_msg_params;
 - Remove unnecessary round braces in mlxcpld_i2c_set_transf_data;
 - Remove the assignment of 'i' variable in mlxcpld_i2c_wait_for_tc;
 - Add extra line in mlxcpld_i2c_xfer;
 - Move assignment of the adapter's fields retries and nr inside
   mlxcpld_i2c_adapter declaration;
v2->v3:
 Comments pointed out by Vladimir:
 - Use tab symbol as indentation in Kconfig
 - Add the Kconfig section preserving the alphabetical order - added
   within "Other I2C/SMBus bus drivers" after I2C_ELEKTOR (but after this
   sections others are not follow alphabetical);
 - Change license to dual;
 - Replace ADRR with ADDR in macros;
 - Remove unused macros: MLXCPLD_LPCI2C_LPF_DFLT,
   MLXCPLD_LPCI2C_HALF_CYC_100, MLXCPLD_LPCI2C_I2C_HOLD_100,
   MLXCPLD_LPCI2C_HALF_CYC_REG, MLXCPLD_LPCI2C_I2C_HOLD_REG;
 - Fix checkpatch warnings (**/ and the end of comment);
 - Add empty line before structures mlxcpld_i2c_regs,
   mlxcpld_i2c_curr_transf, mlxcpld_i2c_priv;
 - Remove unused structure mlxcpld_i2c_regs;
 - Remove from mlxcpld_i2c_priv the next fields:
   retr_num, poll_time, block_sz, xfer_to; use instead macros
   respectively: MLXCPLD_I2C_RETR_NUM, MLXCPLD_I2C_POLL_TIME,
   MLXCPLD_I2C_DATA_REG_SZ, MLXCPLD_I2C_XFER_TO;
 - In mlxcpld_i2c_invalid_len remove unnecessary else;
 - Optimize mlxcpld_i2c_set_transf_data;
 - mlxcpld_i2c_reset - add empty lines after/before mutex
   lock/unlock;
 - mlxcpld_i2c_wait_for_free - cover case timeout is equal
   MLXCPLD_I2C_XFER_TO;
 - mlxcpld_i2c_wait_for_tc:
   - Do not assign err in declaration (also err is removed);
   - Insert empty line before case MLXCPLD_LPCI2C_ACK_IND;
   - inside case MLXCPLD_LPCI2C_ACK_IND - avoid unnecessary
     indentation;
   - Remove case MLXCPLD_LPCI2C_ERR_IND and remove this macro;
 - Add empty lines in mlxcpld_i2c_xfer before/after mutex_lock/
   mutex_unlock;
 - In mlxcpld_i2c_probe add emtpy line after platform_set_drvdata;
 - Replace platfrom handle pdev in mlxcpld_i2c_priv with the pointer
   to the structure device;
 - Place assignment of base_addr near the others;
 - Enclose e-mail with <>;
 Fixes added by Vadim:
 - Change structure description format according to
   Documentation/kernel-documentation.rst guideline;
 - mlxcpld_i2c_wait_for_tc: return error if status reaches default case;
v1->v2
 Fixes added by Vadim:
 - Put new record in Makefile in alphabetic order;
 - Remove http://www.mellanox.com from MAINTAINERS record;
---
 Documentation/i2c/busses/i2c-mlxcpld |  47 +++
 MAINTAINERS                          |   8 +
 drivers/i2c/busses/Kconfig           |  11 +
 drivers/i2c/busses/Makefile          |   1 +
 drivers/i2c/busses/i2c-mlxcpld.c     | 551 +++++++++++++++++++++++++++++++++++
 5 files changed, 618 insertions(+)
 create mode 100644 Documentation/i2c/busses/i2c-mlxcpld
 create mode 100644 drivers/i2c/busses/i2c-mlxcpld.c

diff --git a/Documentation/i2c/busses/i2c-mlxcpld b/Documentation/i2c/busses/i2c-mlxcpld
new file mode 100644
index 0000000..0f8678a
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-mlxcpld
@@ -0,0 +1,47 @@
+Driver i2c-mlxcpld
+
+Author: Michael Shych <michaelsh@mellanox.com>
+
+This is a for Mellanox I2C controller logic, implemented in Lattice CPLD
+device.
+Device supports:
+ - Master mode.
+ - One physical bus.
+ - Polling mode.
+
+This controller is equipped within the next Mellanox systems:
+"msx6710", "msx6720", "msb7700", "msn2700", "msx1410", "msn2410", "msb7800",
+"msn2740", "msn2100".
+
+The next transaction types are supported:
+ - Receive Byte/Block.
+ - Send Byte/Block.
+ - Read Byte/Block.
+ - Write Byte/Block.
+
+Registers:
+CTRL		0x1 - control reg.
+			Resets all the registers.
+HALF_CYC	0x4 - cycle reg.
+			Configure the width of I2C SCL half clock cycle (in 4 LPC_CLK
+			units).
+I2C_HOLD	0x5 - hold reg.
+			OE (output enable) is delayed by value set to this register
+			(in LPC_CLK units)
+CMD			0x6 - command reg.
+			Bit 7(lsb), 0 = write, 1 = read.
+			Bits [6:0] - the 7bit Address of the I2C device.
+			It should be written last as it triggers an I2C transaction.
+NUM_DATA	0x7 - data size reg.
+			Number of address bytes to write in read transaction
+NUM_ADDR	0x8 - address reg.
+			Number of address bytes to write in read transaction.
+STATUS		0x9 - status reg.
+			Bit 0 - transaction is completed.
+			Bit 4 - ACK/NACK.
+DATAx		0xa - 0x54  - 68 bytes data buffer regs.
+			For write transaction address is specified in four first bytes
+			(DATA1 - DATA4), data starting from DATA4.
+			For read transactions address is send in separate transaction and
+			specified in four first bytes (DATA0 - DATA3). Data is reading
+			starting from DATA0.
diff --git a/MAINTAINERS b/MAINTAINERS
index 3d838cf..dfc6a0a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7876,6 +7876,14 @@ W:	http://www.mellanox.com
 Q:	http://patchwork.ozlabs.org/project/netdev/list/
 F:	drivers/net/ethernet/mellanox/mlxsw/
 
+MELLANOX MLXCPLD I2C DRIVER
+M:	Vadim Pasternak <vadimp@mellanox.com>
+M:	Michael Shych <michaelsh@mellanox.com>
+L:	linux-i2c@vger.kernel.org
+S:	Supported
+F:	drivers/i2c/busses/i2c-mlxcpld.c
+F:	Documentation/i2c/busses/i2c-mlxcpld
+
 MELLANOX MLXCPLD LED DRIVER
 M:	Vadim Pasternak <vadimp@mellanox.com>
 L:	linux-leds@vger.kernel.org
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index d252276..6399cea 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -1150,6 +1150,17 @@ config I2C_ELEKTOR
 	  This support is also available as a module.  If so, the module
 	  will be called i2c-elektor.
 
+config I2C_MLXCPLD
+	tristate "Mellanox I2C driver"
+	depends on X86_64
+	help
+	  This exposes the Mellanox platform I2C busses to the linux I2C layer
+	  for X86 based systems.
+	  Controller is implemented as CPLD logic.
+
+	  This driver can also be built as a module. If so, the module will be
+	  called as i2c-mlxcpld.
+
 config I2C_PCA_ISA
 	tristate "PCA9564/PCA9665 on an ISA bus"
 	depends on ISA
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 29764cc..645bf08 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -116,6 +116,7 @@ obj-$(CONFIG_I2C_BCM_KONA)	+= i2c-bcm-kona.o
 obj-$(CONFIG_I2C_BRCMSTB)	+= i2c-brcmstb.o
 obj-$(CONFIG_I2C_CROS_EC_TUNNEL)	+= i2c-cros-ec-tunnel.o
 obj-$(CONFIG_I2C_ELEKTOR)	+= i2c-elektor.o
+obj-$(CONFIG_I2C_MLXCPLD)	+= i2c-mlxcpld.o
 obj-$(CONFIG_I2C_OPAL)		+= i2c-opal.o
 obj-$(CONFIG_I2C_PCA_ISA)	+= i2c-pca-isa.o
 obj-$(CONFIG_I2C_SIBYTE)	+= i2c-sibyte.o
diff --git a/drivers/i2c/busses/i2c-mlxcpld.c b/drivers/i2c/busses/i2c-mlxcpld.c
new file mode 100644
index 0000000..f7a6f3a
--- /dev/null
+++ b/drivers/i2c/busses/i2c-mlxcpld.c
@@ -0,0 +1,551 @@
+/*
+ * drivers/i2c/busses/i2c-mlxcpld.c
+ * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2016 Michael Shych <michaels@mellanox.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the names of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+/* General defines */
+#define MLXPLAT_CPLD_LPC_I2C_BASE_ADDR	0x2000
+#define MLXCPLD_I2C_DEVICE_NAME		"i2c_mlxcpld"
+#define MLXCPLD_I2C_VALID_FLAG		(I2C_M_RECV_LEN | I2C_M_RD)
+#define MLXCPLD_I2C_BUS_NUM		1
+#define MLXCPLD_I2C_DATA_REG_SZ		36
+#define MLXCPLD_I2C_MAX_ADDR_LEN	4
+#define MLXCPLD_I2C_RETR_NUM		2
+#define MLXCPLD_I2C_XFER_TO		500000 /* usec */
+#define MLXCPLD_I2C_POLL_TIME		2000   /* usec */
+
+/* LPC I2C registers */
+#define MLXCPLD_LPCI2C_LPF_REG		0x0
+#define MLXCPLD_LPCI2C_CTRL_REG		0x1
+#define MLXCPLD_LPCI2C_HALF_CYC_REG	0x4
+#define MLXCPLD_LPCI2C_I2C_HOLD_REG	0x5
+#define MLXCPLD_LPCI2C_CMD_REG		0x6
+#define MLXCPLD_LPCI2C_NUM_DAT_REG	0x7
+#define MLXCPLD_LPCI2C_NUM_ADDR_REG	0x8
+#define MLXCPLD_LPCI2C_STATUS_REG	0x9
+#define MLXCPLD_LPCI2C_DATA_REG		0xa
+
+/* LPC I2C masks and parametres */
+#define MLXCPLD_LPCI2C_RST_SEL_MASK	0x1
+#define MLXCPLD_LPCI2C_TRANS_END	0x1
+#define MLXCPLD_LPCI2C_STATUS_NACK	0x10
+#define MLXCPLD_LPCI2C_NO_IND		0
+#define MLXCPLD_LPCI2C_ACK_IND		1
+#define MLXCPLD_LPCI2C_NACK_IND		2
+
+/**
+ * struct mlxcpld_i2c_curr_transf - current transaction parameters:
+ * @cmd: command;
+ * @addr_width: address width;
+ * @data_len: data length;
+ * @cmd: command register;
+ * @msg_num: message number;
+ * @msg: pointer to message buffer;
+ */
+
+struct mlxcpld_i2c_curr_transf {
+	u8 cmd;
+	u8 addr_width;
+	u8 data_len;
+	u8 msg_num;
+	struct i2c_msg *msg;
+};
+
+/**
+ * struct mlxcpld_i2c_priv - private controller data:
+ * @lpc_gen_dec_reg: register space;
+ * @adap: i2c adapter;
+ * @dev_id: device id;
+ * @base_addr: base IO address;
+ * @lock: bus access lock;
+ * @xfer: current i2c transfer block;
+ * @dev: device handle;
+ */
+
+struct mlxcpld_i2c_priv {
+	struct i2c_adapter adap;
+	u16 dev_id;
+	u16 base_addr;
+	struct mutex lock;
+	struct mlxcpld_i2c_curr_transf xfer;
+	struct device *dev;
+};
+
+static void mlxcpld_i2c_lpc_write_buf(u8 *data, u8 len, u32 addr)
+{
+	int i, nbyte, ndword;
+
+	nbyte = len % 4;
+	ndword = len / 4;
+	for (i = 0; i < ndword; i++)
+		outl(*((u32 *)data + i), addr + i * 4);
+	ndword *= 4;
+	addr += ndword;
+	data += ndword;
+	for (i = 0; i < nbyte; i++)
+		outb(*(data + i), addr + i);
+}
+
+static void mlxcpld_i2c_lpc_read_buf(u8 *data, u8 len, u32 addr)
+{
+	int i, nbyte, ndword;
+
+	nbyte = len % 4;
+	ndword = len / 4;
+	for (i = 0; i < ndword; i++)
+		*((u32 *)data + i) = inl(addr + i * 4);
+	ndword *= 4;
+	addr += ndword;
+	data += ndword;
+	for (i = 0; i < nbyte; i++)
+		*(data + i) = inb(addr + i);
+}
+
+static void mlxcpld_i2c_read_comm(struct mlxcpld_i2c_priv *priv, u8 offs,
+				  u8 *data, u8 datalen)
+{
+	u32 addr = priv->base_addr + offs;
+
+	switch (datalen) {
+	case 1:
+		*(data) = inb(addr);
+		break;
+	case 2:
+		*((u16 *)data) = inw(addr);
+		break;
+	case 3:
+		*((u16 *)data) = inw(addr);
+		*(data + 2) = inb(addr + 2);
+		break;
+	case 4:
+		*((u32 *)data) = inl(addr);
+		break;
+	default:
+		mlxcpld_i2c_lpc_read_buf(data, datalen, addr);
+		break;
+	}
+}
+
+static void mlxcpld_i2c_write_comm(struct mlxcpld_i2c_priv *priv, u8 offs,
+				   u8 *data, u8 datalen)
+{
+	u32 addr = priv->base_addr + offs;
+
+	switch (datalen) {
+	case 1:
+		outb(*(data), addr);
+		break;
+	case 2:
+		outw(*((u16 *)data), addr);
+		break;
+	case 3:
+		outw(*((u16 *)data), addr);
+		outb(*(data + 2), addr + 2);
+		break;
+	case 4:
+		outl(*((u32 *)data), addr);
+		break;
+	default:
+		mlxcpld_i2c_lpc_write_buf(data, datalen, addr);
+		break;
+	}
+}
+
+/* Check validity of current i2c message and all transfer.
+ * Calculate also coomon length of all i2c messages in transfer.
+ */
+static int mlxcpld_i2c_invalid_len(struct mlxcpld_i2c_priv *priv,
+				   const struct i2c_msg *msg, u8 *comm_len)
+{
+	u8 max_len = msg->flags == I2C_M_RD ? MLXCPLD_I2C_DATA_REG_SZ -
+		     MLXCPLD_I2C_MAX_ADDR_LEN : MLXCPLD_I2C_DATA_REG_SZ;
+
+	if (msg->len > max_len)
+		return -EINVAL;
+
+	*comm_len += msg->len;
+	if (*comm_len > MLXCPLD_I2C_DATA_REG_SZ)
+		return -EINVAL;
+
+	return 0;
+}
+
+/* Check validity of received i2c messages parameters.
+ * Returns 0 if OK, other - in case of invalid parameters
+ * or common length of data that should be passed to CPLD
+ */
+static int mlxcpld_i2c_check_msg_params(struct mlxcpld_i2c_priv *priv,
+					struct i2c_msg *msgs, int num,
+					u8 *comm_len)
+{
+	int i;
+
+	if (!num) {
+		dev_err(priv->dev, "Incorrect 0 num of messages\n");
+		return -EINVAL;
+	}
+
+	if (unlikely(msgs[0].addr > 0x7f)) {
+		dev_err(priv->dev, "Invalid address 0x%03x\n",
+			msgs[0].addr);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < num; ++i) {
+		if (unlikely(!msgs[i].buf)) {
+			dev_err(priv->dev, "Invalid buf in msg[%d]\n",
+				i);
+			return -EINVAL;
+		}
+		if (unlikely(msgs[0].addr != msgs[i].addr)) {
+			dev_err(priv->dev, "Invalid addr in msg[%d]\n",
+				i);
+			return -EINVAL;
+		}
+		if (unlikely(mlxcpld_i2c_invalid_len(priv, &msgs[i],
+						     comm_len))) {
+			dev_err(priv->dev, "Invalid len %d msg[%d], addr 0x%x, lag %u\n",
+				msgs[i].len, i, msgs[i].addr, msgs[i].flags);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+/* Check if transfer is completed and status of operation.
+ * Returns 0 - transfer completed (both ACK or NACK),
+ * negative - transfer isn't finished.
+ */
+static int mlxcpld_i2c_check_status(struct mlxcpld_i2c_priv *priv, int *status)
+{
+	u8 val;
+
+	mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_STATUS_REG, &val, 1);
+
+	if (val & MLXCPLD_LPCI2C_TRANS_END) {
+		if (val & MLXCPLD_LPCI2C_STATUS_NACK)
+			/* The slave is unable to accept the data. No such
+			 * slave, command not understood, or unable to accept
+			 * any more data.
+			 */
+			*status = MLXCPLD_LPCI2C_NACK_IND;
+		else
+			*status = MLXCPLD_LPCI2C_ACK_IND;
+		return 0;
+	}
+	*status = MLXCPLD_LPCI2C_NO_IND;
+
+	return -EIO;
+}
+
+static void mlxcpld_i2c_set_transf_data(struct mlxcpld_i2c_priv *priv,
+					struct i2c_msg *msgs, int num,
+					u8 comm_len)
+{
+	priv->xfer.msg = msgs;
+	priv->xfer.msg_num = num;
+
+	/*
+	 * All upper layers currently are never use transfer with more than
+	 * 2 messages. Actually, it's also not so relevant in Mellanox systems
+	 * because of HW limitation. Max size of transfer is o more than 20B
+	 * in current x86 LPCI2C bridge.
+	 */
+	priv->xfer.cmd = msgs[num - 1].flags & I2C_M_RD;
+
+	if (priv->xfer.cmd == I2C_M_RD && comm_len != msgs[0].len) {
+		priv->xfer.addr_width = msgs[0].len;
+		priv->xfer.data_len = comm_len - priv->xfer.addr_width;
+	} else {
+		priv->xfer.addr_width = 0;
+		priv->xfer.data_len = comm_len;
+	}
+}
+
+/* Reset CPLD LPCI2C block */
+static void mlxcpld_i2c_reset(struct mlxcpld_i2c_priv *priv)
+{
+	u8 val;
+
+	mutex_lock(&priv->lock);
+
+	mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_CTRL_REG, &val, 1);
+	val &= ~MLXCPLD_LPCI2C_RST_SEL_MASK;
+	mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_CTRL_REG, &val, 1);
+
+	mutex_unlock(&priv->lock);
+}
+
+/* Make sure the CPLD is ready to start transmitting.
+ * Return 0 if it is, -EBUSY if it is not.
+ */
+static int mlxcpld_i2c_check_busy(struct mlxcpld_i2c_priv *priv)
+{
+	u8 val;
+
+	mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_STATUS_REG, &val, 1);
+
+	if (val & MLXCPLD_LPCI2C_TRANS_END)
+		return 0;
+
+	return -EIO;
+}
+
+static int mlxcpld_i2c_wait_for_free(struct mlxcpld_i2c_priv *priv)
+{
+	int timeout = 0;
+
+	do {
+		if (!mlxcpld_i2c_check_busy(priv))
+			break;
+		usleep_range(MLXCPLD_I2C_POLL_TIME / 2, MLXCPLD_I2C_POLL_TIME);
+		timeout += MLXCPLD_I2C_POLL_TIME;
+	} while (timeout <= MLXCPLD_I2C_XFER_TO);
+
+	if (timeout > MLXCPLD_I2C_XFER_TO)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+/*
+ * Wait for master transfer to complete.
+ * It puts current process to sleep until we get interrupt or timeout expires.
+ * Returns the number of transferred or read bytes or error (<0).
+ */
+static int mlxcpld_i2c_wait_for_tc(struct mlxcpld_i2c_priv *priv)
+{
+	int status, i, timeout = 0;
+	u8 datalen;
+
+	do {
+		usleep_range(MLXCPLD_I2C_POLL_TIME / 2, MLXCPLD_I2C_POLL_TIME);
+		if (!mlxcpld_i2c_check_status(priv, &status))
+			break;
+		timeout += MLXCPLD_I2C_POLL_TIME;
+	} while (status == 0 && timeout < MLXCPLD_I2C_XFER_TO);
+
+	switch (status) {
+	case MLXCPLD_LPCI2C_NO_IND:
+		return -ETIMEDOUT;
+
+	case MLXCPLD_LPCI2C_ACK_IND:
+		if (priv->xfer.cmd != I2C_M_RD)
+			return (priv->xfer.addr_width + priv->xfer.data_len);
+
+		if (priv->xfer.msg_num == 1)
+			i = 0;
+		else
+			i = 1;
+
+		if (!priv->xfer.msg[i].buf)
+			return -EINVAL;
+
+		/*
+		 * Actual read data len will be always the same as
+		 * requested len. 0xff (line pull-up) will be returned
+		 * if slave has no data to return. Thus don't read
+		 * MLXCPLD_LPCI2C_NUM_DAT_REG reg from CPLD.
+		 */
+		datalen = priv->xfer.data_len;
+
+		mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_DATA_REG,
+				      priv->xfer.msg[i].buf, datalen);
+
+		return datalen;
+
+	case MLXCPLD_LPCI2C_NACK_IND:
+		return -EAGAIN;
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static void mlxcpld_i2c_xfer_msg(struct mlxcpld_i2c_priv *priv)
+{
+	int i, len = 0;
+	u8 cmd;
+
+	mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_NUM_DAT_REG,
+			       &priv->xfer.data_len, 1);
+	mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_NUM_ADDR_REG,
+			       &priv->xfer.addr_width, 1);
+
+	for (i = 0; i < priv->xfer.msg_num; i++) {
+		if ((priv->xfer.msg[i].flags & I2C_M_RD) != I2C_M_RD) {
+			/* Don't write to CPLD buffer in read transaction */
+			mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_DATA_REG +
+					       len, priv->xfer.msg[i].buf,
+					       priv->xfer.msg[i].len);
+			len += priv->xfer.msg[i].len;
+		}
+	}
+
+	/* Set target slave address with command for master transfer.
+	 * It should be latest executed function before CPLD transaction.
+	 */
+	cmd = (priv->xfer.msg[0].addr << 1) | priv->xfer.cmd;
+	mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_CMD_REG, &cmd, 1);
+}
+
+/* Generic lpc-i2c transfer.
+ * Returns the number of processed messages or error (<0).
+ */
+static int mlxcpld_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
+			    int num)
+{
+	struct mlxcpld_i2c_priv *priv = i2c_get_adapdata(adap);
+	u8 comm_len = 0;
+	int err;
+
+	err = mlxcpld_i2c_check_msg_params(priv, msgs, num, &comm_len);
+	if (err) {
+		dev_err(priv->dev, "Incorrect message\n");
+		return err;
+	}
+
+	/* Check bus state */
+	if (mlxcpld_i2c_wait_for_free(priv)) {
+		dev_err(priv->dev, "LPCI2C bridge is busy\n");
+
+		/*
+		 * Usually it means something serious has happened.
+		 * We can not have unfinished previous transfer
+		 * so it doesn't make any sense to try to stop it.
+		 * Probably we were not able to recover from the
+		 * previous error.
+		 * The only reasonable thing - is soft reset.
+		 */
+		mlxcpld_i2c_reset(priv);
+		if (mlxcpld_i2c_check_busy(priv)) {
+			dev_err(priv->dev, "LPCI2C bridge is busy after reset\n");
+			return -EIO;
+		}
+	}
+
+	mlxcpld_i2c_set_transf_data(priv, msgs, num, comm_len);
+
+	mutex_lock(&priv->lock);
+
+	/* Do real transfer. Can't fail */
+	mlxcpld_i2c_xfer_msg(priv);
+
+	/* Wait for transaction complete */
+	err = mlxcpld_i2c_wait_for_tc(priv);
+
+	mutex_unlock(&priv->lock);
+
+	return err < 0 ? err : num;
+}
+
+static u32 mlxcpld_i2c_func(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_BLOCK_DATA;
+}
+
+static const struct i2c_algorithm mlxcpld_i2c_algo = {
+	.master_xfer	= mlxcpld_i2c_xfer,
+	.functionality	= mlxcpld_i2c_func
+};
+
+static struct i2c_adapter mlxcpld_i2c_adapter = {
+	.owner          = THIS_MODULE,
+	.name           = "i2c-mlxcpld",
+	.class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
+	.algo           = &mlxcpld_i2c_algo,
+	.retries	= MLXCPLD_I2C_RETR_NUM,
+	.nr		= MLXCPLD_I2C_BUS_NUM,
+};
+
+static int mlxcpld_i2c_probe(struct platform_device *pdev)
+{
+	struct mlxcpld_i2c_priv *priv;
+	int err;
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(struct mlxcpld_i2c_priv),
+			    GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	mutex_init(&priv->lock);
+	platform_set_drvdata(pdev, priv);
+
+	priv->dev = &pdev->dev;
+
+	/* Register with i2c layer */
+	mlxcpld_i2c_adapter.timeout = usecs_to_jiffies(MLXCPLD_I2C_XFER_TO);
+	priv->adap = mlxcpld_i2c_adapter;
+	priv->adap.dev.parent = &pdev->dev;
+	priv->base_addr = MLXPLAT_CPLD_LPC_I2C_BASE_ADDR;
+	i2c_set_adapdata(&priv->adap, priv);
+
+	err = i2c_add_numbered_adapter(&priv->adap);
+	if (err)
+		mutex_destroy(&priv->lock);
+
+	return err;
+}
+
+static int mlxcpld_i2c_remove(struct platform_device *pdev)
+{
+	struct mlxcpld_i2c_priv *priv = platform_get_drvdata(pdev);
+
+	i2c_del_adapter(&priv->adap);
+	mutex_destroy(&priv->lock);
+
+	return 0;
+}
+
+static struct platform_driver mlxcpld_i2c_driver = {
+	.probe		= mlxcpld_i2c_probe,
+	.remove		= mlxcpld_i2c_remove,
+	.driver = {
+		.name = MLXCPLD_I2C_DEVICE_NAME,
+	},
+};
+
+module_platform_driver(mlxcpld_i2c_driver);
+
+MODULE_AUTHOR("Michael Shych <michaels@mellanox.com>");
+MODULE_DESCRIPTION("Mellanox I2C-CPLD controller driver");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS("platform:i2c-mlxcpld");
-- 
2.1.4

^ permalink raw reply related

* RE: [patch v4 1/1] i2c: add master driver for mellanox systems
From: Vadim Pasternak @ 2016-11-07  5:49 UTC (permalink / raw)
  To: Vladimir Zapolskiy, wsa@the-dreams.de
  Cc: linux-i2c@vger.kernel.org, linux-kernel@vger.kernel.org,
	jiri@resnulli.us, Michael Shych
In-Reply-To: <fe5f890f-6be1-130f-3978-2d73b4a24e7a@mleia.com>

Hi Vladimir,

Thank you very much for reviews.

Thanks,
Vadim.

> -----Original Message-----
> From: Vladimir Zapolskiy [mailto:vz@mleia.com]
> Sent: Monday, November 07, 2016 2:47 AM
> To: Vadim Pasternak <vadimp@mellanox.com>; wsa@the-dreams.de
> Cc: linux-i2c@vger.kernel.org; linux-kernel@vger.kernel.org; jiri@resnulli.us;
> Michael Shych <michaelsh@mellanox.com>
> Subject: Re: [patch v4 1/1] i2c: add master driver for mellanox systems
> 
> Hi Vadim,
> 
> please find below some more nitpickings.
> 
> On 11/04/2016 11:15 AM, vadimp@mellanox.com wrote:
> > From: Vadim Pasternak <vadimp@mellanox.com>
> >
> 
> [snip]
> 
> > diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
> > index d252276..b9e1c4c 100644
> > --- a/drivers/i2c/busses/Kconfig
> > +++ b/drivers/i2c/busses/Kconfig
> > @@ -1150,6 +1150,18 @@ config I2C_ELEKTOR
> >  	  This support is also available as a module.  If so, the module
> >  	  will be called i2c-elektor.
> >
> > +config I2C_MLXCPLD
> > +	tristate "Mellanox I2C driver"
> > +	depends on X86_64
> > +	default n
> 
> Please just remove 'default n' line, unset default value in Kconfig is the same as
> 'default n'.
> 
> [snip]
> 
> > +/* General defines */
> > +#define MLXPLAT_CPLD_LPC_I2C_BASE_ADDR	0x2000
> > +#define MLXCPLD_I2C_DEVICE_NAME		"i2c_mlxcpld"
> > +#define MLXCPLD_I2C_VALID_FLAG		(I2C_M_RECV_LEN |
> I2C_M_RD)
> > +#define MLXCPLD_I2C_BUS_NUM		1
> > +#define MLXCPLD_I2C_DATA_REG_SZ		36
> > +#define MLXCPLD_I2C_MAX_ADDR_LEN	4
> > +#define MLXCPLD_I2C_RETR_NUM		2
> > +#define MLXCPLD_I2C_XFER_TO		500000 /* msec */
> > +#define MLXCPLD_I2C_POLL_TIME		2000   /* msec */
> 
> Two lines above define macro values with the microsecond unit, its short form is
> denoted as "usec" and "msec" or "ms" is used to denote milliseconds. Please
> correct it, transfer timeout of "500 seconds" is confusing.
> 
> [snip]
> 
> > +
> > +static int mlxcpld_i2c_probe(struct platform_device *pdev) {
> > +	struct mlxcpld_i2c_priv *priv;
> > +	int err;
> > +
> > +	priv = devm_kzalloc(&pdev->dev, sizeof(struct mlxcpld_i2c_priv),
> > +			    GFP_KERNEL);
> > +	if (!priv)
> > +		return -ENOMEM;
> > +
> > +	mutex_init(&priv->lock);
> > +	platform_set_drvdata(pdev, priv);
> > +
> > +	priv->dev = &pdev->dev;
> > +
> > +	/* Register with i2c layer */
> > +	mlxcpld_i2c_adapter.timeout =
> usecs_to_jiffies(MLXCPLD_I2C_XFER_TO);
> > +	priv->adap = mlxcpld_i2c_adapter;
> > +	priv->adap.dev.parent = &pdev->dev;
> > +	priv->base_addr = MLXPLAT_CPLD_LPC_I2C_BASE_ADDR;
> > +	i2c_set_adapdata(&priv->adap, priv);
> > +
> > +	err = i2c_add_numbered_adapter(&priv->adap);
> > +	if (err) {
> > +		dev_err(&pdev->dev, "Failed to add %s adapter (%d)\n",
> > +			MLXCPLD_I2C_DEVICE_NAME, err);
> > +		goto fail_adapter;
> > +	}
> > +
> > +	return 0;
> > +
> > +fail_adapter:
> > +	mutex_destroy(&priv->lock);
> > +	return err;
> 
> Here you can save some more lines of code by changing it to
> 
> 	err = i2c_add_numbered_adapter(&priv->adap);
> 	if (err)
> 		mutex_destroy(&priv->lock);
> 
> 	return err;
> 
> Note, dev_err() is not needed here, because printing of the error message is
> delegated to the I2C core.
> 
> > +}
> > +
> 
> Please feel free to add a tag to the next version:
> 
> Reviewed-by: Vladimir Zapolskiy <vz@mleia.com>
> 
> --
> With best wishes,
> Vladimir

^ permalink raw reply

* Re: [Linux-parport] True Parallel Port Interface for Bit-banging?
From: Sebastian Frias @ 2016-11-07 12:44 UTC (permalink / raw)
  To: Maciej S. Szmigiero
  Cc: Wolfram Sang, Sudip Mukherjee, linux-parport, philb, tim,
	Jean Delvare, linux-i2c
In-Reply-To: <5461ac01-6054-e222-f707-0b475c24276d@maciej.szmigiero.name>

On 10/29/2016 01:12 AM, Maciej S. Szmigiero wrote:
>> Would you mind sharing the laptop's model?
> 
> This is Elitebook model 8570p.

That seems like a fairly recent laptop:

http://www.notebookcheck.net/Review-HP-EliteBook-8570p-B6Q03EA-ABD-Notebook.82291.0.html

and it has a true parallel port? Thanks a lot for the pointer!

>> There are a bunch of
>> Elitebooks and maybe not all have the ports wired.
>> Does your laptop has the Parallel Port on the docking or on the laptop
>> itself?
> 
> Only a serial port socket is built-it, parallel port socket is
> available only via a port replicator.
> 
> According to description of this replicator it is compatible with
> a lot of different Elitebooks and Probooks:
> http://h30094.www3.hp.com/product.aspx?sku=10432928&mfg_part=A7E34AA&pagemode=ca
> 
> I wasn't able find any note in this replicator description that port
> availability depends on connected laptop model.
> You can try to search for particular laptop model schematics, even
> if it is available only for sale sometimes there is a preview
> page with block diagram which clearly show where the parallel port
> is connected (this is true for my laptop model for example).
> 
> However, whether the port is on standard I/O address and interrupt
> line requires some more digging.

Thanks for the information.

>> Do you know the command to enable them thru PnP? Shouldn't loading
>> the kernel module be enough? Or is it the other way around and 
>> enabling thru PnP triggers the kernel module load process?
> 
> If you want to use them under Linux then everything should be taken
> care of by kernel's PnP support.
> It can be problem if you want to use them under pure DOS.
> 

I see, thanks.

^ permalink raw reply

* [PATCHv7 00/11] i2c: Relax mandatory I2C ID table passing
From: Kieran Bingham @ 2016-11-07 12:47 UTC (permalink / raw)
  To: Wolfram Sang, Lee Jones, Kieran Bingham
  Cc: linux-i2c, linux-kernel, Javier Martinez Canillas, sameo

Version 7 of this patchset performs a rebase to linux-4.9-rc4 and adjust
the usage of strncasecmps to sysfs_streq. I have also renamed the
function i2c_of_match_device_strip_vendor to i2c_of_match_device_sysfs
which feels more appropriate now.

Retested with successful usage of full compatible strings, and shortened
device id's based on the vendor prefix being stripped.

Wolfram, for your convenience this series is available as a tagged commit
at: https://git.kernel.org/pub/scm/linux/kernel/git/kbingham/linux.git 
i2c-dt/v4.9-rc4-probe-conversion-v7, though this includes the TESTPATCH so
it is not by itself suitable for a merge.

Verifying the sysfs_streq usage can be seen below:

root@arm:~# ./new_i2c_device ds1307 0x68
ds1307 0x68 > /sys/bus/i2c/devices/i2c-2/new_device
[  216.289958] rtc-ds1307 2-0068: rtc core: registered ds1307 as rtc0
[  216.296740] rtc-ds1307 2-0068: 56 bytes nvram
[  216.301534] i2c i2c-2: new_device: Instantiated device ds1307 at 0x68
root@arm:~# 
root@arm:~# cat /sys/class/rtc/rtc0/date 
2016-11-07
root@arm:~# cat /sys/class/rtc/rtc0/name 
ds1307
root@arm:~# ./delete_i2c_device 0x68
[  237.018514] i2c i2c-2: delete_device: Deleting device ds1307 at 0x68
root@arm:~# ./new_i2c_device maxim,ds1307 0x68
maxim,ds1307 0x68 > /sys/bus/i2c/devices/i2c-2/new_device
[  243.346216] rtc-ds1307 2-0068: I'm a Maxim ... 
[  243.370115] rtc-ds1307 2-0068: rtc core: registered maxim,ds1307 as rtc0
[  243.377517] rtc-ds1307 2-0068: 56 bytes nvram
[  243.382343] i2c i2c-2: new_device: Instantiated device maxim,ds1307 at 0x68
root@arm:~# ./delete_i2c_device 0x68
[  263.897905] i2c i2c-2: delete_device: Deleting device maxim,ds1307 at 0x68
root@arm:~# ./new_i2c_device maxim,ds13072 0x68
maxim,ds13072 0x68 > /sys/bus/i2c/devices/i2c-2/new_device
[  266.357120] i2c i2c-2: new_device: Instantiated device maxim,ds13072 at 0x68
root@arm:~# ./delete_i2c_device 0x68
[  268.966851] i2c i2c-2: delete_device: Deleting device maxim,ds13072 at 0x68
root@arm:~# ./new_i2c_device maxim,ds130 0x68
maxim,ds130 0x68 > /sys/bus/i2c/devices/i2c-2/new_device
[  272.005528] i2c i2c-2: new_device: Instantiated device maxim,ds130 at 0x68
root@arm:~# ./delete_i2c_device 0x68
[  274.182360] i2c i2c-2: delete_device: Deleting device maxim,ds130 at 0x68
root@arm:~# ./new_i2c_device ds1307 0x68
ds1307 0x68 > /sys/bus/i2c/devices/i2c-2/new_device
[  281.313329] rtc-ds1307 2-0068: rtc core: registered ds1307 as rtc0
[  281.320218] rtc-ds1307 2-0068: 56 bytes nvram
[  281.325043] i2c i2c-2: new_device: Instantiated device ds1307 at 0x68



Kieran Bingham (3):
  i2c: match dt-style device names from sysfs interface
  i2c: match vendorless strings on the internal string length
  [TESTPATCH] rtc: convert ds1307 to interim probe_new

Lee Jones (8):
  i2c: Add pointer dereference protection to i2c_match_id()
  i2c: Add the ability to match device to compatible string without an
    of_node
  i2c: Match using traditional OF methods, then by vendor-less
    compatible strings
  i2c: Make I2C ID tables non-mandatory for DT'ed devices
  i2c: Export i2c_match_id() for direct use by device drivers
  i2c: Provide a temporary .probe_new() call-back type
  mfd: 88pm860x: Move over to new I2C device .probe() call
  mfd: as3722: Rid driver of superfluous I2C device ID structure

 drivers/i2c/i2c-core.c      | 84 ++++++++++++++++++++++++++++++++++++++++-----
 drivers/mfd/88pm860x-core.c |  5 ++-
 drivers/mfd/as3722.c        | 12 ++-----
 drivers/rtc/rtc-ds1307.c    | 54 ++++++++++++++++-------------
 include/linux/i2c.h         | 22 +++++++++++-
 5 files changed, 131 insertions(+), 46 deletions(-)

-- 
2.7.4

^ permalink raw reply

* [PATCHv7 01/11] i2c: Add pointer dereference protection to i2c_match_id()
From: Kieran Bingham @ 2016-11-07 12:47 UTC (permalink / raw)
  To: Wolfram Sang, Lee Jones, Kieran Bingham
  Cc: linux-i2c, linux-kernel, Javier Martinez Canillas, sameo
In-Reply-To: <1478522866-29620-1-git-send-email-kieran@bingham.xyz>

From: Lee Jones <lee.jones@linaro.org>

Here we're providing dereference protection for i2c_match_id(), which
saves us having to do it each time it's called.  We're also stripping
out the (now) needless checks in i2c_device_match().  This patch paves
the way for other, similar code trimming.

Acked-by: Grant Likely <grant.likely@linaro.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
Tested-by: Kieran Bingham <kieran@bingham.xyz>
Reviewed-by: Javier Martinez Canillas <javier@osg.samsung.com>
Tested-by: Javier Martinez Canillas <javier@osg.samsung.com>
Signed-off-by: Kieran Bingham <kieran@bingham.xyz>
---
 drivers/i2c/i2c-core.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index b432b64e307a..86083e5e5520 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -679,6 +679,9 @@ static inline int i2c_acpi_install_space_handler(struct i2c_adapter *adapter)
 static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
 						const struct i2c_client *client)
 {
+	if (!(id && client))
+		return NULL;
+
 	while (id->name[0]) {
 		if (strcmp(client->name, id->name) == 0)
 			return id;
@@ -692,8 +695,6 @@ static int i2c_device_match(struct device *dev, struct device_driver *drv)
 	struct i2c_client	*client = i2c_verify_client(dev);
 	struct i2c_driver	*driver;
 
-	if (!client)
-		return 0;
 
 	/* Attempt an OF style match */
 	if (of_driver_match_device(dev, drv))
@@ -704,9 +705,10 @@ static int i2c_device_match(struct device *dev, struct device_driver *drv)
 		return 1;
 
 	driver = to_i2c_driver(drv);
-	/* match on an id table if there is one */
-	if (driver->id_table)
-		return i2c_match_id(driver->id_table, client) != NULL;
+
+	/* Finally an I2C match */
+	if (i2c_match_id(driver->id_table, client))
+		return 1;
 
 	return 0;
 }
-- 
2.7.4

^ permalink raw reply related

* [PATCHv7 02/11] i2c: Add the ability to match device to compatible string without an of_node
From: Kieran Bingham @ 2016-11-07 12:47 UTC (permalink / raw)
  To: Wolfram Sang, Lee Jones, Kieran Bingham
  Cc: linux-i2c, linux-kernel, Javier Martinez Canillas, sameo
In-Reply-To: <1478522866-29620-1-git-send-email-kieran@bingham.xyz>

From: Lee Jones <lee.jones@linaro.org>

A great deal of I2C devices are currently matched via DT node name, and
as such the compatible naming convention of '<vendor>,<device>' has gone
somewhat awry - some nodes don't supply one, some supply an arbitrary
string and others the correct device name with an arbitrary vendor prefix.

In an effort to correct this problem we have to supply a mechanism to
match a device by compatible string AND by simple device name.  This
function strips off the '<vendor>,' part of a supplied compatible string
and attempts to match without it.

The plan is to remove this function once all of the compatible strings
for each device have been brought into line.

Acked-by: Grant Likely <grant.likely@linaro.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
[Kieran: strnicmp to strncasecmp]
Tested-by: Kieran Bingham <kieran@bingham.xyz>
Reviewed-by: Javier Martinez Canillas <javier@osg.samsung.com>
Tested-by: Javier Martinez Canillas <javier@osg.samsung.com>
Signed-off-by: Kieran Bingham <kieran@bingham.xyz>

---
changes from v6
 - Rename i2c_of_match_device_strip_vendor to i2c_of_match_device_sysfs

 drivers/i2c/i2c-core.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 86083e5e5520..dcbda850804f 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -1769,6 +1769,27 @@ struct i2c_adapter *of_get_i2c_adapter_by_node(struct device_node *node)
 	return adapter;
 }
 EXPORT_SYMBOL(of_get_i2c_adapter_by_node);
+
+static const struct of_device_id*
+i2c_of_match_device_sysfs(const struct of_device_id *matches,
+				  struct i2c_client *client)
+{
+	const char *name;
+
+	for (; matches->compatible[0]; matches++) {
+		name = strchr(matches->compatible, ',');
+		if (!name)
+			name = matches->compatible;
+		else
+			name++;
+
+		if (!strncasecmp(client->name, name, strlen(client->name)))
+			return matches;
+	}
+
+	return NULL;
+}
+
 #else
 static void of_i2c_register_devices(struct i2c_adapter *adap) { }
 #endif /* CONFIG_OF */
-- 
2.7.4

^ permalink raw reply related

* [PATCHv7 03/11] i2c: Match using traditional OF methods, then by vendor-less compatible strings
From: Kieran Bingham @ 2016-11-07 12:47 UTC (permalink / raw)
  To: Wolfram Sang, Lee Jones, Kieran Bingham
  Cc: linux-i2c, linux-kernel, Javier Martinez Canillas, sameo
In-Reply-To: <1478522866-29620-1-git-send-email-kieran@bingham.xyz>

From: Lee Jones <lee.jones@linaro.org>

This function provides a single call for all I2C devices which need to
match firstly using traditional OF means i.e by of_node, then if that
fails we attempt to match using the supplied I2C client name with a
list of supplied compatible strings with the '<vendor>,' string
removed.  The latter is required due to the unruly naming conventions
used currently by I2C devices.

Acked-by: Grant Likely <grant.likely@linaro.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
[Kieran: Fix static inline usage on !CONFIG_OF]
Tested-by: Kieran Bingham <kieran@bingham.xyz>
Reviewed-by: Javier Martinez Canillas <javier@osg.samsung.com>
Tested-by: Javier Martinez Canillas <javier@osg.samsung.com>
Signed-off-by: Kieran Bingham <kieran@bingham.xyz>

---
changes from v6
 - Rename i2c_of_match_device_strip_vendor to i2c_of_match_device_sysfs

 drivers/i2c/i2c-core.c | 16 ++++++++++++++++
 include/linux/i2c.h    | 12 ++++++++++++
 2 files changed, 28 insertions(+)

diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index dcbda850804f..2adf4a1ed7ca 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -1790,6 +1790,22 @@ i2c_of_match_device_sysfs(const struct of_device_id *matches,
 	return NULL;
 }
 
+const struct of_device_id
+*i2c_of_match_device(const struct of_device_id *matches,
+		     struct i2c_client *client)
+{
+	const struct of_device_id *match;
+
+	if (!(client && matches))
+		return NULL;
+
+	match = of_match_device(matches, &client->dev);
+	if (match)
+		return match;
+
+	return i2c_of_match_device_sysfs(matches, client);
+}
+EXPORT_SYMBOL_GPL(i2c_of_match_device);
 #else
 static void of_i2c_register_devices(struct i2c_adapter *adap) { }
 #endif /* CONFIG_OF */
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 6422eef428c4..c0a4a12815aa 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -774,6 +774,10 @@ extern struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node)
 /* must call i2c_put_adapter() when done with returned i2c_adapter device */
 struct i2c_adapter *of_get_i2c_adapter_by_node(struct device_node *node);
 
+extern const struct of_device_id
+*i2c_of_match_device(const struct of_device_id *matches,
+		     struct i2c_client *client);
+
 #else
 
 static inline struct i2c_client *of_find_i2c_device_by_node(struct device_node *node)
@@ -790,6 +794,14 @@ static inline struct i2c_adapter *of_get_i2c_adapter_by_node(struct device_node
 {
 	return NULL;
 }
+
+static inline const struct of_device_id
+*i2c_of_match_device(const struct of_device_id *matches,
+		     struct i2c_client *client)
+{
+	return NULL;
+}
+
 #endif /* CONFIG_OF */
 
 #if IS_ENABLED(CONFIG_ACPI)
-- 
2.7.4

^ permalink raw reply related

* [PATCHv7 04/11] i2c: Make I2C ID tables non-mandatory for DT'ed devices
From: Kieran Bingham @ 2016-11-07 12:47 UTC (permalink / raw)
  To: Wolfram Sang, Lee Jones, Kieran Bingham
  Cc: linux-i2c, linux-kernel, Javier Martinez Canillas, sameo
In-Reply-To: <1478522866-29620-1-git-send-email-kieran@bingham.xyz>

From: Lee Jones <lee.jones@linaro.org>

Currently the I2C framework insists on devices supplying an I2C ID
table.  Many of the devices which do so unnecessarily adding quite a
few wasted lines to kernel code.  This patch allows drivers a means
to 'not' supply the aforementioned table and match on DT match tables
instead.

Acked-by: Grant Likely <grant.likely@linaro.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
Tested-by: Kieran Bingham <kieran@bingham.xyz>
Reviewed-by: Javier Martinez Canillas <javier@osg.samsung.com>
Tested-by: Javier Martinez Canillas <javier@osg.samsung.com>
Signed-off-by: Kieran Bingham <kieran@bingham.xyz>
---
 drivers/i2c/i2c-core.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 2adf4a1ed7ca..6439174c0ff5 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -697,7 +697,7 @@ static int i2c_device_match(struct device *dev, struct device_driver *drv)
 
 
 	/* Attempt an OF style match */
-	if (of_driver_match_device(dev, drv))
+	if (i2c_of_match_device(drv->of_match_table, client))
 		return 1;
 
 	/* Then ACPI style match */
@@ -923,7 +923,15 @@ static int i2c_device_probe(struct device *dev)
 	}
 
 	driver = to_i2c_driver(dev->driver);
-	if (!driver->probe || !driver->id_table)
+	if (!driver->probe)
+		return -EINVAL;
+
+	/*
+	 * An I2C ID table is not mandatory, if and only if, a suitable Device
+	 * Tree match table entry is supplied for the probing device.
+	 */
+	if (!driver->id_table &&
+	    !i2c_of_match_device(dev->driver->of_match_table, client))
 		return -ENODEV;
 
 	if (client->flags & I2C_CLIENT_WAKE) {
-- 
2.7.4

^ permalink raw reply related

* [PATCHv7 06/11] i2c: Provide a temporary .probe_new() call-back type
From: Kieran Bingham @ 2016-11-07 12:47 UTC (permalink / raw)
  To: Wolfram Sang, Lee Jones, Kieran Bingham
  Cc: linux-i2c, linux-kernel, Javier Martinez Canillas, sameo
In-Reply-To: <1478522866-29620-1-git-send-email-kieran@bingham.xyz>

From: Lee Jones <lee.jones@linaro.org>

This will aid the seamless removal of the current probe()'s, more
commonly unused than used second parameter.  Most I2C drivers can
simply switch over to the new interface, others which have DT
support can use its own matching instead and others can call
i2c_match_id() themselves.  This brings I2C's device probe method
into line with other similar interfaces in the kernel and prevents
the requirement to pass an i2c_device_id table.

Suggested-by: Grant Likely <grant.likely@linaro.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
[Kieran: fix rebase conflicts and adapt for dev_pm_domain_{attach,detach}]
Tested-by: Kieran Bingham <kieran@bingham.xyz>
Reviewed-by: Javier Martinez Canillas <javier@osg.samsung.com>
Tested-by: Javier Martinez Canillas <javier@osg.samsung.com>
Signed-off-by: Kieran Bingham <kieran@bingham.xyz>
---
Changes since v4 [Kieran]
 - Rename .probe2 to probe_new
 - Checkpatch warnings fixed

 drivers/i2c/i2c-core.c | 15 ++++++++++++---
 include/linux/i2c.h    |  8 +++++++-
 2 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 48237d035246..3d377598647a 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -924,8 +924,6 @@ static int i2c_device_probe(struct device *dev)
 	}
 
 	driver = to_i2c_driver(dev->driver);
-	if (!driver->probe)
-		return -EINVAL;
 
 	/*
 	 * An I2C ID table is not mandatory, if and only if, a suitable Device
@@ -967,7 +965,18 @@ static int i2c_device_probe(struct device *dev)
 	if (status == -EPROBE_DEFER)
 		goto err_clear_wakeup_irq;
 
-	status = driver->probe(client, i2c_match_id(driver->id_table, client));
+	/*
+	 * When there are no more users of probe(),
+	 * rename probe_new to probe.
+	 */
+	if (driver->probe_new)
+		status = driver->probe_new(client);
+	else if (driver->probe)
+		status = driver->probe(client,
+				       i2c_match_id(driver->id_table, client));
+	else
+		status = -EINVAL;
+
 	if (status)
 		goto err_detach_pm_domain;
 
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 7e00efd6a62f..82cf90945bb8 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -135,7 +135,8 @@ enum i2c_alert_protocol {
  * struct i2c_driver - represent an I2C device driver
  * @class: What kind of i2c device we instantiate (for detect)
  * @attach_adapter: Callback for bus addition (deprecated)
- * @probe: Callback for device binding
+ * @probe: Callback for device binding - soon to be deprecated
+ * @probe_new: New callback for device binding
  * @remove: Callback for device unbinding
  * @shutdown: Callback for device shutdown
  * @alert: Alert callback, for example for the SMBus alert protocol
@@ -178,6 +179,11 @@ struct i2c_driver {
 	int (*probe)(struct i2c_client *, const struct i2c_device_id *);
 	int (*remove)(struct i2c_client *);
 
+	/* New driver model interface to aid the seamless removal of the
+	 * current probe()'s, more commonly unused than used second parameter.
+	 */
+	int (*probe_new)(struct i2c_client *);
+
 	/* driver model interfaces that don't relate to enumeration  */
 	void (*shutdown)(struct i2c_client *);
 
-- 
2.7.4

^ permalink raw reply related

* [PATCHv7 07/11] i2c: match dt-style device names from sysfs interface
From: Kieran Bingham @ 2016-11-07 12:47 UTC (permalink / raw)
  To: Wolfram Sang, Lee Jones, Kieran Bingham
  Cc: linux-i2c, linux-kernel, Javier Martinez Canillas, sameo
In-Reply-To: <1478522866-29620-1-git-send-email-kieran@bingham.xyz>

A user can choose to instantiate a device on an i2c bus using the sysfs
interface by providing a string and address to match and communicate
with the device on the bus. Presently this string is only matched
against the old i2c device id style strings, even in the presence of
full device tree compatible strings with vendor prefixes.

Providing a vendor-prefixed string to the sysfs interface will not match
against the device tree of_match_device() calls as there is no device
tree node to parse from the sysfs interface.

Convert i2c_of_match_device_strip_vendor() such that it can match both
vendor prefixed and stripped compatible strings on the sysfs interface.

Signed-off-by: Kieran Bingham <kieran@bingham.xyz>

---
Changes from v7
 - strncasecmp usage converted to sysfs_streq

 drivers/i2c/i2c-core.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 3d377598647a..c338c8f3b3db 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -1795,6 +1795,15 @@ i2c_of_match_device_sysfs(const struct of_device_id *matches,
 	const char *name;
 
 	for (; matches->compatible[0]; matches++) {
+		/*
+		 * Adding devices through the i2c sysfs interface provides us
+		 * a string to match which may be compatible with the device
+		 * tree compatible strings, however with no actual of_node the
+		 * of_match_device() will not match
+		 */
+		if (sysfs_streq(client->name, matches->compatible))
+			return matches;
+
 		name = strchr(matches->compatible, ',');
 		if (!name)
 			name = matches->compatible;
-- 
2.7.4

^ permalink raw reply related

* [PATCHv7 08/11] i2c: match vendorless strings on the internal string length
From: Kieran Bingham @ 2016-11-07 12:47 UTC (permalink / raw)
  To: Wolfram Sang, Lee Jones, Kieran Bingham
  Cc: linux-i2c, linux-kernel, Javier Martinez Canillas, sameo
In-Reply-To: <1478522866-29620-1-git-send-email-kieran@bingham.xyz>

If a user provides a shortened string to match a device to the sysfs i2c
interface it will match on the first string that contains that string
prefix.

for example:
  echo a 0x68 > /sys/bus/i2c/devices/i2c-2/new_device
will match as3711, as3722, and ak8975 incorrectly.

Correct this by using sysfs_streq to match the string exactly

Signed-off-by: Kieran Bingham <kieran@bingham.xyz>

---
Changes from v7
 - strncasecmp usage converted to sysfs_streq

 drivers/i2c/i2c-core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index c338c8f3b3db..8b93a262e237 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -1810,7 +1810,7 @@ i2c_of_match_device_sysfs(const struct of_device_id *matches,
 		else
 			name++;
 
-		if (!strncasecmp(client->name, name, strlen(client->name)))
+		if (sysfs_streq(client->name, name))
 			return matches;
 	}
 
-- 
2.7.4

^ permalink raw reply related

* [PATCHv7 09/11] mfd: 88pm860x: Move over to new I2C device .probe() call
From: Kieran Bingham @ 2016-11-07 12:47 UTC (permalink / raw)
  To: Wolfram Sang, Lee Jones, Kieran Bingham
  Cc: linux-i2c, linux-kernel, Javier Martinez Canillas, sameo
In-Reply-To: <1478522866-29620-1-git-send-email-kieran@bingham.xyz>

From: Lee Jones <lee.jones@linaro.org>

As part of an effort to rid the mostly unused second parameter for I2C
related .probe() functions and to conform to other existing frameworks
we're moving over to a temporary replacement .probe() call-back.

Acked-by: Grant Likely <grant.likely@linaro.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
Signed-off-by: Kieran Bingham <kieran@bingham.xyz>

---
Changes since v4
 - Rename .probe2 to probe_new

 drivers/mfd/88pm860x-core.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c
index 25e1aafae60c..227b99018657 100644
--- a/drivers/mfd/88pm860x-core.c
+++ b/drivers/mfd/88pm860x-core.c
@@ -1132,8 +1132,7 @@ static int pm860x_dt_init(struct device_node *np,
 	return 0;
 }
 
-static int pm860x_probe(struct i2c_client *client,
-				  const struct i2c_device_id *id)
+static int pm860x_probe(struct i2c_client *client)
 {
 	struct pm860x_platform_data *pdata = dev_get_platdata(&client->dev);
 	struct device_node *node = client->dev.of_node;
@@ -1259,7 +1258,7 @@ static struct i2c_driver pm860x_driver = {
 		.pm     = &pm860x_pm_ops,
 		.of_match_table	= pm860x_dt_ids,
 	},
-	.probe		= pm860x_probe,
+	.probe_new	= pm860x_probe,
 	.remove		= pm860x_remove,
 	.id_table	= pm860x_id_table,
 };
-- 
2.7.4

^ permalink raw reply related

* [PATCHv7 10/11] mfd: as3722: Rid driver of superfluous I2C device ID structure
From: Kieran Bingham @ 2016-11-07 12:47 UTC (permalink / raw)
  To: Wolfram Sang, Lee Jones, Kieran Bingham
  Cc: linux-i2c, linux-kernel, Javier Martinez Canillas, sameo
In-Reply-To: <1478522866-29620-1-git-send-email-kieran@bingham.xyz>

From: Lee Jones <lee.jones@linaro.org>

Also remove unused second probe() parameter 'i2c_device_id'.

Acked-by: Grant Likely <grant.likely@linaro.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
Signed-off-by: Kieran Bingham <kieran@bingham.xyz>

---
Changes since v4
 - Rename .probe2 to probe_new

 drivers/mfd/as3722.c | 12 ++----------
 1 file changed, 2 insertions(+), 10 deletions(-)

diff --git a/drivers/mfd/as3722.c b/drivers/mfd/as3722.c
index f87342c211bc..7d8c5e4136e2 100644
--- a/drivers/mfd/as3722.c
+++ b/drivers/mfd/as3722.c
@@ -354,8 +354,7 @@ static int as3722_i2c_of_probe(struct i2c_client *i2c,
 	return 0;
 }
 
-static int as3722_i2c_probe(struct i2c_client *i2c,
-			const struct i2c_device_id *id)
+static int as3722_i2c_probe(struct i2c_client *i2c)
 {
 	struct as3722 *as3722;
 	unsigned long irq_flags;
@@ -441,12 +440,6 @@ static const struct of_device_id as3722_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, as3722_of_match);
 
-static const struct i2c_device_id as3722_i2c_id[] = {
-	{ "as3722", 0 },
-	{},
-};
-MODULE_DEVICE_TABLE(i2c, as3722_i2c_id);
-
 static const struct dev_pm_ops as3722_pm_ops = {
 	SET_SYSTEM_SLEEP_PM_OPS(as3722_i2c_suspend, as3722_i2c_resume)
 };
@@ -457,8 +450,7 @@ static struct i2c_driver as3722_i2c_driver = {
 		.of_match_table = as3722_of_match,
 		.pm = &as3722_pm_ops,
 	},
-	.probe = as3722_i2c_probe,
-	.id_table = as3722_i2c_id,
+	.probe_new = as3722_i2c_probe,
 };
 
 module_i2c_driver(as3722_i2c_driver);
-- 
2.7.4

^ permalink raw reply related

* [PATCHv7 05/11] i2c: Export i2c_match_id() for direct use by device drivers
From: Kieran Bingham @ 2016-11-07 12:47 UTC (permalink / raw)
  To: Wolfram Sang, Lee Jones, Kieran Bingham
  Cc: linux-i2c, linux-kernel, Javier Martinez Canillas, sameo
In-Reply-To: <1478522866-29620-1-git-send-email-kieran@bingham.xyz>

From: Lee Jones <lee.jones@linaro.org>

When there was no other way to match a I2C device to driver i2c_match_id()
was exclusively used.  However, now there are other types of tables which
are commonly supplied, matching on an i2c_device_id table is used less
frequently.  Instead of _always_ calling i2c_match_id() from within the
framework, we only need to do so from drivers which have no other way of
matching.  This patch makes i2c_match_id() available to the aforementioned
device drivers.

Acked-by: Grant Likely <grant.likely@linaro.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
Tested-by: Kieran Bingham <kieran@bingham.xyz>
Reviewed-by: Javier Martinez Canillas <javier@osg.samsung.com>
Tested-by: Javier Martinez Canillas <javier@osg.samsung.com>
Signed-off-by: Kieran Bingham <kieran@bingham.xyz>
---
 drivers/i2c/i2c-core.c | 3 ++-
 include/linux/i2c.h    | 2 ++
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 6439174c0ff5..48237d035246 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -676,7 +676,7 @@ static inline int i2c_acpi_install_space_handler(struct i2c_adapter *adapter)
 
 /* ------------------------------------------------------------------------- */
 
-static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
+const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
 						const struct i2c_client *client)
 {
 	if (!(id && client))
@@ -689,6 +689,7 @@ static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
 	}
 	return NULL;
 }
+EXPORT_SYMBOL_GPL(i2c_match_id);
 
 static int i2c_device_match(struct device *dev, struct device_driver *drv)
 {
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index c0a4a12815aa..7e00efd6a62f 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -243,6 +243,8 @@ struct i2c_client {
 
 extern struct i2c_client *i2c_verify_client(struct device *dev);
 extern struct i2c_adapter *i2c_verify_adapter(struct device *dev);
+extern const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
+					const struct i2c_client *client);
 
 static inline struct i2c_client *kobj_to_i2c_client(struct kobject *kobj)
 {
-- 
2.7.4

^ permalink raw reply related

* [PATCHv7 11/11] [TESTPATCH] rtc: convert ds1307 to interim probe_new
From: Kieran Bingham @ 2016-11-07 12:47 UTC (permalink / raw)
  To: Wolfram Sang, Lee Jones, Kieran Bingham
  Cc: linux-i2c, linux-kernel, Javier Martinez Canillas, sameo
In-Reply-To: <1478522866-29620-1-git-send-email-kieran@bingham.xyz>

Just for testing, specify a maxim,ds1307 device to identify the code path used
when instantiating the driver from userspace.

root@arm:~# echo maxim,ds1307 0x68 > /sys/bus/i2c/devices/i2c-2/new_device
[   49.807383] rtc-ds1307 2-0068: I'm a Maxim ...
[   49.814706] rtc-ds1307 2-0068: rtc core: registered maxim,ds1307 as rtc0
[   49.821813] rtc-ds1307 2-0068: 56 bytes nvram
[   49.826444] i2c i2c-2: new_device: Instantiated device maxim,ds1307 at 0x68

This patch also demonstrates how to obtain data from the id's using the
new methods.
---
 drivers/rtc/rtc-ds1307.c | 54 +++++++++++++++++++++++++++---------------------
 1 file changed, 31 insertions(+), 23 deletions(-)

diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index 4e31036ee259..a5b744e9716c 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -31,6 +31,7 @@
  */
 enum ds_type {
 	ds_1307,
+	maxim_1307,
 	ds_1337,
 	ds_1338,
 	ds_1339,
@@ -144,6 +145,10 @@ static struct chip_desc chips[last_ds_type] = {
 		.nvram_offset	= 8,
 		.nvram_size	= 56,
 	},
+	[maxim_1307] = {
+		.nvram_offset	= 8,
+		.nvram_size	= 56,
+	},
 	[ds_1337] = {
 		.alarm		= 1,
 	},
@@ -173,23 +178,6 @@ static struct chip_desc chips[last_ds_type] = {
 	},
 };
 
-static const struct i2c_device_id ds1307_id[] = {
-	{ "ds1307", ds_1307 },
-	{ "ds1337", ds_1337 },
-	{ "ds1338", ds_1338 },
-	{ "ds1339", ds_1339 },
-	{ "ds1388", ds_1388 },
-	{ "ds1340", ds_1340 },
-	{ "ds3231", ds_3231 },
-	{ "m41t00", m41t00 },
-	{ "mcp7940x", mcp794xx },
-	{ "mcp7941x", mcp794xx },
-	{ "pt7c4338", ds_1307 },
-	{ "rx8025", rx_8025 },
-	{ "isl12057", ds_1337 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, ds1307_id);
 
 /*----------------------------------------------------------------------*/
 
@@ -1262,13 +1250,20 @@ static void ds1307_clks_register(struct ds1307 *ds1307)
 
 #endif /* CONFIG_COMMON_CLK */
 
-static int ds1307_probe(struct i2c_client *client,
-			const struct i2c_device_id *id)
+static const struct of_device_id ds1307_dt_ids[] = {
+	{ .compatible = "dallas,ds1307", .data = (void *)ds_1307 },
+	{ .compatible = "maxim,ds1307", .data = (void *)maxim_1307 },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, ds1307_dt_ids);
+
+static int ds1307_probe(struct i2c_client *client)
 {
 	struct ds1307		*ds1307;
 	int			err = -ENODEV;
 	int			tmp, wday;
-	struct chip_desc	*chip = &chips[id->driver_data];
+	const struct of_device_id 	*idof;
+	struct chip_desc	*chip;
 	struct i2c_adapter	*adapter = to_i2c_adapter(client->dev.parent);
 	bool			want_irq = false;
 	bool			ds1307_can_wakeup_device = false;
@@ -1294,10 +1289,20 @@ static int ds1307_probe(struct i2c_client *client,
 	if (!ds1307)
 		return -ENOMEM;
 
+	/* If we've got this far, this shouldn't be able to fail - but check anyway for now */
+	idof = i2c_of_match_device(ds1307_dt_ids, client);
+	if (!idof) {
+		dev_err(&client->dev, "Probe failed to find an id entry\n");
+		return -ENODEV;
+	}
+
+	/* Now we can set our chip entry */
+	chip = &chips[(int)idof->data];
+
 	i2c_set_clientdata(client, ds1307);
 
 	ds1307->client	= client;
-	ds1307->type	= id->driver_data;
+	ds1307->type	= (int) idof->data;
 
 	if (!pdata && client->dev.of_node)
 		ds1307_trickle_of_init(client, chip);
@@ -1479,6 +1484,9 @@ static int ds1307_probe(struct i2c_client *client,
 	 */
 	tmp = ds1307->regs[DS1307_REG_SECS];
 	switch (ds1307->type) {
+	case maxim_1307:
+		dev_info(&client->dev, "I'm a Maxim ... \n");
+		/* fallthrough */
 	case ds_1307:
 	case m41t00:
 		/* clock halted?  turn it on, so clock can tick. */
@@ -1678,10 +1686,10 @@ static int ds1307_remove(struct i2c_client *client)
 static struct i2c_driver ds1307_driver = {
 	.driver = {
 		.name	= "rtc-ds1307",
+		.of_match_table = of_match_ptr(ds1307_dt_ids),
 	},
-	.probe		= ds1307_probe,
+	.probe_new	= ds1307_probe,
 	.remove		= ds1307_remove,
-	.id_table	= ds1307_id,
 };
 
 module_i2c_driver(ds1307_driver);
-- 
2.7.4

^ permalink raw reply related

* Re: [PATCH v4 14/14] i2c: mux: demux-pinctrl: make drivers with no pinctrl work again
From: Geert Uytterhoeven @ 2016-11-07 13:10 UTC (permalink / raw)
  To: Wolfram Sang; +Cc: Linux-Renesas, Simon Horman, Linux I2C
In-Reply-To: <20161106202032.5227-15-wsa+renesas@sang-engineering.com>

On Sun, Nov 6, 2016 at 9:20 PM, Wolfram Sang
<wsa+renesas@sang-engineering.com> wrote:
> Some drivers like i2c-gpio do not have dedicated pinctrl states. They
> broke when error checking for pinctrl was added. Detect them now, and in
> their case, simply skip over pinctrl configuration.
>
> Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
> ---
>  drivers/i2c/muxes/i2c-demux-pinctrl.c | 22 ++++++++++++++++++++--
>  1 file changed, 20 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/i2c/muxes/i2c-demux-pinctrl.c b/drivers/i2c/muxes/i2c-demux-pinctrl.c
> index b3893f6282ba5b..3e6fe1760d82fc 100644
> --- a/drivers/i2c/muxes/i2c-demux-pinctrl.c
> +++ b/drivers/i2c/muxes/i2c-demux-pinctrl.c
> @@ -69,10 +69,28 @@ static int i2c_demux_activate_master(struct i2c_demux_pinctrl_priv *priv, u32 ne
>                 goto err_with_revert;
>         }
>
> -       p = devm_pinctrl_get_select(adap->dev.parent, priv->bus_name);
> +       /*
> +        * Check if there are pinctrl states at all. Note: we cant' use

can't

> +        * devm_pinctrl_get_select() because we need to distinguish between
> +        * the -ENODEV from devm_pinctrl_get() and pinctrl_lookup_state().
> +        */
> +       p = devm_pinctrl_get(adap->dev.parent);

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ 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