generic: rtl8366_smi: increase delay after switch hw reset
[openwrt/staging/chunkeey.git] / target / linux / generic / files / drivers / net / phy / rtl8366_smi.c
index e48ca99ce84dd27b1f8e5d3362237e6562894486..be85274e783a001128e7e8eed4403ede622e470b 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/skbuff.h>
 #include <linux/rtl8366.h>
 
-#ifdef CONFIG_RTL8366S_PHY_DEBUG_FS
+#ifdef CONFIG_RTL8366_SMI_DEBUG_FS
 #include <linux/debugfs.h>
 #endif
 
@@ -25,6 +25,9 @@
 
 #define RTL8366_SMI_ACK_RETRY_COUNT         5
 
+#define RTL8366_SMI_HW_STOP_DELAY              25      /* msecs */
+#define RTL8366_SMI_HW_START_DELAY             100     /* msecs */
+
 static inline void rtl8366_smi_clk_delay(struct rtl8366_smi *smi)
 {
        ndelay(smi->clk_delay);
@@ -308,6 +311,19 @@ int rtl8366_smi_rmwr(struct rtl8366_smi *smi, u32 addr, u32 mask, u32 data)
 }
 EXPORT_SYMBOL_GPL(rtl8366_smi_rmwr);
 
+static int rtl8366_reset(struct rtl8366_smi *smi)
+{
+       if (smi->hw_reset) {
+               smi->hw_reset(true);
+               msleep(RTL8366_SMI_HW_STOP_DELAY);
+               smi->hw_reset(false);
+               msleep(RTL8366_SMI_HW_START_DELAY);
+               return 0;
+       }
+
+       return smi->ops->reset_chip(smi);
+}
+
 static int rtl8366_mc_is_used(struct rtl8366_smi *smi, int mc_index, int *used)
 {
        int err;
@@ -579,7 +595,7 @@ static int rtl8366_init_vlan(struct rtl8366_smi *smi)
        return rtl8366_enable_vlan(smi, 1);
 }
 
-#ifdef CONFIG_RTL8366S_PHY_DEBUG_FS
+#ifdef CONFIG_RTL8366_SMI_DEBUG_FS
 int rtl8366_debugfs_open(struct inode *inode, struct file *file)
 {
        file->private_data = inode->i_private;
@@ -890,7 +906,7 @@ static void rtl8366_debugfs_remove(struct rtl8366_smi *smi)
 #else
 static inline void rtl8366_debugfs_init(struct rtl8366_smi *smi) {}
 static inline void rtl8366_debugfs_remove(struct rtl8366_smi *smi) {}
-#endif /* CONFIG_RTL8366S_PHY_DEBUG_FS */
+#endif /* CONFIG_RTL8366_SMI_DEBUG_FS */
 
 static int rtl8366_smi_mii_init(struct rtl8366_smi *smi)
 {
@@ -933,6 +949,31 @@ static void rtl8366_smi_mii_cleanup(struct rtl8366_smi *smi)
        mdiobus_free(smi->mii_bus);
 }
 
+int rtl8366_sw_reset_switch(struct switch_dev *dev)
+{
+       struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev);
+       int err;
+
+       err = rtl8366_reset(smi);
+       if (err)
+               return err;
+
+       err = smi->ops->setup(smi);
+       if (err)
+               return err;
+
+       err = rtl8366_reset_vlan(smi);
+       if (err)
+               return err;
+
+       err = rtl8366_enable_vlan(smi, 1);
+       if (err)
+               return err;
+
+       return rtl8366_enable_all_ports(smi, 1);
+}
+EXPORT_SYMBOL_GPL(rtl8366_sw_reset_switch);
+
 int rtl8366_sw_get_port_pvid(struct switch_dev *dev, int port, int *val)
 {
        struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev);
@@ -1202,6 +1243,13 @@ static int __rtl8366_smi_init(struct rtl8366_smi *smi, const char *name)
        }
 
        spin_lock_init(&smi->lock);
+
+       /* start the switch */
+       if (smi->hw_reset) {
+               smi->hw_reset(false);
+               msleep(RTL8366_SMI_HW_START_DELAY);
+       }
+
        return 0;
 
  err_free_sda:
@@ -1212,6 +1260,9 @@ static int __rtl8366_smi_init(struct rtl8366_smi *smi, const char *name)
 
 static void __rtl8366_smi_cleanup(struct rtl8366_smi *smi)
 {
+       if (smi->hw_reset)
+               smi->hw_reset(true);
+
        gpio_free(smi->gpio_sck);
        gpio_free(smi->gpio_sda);
 }
@@ -1266,8 +1317,6 @@ int rtl8366_smi_init(struct rtl8366_smi *smi)
        if (err)
                goto err_out;
 
-       spin_lock_init(&smi->lock);
-
        dev_info(smi->parent, "using GPIO pins %u (SDA) and %u (SCK)\n",
                 smi->gpio_sda, smi->gpio_sck);
 
@@ -1277,6 +1326,10 @@ int rtl8366_smi_init(struct rtl8366_smi *smi)
                goto err_free_sck;
        }
 
+       err = rtl8366_reset(smi);
+       if (err)
+               goto err_free_sck;
+
        err = smi->ops->setup(smi);
        if (err) {
                dev_err(smi->parent, "chip setup failed, err=%d\n", err);
@@ -1313,8 +1366,7 @@ void rtl8366_smi_cleanup(struct rtl8366_smi *smi)
 {
        rtl8366_debugfs_remove(smi);
        rtl8366_smi_mii_cleanup(smi);
-       gpio_free(smi->gpio_sck);
-       gpio_free(smi->gpio_sda);
+       __rtl8366_smi_cleanup(smi);
 }
 EXPORT_SYMBOL_GPL(rtl8366_smi_cleanup);