From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Sun, 3 May 2020 21:40:27 +0200 Subject: phy: amlogic: meson8b-usb2: Add support for reading the "ID" signal The first USB PHY on Amlogic Meson8/8b/8m2/GXBB SoCs is OTG capable. This means that the USB "ID" signal is routed to the PHY. Add support for the gpio-controller and #gpio-cells properties so the value of the "ID" signal can be read as a GPIO (from the PHY) for example by the usb-conn-gpio driver. The registers also have a bit for the VBUS signal. That either is not wired in hardware inside the SoC silicon or not wired on the boards (e.g. Odroid-C1), which is why it's value is not exposed for now. Signed-off-by: Martin Blumenstingl --- drivers/phy/amlogic/phy-meson8b-usb2.c | 42 +++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/drivers/phy/amlogic/phy-meson8b-usb2.c b/drivers/phy/amlogic/phy-meson8b-usb2.c index 111111111111..222222222222 100644 --- a/drivers/phy/amlogic/phy-meson8b-usb2.c +++ b/drivers/phy/amlogic/phy-meson8b-usb2.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -127,6 +128,7 @@ struct phy_meson8b_usb2_priv { struct clk *clk_usb_general; struct clk *clk_usb; struct reset_control *reset; + struct gpio_chip gpiochip; const struct phy_meson8b_usb2_match_data *match; }; @@ -236,12 +238,44 @@ static const struct phy_ops phy_meson8b_usb2_ops = { .owner = THIS_MODULE, }; +static int phy_meson8b_usb2_id_gpio_get_direction(struct gpio_chip *gc, + unsigned int offset) +{ + return GPIO_LINE_DIRECTION_IN; +} + +static int phy_meson8b_usb2_id_gpio_get_value(struct gpio_chip *gc, + unsigned int offset) +{ + struct phy_meson8b_usb2_priv *priv = gpiochip_get_data(gc); + unsigned int val; + + regmap_read(priv->regmap, REG_ADP_BC, &val); + + return (val & REG_ADP_BC_ID_DIG) ? 1 : 0; +} + +static int phy_meson8b_usb2_id_gpiochip_add(struct device *dev, + struct phy_meson8b_usb2_priv *priv) +{ + priv->gpiochip.label = dev_name(dev); + priv->gpiochip.parent = dev; + priv->gpiochip.get_direction = phy_meson8b_usb2_id_gpio_get_direction; + priv->gpiochip.get = phy_meson8b_usb2_id_gpio_get_value; + priv->gpiochip.of_gpio_n_cells = 2; + priv->gpiochip.base = -1; + priv->gpiochip.ngpio = 1; + + return devm_gpiochip_add_data(dev, &priv->gpiochip, priv); +} + static int phy_meson8b_usb2_probe(struct platform_device *pdev) { struct phy_meson8b_usb2_priv *priv; - struct phy *phy; struct phy_provider *phy_provider; void __iomem *base; + struct phy *phy; + int ret; priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) @@ -280,6 +314,12 @@ static int phy_meson8b_usb2_probe(struct platform_device *pdev) return -EINVAL; } + if (device_property_read_bool(&pdev->dev, "gpio-controller")) { + ret = phy_meson8b_usb2_id_gpiochip_add(&pdev->dev, priv); + if (ret) + return ret; + } + phy = devm_phy_create(&pdev->dev, NULL, &phy_meson8b_usb2_ops); if (IS_ERR(phy)) { return dev_err_probe(&pdev->dev, PTR_ERR(phy), -- Armbian