#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;
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;
/* 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;
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);
/* 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;
}
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;
}
{
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;
}
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");
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;