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

From: Chunfeng Yun
Date: Tue Jul 27 2021 - 21:35:12 EST


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