From f7aa08595db07f4c56484b3cef961553b8c09b02 Mon Sep 17 00:00:00 2001
From: John Crispin <john@phrozen.org>
Date: Thu, 24 May 2018 00:23:16 +0200
Subject: [PATCH] kernel: add reset control support to rtl8366 driver

Signed-off-by: John Crispin <john@phrozen.org>
---
 .../files/arch/mips/ath79/mach-tl-wr1043nd.c  |  4 ++--
 .../files/drivers/net/phy/rtl8366_smi.c       | 19 +++++++++++++++----
 .../files/drivers/net/phy/rtl8366_smi.h       |  6 +++++-
 .../generic/files/include/linux/rtl8366.h     |  4 +++-
 4 files changed, 25 insertions(+), 8 deletions(-)

diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr1043nd.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr1043nd.c
index 61aeb52d02..4e4b85d736 100644
--- a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr1043nd.c
+++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr1043nd.c
@@ -83,7 +83,7 @@ static struct gpio_keys_button tl_wr1043nd_gpio_keys[] __initdata = {
 	}
 };
 
-static void tl_wr1043nd_rtl8366rb_hw_reset(bool active)
+static void tl_wr1043nd_rtl8366rb_hw_reset(struct rtl8366_smi *smi, bool active)
 {
 	if (active)
 		ath79_device_reset_set(AR71XX_RESET_GE0_PHY);
@@ -110,7 +110,7 @@ static void __init tl_wr1043nd_setup(void)
 	u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00);
 	u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000);
 
-	tl_wr1043nd_rtl8366rb_hw_reset(true);
+	tl_wr1043nd_rtl8366rb_hw_reset(NULL, true);
 
 	ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0);
 	ath79_eth0_data.mii_bus_dev = &tl_wr1043nd_rtl8366rb_device.dev;
diff --git a/target/linux/generic/files/drivers/net/phy/rtl8366_smi.c b/target/linux/generic/files/drivers/net/phy/rtl8366_smi.c
index c21ad9425d..00ad68e0bc 100644
--- a/target/linux/generic/files/drivers/net/phy/rtl8366_smi.c
+++ b/target/linux/generic/files/drivers/net/phy/rtl8366_smi.c
@@ -319,9 +319,9 @@ EXPORT_SYMBOL_GPL(rtl8366_smi_rmwr);
 static int rtl8366_reset(struct rtl8366_smi *smi)
 {
 	if (smi->hw_reset) {
-		smi->hw_reset(true);
+		smi->hw_reset(smi, true);
 		msleep(RTL8366_SMI_HW_STOP_DELAY);
-		smi->hw_reset(false);
+		smi->hw_reset(smi, false);
 		msleep(RTL8366_SMI_HW_START_DELAY);
 		return 0;
 	}
@@ -1300,7 +1300,7 @@ static int __rtl8366_smi_init(struct rtl8366_smi *smi, const char *name)
 
 	/* start the switch */
 	if (smi->hw_reset) {
-		smi->hw_reset(false);
+		smi->hw_reset(smi, false);
 		msleep(RTL8366_SMI_HW_START_DELAY);
 	}
 
@@ -1315,7 +1315,7 @@ 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);
+		smi->hw_reset(smi, true);
 
 	gpio_free(smi->gpio_sck);
 	gpio_free(smi->gpio_sda);
@@ -1425,6 +1425,14 @@ void rtl8366_smi_cleanup(struct rtl8366_smi *smi)
 EXPORT_SYMBOL_GPL(rtl8366_smi_cleanup);
 
 #ifdef CONFIG_OF
+static void rtl8366_smi_reset(struct rtl8366_smi *smi, bool active)
+{
+	if (active)
+		reset_control_assert(smi->reset);
+	else
+		reset_control_deassert(smi->reset);
+}
+
 int rtl8366_smi_probe_of(struct platform_device *pdev, struct rtl8366_smi *smi)
 {
 	int sck = of_get_named_gpio(pdev->dev.of_node, "gpio-sck", 0);
@@ -1437,6 +1445,9 @@ int rtl8366_smi_probe_of(struct platform_device *pdev, struct rtl8366_smi *smi)
 
 	smi->gpio_sda = sda;
 	smi->gpio_sck = sck;
+	smi->reset = devm_reset_control_get(&pdev->dev, "switch");
+	if (!IS_ERR(smi->reset))
+		smi->hw_reset = rtl8366_smi_reset;
 
 	return 0;
 }
diff --git a/target/linux/generic/files/drivers/net/phy/rtl8366_smi.h b/target/linux/generic/files/drivers/net/phy/rtl8366_smi.h
index 4bb9e9a66e..e5f34bf9cf 100644
--- a/target/linux/generic/files/drivers/net/phy/rtl8366_smi.h
+++ b/target/linux/generic/files/drivers/net/phy/rtl8366_smi.h
@@ -14,6 +14,7 @@
 #include <linux/phy.h>
 #include <linux/switch.h>
 #include <linux/platform_device.h>
+#include <linux/reset.h>
 
 struct rtl8366_smi_ops;
 struct rtl8366_vlan_ops;
@@ -33,7 +34,7 @@ struct rtl8366_smi {
 	struct device		*parent;
 	unsigned int		gpio_sda;
 	unsigned int		gpio_sck;
-	void			(*hw_reset)(bool active);
+	void			(*hw_reset)(struct rtl8366_smi *smi, bool active);
 	unsigned int		clk_delay;	/* ns */
 	u8			cmd_read;
 	u8			cmd_write;
@@ -54,6 +55,9 @@ struct rtl8366_smi {
 	int			vlan4k_enabled;
 
 	char			buf[4096];
+
+	struct reset_control	*reset;
+
 #ifdef CONFIG_RTL8366_SMI_DEBUG_FS
 	struct dentry           *debugfs_root;
 	u16			dbg_reg;
diff --git a/target/linux/generic/files/include/linux/rtl8366.h b/target/linux/generic/files/include/linux/rtl8366.h
index 78daed2205..e3ce8f5361 100644
--- a/target/linux/generic/files/include/linux/rtl8366.h
+++ b/target/linux/generic/files/include/linux/rtl8366.h
@@ -15,6 +15,8 @@
 #define RTL8366S_DRIVER_NAME	"rtl8366s"
 #define RTL8366RB_DRIVER_NAME	"rtl8366rb"
 
+struct rtl8366_smi;
+
 enum rtl8366_type {
 	RTL8366_TYPE_UNKNOWN,
 	RTL8366_TYPE_S,
@@ -29,7 +31,7 @@ struct rtl8366_initval {
 struct rtl8366_platform_data {
 	unsigned	gpio_sda;
 	unsigned	gpio_sck;
-	void		(*hw_reset)(bool active);
+	void		(*hw_reset)(struct rtl8366_smi *smi, bool active);
 
 	unsigned	num_initvals;
 	struct rtl8366_initval *initvals;
-- 
2.30.2