ralink: fix mt7628 ehci support
authorJohn Crispin <john@openwrt.org>
Fri, 19 Feb 2016 16:39:12 +0000 (16:39 +0000)
committerJohn Crispin <john@openwrt.org>
Fri, 19 Feb 2016 16:39:12 +0000 (16:39 +0000)
the u2_phy init was missing

Backport of r48747

Signed-off-by: John Crispin <blogic@openwrt.org>
SVN-Revision: 48749

target/linux/ramips/dts/mt7628an.dtsi
target/linux/ramips/patches-3.18/0037-USB-phy-add-ralink-SoC-driver.patch

index bd8ccdb3e21a1aa1ac4ab2df68fe9202aa492d44..dde572bf9db973cd36dfa2d48234564d563105b7 100644 (file)
                #reset-cells = <1>;
        };
 
-       usbphy: usbphy {
+       usbphy: usbphy@10120000 {
                compatible = "ralink,mt7628an-usbphy", "ralink,mt7620a-usbphy";
+               reg = <0x10120000 1000>;
                #phy-cells = <1>;
 
-               resets = <&rstctrl 22>;
-               reset-names = "host";
+               resets = <&rstctrl 22 &rstctrl 25>;
+               reset-names = "host", "device";
        };
 
        sdhci@10130000 {
index 2448d0ab3130b4e05f5f4917a124cf7ed13cc2bd..6cbb7e3df0bce4e358b33c834c45bc58173360fa 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/phy/Kconfig
 +++ b/drivers/phy/Kconfig
-@@ -239,6 +239,11 @@ config PHY_XGENE
+@@ -239,6 +239,11 @@
        help
          This option enables support for APM X-Gene SoC multi-purpose PHY.
  
        depends on RESET_CONTROLLER
 --- a/drivers/phy/Makefile
 +++ b/drivers/phy/Makefile
-@@ -31,3 +31,4 @@ obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY) +=
+@@ -31,3 +31,4 @@
  obj-$(CONFIG_PHY_XGENE)                       += phy-xgene.o
  obj-$(CONFIG_PHY_STIH407_USB)         += phy-stih407-usb.o
  obj-$(CONFIG_PHY_STIH41X_USB)         += phy-stih41x-usb.o
 +obj-$(CONFIG_PHY_RALINK_USB)          += phy-ralink-usb.o
 --- /dev/null
 +++ b/drivers/phy/phy-ralink-usb.c
-@@ -0,0 +1,175 @@
+@@ -0,0 +1,228 @@
 +/*
 + * Allwinner ralink USB phy driver
 + *
-+ * Copyright (C) 2014 John Crispin <blogic@openwrt.org>
++ * Copyright (C) 2016 John Crispin <blogic@openwrt.org>
 + *
 + * Based on code from
 + * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
 +#define RT_SYSC_REG_CLKCFG1           0x030
 +#define RT_SYSC_REG_USB_PHY_CFG               0x05c
 +
++#define OFS_U2_PHY_AC0                  0x00
++#define OFS_U2_PHY_AC1                  0x04
++#define OFS_U2_PHY_AC2                  0x08
++#define OFS_U2_PHY_ACR0                 0x10
++#define OFS_U2_PHY_ACR1                 0x14
++#define OFS_U2_PHY_ACR2                 0x18
++#define OFS_U2_PHY_ACR3                 0x1C
++#define OFS_U2_PHY_ACR4                 0x20
++#define OFS_U2_PHY_AMON0                0x24
++#define OFS_U2_PHY_DCR0                 0x60
++#define OFS_U2_PHY_DCR1                 0x64
++#define OFS_U2_PHY_DTM0                 0x68
++#define OFS_U2_PHY_DTM1                 0x6C
++
 +#define RT_RSTCTRL_UDEV                       BIT(25)
 +#define RT_RSTCTRL_UHST                       BIT(22)
 +#define RT_SYSCFG1_USB0_HOST_MODE     BIT(10)
 +#define USB_PHY_UTMI_8B60M            BIT(1)
 +#define UDEV_WAKEUP                   BIT(0)
 +
-+static atomic_t usb_pwr_ref = ATOMIC_INIT(0);
-+static struct reset_control *rstdev;
-+static struct reset_control *rsthost;
-+static u32 phy_clk;
-+static struct phy *rt_phy;
++struct ralink_usb_phy {
++      struct reset_control    *rstdev;
++      struct reset_control    *rsthost;
++      u32                     clk;
++      struct phy              *phy;
++      void __iomem            *base;
++};
 +
-+static void usb_phy_enable(int state)
++static void u2_phy_w32(struct ralink_usb_phy *phy, u32 val, u32 reg)
 +{
-+      if (state)
-+              rt_sysc_m32(0, phy_clk, RT_SYSC_REG_CLKCFG1);
-+      else
-+              rt_sysc_m32(phy_clk, 0, RT_SYSC_REG_CLKCFG1);
-+      mdelay(100);
++      iowrite32(val, phy->base + reg);
 +}
 +
-+static int ralink_usb_phy_init(struct phy *_phy)
++static u32 u2_phy_r32(struct ralink_usb_phy *phy, u32 reg)
 +{
-+      return 0;
++      return ioread32(phy->base + reg);
 +}
 +
-+static int ralink_usb_phy_exit(struct phy *_phy)
++static void
++u2_phy_init(struct ralink_usb_phy *phy)
 +{
-+      return 0;
++      u2_phy_r32(phy, OFS_U2_PHY_AC2);
++      u2_phy_r32(phy, OFS_U2_PHY_ACR0);
++      u2_phy_r32(phy, OFS_U2_PHY_DCR0);
++
++      u2_phy_w32(phy, 0x00ffff02, OFS_U2_PHY_DCR0);
++      u2_phy_r32(phy, OFS_U2_PHY_DCR0);
++      u2_phy_w32(phy, 0x00555502, OFS_U2_PHY_DCR0);
++      u2_phy_r32(phy, OFS_U2_PHY_DCR0);
++      u2_phy_w32(phy, 0x00aaaa02, OFS_U2_PHY_DCR0);
++      u2_phy_r32(phy, OFS_U2_PHY_DCR0);
++      u2_phy_w32(phy, 0x00000402, OFS_U2_PHY_DCR0);
++      u2_phy_r32(phy, OFS_U2_PHY_DCR0);
++      u2_phy_w32(phy, 0x0048086a, OFS_U2_PHY_AC0);
++      u2_phy_w32(phy, 0x4400001c, OFS_U2_PHY_AC1);
++      u2_phy_w32(phy, 0xc0200000, OFS_U2_PHY_ACR3);
++      u2_phy_w32(phy, 0x02000000, OFS_U2_PHY_DTM0);
 +}
 +
 +static int ralink_usb_phy_power_on(struct phy *_phy)
 +{
-+      if (atomic_inc_return(&usb_pwr_ref) == 1) {
-+              int host = 1;
-+              u32 t;
-+
-+              usb_phy_enable(1);
-+
-+              if (host) {
-+                      rt_sysc_m32(0, RT_SYSCFG1_USB0_HOST_MODE, RT_SYSC_REG_SYSCFG1);
-+                      if (!IS_ERR(rsthost))
-+                              reset_control_deassert(rsthost);
-+                      if (!IS_ERR(rstdev))
-+                              reset_control_deassert(rstdev);
-+              } else {
-+                      rt_sysc_m32(RT_SYSCFG1_USB0_HOST_MODE, 0, RT_SYSC_REG_SYSCFG1);
-+                      if (!IS_ERR(rstdev))
-+                              reset_control_deassert(rstdev);
-+              }
-+              mdelay(100);
-+
-+              t = rt_sysc_r32(RT_SYSC_REG_USB_PHY_CFG);
-+              dev_info(&_phy->dev, "remote usb device wakeup %s\n",
-+                      (t & UDEV_WAKEUP) ? ("enabbled") : ("disabled"));
-+              if (t & USB_PHY_UTMI_8B60M)
-+                      dev_info(&_phy->dev, "UTMI 8bit 60MHz\n");
-+              else
-+                      dev_info(&_phy->dev, "UTMI 16bit 30MHz\n");
-+      }
++      struct ralink_usb_phy *phy = phy_get_drvdata(_phy);
++      u32 t;
++
++      /* enable the phy */
++      rt_sysc_m32(0, phy->clk, RT_SYSC_REG_CLKCFG1);
++
++      /* setup host mode */
++      rt_sysc_m32(0, RT_SYSCFG1_USB0_HOST_MODE, RT_SYSC_REG_SYSCFG1);
++
++      /* deassert the reset lines */
++      reset_control_deassert(phy->rsthost);
++      reset_control_deassert(phy->rstdev);
++
++      /*
++       * The SDK kernel had a delay of 100ms. however on device
++       * testing showed that 10ms is enough
++       */
++      mdelay(10);
++
++      if (!IS_ERR(phy->base))
++              u2_phy_init(phy);
++
++      /* print some status info */
++      t = rt_sysc_r32(RT_SYSC_REG_USB_PHY_CFG);
++      dev_info(&phy->phy->dev, "remote usb device wakeup %s\n",
++              (t & UDEV_WAKEUP) ? ("enabled") : ("disabled"));
++      if (t & USB_PHY_UTMI_8B60M)
++              dev_info(&phy->phy->dev, "UTMI 8bit 60MHz\n");
++      else
++              dev_info(&phy->phy->dev, "UTMI 16bit 30MHz\n");
 +
 +      return 0;
 +}
 +
 +static int ralink_usb_phy_power_off(struct phy *_phy)
 +{
-+      if (atomic_dec_return(&usb_pwr_ref) == 0) {
-+              usb_phy_enable(0);
-+              if (!IS_ERR(rstdev))
-+                      reset_control_assert(rstdev);
-+              if (!IS_ERR(rsthost))
-+                      reset_control_assert(rsthost);
-+      }
++      struct ralink_usb_phy *phy = phy_get_drvdata(_phy);
++
++      /* assert the reset lines */
++      reset_control_assert(phy->rstdev);
++      reset_control_assert(phy->rsthost);
++
++      /* disable the phy */
++      rt_sysc_m32(phy->clk, 0, RT_SYSC_REG_CLKCFG1);
 +
 +      return 0;
 +}
 +
 +static struct phy_ops ralink_usb_phy_ops = {
-+      .init           = ralink_usb_phy_init,
-+      .exit           = ralink_usb_phy_exit,
 +      .power_on       = ralink_usb_phy_power_on,
 +      .power_off      = ralink_usb_phy_power_off,
 +      .owner          = THIS_MODULE,
 +};
 +
-+static struct phy *ralink_usb_phy_xlate(struct device *dev,
-+                                      struct of_phandle_args *args)
-+{
-+      return rt_phy;
-+}
-+
 +static const struct of_device_id ralink_usb_phy_of_match[] = {
-+      { .compatible = "ralink,rt3xxx-usbphy", .data = (void *) (RT_CLKCFG1_UPHY1_CLK_EN | RT_CLKCFG1_UPHY0_CLK_EN) },
-+      { .compatible = "ralink,mt7620a-usbphy", .data = (void *) (MT7620_CLKCFG1_UPHY1_CLK_EN | MT7620_CLKCFG1_UPHY0_CLK_EN) },
++      {
++              .compatible = "ralink,rt3xxx-usbphy",
++              .data = (void *) (RT_CLKCFG1_UPHY1_CLK_EN |
++                                RT_CLKCFG1_UPHY0_CLK_EN)
++      },
++      {
++              .compatible = "ralink,mt7620a-usbphy",
++              .data = (void *) (MT7620_CLKCFG1_UPHY1_CLK_EN |
++                                MT7620_CLKCFG1_UPHY0_CLK_EN) },
 +      { },
 +};
 +MODULE_DEVICE_TABLE(of, ralink_usb_phy_of_match);
 +
 +static int ralink_usb_phy_probe(struct platform_device *pdev)
 +{
++      struct resource *res;
 +      struct device *dev = &pdev->dev;
 +      struct phy_provider *phy_provider;
 +      const struct of_device_id *match;
++      struct ralink_usb_phy *phy;
++
++      phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
++      if (!phy)
++              return -ENOMEM;
 +
 +      match = of_match_device(ralink_usb_phy_of_match, &pdev->dev);
-+      phy_clk = (int) match->data;
++      if (!match)
++              return -ENODEV;
++
++      phy->clk = (int) match->data;
 +
-+      rsthost = devm_reset_control_get(&pdev->dev, "host");
-+      rstdev = devm_reset_control_get(&pdev->dev, "device");
++      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      phy->base = devm_ioremap_resource(&pdev->dev, res);
++
++      phy->rsthost = devm_reset_control_get(&pdev->dev, "host");
++      if (IS_ERR(phy->rsthost)) {
++              dev_err(dev, "host reset is missing\n");
++              return PTR_ERR(phy->rsthost);
++      }
++
++      phy->rstdev = devm_reset_control_get(&pdev->dev, "device");
++      if (IS_ERR(phy->rstdev)) {
++              dev_err(dev, "device reset is missing\n");
++              return PTR_ERR(phy->rstdev);
++      }
 +
-+      rt_phy = devm_phy_create(dev, NULL, &ralink_usb_phy_ops, NULL);
-+      if (IS_ERR(rt_phy)) {
++      phy->phy = devm_phy_create(dev, NULL, &ralink_usb_phy_ops, NULL);
++      if (IS_ERR(phy->phy)) {
 +              dev_err(dev, "failed to create PHY\n");
-+              return PTR_ERR(rt_phy);
++              return PTR_ERR(phy->phy);
 +      }
++      phy_set_drvdata(phy->phy, phy);
 +
-+      phy_provider = devm_of_phy_provider_register(dev, ralink_usb_phy_xlate);
++      phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
 +
 +      return PTR_ERR_OR_ZERO(phy_provider);
 +}