]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
dwc3: add support for Amlogic A1 family
authorAlexey Romanov <avromanov@salutedevices.com>
Thu, 5 Oct 2023 08:54:28 +0000 (11:54 +0300)
committerNeil Armstrong <neil.armstrong@linaro.org>
Thu, 12 Oct 2023 11:39:41 +0000 (13:39 +0200)
Now the driver supports also A1 phy layer.

Signed-off-by: Alexey Romanov <avromanov@salutedevices.com>
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Link: https://lore.kernel.org/r/20231005085434.74755-8-avromanov@salutedevices.com
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
drivers/usb/dwc3/dwc3-meson-g12a.c

index dc5a976f71aa62a530d2309356855f35a211fe06..e0356e653fccdf415c41b0a5875cf82c15f03c93 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/bitfield.h>
 #include <linux/bitops.h>
 #include <linux/compat.h>
+#include <dt-bindings/clock/amlogic,a1-peripherals-clkc.h>
 
 /* USB2 Ports Control Registers */
 
@@ -103,10 +104,22 @@ enum {
        PHY_COUNT,
 };
 
-static const char *phy_names[PHY_COUNT] = {
+static const char *const dwc3_meson_g12a_phy_names[] = {
        "usb2-phy0", "usb2-phy1", "usb3-phy0",
 };
 
+static const char *const dwc3_meson_a1_phy_names[] = {
+       "usb2-phy0", "usb2-phy1"
+};
+
+struct dwc3_meson_g12a;
+
+struct dwc3_meson_g12a_drvdata {
+       const char *const *phy_names;
+       unsigned int phy_cnt;
+       int (*clk_init)(struct dwc3_meson_g12a *priv);
+};
+
 struct dwc3_meson_g12a {
        struct udevice          *dev;
        struct regmap           *regmap;
@@ -120,6 +133,7 @@ struct dwc3_meson_g12a {
 #if CONFIG_IS_ENABLED(DM_REGULATOR)
        struct udevice          *vbus_supply;
 #endif
+       struct dwc3_meson_g12a_drvdata *drvdata;
 };
 
 #define U2P_REG_SIZE                                           0x20
@@ -294,10 +308,11 @@ int dwc3_meson_g12a_force_mode(struct udevice *dev, enum usb_dr_mode mode)
 
 static int dwc3_meson_g12a_get_phys(struct dwc3_meson_g12a *priv)
 {
+       struct dwc3_meson_g12a_drvdata *data = priv->drvdata;
        int i, ret;
 
-       for (i = 0 ; i < PHY_COUNT ; ++i) {
-               ret = generic_phy_get_by_name(priv->dev, phy_names[i],
+       for (i = 0 ; i < data->phy_cnt; ++i) {
+               ret = generic_phy_get_by_name(priv->dev, data->phy_names[i],
                                              &priv->phys[i]);
                if (ret == -ENOENT || ret == -ENODATA)
                        continue;
@@ -355,18 +370,36 @@ static int dwc3_meson_g12a_clk_init(struct dwc3_meson_g12a *priv)
        return 0;
 }
 
+static int dwc3_meson_a1_clk_init(struct dwc3_meson_g12a *priv)
+{
+       int ret;
+
+       ret = clk_get_by_name(priv->dev, "usb_bus", &priv->clk);
+       if (ret)
+               return ret;
+
+       ret = clk_enable(&priv->clk);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
 static int dwc3_meson_g12a_probe(struct udevice *dev)
 {
        struct dwc3_meson_g12a *priv = dev_get_plat(dev);
+       struct dwc3_meson_g12a_drvdata *data =
+               (struct dwc3_meson_g12a_drvdata *)dev_get_driver_data(dev);
        int ret, i;
 
+       priv->drvdata = data;
        priv->dev = dev;
 
        ret = regmap_init_mem(dev_ofnode(dev), &priv->regmap);
        if (ret)
                return ret;
 
-       ret = dwc3_meson_g12a_clk_init(priv);
+       ret = data->clk_init(priv);
        if (ret)
                return ret;
 
@@ -399,7 +432,7 @@ static int dwc3_meson_g12a_probe(struct udevice *dev)
        if (ret)
                return ret;
 
-       for (i = 0 ; i < PHY_COUNT ; ++i) {
+       for (i = 0 ; i < data->phy_cnt; ++i) {
                if (!priv->phys[i].dev)
                        continue;
 
@@ -408,7 +441,7 @@ static int dwc3_meson_g12a_probe(struct udevice *dev)
                        goto err_phy_init;
        }
 
-       for (i = 0; i < PHY_COUNT; ++i) {
+       for (i = 0; i < data->phy_cnt; ++i) {
                if (!priv->phys[i].dev)
                        continue;
 
@@ -420,7 +453,7 @@ static int dwc3_meson_g12a_probe(struct udevice *dev)
        return 0;
 
 err_phy_init:
-       for (i = 0 ; i < PHY_COUNT ; ++i) {
+       for (i = 0 ; i < data->phy_cnt ; ++i) {
                if (!priv->phys[i].dev)
                        continue;
 
@@ -433,20 +466,21 @@ err_phy_init:
 static int dwc3_meson_g12a_remove(struct udevice *dev)
 {
        struct dwc3_meson_g12a *priv = dev_get_plat(dev);
+       struct dwc3_meson_g12a_drvdata *data = priv->drvdata;
        int i;
 
        reset_release_all(&priv->reset, 1);
 
        clk_release_all(&priv->clk, 1);
 
-       for (i = 0; i < PHY_COUNT; ++i) {
+       for (i = 0; i < data->phy_cnt; ++i) {
                if (!priv->phys[i].dev)
                        continue;
 
                 generic_phy_power_off(&priv->phys[i]);
        }
 
-       for (i = 0 ; i < PHY_COUNT ; ++i) {
+       for (i = 0 ; i < data->phy_cnt; ++i) {
                if (!priv->phys[i].dev)
                        continue;
 
@@ -456,11 +490,26 @@ static int dwc3_meson_g12a_remove(struct udevice *dev)
        return dm_scan_fdt_dev(dev);
 }
 
+static const struct dwc3_meson_g12a_drvdata meson_g12a_drvdata = {
+       .phy_names = dwc3_meson_g12a_phy_names,
+       .phy_cnt = ARRAY_SIZE(dwc3_meson_g12a_phy_names),
+       .clk_init = dwc3_meson_g12a_clk_init,
+};
+
+static const struct dwc3_meson_g12a_drvdata meson_a1_drvdata = {
+       .phy_names = dwc3_meson_a1_phy_names,
+       .phy_cnt = ARRAY_SIZE(dwc3_meson_a1_phy_names),
+       .clk_init = dwc3_meson_a1_clk_init,
+};
+
 static int dwc3_meson_g12a_child_pre_probe(struct udevice *dev)
 {
        if (ofnode_device_is_compatible(dev_ofnode(dev), "amlogic,meson-g12a-usb"))
                return dwc3_meson_g12a_force_mode(dev->parent, USB_DR_MODE_PERIPHERAL);
 
+       if (ofnode_device_is_compatible(dev_ofnode(dev), "amlogic,meson-a1-usb"))
+               return dwc3_meson_g12a_force_mode(dev->parent, USB_DR_MODE_PERIPHERAL);
+
        return 0;
 }
 
@@ -469,11 +518,21 @@ static int dwc3_meson_g12a_child_post_remove(struct udevice *dev)
        if (ofnode_device_is_compatible(dev_ofnode(dev), "amlogic,meson-g12a-usb"))
                return dwc3_meson_g12a_force_mode(dev->parent, USB_DR_MODE_HOST);
 
+       if (ofnode_device_is_compatible(dev_ofnode(dev), "amlogic,meson-a1-usb"))
+               return dwc3_meson_g12a_force_mode(dev->parent, USB_DR_MODE_HOST);
+
        return 0;
 }
 
 static const struct udevice_id dwc3_meson_g12a_ids[] = {
-       { .compatible = "amlogic,meson-g12a-usb-ctrl" },
+       {
+               .compatible = "amlogic,meson-g12a-usb-ctrl",
+               .data = (ulong)&meson_g12a_drvdata,
+       },
+       {
+               .compatible = "amlogic,meson-a1-usb-ctrl",
+               .data = (ulong)&meson_a1_drvdata,
+       },
        { }
 };