[openwrt/openwrt] realtek: fix RTL8231 gpio expander usage with RTL839X SoC

LEDE Commits lede-commits at lists.infradead.org
Tue Jan 26 09:07:18 EST 2021


ynezz pushed a commit to openwrt/openwrt.git, branch master:
https://git.openwrt.org/e1bca7c77d80b3f35f5045cd8983349819165f1e

commit e1bca7c77d80b3f35f5045cd8983349819165f1e
Author: Birger Koblitz <git at birger-koblitz.de>
AuthorDate: Thu Jan 21 15:09:47 2021 +0100

    realtek: fix RTL8231 gpio expander usage with RTL839X SoC
    
    This fixes the usage of the RTL8231 GPIO extender chip
    when used with the RTL839X SoCs. Specifically,
    the PHY addresses may be different from 0.
    
    Signed-off-by: Birger Koblitz <git at birger-koblitz.de>
---
 .../realtek/files-5.4/drivers/gpio/gpio-rtl8231.c  | 64 ++++++++++++++--------
 1 file changed, 40 insertions(+), 24 deletions(-)

diff --git a/target/linux/realtek/files-5.4/drivers/gpio/gpio-rtl8231.c b/target/linux/realtek/files-5.4/drivers/gpio/gpio-rtl8231.c
index be5efc2997..031f60f530 100644
--- a/target/linux/realtek/files-5.4/drivers/gpio/gpio-rtl8231.c
+++ b/target/linux/realtek/files-5.4/drivers/gpio/gpio-rtl8231.c
@@ -12,6 +12,8 @@
 #define RTL8231_GPIO_DIR(gpio)			((0x0005) + ((gpio) >> 4))
 #define RTL8231_GPIO_DATA(gpio)			((0x001C) + ((gpio) >> 4))
 
+#define USEC_TIMEOUT 5000
+
 struct rtl8231_gpios {
 	struct gpio_chip gc;
 	struct device *dev;
@@ -27,7 +29,7 @@ extern struct rtl83xx_soc_info soc_info;
 
 static u32 rtl8231_read(struct rtl8231_gpios *gpios, u32 reg)
 {
-	u32 t = 0;
+	u32 t = 0, n = 0;
 	u8 bus_id = gpios->smi_bus_id;
 
 	reg &= 0x1f;
@@ -38,10 +40,18 @@ static u32 rtl8231_read(struct rtl8231_gpios *gpios, u32 reg)
 
 	/* Set execution bit: cleared when operation completed */
 	t |= 1;
+
+	// Start execution
 	sw_w32(t, gpios->ext_gpio_indrt_access);
-	do {	/* TODO: Return 0x80000000 if timeout */
+	do {
+		udelay(1);
 		t = sw_r32(gpios->ext_gpio_indrt_access);
-	} while (t & 1);
+		n++;
+	} while ((t & 1) && (n < USEC_TIMEOUT));
+
+	if (n >= USEC_TIMEOUT)
+		return 0x80000000;
+	
 	pr_debug("%s: %x, %x, %x\n", __func__, bus_id, reg, (t & 0xffff0000) >> 16);
 
 	return (t & 0xffff0000) >> 16;
@@ -49,7 +59,7 @@ static u32 rtl8231_read(struct rtl8231_gpios *gpios, u32 reg)
 
 static int rtl8231_write(struct rtl8231_gpios *gpios, u32 reg, u32 data)
 {
-	u32 t = 0;
+	u32 t = 0, n = 0;
 	u8 bus_id = gpios->smi_bus_id;
 
 	pr_debug("%s: %x, %x, %x\n", __func__, bus_id, reg, data);
@@ -62,10 +72,16 @@ static int rtl8231_write(struct rtl8231_gpios *gpios, u32 reg, u32 data)
 
 	/* Set execution bit: cleared when operation completed */
 	t |= 1;
+
+	// Start execution
 	sw_w32(t, gpios->ext_gpio_indrt_access);
-	do {	/* TODO: Return -1 if timeout */
+	do {
+		udelay(1);
 		t = sw_r32(gpios->ext_gpio_indrt_access);
-	} while (t & 1);
+	} while ((t & 1) && (n < USEC_TIMEOUT));
+
+	if (n >= USEC_TIMEOUT)
+		return -1;
 
 	return 0;
 }
@@ -94,7 +110,7 @@ static int rtl8231_pin_dir(struct rtl8231_gpios *gpios, u32 gpio, u32 dir)
 	int dpin = pin;
 
 	if (gpio > 31) {
-		pr_info("WARNING: HIGH pin\n");
+		pr_debug("WARNING: HIGH pin\n");
 		dpin = pin << 5;
 		pin_dir_addr = pin_sel_addr;
 	}
@@ -226,26 +242,21 @@ int rtl8231_init(struct rtl8231_gpios *gpios)
 {
 	pr_info("%s called, MDIO bus ID: %d\n", __func__, gpios->smi_bus_id);
 
+	gpios->reg_cached = 0;
+
 	if (soc_info.family == RTL8390_FAMILY_ID) {
+		// RTL8390: Enable external gpio in global led control register
 		sw_w32_mask(0x7 << 18, 0x4 << 18, RTL839X_LED_GLB_CTRL);
-		return 0;
+	} else if (soc_info.family == RTL8380_FAMILY_ID) {
+		// RTL8380: Enable RTL8231 indirect access mode
+		sw_w32_mask(0, 1, RTL838X_EXTRA_GPIO_CTRL);
+		sw_w32_mask(3, 1, RTL838X_DMY_REG5);
 	}
 
-	/* Enable RTL8231 indirect access mode */
-	sw_w32_mask(0, 1, RTL838X_EXTRA_GPIO_CTRL);
-	sw_w32_mask(3, 1, RTL838X_DMY_REG5);
-
-	/* Enable RTL8231 via GPIO_A1 line
-	rtl838x_w32_mask(0, 1 << RTL838X_GPIO_A1, RTL838X_GPIO_PABC_DIR);
-	rtl838x_w32_mask(0, 1 << RTL838X_GPIO_A1, RTL838X_GPIO_PABC_DATA); */
-	mdelay(50); /* wait 50ms for reset */
-
 	/*Select GPIO functionality for pins 0-15, 16-31 and 32-37 */
 	rtl8231_write(gpios, RTL8231_GPIO_PIN_SEL(0), 0xffff);
 	rtl8231_write(gpios, RTL8231_GPIO_PIN_SEL(16), 0xffff);
 
-	gpios->reg_cached = 0;
-
 	return 0;
 }
 
@@ -262,7 +273,7 @@ static int rtl8231_gpio_probe(struct platform_device *pdev)
 	struct device_node *np = dev->of_node;
 	struct rtl8231_gpios *gpios;
 	int err;
-	u8 indirect_bus_id;
+	u32 indirect_bus_id;
 
 	pr_info("Probing RTL8231 GPIOs\n");
 
@@ -284,10 +295,15 @@ static int rtl8231_gpio_probe(struct platform_device *pdev)
 		gpios->ext_gpio_indrt_access = RTL839X_EXT_GPIO_INDRT_ACCESS;
 	}
 
-	if (!of_property_read_u8(np, "indirect-access-bus-id", &indirect_bus_id)) {
-		gpios->smi_bus_id = indirect_bus_id;
-		rtl8231_init(gpios);
-	}
+	/*
+	 * We use a default MDIO bus ID for the 8231 of 0, which can be overriden
+	 * by the indirect-access-bus-id property in the dts.
+	 */
+	gpios->smi_bus_id = 0;
+	of_property_read_u32(np, "indirect-access-bus-id", &indirect_bus_id);
+	gpios->smi_bus_id = indirect_bus_id;
+
+	rtl8231_init(gpios);
 
 	gpios->dev = dev;
 	gpios->gc.base = 160;



More information about the lede-commits mailing list