ramips: ethernet: ralink: use the reset controller api for esw & ephy
[openwrt/staging/dedeckeh.git] / target / linux / ramips / files / drivers / net / ethernet / ralink / esw_rt3050.c
index 292f11a1700e03862e35a772a64e4f56da818b59..cd6ae075950e71ffe8b0f5287124eb09f5ac741f 100644 (file)
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <asm/mach-ralink/ralink_regs.h>
+#include <linux/of_device.h>
 #include <linux/of_irq.h>
 
 #include <linux/switch.h>
+#include <linux/reset.h>
 
 #include "mtk_eth_soc.h"
 
 
 #define RT5350_ESW_REG_PXTPC(_x)       (0x150 + (4 * _x))
 #define RT5350_EWS_REG_LED_POLARITY    0x168
-#define RT5350_RESET_EPHY              BIT(24)
 
 enum {
        /* Global attributes. */
@@ -232,6 +233,8 @@ struct rt305x_esw {
        int                     led_frequency;
        struct esw_vlan vlans[RT305X_ESW_NUM_VLANS];
        struct esw_port ports[RT305X_ESW_NUM_PORTS];
+       struct reset_control    *rst_esw;
+       struct reset_control    *rst_ephy;
 
 };
 
@@ -254,6 +257,29 @@ static inline void esw_rmw_raw(struct rt305x_esw *esw, unsigned reg,
        __raw_writel(t | val, esw->base + reg);
 }
 
+static void esw_reset(struct rt305x_esw *esw)
+{
+       if (!esw->rst_esw)
+               return;
+
+       reset_control_assert(esw->rst_esw);
+       usleep_range(60, 120);
+       reset_control_deassert(esw->rst_esw);
+       /* the esw takes long to reset otherwise the board hang */
+       msleep(10);
+}
+
+static void esw_reset_ephy(struct rt305x_esw *esw)
+{
+       if (!esw->rst_ephy)
+               return;
+
+       reset_control_assert(esw->rst_ephy);
+       usleep_range(60, 120);
+       reset_control_deassert(esw->rst_ephy);
+       usleep_range(60, 120);
+}
+
 static void esw_rmw(struct rt305x_esw *esw, unsigned reg,
                    unsigned long mask, unsigned long val)
 {
@@ -505,8 +531,7 @@ static void esw_hw_init(struct rt305x_esw *esw)
                esw->ports[i].disable = (port_disable & (1 << i)) != 0;
 
        if (ralink_soc == RT305X_SOC_RT3352) {
-               /* reset EPHY */
-               fe_reset(RT5350_RESET_EPHY);
+               esw_reset_ephy(esw);
 
                rt305x_mii_write(esw, 0, 31, 0x8000);
                for (i = 0; i < 5; i++) {
@@ -556,8 +581,7 @@ static void esw_hw_init(struct rt305x_esw *esw)
                /* select local register */
                rt305x_mii_write(esw, 0, 31, 0x8000);
        } else if (ralink_soc == RT305X_SOC_RT5350) {
-               /* reset EPHY */
-               fe_reset(RT5350_RESET_EPHY);
+               esw_reset_ephy(esw);
 
                /* set the led polarity */
                esw_w32(esw, esw->reg_led_polarity & 0x1F,
@@ -614,8 +638,7 @@ static void esw_hw_init(struct rt305x_esw *esw)
        } else if (ralink_soc == MT762X_SOC_MT7628AN || ralink_soc == MT762X_SOC_MT7688) {
                int i;
 
-               /* reset EPHY */
-               fe_reset(RT5350_RESET_EPHY);
+               esw_reset_ephy(esw);
 
                /* set the led polarity */
                esw_w32(esw, esw->reg_led_polarity & 0x1F,
@@ -1385,6 +1408,13 @@ static int esw_probe(struct platform_device *pdev)
        if (reg_init)
                esw->reg_led_polarity = be32_to_cpu(*reg_init);
 
+       esw->rst_esw = devm_reset_control_get(&pdev->dev, "esw");
+       if (IS_ERR(esw->rst_esw))
+               esw->rst_esw = NULL;
+       esw->rst_ephy = devm_reset_control_get(&pdev->dev, "ephy");
+       if (IS_ERR(esw->rst_ephy))
+               esw->rst_ephy = NULL;
+
        swdev = &esw->swdev;
        swdev->of_node = pdev->dev.of_node;
        swdev->name = "rt305x-esw";