diff mbox series

[3/3] phy: ti: j721e-wiz: Manage typec-gpio-dir

Message ID 20191022132249.869-4-rogerq@ti.com
State New
Headers show
Series phy: cadence: j721e-wiz: Add Type-C plug flip support | expand

Commit Message

Roger Quadros Oct. 22, 2019, 1:22 p.m. UTC
Based on this GPIO state we need to configure LN10
bit to swap lane0 and lane1 if required (flipped connector).

Type-C companions typically need some time after the cable is
plugged before and before they reflect the correct status of
Type-C plug orientation on the DIR line.

Type-C Spec specifies CC attachment debounce time (tCCDebounce)
of 100 ms (min) to 200 ms (max).

Use the DT property to figure out if we need to add delay
or not before sampling the Type-C DIR line.

Signed-off-by: Roger Quadros <rogerq@ti.com>

Signed-off-by: Sekhar Nori <nsekhar@ti.com>

---
 drivers/phy/ti/phy-j721e-wiz.c | 41 ++++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)

-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

Comments

Jyri Sarha Oct. 23, 2019, 5:28 a.m. UTC | #1
On 22/10/2019 16:22, Roger Quadros wrote:
> Based on this GPIO state we need to configure LN10

> bit to swap lane0 and lane1 if required (flipped connector).

> 

> Type-C companions typically need some time after the cable is

> plugged before and before they reflect the correct status of

> Type-C plug orientation on the DIR line.

> 

> Type-C Spec specifies CC attachment debounce time (tCCDebounce)

> of 100 ms (min) to 200 ms (max).

> 

> Use the DT property to figure out if we need to add delay

> or not before sampling the Type-C DIR line.

> 

> Signed-off-by: Roger Quadros <rogerq@ti.com>

> Signed-off-by: Sekhar Nori <nsekhar@ti.com>

> ---

>  drivers/phy/ti/phy-j721e-wiz.c | 41 ++++++++++++++++++++++++++++++++++

>  1 file changed, 41 insertions(+)

> 

> diff --git a/drivers/phy/ti/phy-j721e-wiz.c b/drivers/phy/ti/phy-j721e-wiz.c

> index 2a95da843e9f..2becdbcb762a 100644

> --- a/drivers/phy/ti/phy-j721e-wiz.c

> +++ b/drivers/phy/ti/phy-j721e-wiz.c

> @@ -9,6 +9,8 @@

>  #include <dt-bindings/phy/phy.h>

>  #include <linux/clk.h>

>  #include <linux/clk-provider.h>

> +#include <linux/gpio.h>

> +#include <linux/gpio/consumer.h>

>  #include <linux/io.h>

>  #include <linux/module.h>

>  #include <linux/mux/consumer.h>

> @@ -22,6 +24,7 @@

>  #define WIZ_SERDES_CTRL		0x404

>  #define WIZ_SERDES_TOP_CTRL	0x408

>  #define WIZ_SERDES_RST		0x40c

> +#define WIZ_SERDES_TYPEC	0x410

>  #define WIZ_LANECTL(n)		(0x480 + (0x40 * (n)))

>  

>  #define WIZ_MAX_LANES		4

> @@ -29,6 +32,8 @@

>  #define WIZ_DIV_NUM_CLOCKS_16G	2

>  #define WIZ_DIV_NUM_CLOCKS_10G	1

>  

> +#define WIZ_SERDES_TYPEC_LN10_SWAP	BIT(30)

> +

>  enum wiz_lane_standard_mode {

>  	LANE_MODE_GEN1,

>  	LANE_MODE_GEN2,

> @@ -206,6 +211,8 @@ struct wiz {

>  	u32			num_lanes;

>  	struct platform_device	*serdes_pdev;

>  	struct reset_controller_dev wiz_phy_reset_dev;

> +	struct gpio_desc	*gpio_typec_dir;

> +	int			typec_dir_delay;

>  };

>  

>  static int wiz_reset(struct wiz *wiz)

> @@ -703,6 +710,21 @@ static int wiz_phy_reset_deassert(struct reset_controller_dev *rcdev,

>  	struct wiz *wiz = dev_get_drvdata(dev);

>  	int ret;

>  

> +	/* if typec-dir gpio was specified, set LN10 SWAP bit based on that */

> +	if (id == 0 && wiz->gpio_typec_dir) {

> +		if (wiz->typec_dir_delay)

> +			msleep_interruptible(wiz->typec_dir_delay);

> +

> +		if (gpiod_get_value_cansleep(wiz->gpio_typec_dir)) {

> +			regmap_update_bits(wiz->regmap, WIZ_SERDES_TYPEC,

> +					   WIZ_SERDES_TYPEC_LN10_SWAP,

> +					   WIZ_SERDES_TYPEC_LN10_SWAP);


A nit pick, but wouldn't it be more coherent with the rest of the driver
to define a REG_FIELD also for TYPEC_LN10_SWAP bit?

> +		} else {

> +			regmap_update_bits(wiz->regmap, WIZ_SERDES_TYPEC,

> +					   WIZ_SERDES_TYPEC_LN10_SWAP, 0);

> +		}

> +	}

> +

>  	if (id == 0) {

>  		ret = regmap_field_write(wiz->phy_reset_n, true);

>  		return ret;

> @@ -789,6 +811,25 @@ static int wiz_probe(struct platform_device *pdev)

>  		goto err_addr_to_resource;

>  	}

>  

> +	wiz->gpio_typec_dir = devm_gpiod_get_optional(dev, "typec-dir",

> +						      GPIOD_IN);

> +	if (IS_ERR(wiz->gpio_typec_dir)) {

> +		ret = PTR_ERR(wiz->gpio_typec_dir);

> +		if (ret != -EPROBE_DEFER)

> +			dev_err(dev, "Failed to request typec-dir gpio: %d\n",

> +				ret);

> +		goto err_addr_to_resource;

> +	}

> +

> +	if (wiz->gpio_typec_dir) {

> +		ret = of_property_read_u32(node, "typec-dir-debounce",

> +					   &wiz->typec_dir_delay);

> +		if (ret && ret != -EINVAL) {

> +			dev_err(dev, "Invalid typec-dir-debounce property\n");

> +			goto err_addr_to_resource;

> +		}

> +	}

> +

>  	wiz->dev = dev;

>  	wiz->regmap = regmap;

>  	wiz->num_lanes = num_lanes;

> 



-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
Roger Quadros Oct. 23, 2019, 8:10 a.m. UTC | #2
On 23/10/2019 08:28, Jyri Sarha wrote:
> On 22/10/2019 16:22, Roger Quadros wrote:

>> Based on this GPIO state we need to configure LN10

>> bit to swap lane0 and lane1 if required (flipped connector).

>>

>> Type-C companions typically need some time after the cable is

>> plugged before and before they reflect the correct status of

>> Type-C plug orientation on the DIR line.

>>

>> Type-C Spec specifies CC attachment debounce time (tCCDebounce)

>> of 100 ms (min) to 200 ms (max).

>>

>> Use the DT property to figure out if we need to add delay

>> or not before sampling the Type-C DIR line.

>>

>> Signed-off-by: Roger Quadros <rogerq@ti.com>

>> Signed-off-by: Sekhar Nori <nsekhar@ti.com>

>> ---

>>   drivers/phy/ti/phy-j721e-wiz.c | 41 ++++++++++++++++++++++++++++++++++

>>   1 file changed, 41 insertions(+)

>>

>> diff --git a/drivers/phy/ti/phy-j721e-wiz.c b/drivers/phy/ti/phy-j721e-wiz.c

>> index 2a95da843e9f..2becdbcb762a 100644

>> --- a/drivers/phy/ti/phy-j721e-wiz.c

>> +++ b/drivers/phy/ti/phy-j721e-wiz.c

>> @@ -9,6 +9,8 @@

>>   #include <dt-bindings/phy/phy.h>

>>   #include <linux/clk.h>

>>   #include <linux/clk-provider.h>

>> +#include <linux/gpio.h>

>> +#include <linux/gpio/consumer.h>

>>   #include <linux/io.h>

>>   #include <linux/module.h>

>>   #include <linux/mux/consumer.h>

>> @@ -22,6 +24,7 @@

>>   #define WIZ_SERDES_CTRL		0x404

>>   #define WIZ_SERDES_TOP_CTRL	0x408

>>   #define WIZ_SERDES_RST		0x40c

>> +#define WIZ_SERDES_TYPEC	0x410

>>   #define WIZ_LANECTL(n)		(0x480 + (0x40 * (n)))

>>   

>>   #define WIZ_MAX_LANES		4

>> @@ -29,6 +32,8 @@

>>   #define WIZ_DIV_NUM_CLOCKS_16G	2

>>   #define WIZ_DIV_NUM_CLOCKS_10G	1

>>   

>> +#define WIZ_SERDES_TYPEC_LN10_SWAP	BIT(30)

>> +

>>   enum wiz_lane_standard_mode {

>>   	LANE_MODE_GEN1,

>>   	LANE_MODE_GEN2,

>> @@ -206,6 +211,8 @@ struct wiz {

>>   	u32			num_lanes;

>>   	struct platform_device	*serdes_pdev;

>>   	struct reset_controller_dev wiz_phy_reset_dev;

>> +	struct gpio_desc	*gpio_typec_dir;

>> +	int			typec_dir_delay;

>>   };

>>   

>>   static int wiz_reset(struct wiz *wiz)

>> @@ -703,6 +710,21 @@ static int wiz_phy_reset_deassert(struct reset_controller_dev *rcdev,

>>   	struct wiz *wiz = dev_get_drvdata(dev);

>>   	int ret;

>>   

>> +	/* if typec-dir gpio was specified, set LN10 SWAP bit based on that */

>> +	if (id == 0 && wiz->gpio_typec_dir) {

>> +		if (wiz->typec_dir_delay)

>> +			msleep_interruptible(wiz->typec_dir_delay);

>> +

>> +		if (gpiod_get_value_cansleep(wiz->gpio_typec_dir)) {

>> +			regmap_update_bits(wiz->regmap, WIZ_SERDES_TYPEC,

>> +					   WIZ_SERDES_TYPEC_LN10_SWAP,

>> +					   WIZ_SERDES_TYPEC_LN10_SWAP);

> 

> A nit pick, but wouldn't it be more coherent with the rest of the driver

> to define a REG_FIELD also for TYPEC_LN10_SWAP bit?


I agree. Although, I hate fields as you need to do so much boilerplate just to
flip one bit.

cheers,
-roger
> 

>> +		} else {

>> +			regmap_update_bits(wiz->regmap, WIZ_SERDES_TYPEC,

>> +					   WIZ_SERDES_TYPEC_LN10_SWAP, 0);

>> +		}

>> +	}

>> +

>>   	if (id == 0) {

>>   		ret = regmap_field_write(wiz->phy_reset_n, true);

>>   		return ret;

>> @@ -789,6 +811,25 @@ static int wiz_probe(struct platform_device *pdev)

>>   		goto err_addr_to_resource;

>>   	}

>>   

>> +	wiz->gpio_typec_dir = devm_gpiod_get_optional(dev, "typec-dir",

>> +						      GPIOD_IN);

>> +	if (IS_ERR(wiz->gpio_typec_dir)) {

>> +		ret = PTR_ERR(wiz->gpio_typec_dir);

>> +		if (ret != -EPROBE_DEFER)

>> +			dev_err(dev, "Failed to request typec-dir gpio: %d\n",

>> +				ret);

>> +		goto err_addr_to_resource;

>> +	}

>> +

>> +	if (wiz->gpio_typec_dir) {

>> +		ret = of_property_read_u32(node, "typec-dir-debounce",

>> +					   &wiz->typec_dir_delay);

>> +		if (ret && ret != -EINVAL) {

>> +			dev_err(dev, "Invalid typec-dir-debounce property\n");

>> +			goto err_addr_to_resource;

>> +		}

>> +	}

>> +

>>   	wiz->dev = dev;

>>   	wiz->regmap = regmap;

>>   	wiz->num_lanes = num_lanes;

>>

> 

> 


-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
diff mbox series

Patch

diff --git a/drivers/phy/ti/phy-j721e-wiz.c b/drivers/phy/ti/phy-j721e-wiz.c
index 2a95da843e9f..2becdbcb762a 100644
--- a/drivers/phy/ti/phy-j721e-wiz.c
+++ b/drivers/phy/ti/phy-j721e-wiz.c
@@ -9,6 +9,8 @@ 
 #include <dt-bindings/phy/phy.h>
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/mux/consumer.h>
@@ -22,6 +24,7 @@ 
 #define WIZ_SERDES_CTRL		0x404
 #define WIZ_SERDES_TOP_CTRL	0x408
 #define WIZ_SERDES_RST		0x40c
+#define WIZ_SERDES_TYPEC	0x410
 #define WIZ_LANECTL(n)		(0x480 + (0x40 * (n)))
 
 #define WIZ_MAX_LANES		4
@@ -29,6 +32,8 @@ 
 #define WIZ_DIV_NUM_CLOCKS_16G	2
 #define WIZ_DIV_NUM_CLOCKS_10G	1
 
+#define WIZ_SERDES_TYPEC_LN10_SWAP	BIT(30)
+
 enum wiz_lane_standard_mode {
 	LANE_MODE_GEN1,
 	LANE_MODE_GEN2,
@@ -206,6 +211,8 @@  struct wiz {
 	u32			num_lanes;
 	struct platform_device	*serdes_pdev;
 	struct reset_controller_dev wiz_phy_reset_dev;
+	struct gpio_desc	*gpio_typec_dir;
+	int			typec_dir_delay;
 };
 
 static int wiz_reset(struct wiz *wiz)
@@ -703,6 +710,21 @@  static int wiz_phy_reset_deassert(struct reset_controller_dev *rcdev,
 	struct wiz *wiz = dev_get_drvdata(dev);
 	int ret;
 
+	/* if typec-dir gpio was specified, set LN10 SWAP bit based on that */
+	if (id == 0 && wiz->gpio_typec_dir) {
+		if (wiz->typec_dir_delay)
+			msleep_interruptible(wiz->typec_dir_delay);
+
+		if (gpiod_get_value_cansleep(wiz->gpio_typec_dir)) {
+			regmap_update_bits(wiz->regmap, WIZ_SERDES_TYPEC,
+					   WIZ_SERDES_TYPEC_LN10_SWAP,
+					   WIZ_SERDES_TYPEC_LN10_SWAP);
+		} else {
+			regmap_update_bits(wiz->regmap, WIZ_SERDES_TYPEC,
+					   WIZ_SERDES_TYPEC_LN10_SWAP, 0);
+		}
+	}
+
 	if (id == 0) {
 		ret = regmap_field_write(wiz->phy_reset_n, true);
 		return ret;
@@ -789,6 +811,25 @@  static int wiz_probe(struct platform_device *pdev)
 		goto err_addr_to_resource;
 	}
 
+	wiz->gpio_typec_dir = devm_gpiod_get_optional(dev, "typec-dir",
+						      GPIOD_IN);
+	if (IS_ERR(wiz->gpio_typec_dir)) {
+		ret = PTR_ERR(wiz->gpio_typec_dir);
+		if (ret != -EPROBE_DEFER)
+			dev_err(dev, "Failed to request typec-dir gpio: %d\n",
+				ret);
+		goto err_addr_to_resource;
+	}
+
+	if (wiz->gpio_typec_dir) {
+		ret = of_property_read_u32(node, "typec-dir-debounce",
+					   &wiz->typec_dir_delay);
+		if (ret && ret != -EINVAL) {
+			dev_err(dev, "Invalid typec-dir-debounce property\n");
+			goto err_addr_to_resource;
+		}
+	}
+
 	wiz->dev = dev;
 	wiz->regmap = regmap;
 	wiz->num_lanes = num_lanes;