diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index e28e3065c99d..3e26bdf8806b 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -1390,17 +1390,12 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty dev_dbg(dev, "Reference clock set to %i Hz\n", uartclk); + /* + * Set up each port's state before registering the gpiochip, + * since the gpiochip callbacks will read s->p[i].regmap as + * soon as gpiolib exposes the controller. + */ for (i = 0; i < devtype->nr; i++) { - unsigned int line; - - line = find_first_zero_bit(max310x_lines, MAX310X_UART_NRMAX); - if (line == MAX310X_UART_NRMAX) { - ret = -ERANGE; - goto out_uart; - } - - /* Initialize port data */ - s->p[i].port.line = line; s->p[i].port.dev = dev; s->p[i].port.irq = irq; s->p[i].port.type = PORT_MAX310X; @@ -1430,20 +1425,16 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty INIT_WORK(&s->p[i].md_work, max310x_md_proc); /* Initialize queue for changing RS485 mode */ INIT_WORK(&s->p[i].rs_work, max310x_rs_proc); - - /* Register port */ - ret = uart_add_one_port(&max310x_uart, &s->p[i].port); - if (ret) - goto out_uart; - - set_bit(line, max310x_lines); - - /* Go to suspend mode */ - max310x_power(&s->p[i].port, 0); } #ifdef CONFIG_GPIOLIB - /* Setup GPIO controller */ + /* + * Register the GPIO controller before adding the UART ports so + * that consumers referencing the chip's own GPIOs from device + * tree (for example rs485-term-gpios = <&max310x ...>) can + * resolve them at uart_add_one_port() time instead of receiving + * -EPROBE_DEFER from their own provider. + */ s->gpio.owner = THIS_MODULE; s->gpio.parent = dev; s->gpio.label = devtype->name; @@ -1460,6 +1451,27 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty goto out_uart; #endif + for (i = 0; i < devtype->nr; i++) { + unsigned int line; + + line = find_first_zero_bit(max310x_lines, MAX310X_UART_NRMAX); + if (line == MAX310X_UART_NRMAX) { + ret = -ERANGE; + goto out_uart; + } + s->p[i].port.line = line; + + /* Register port */ + ret = uart_add_one_port(&max310x_uart, &s->p[i].port); + if (ret) + goto out_uart; + + set_bit(line, max310x_lines); + + /* Go to suspend mode */ + max310x_power(&s->p[i].port, 0); + } + /* Setup interrupt */ ret = devm_request_threaded_irq(dev, irq, NULL, max310x_ist, IRQF_ONESHOT | IRQF_SHARED, dev_name(dev), s);