serial: Allow uart_get_rs485_mode() to return errno
We're about to amend uart_get_rs485_mode() to support a GPIO pin for rs485 bus termination. Retrieving the GPIO descriptor may fail, so allow uart_get_rs485_mode() to return an errno and change all callers to check for failure. The GPIO descriptor is going to be stored in struct uart_port. Pass that struct to uart_get_rs485_mode() in lieu of a struct device and struct serial_rs485, both of which are directly accessible from struct uart_port. A few drivers call uart_get_rs485_mode() before setting the struct device pointer in struct uart_port. Shuffle those calls around where necessary. [Heiko Stuebner did the ar933x_uart.c portion, hence his Signed-off-by.] Signed-off-by: Heiko Stuebner <heiko@sntech.de> Signed-off-by: Lukas Wunner <lukas@wunner.de> Link: https://lore.kernel.org/r/271e814af4b0db3bffbbb74abf2b46b75add4516.1589285873.git.lukas@wunner.de Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
		
							parent
							
								
									e0a851fe6b
								
							
						
					
					
						commit
						c150c0f362
					
				| @ -1026,7 +1026,9 @@ int serial8250_register_8250_port(struct uart_8250_port *up) | |||||||
| 
 | 
 | ||||||
| 		if (up->port.dev) { | 		if (up->port.dev) { | ||||||
| 			uart->port.dev = up->port.dev; | 			uart->port.dev = up->port.dev; | ||||||
| 			uart_get_rs485_mode(uart->port.dev, &uart->port.rs485); | 			ret = uart_get_rs485_mode(&uart->port); | ||||||
|  | 			if (ret) | ||||||
|  | 				goto err; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (up->port.flags & UPF_FIXED_TYPE) | 		if (up->port.flags & UPF_FIXED_TYPE) | ||||||
|  | |||||||
| @ -766,8 +766,6 @@ static int ar933x_uart_probe(struct platform_device *pdev) | |||||||
| 		goto err_disable_clk; | 		goto err_disable_clk; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	uart_get_rs485_mode(&pdev->dev, &port->rs485); |  | ||||||
| 
 |  | ||||||
| 	port->mapbase = mem_res->start; | 	port->mapbase = mem_res->start; | ||||||
| 	port->line = id; | 	port->line = id; | ||||||
| 	port->irq = irq_res->start; | 	port->irq = irq_res->start; | ||||||
| @ -786,6 +784,10 @@ static int ar933x_uart_probe(struct platform_device *pdev) | |||||||
| 	baud = ar933x_uart_get_baud(port->uartclk, 0, AR933X_UART_MAX_STEP); | 	baud = ar933x_uart_get_baud(port->uartclk, 0, AR933X_UART_MAX_STEP); | ||||||
| 	up->max_baud = min_t(unsigned int, baud, AR933X_UART_MAX_BAUD); | 	up->max_baud = min_t(unsigned int, baud, AR933X_UART_MAX_BAUD); | ||||||
| 
 | 
 | ||||||
|  | 	ret = uart_get_rs485_mode(port); | ||||||
|  | 	if (ret) | ||||||
|  | 		goto err_disable_clk; | ||||||
|  | 
 | ||||||
| 	up->gpios = mctrl_gpio_init(port, 0); | 	up->gpios = mctrl_gpio_init(port, 0); | ||||||
| 	if (IS_ERR(up->gpios) && PTR_ERR(up->gpios) != -ENOSYS) | 	if (IS_ERR(up->gpios) && PTR_ERR(up->gpios) != -ENOSYS) | ||||||
| 		return PTR_ERR(up->gpios); | 		return PTR_ERR(up->gpios); | ||||||
|  | |||||||
| @ -2491,8 +2491,6 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port, | |||||||
| 	atmel_init_property(atmel_port, pdev); | 	atmel_init_property(atmel_port, pdev); | ||||||
| 	atmel_set_ops(port); | 	atmel_set_ops(port); | ||||||
| 
 | 
 | ||||||
| 	uart_get_rs485_mode(&mpdev->dev, &port->rs485); |  | ||||||
| 
 |  | ||||||
| 	port->iotype		= UPIO_MEM; | 	port->iotype		= UPIO_MEM; | ||||||
| 	port->flags		= UPF_BOOT_AUTOCONF | UPF_IOREMAP; | 	port->flags		= UPF_BOOT_AUTOCONF | UPF_IOREMAP; | ||||||
| 	port->ops		= &atmel_pops; | 	port->ops		= &atmel_pops; | ||||||
| @ -2506,6 +2504,10 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port, | |||||||
| 
 | 
 | ||||||
| 	memset(&atmel_port->rx_ring, 0, sizeof(atmel_port->rx_ring)); | 	memset(&atmel_port->rx_ring, 0, sizeof(atmel_port->rx_ring)); | ||||||
| 
 | 
 | ||||||
|  | 	ret = uart_get_rs485_mode(port); | ||||||
|  | 	if (ret) | ||||||
|  | 		return ret; | ||||||
|  | 
 | ||||||
| 	/* for console, the clock could already be configured */ | 	/* for console, the clock could already be configured */ | ||||||
| 	if (!atmel_port->clk) { | 	if (!atmel_port->clk) { | ||||||
| 		atmel_port->clk = clk_get(&mpdev->dev, "usart"); | 		atmel_port->clk = clk_get(&mpdev->dev, "usart"); | ||||||
|  | |||||||
| @ -2619,7 +2619,9 @@ static int lpuart_probe(struct platform_device *pdev) | |||||||
| 	if (ret) | 	if (ret) | ||||||
| 		goto failed_attach_port; | 		goto failed_attach_port; | ||||||
| 
 | 
 | ||||||
| 	uart_get_rs485_mode(&pdev->dev, &sport->port.rs485); | 	ret = uart_get_rs485_mode(&sport->port); | ||||||
|  | 	if (ret) | ||||||
|  | 		goto failed_get_rs485; | ||||||
| 
 | 
 | ||||||
| 	if (sport->port.rs485.flags & SER_RS485_RX_DURING_TX) | 	if (sport->port.rs485.flags & SER_RS485_RX_DURING_TX) | ||||||
| 		dev_err(&pdev->dev, "driver doesn't support RX during TX\n"); | 		dev_err(&pdev->dev, "driver doesn't support RX during TX\n"); | ||||||
| @ -2632,6 +2634,7 @@ static int lpuart_probe(struct platform_device *pdev) | |||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| 
 | 
 | ||||||
|  | failed_get_rs485: | ||||||
| failed_attach_port: | failed_attach_port: | ||||||
| failed_irq_request: | failed_irq_request: | ||||||
| 	lpuart_disable_clks(sport); | 	lpuart_disable_clks(sport); | ||||||
|  | |||||||
| @ -2304,7 +2304,11 @@ static int imx_uart_probe(struct platform_device *pdev) | |||||||
| 	sport->ucr4 = readl(sport->port.membase + UCR4); | 	sport->ucr4 = readl(sport->port.membase + UCR4); | ||||||
| 	sport->ufcr = readl(sport->port.membase + UFCR); | 	sport->ufcr = readl(sport->port.membase + UFCR); | ||||||
| 
 | 
 | ||||||
| 	uart_get_rs485_mode(&pdev->dev, &sport->port.rs485); | 	ret = uart_get_rs485_mode(&sport->port); | ||||||
|  | 	if (ret) { | ||||||
|  | 		clk_disable_unprepare(sport->clk_ipg); | ||||||
|  | 		return ret; | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	if (sport->port.rs485.flags & SER_RS485_ENABLED && | 	if (sport->port.rs485.flags & SER_RS485_ENABLED && | ||||||
| 	    (!sport->have_rtscts && !sport->have_rtsgpio)) | 	    (!sport->have_rtscts && !sport->have_rtsgpio)) | ||||||
|  | |||||||
| @ -1608,7 +1608,9 @@ static int serial_omap_probe_rs485(struct uart_omap_port *up, | |||||||
| 	if (!np) | 	if (!np) | ||||||
| 		return 0; | 		return 0; | ||||||
| 
 | 
 | ||||||
| 	uart_get_rs485_mode(up->dev, rs485conf); | 	ret = uart_get_rs485_mode(&up->port); | ||||||
|  | 	if (ret) | ||||||
|  | 		return ret; | ||||||
| 
 | 
 | ||||||
| 	if (of_property_read_bool(np, "rs485-rts-active-high")) { | 	if (of_property_read_bool(np, "rs485-rts-active-high")) { | ||||||
| 		rs485conf->flags |= SER_RS485_RTS_ON_SEND; | 		rs485conf->flags |= SER_RS485_RTS_ON_SEND; | ||||||
|  | |||||||
| @ -3295,8 +3295,10 @@ EXPORT_SYMBOL(uart_remove_one_port); | |||||||
|  * This function implements the device tree binding described in |  * This function implements the device tree binding described in | ||||||
|  * Documentation/devicetree/bindings/serial/rs485.txt. |  * Documentation/devicetree/bindings/serial/rs485.txt. | ||||||
|  */ |  */ | ||||||
| void uart_get_rs485_mode(struct device *dev, struct serial_rs485 *rs485conf) | int uart_get_rs485_mode(struct uart_port *port) | ||||||
| { | { | ||||||
|  | 	struct serial_rs485 *rs485conf = &port->rs485; | ||||||
|  | 	struct device *dev = port->dev; | ||||||
| 	u32 rs485_delay[2]; | 	u32 rs485_delay[2]; | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| @ -3328,6 +3330,8 @@ void uart_get_rs485_mode(struct device *dev, struct serial_rs485 *rs485conf) | |||||||
| 		rs485conf->flags &= ~SER_RS485_RTS_ON_SEND; | 		rs485conf->flags &= ~SER_RS485_RTS_ON_SEND; | ||||||
| 		rs485conf->flags |= SER_RS485_RTS_AFTER_SEND; | 		rs485conf->flags |= SER_RS485_RTS_AFTER_SEND; | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
| } | } | ||||||
| EXPORT_SYMBOL_GPL(uart_get_rs485_mode); | EXPORT_SYMBOL_GPL(uart_get_rs485_mode); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -159,9 +159,7 @@ static int stm32_init_rs485(struct uart_port *port, | |||||||
| 	if (!pdev->dev.of_node) | 	if (!pdev->dev.of_node) | ||||||
| 		return -ENODEV; | 		return -ENODEV; | ||||||
| 
 | 
 | ||||||
| 	uart_get_rs485_mode(&pdev->dev, rs485conf); | 	return uart_get_rs485_mode(port); | ||||||
| 
 |  | ||||||
| 	return 0; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int stm32_pending_rx(struct uart_port *port, u32 *sr, int *last_res, | static int stm32_pending_rx(struct uart_port *port, u32 *sr, int *last_res, | ||||||
| @ -959,7 +957,9 @@ static int stm32_init_port(struct stm32_port *stm32port, | |||||||
| 
 | 
 | ||||||
| 	port->rs485_config = stm32_config_rs485; | 	port->rs485_config = stm32_config_rs485; | ||||||
| 
 | 
 | ||||||
| 	stm32_init_rs485(port, pdev); | 	ret = stm32_init_rs485(port, pdev); | ||||||
|  | 	if (ret) | ||||||
|  | 		return ret; | ||||||
| 
 | 
 | ||||||
| 	if (stm32port->info->cfg.has_wakeup) { | 	if (stm32port->info->cfg.has_wakeup) { | ||||||
| 		stm32port->wakeirq = platform_get_irq(pdev, 1); | 		stm32port->wakeirq = platform_get_irq(pdev, 1); | ||||||
|  | |||||||
| @ -472,5 +472,5 @@ extern int uart_handle_break(struct uart_port *port); | |||||||
| 					 (cflag) & CRTSCTS || \ | 					 (cflag) & CRTSCTS || \ | ||||||
| 					 !((cflag) & CLOCAL)) | 					 !((cflag) & CLOCAL)) | ||||||
| 
 | 
 | ||||||
| void uart_get_rs485_mode(struct device *dev, struct serial_rs485 *rs485conf); | int uart_get_rs485_mode(struct uart_port *port); | ||||||
| #endif /* LINUX_SERIAL_CORE_H */ | #endif /* LINUX_SERIAL_CORE_H */ | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user