diff mbox

[v2,1/4] i2c: mux-pinctrl: Rework to honor disabled child nodes

Message ID 1425039885-5137-2-git-send-email-sebastian.hesselbarth@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Sebastian Hesselbarth Feb. 27, 2015, 12:24 p.m. UTC
I2C mux pinctrl driver currently determines the number of sub-busses by
counting available pinctrl-names. Unfortunately, this requires each
incarnation of the devicetree node with different available sub-busses
to be rewritten.

This patch reworks i2c-mux-pinctrl driver to count the number of
available sub-nodes instead. The rework should be compatible to the old
way of probing for sub-busses and additionally allows to disable unused
sub-busses with standard DT property status = "disabled".

This also amends the corresponding devicetree binding documentation to
reflect the new functionality to disable unused sub-nodes. While at it,
also fix two references to binding documentation files that miss an "i2c-"
prefix.

Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Tested-by: Stephen Warren <swarren@nvidia.com>
---
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Gregory Clement <gregory.clement@free-electrons.com>
Cc: Gabriel Dobato <dobatog@gmail.com>
Cc: Wolfram Sang <wsa@the-dreams.de>
Cc: Stephen Warren <swarren@wwwdotorg.org>
Cc: linux-i2c@vger.kernel.org
Cc: devicetree@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
---
 .../devicetree/bindings/i2c/i2c-mux-pinctrl.txt    | 25 ++++----
 drivers/i2c/muxes/i2c-mux-pinctrl.c                | 70 ++++++++++++++--------
 2 files changed, 59 insertions(+), 36 deletions(-)

Comments

Stephen Warren March 2, 2015, 8:01 p.m. UTC | #1
On 02/27/2015 05:24 AM, Sebastian Hesselbarth wrote:
> I2C mux pinctrl driver currently determines the number of sub-busses by
> counting available pinctrl-names. Unfortunately, this requires each
> incarnation of the devicetree node with different available sub-busses
> to be rewritten.
>
> This patch reworks i2c-mux-pinctrl driver to count the number of
> available sub-nodes instead. The rework should be compatible to the old
> way of probing for sub-busses and additionally allows to disable unused
> sub-busses with standard DT property status = "disabled".
>
> This also amends the corresponding devicetree binding documentation to
> reflect the new functionality to disable unused sub-nodes. While at it,
> also fix two references to binding documentation files that miss an "i2c-"
> prefix.

> diff --git a/Documentation/devicetree/bindings/i2c/i2c-mux-pinctrl.txt b/Documentation/devicetree/bindings/i2c/i2c-mux-pinctrl.txt

> -For each named state defined in the pinctrl-names property, an I2C child bus
> -will be created. I2C child bus numbers are assigned based on the index into
> -the pinctrl-names property.
> +For each enabled child node an I2C child bus will be created. I2C child bus
> +numbers are assigned based on the order of child nodes.

I think that I2C bus numbers are an internal concept for the OS. As 
such, we should probably remove any mention re: the bus numbers from the 
binding.

> -The only exception is that no bus will be created for a state named "idle". If
> -such a state is defined, it must be the last entry in pinctrl-names. For
> -example:
> +There must be a corresponding pinctrl-names entry for each enabled child
> +node at the position of the child node's "reg" property. Also, there can be
> +an idle pinctrl state defined at the end of possible pinctrl states. If such
> +a state is defined, it must be the last entry in pinctrl-names. For example:

What about gaps in the numbering sequence? IIRC, in a situation with 5 
nodes with reg 0, 1, 2, 3, 4 but where only the nodes with reg of 1, 3 
enabled, we only want 2 entries in pinctrl-names? If so, "at the 
position of the child node's "reg" property" isn't correct, since "at 
the position" implies there must be gaps in pinctrl-names. "In the same 
order as the reg property values for enabled subnodes" might be a better 
description.

Perhaps I'm misremembering and you explicitly didn't want to remove 
entries from pinctrl-names if child nodes were disabled? If so, then 
surely then in the text above, "for each enabled child" should be 
replaced with "for each child"?

> @@ -68,6 +68,7 @@ Example:
>   		pinctrl-1 = <&state_i2cmux_pta>;
>   		pinctrl-2 = <&state_i2cmux_idle>;
>
> +		/* Enabled child bus 0 */
>   		i2c@0 {
>   			reg = <0>;
>   			#address-cells = <1>;
> @@ -79,10 +80,12 @@ Example:
>   			};
>   		};
>
> +		/* Disabled child bus 1 */
>   		i2c@1 {
>   			reg = <1>;
>   			#address-cells = <1>;
>   			#size-cells = <0>;
> +			status = "disabled";

To make the example cover more cases, perhaps make child node i2c@0 
disabled and i2c@1 enabled. Then, the example would show what happens to 
pinctrl-names when there are gaps in the reg property numbering space of 
enabled children?
Sebastian Hesselbarth March 4, 2015, 9:10 a.m. UTC | #2
On 02.03.2015 21:01, Stephen Warren wrote:
> On 02/27/2015 05:24 AM, Sebastian Hesselbarth wrote:
>> I2C mux pinctrl driver currently determines the number of sub-busses by
>> counting available pinctrl-names. Unfortunately, this requires each
>> incarnation of the devicetree node with different available sub-busses
>> to be rewritten.
>>
>> This patch reworks i2c-mux-pinctrl driver to count the number of
>> available sub-nodes instead. The rework should be compatible to the old
>> way of probing for sub-busses and additionally allows to disable unused
>> sub-busses with standard DT property status = "disabled".
>>
>> This also amends the corresponding devicetree binding documentation to
>> reflect the new functionality to disable unused sub-nodes. While at it,
>> also fix two references to binding documentation files that miss an
>> "i2c-"
>> prefix.
>
>> diff --git a/Documentation/devicetree/bindings/i2c/i2c-mux-pinctrl.txt
>> b/Documentation/devicetree/bindings/i2c/i2c-mux-pinctrl.txt
>
>> -For each named state defined in the pinctrl-names property, an I2C
>> child bus
>> -will be created. I2C child bus numbers are assigned based on the
>> index into
>> -the pinctrl-names property.
>> +For each enabled child node an I2C child bus will be created. I2C
>> child bus
>> +numbers are assigned based on the order of child nodes.
>
> I think that I2C bus numbers are an internal concept for the OS. As
> such, we should probably remove any mention re: the bus numbers from the
> binding.

Stephen,

yeah as you can see I am struggling to find a good documentation. I
agree that we should get rid of the bus number thing above.

>> -The only exception is that no bus will be created for a state named
>> "idle". If
>> -such a state is defined, it must be the last entry in pinctrl-names. For
>> -example:
>> +There must be a corresponding pinctrl-names entry for each enabled child
>> +node at the position of the child node's "reg" property. Also, there
>> can be
>> +an idle pinctrl state defined at the end of possible pinctrl states.
>> If such
>> +a state is defined, it must be the last entry in pinctrl-names. For
>> example:
>
> What about gaps in the numbering sequence? IIRC, in a situation with 5
> nodes with reg 0, 1, 2, 3, 4 but where only the nodes with reg of 1, 3
> enabled, we only want 2 entries in pinctrl-names? If so, "at the
> position of the child node's "reg" property" isn't correct, since "at
> the position" implies there must be gaps in pinctrl-names. "In the same
> order as the reg property values for enabled subnodes" might be a better
> description.

Good point. The idea was to _have_ gaps in pinctrl-names to allow to
configure the current mux layout by status properties only. The existing
implementation (and docu) suggested you have to amend pinctrl-names to
achieve a specific setup.

> Perhaps I'm misremembering and you explicitly didn't want to remove
> entries from pinctrl-names if child nodes were disabled? If so, then
> surely then in the text above, "for each enabled child" should be
> replaced with "for each child"?

True.

>> @@ -68,6 +68,7 @@ Example:
>>           pinctrl-1 = <&state_i2cmux_pta>;
>>           pinctrl-2 = <&state_i2cmux_idle>;
>>
>> +        /* Enabled child bus 0 */
>>           i2c@0 {
>>               reg = <0>;
>>               #address-cells = <1>;
>> @@ -79,10 +80,12 @@ Example:
>>               };
>>           };
>>
>> +        /* Disabled child bus 1 */
>>           i2c@1 {
>>               reg = <1>;
>>               #address-cells = <1>;
>>               #size-cells = <0>;
>> +            status = "disabled";
>
> To make the example cover more cases, perhaps make child node i2c@0
> disabled and i2c@1 enabled. Then, the example would show what happens to
> pinctrl-names when there are gaps in the reg property numbering space of
> enabled children?

The idea was to make nothing happen to pinctrl-names if you enable/
disable any of the children. But I can move the disabled status to
i2c@0 to make it more clear that there should still be a pinctrl-names
cell for it.

Sebastian
diff mbox

Patch

diff --git a/Documentation/devicetree/bindings/i2c/i2c-mux-pinctrl.txt b/Documentation/devicetree/bindings/i2c/i2c-mux-pinctrl.txt
index ae8af1694e95..40cf6d86f935 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-mux-pinctrl.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-mux-pinctrl.txt
@@ -28,21 +28,21 @@  Also required are:
 * Standard pinctrl properties that specify the pin mux state for each child
   bus. See ../pinctrl/pinctrl-bindings.txt.
 
-* Standard I2C mux properties. See mux.txt in this directory.
+* Standard I2C mux properties. See i2c-mux.txt in this directory.
 
-* I2C child bus nodes. See mux.txt in this directory.
+* I2C child bus nodes. See i2c-mux.txt in this directory.
 
-For each named state defined in the pinctrl-names property, an I2C child bus
-will be created. I2C child bus numbers are assigned based on the index into
-the pinctrl-names property.
+For each enabled child node an I2C child bus will be created. I2C child bus
+numbers are assigned based on the order of child nodes.
 
-The only exception is that no bus will be created for a state named "idle". If
-such a state is defined, it must be the last entry in pinctrl-names. For
-example:
+There must be a corresponding pinctrl-names entry for each enabled child
+node at the position of the child node's "reg" property. Also, there can be
+an idle pinctrl state defined at the end of possible pinctrl states. If such
+a state is defined, it must be the last entry in pinctrl-names. For example:
 
-	pinctrl-names = "ddc", "pta", "idle"  ->  ddc = bus 0, pta = bus 1
-	pinctrl-names = "ddc", "idle", "pta"  ->  Invalid ("idle" not last)
-	pinctrl-names = "idle", "ddc", "pta"  ->  Invalid ("idle" not last)
+       pinctrl-names = "ddc", "pta", "idle"  ->  ddc = bus 0, pta = bus 1
+       pinctrl-names = "ddc", "idle", "pta"  ->  Invalid ("idle" not last)
+       pinctrl-names = "idle", "ddc", "pta"  ->  Invalid ("idle" not last)
 
 Whenever an access is made to a device on a child bus, the relevant pinctrl
 state will be programmed into hardware.
@@ -68,6 +68,7 @@  Example:
 		pinctrl-1 = <&state_i2cmux_pta>;
 		pinctrl-2 = <&state_i2cmux_idle>;
 
+		/* Enabled child bus 0 */
 		i2c@0 {
 			reg = <0>;
 			#address-cells = <1>;
@@ -79,10 +80,12 @@  Example:
 			};
 		};
 
+		/* Disabled child bus 1 */
 		i2c@1 {
 			reg = <1>;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			status = "disabled";
 
 			eeprom {
 				compatible = "eeprom";
diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c
index b48378c4b40d..033dacfabfdf 100644
--- a/drivers/i2c/muxes/i2c-mux-pinctrl.c
+++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c
@@ -56,9 +56,12 @@  static int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux,
 				struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
-	int num_names, i, ret;
+	struct device_node *child;
+	struct property *prop;
+	int num_names, num_children, ret;
 	struct device_node *adapter_np;
 	struct i2c_adapter *adapter;
+	const char *state;
 
 	if (!np)
 		return 0;
@@ -77,32 +80,16 @@  static int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux,
 		return num_names;
 	}
 
-	mux->pdata->pinctrl_states = devm_kzalloc(&pdev->dev,
-		sizeof(*mux->pdata->pinctrl_states) * num_names,
-		GFP_KERNEL);
-	if (!mux->pdata->pinctrl_states) {
-		dev_err(mux->dev, "Cannot allocate pinctrl_states\n");
-		return -ENOMEM;
+	num_children = of_get_available_child_count(np);
+	if (num_children < 0) {
+		dev_err(mux->dev, "Unable to count available children: %d\n",
+			num_children);
+		return num_children;
 	}
 
-	for (i = 0; i < num_names; i++) {
-		ret = of_property_read_string_index(np, "pinctrl-names", i,
-			&mux->pdata->pinctrl_states[mux->pdata->bus_count]);
-		if (ret < 0) {
-			dev_err(mux->dev, "Cannot parse pinctrl-names: %d\n",
-				ret);
-			return ret;
-		}
-		if (!strcmp(mux->pdata->pinctrl_states[mux->pdata->bus_count],
-			    "idle")) {
-			if (i != num_names - 1) {
-				dev_err(mux->dev, "idle state must be last\n");
-				return -EINVAL;
-			}
-			mux->pdata->pinctrl_state_idle = "idle";
-		} else {
-			mux->pdata->bus_count++;
-		}
+	if (num_names < num_children) {
+		dev_err(mux->dev, "Found less pinctrl states than children\n");
+		return -EINVAL;
 	}
 
 	adapter_np = of_parse_phandle(np, "i2c-parent", 0);
@@ -118,6 +105,39 @@  static int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux,
 	mux->pdata->parent_bus_num = i2c_adapter_id(adapter);
 	put_device(&adapter->dev);
 
+	mux->pdata->pinctrl_states = devm_kzalloc(&pdev->dev,
+		sizeof(*mux->pdata->pinctrl_states) * num_children,
+		GFP_KERNEL);
+	if (!mux->pdata->pinctrl_states) {
+		dev_err(mux->dev, "Cannot allocate pinctrl_states\n");
+		return -ENOMEM;
+	}
+
+	of_property_for_each_string(np, "pinctrl-names", prop, state)
+		if (!strcmp(state, "idle"))
+			mux->pdata->pinctrl_state_idle = "idle";
+
+	for_each_available_child_of_node(np, child) {
+		u32 reg;
+
+		ret = of_property_read_u32(child, "reg", &reg);
+		if (ret < 0) {
+			dev_err(mux->dev, "Missing reg property for child node: %d\n",
+				ret);
+			return ret;
+		}
+
+		ret = of_property_read_string_index(np,
+				    "pinctrl-names", reg, &state);
+		if (ret < 0) {
+			dev_err(mux->dev, "Cannot parse pinctrl-names for mux %d: %d\n",
+				reg, ret);
+			return ret;
+		}
+
+		mux->pdata->pinctrl_states[mux->pdata->bus_count++] = state;
+	}
+
 	return 0;
 }
 #else