diff mbox series

[1/2] phy: introduce phy mode PHY_MODE_UART and phy_get_mode_ext()

Message ID 1627383013-4535-1-git-send-email-macpaul.lin@mediatek.com (mailing list archive)
State New, archived
Headers show
Series [1/2] phy: introduce phy mode PHY_MODE_UART and phy_get_mode_ext() | expand

Commit Message

Macpaul Lin July 27, 2021, 10:50 a.m. UTC
Some embedded platform shared PINs between USB and UART.

For example, some phone will use special cable detection in boot loader
to switch USB port function into UART mode. Hence Kernel need to query
the hardware state from PHY registers to confirm the initialzation flow
for PHY and USB driver.

To support this kind of PIN switch, new PHY MODE and query API is
required. Here we introduce a new PHY mode: PHY_MODE_UART.

API phy_get_mode_ext() can be used to query the MODE from hardware
instead of reading it from phy attributes.

Signed-off-by: Macpaul Lin <macpaul.lin@mediatek.com>
---
 drivers/phy/phy-core.c  |   17 +++++++++++++++++
 include/linux/phy/phy.h |    3 +++
 2 files changed, 20 insertions(+)

Comments

Chunfeng Yun (云春峰) July 28, 2021, 1:35 a.m. UTC | #1
On Tue, 2021-07-27 at 18:50 +0800, Macpaul Lin wrote:
> Some embedded platform shared PINs between USB and UART.
> 
> For example, some phone will use special cable detection in boot loader
> to switch USB port function into UART mode. Hence Kernel need to query
> the hardware state from PHY registers to confirm the initialzation flow
> for PHY and USB driver.
> 
> To support this kind of PIN switch, new PHY MODE and query API is
> required. Here we introduce a new PHY mode: PHY_MODE_UART.
> 
> API phy_get_mode_ext() can be used to query the MODE from hardware
> instead of reading it from phy attributes.
> 
> Signed-off-by: Macpaul Lin <macpaul.lin@mediatek.com>
> ---
>  drivers/phy/phy-core.c  |   17 +++++++++++++++++
>  include/linux/phy/phy.h |    3 +++
>  2 files changed, 20 insertions(+)
> 
> diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
> index ccb575b..b8f6539 100644
> --- a/drivers/phy/phy-core.c
> +++ b/drivers/phy/phy-core.c
> @@ -373,6 +373,23 @@ int phy_set_mode_ext(struct phy *phy, enum phy_mode mode, int submode)
>  }
>  EXPORT_SYMBOL_GPL(phy_set_mode_ext);
>  
> +int phy_get_mode_ext(struct phy *phy)
> +{
> +	int ret;
> +
> +	if (!phy || !phy->ops->get_mode_ext)
> +		return 0;
> +
> +	mutex_lock(&phy->mutex);
> +	ret = phy->ops->get_mode_ext(phy);
> +	if (!ret)
> +		ret = phy->attrs.mode;
> +	mutex_unlock(&phy->mutex);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(phy_get_mode_ext);
> +
>  int phy_set_media(struct phy *phy, enum phy_media media)
>  {
>  	int ret;
> diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
> index 0ed434d..7d32c6b 100644
> --- a/include/linux/phy/phy.h
> +++ b/include/linux/phy/phy.h
> @@ -34,6 +34,7 @@ enum phy_mode {
>  	PHY_MODE_USB_DEVICE_HS,
>  	PHY_MODE_USB_DEVICE_SS,
>  	PHY_MODE_USB_OTG,
> +	PHY_MODE_UART,
>  	PHY_MODE_UFS_HS_A,
>  	PHY_MODE_UFS_HS_B,
>  	PHY_MODE_PCIE,
> @@ -70,6 +71,7 @@ enum phy_media {
>   * @power_on: powering on the phy
>   * @power_off: powering off the phy
>   * @set_mode: set the mode of the phy
> + * @get_mode_ext: get the extented mode of the phy
>   * @set_media: set the media type of the phy (optional)
>   * @set_speed: set the speed of the phy (optional)
>   * @reset: resetting the phy
> @@ -83,6 +85,7 @@ struct phy_ops {
>  	int	(*power_on)(struct phy *phy);
>  	int	(*power_off)(struct phy *phy);
>  	int	(*set_mode)(struct phy *phy, enum phy_mode mode, int submode);
> +	int	(*get_mode_ext)(struct phy *phy);
>  	int	(*set_media)(struct phy *phy, enum phy_media media);
>  	int	(*set_speed)(struct phy *phy, int speed);
>  
add prototype of phy_get_mode_ext(struct phy *phy) for both cases that
CONFIG_GENERIC_PHY is enabled or not in linux/phy/phy.h
diff mbox series

Patch

diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
index ccb575b..b8f6539 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c
@@ -373,6 +373,23 @@  int phy_set_mode_ext(struct phy *phy, enum phy_mode mode, int submode)
 }
 EXPORT_SYMBOL_GPL(phy_set_mode_ext);
 
+int phy_get_mode_ext(struct phy *phy)
+{
+	int ret;
+
+	if (!phy || !phy->ops->get_mode_ext)
+		return 0;
+
+	mutex_lock(&phy->mutex);
+	ret = phy->ops->get_mode_ext(phy);
+	if (!ret)
+		ret = phy->attrs.mode;
+	mutex_unlock(&phy->mutex);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(phy_get_mode_ext);
+
 int phy_set_media(struct phy *phy, enum phy_media media)
 {
 	int ret;
diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
index 0ed434d..7d32c6b 100644
--- a/include/linux/phy/phy.h
+++ b/include/linux/phy/phy.h
@@ -34,6 +34,7 @@  enum phy_mode {
 	PHY_MODE_USB_DEVICE_HS,
 	PHY_MODE_USB_DEVICE_SS,
 	PHY_MODE_USB_OTG,
+	PHY_MODE_UART,
 	PHY_MODE_UFS_HS_A,
 	PHY_MODE_UFS_HS_B,
 	PHY_MODE_PCIE,
@@ -70,6 +71,7 @@  enum phy_media {
  * @power_on: powering on the phy
  * @power_off: powering off the phy
  * @set_mode: set the mode of the phy
+ * @get_mode_ext: get the extented mode of the phy
  * @set_media: set the media type of the phy (optional)
  * @set_speed: set the speed of the phy (optional)
  * @reset: resetting the phy
@@ -83,6 +85,7 @@  struct phy_ops {
 	int	(*power_on)(struct phy *phy);
 	int	(*power_off)(struct phy *phy);
 	int	(*set_mode)(struct phy *phy, enum phy_mode mode, int submode);
+	int	(*get_mode_ext)(struct phy *phy);
 	int	(*set_media)(struct phy *phy, enum phy_media media);
 	int	(*set_speed)(struct phy *phy, int speed);