diff options
Diffstat (limited to 'target')
-rw-r--r-- | target/linux/realtek/files-5.4/drivers/gpio/gpio-rtl8231.c | 64 |
1 files 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; |