--- a/arch/mips/ath79/dev-common.c +++ b/arch/mips/ath79/dev-common.c @@ -20,9 +20,37 @@ #include #include +#include #include "common.h" #include "dev-common.h" +static void ath79_enable_uart(struct platform_device* pdev) { + if (soc_is_ar71xx()) + ath79_gpio_function_enable(AR71XX_GPIO_FUNC_UART_EN); + else if (soc_is_ar724x()) + ath79_gpio_function_enable(AR724X_GPIO_FUNC_UART_EN); + else if (soc_is_ar913x()) + ath79_gpio_function_enable(AR913X_GPIO_FUNC_UART_EN); + else if (soc_is_ar933x()) + ath79_gpio_function_enable(AR933X_GPIO_FUNC_UART_EN); +} + +static void ath79_disable_uart(struct platform_device* pdev) { + if (soc_is_ar71xx()) + ath79_gpio_function_disable(AR71XX_GPIO_FUNC_UART_EN); + else if (soc_is_ar724x()) + ath79_gpio_function_disable(AR724X_GPIO_FUNC_UART_EN); + else if (soc_is_ar913x()) + ath79_gpio_function_disable(AR913X_GPIO_FUNC_UART_EN); + else if (soc_is_ar933x()) + ath79_gpio_function_disable(AR933X_GPIO_FUNC_UART_EN); +} + +static struct ath79_platform_uart_hooks platform_hooks = { + .probe = ath79_enable_uart, + .remove = ath79_disable_uart, +}; + static struct resource ath79_uart_resources[] = { { .start = AR71XX_UART_BASE, @@ -72,6 +100,9 @@ static struct platform_device ar933x_uar .id = -1, .resource = ar933x_uart_resources, .num_resources = ARRAY_SIZE(ar933x_uart_resources), + .dev = { + .platform_data = &platform_hooks + }, }; void __init ath79_register_uart(void) @@ -97,6 +128,7 @@ void __init ath79_register_uart(void) soc_is_qca955x() || soc_is_qca956x()) { ath79_uart_data[0].uartclk = uart_clk_rate; + ath79_enable_uart(&ath79_uart_device); platform_device_register(&ath79_uart_device); } else if (soc_is_ar933x()) { platform_device_register(&ar933x_uart_device); --- /dev/null +++ b/arch/mips/include/asm/mach-ath79/ath79_uart_platform.h @@ -0,0 +1,21 @@ +/* + * Platform data definition for Atheros AR71XX/AR724X/AR913X UART controller + * + * Copyright (C) 2015 Piotr Madalinski + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#ifndef _ATH79_UART_PLATFORM_H +#define _ATH79_UART_PLATFORM_H + +struct platform_device; + +struct ath79_platform_uart_hooks { + void (*probe)(struct platform_device*); + void (*remove)(struct platform_device*); +}; + +#endif /* _ATH79_UART_PLATFORM_H */ --- a/drivers/tty/serial/ar933x_uart.c +++ b/drivers/tty/serial/ar933x_uart.c @@ -31,6 +31,7 @@ #include #include +#include #define DRIVER_NAME "ar933x-uart" @@ -50,6 +51,7 @@ struct ar933x_uart_port { unsigned int min_baud; unsigned int max_baud; struct clk *clk; + struct ath79_platform_uart_hooks *platform_hooks; }; static inline bool ar933x_uart_console_enabled(void) @@ -669,6 +671,10 @@ static int ar933x_uart_probe(struct plat return PTR_ERR(up->clk); } + up->platform_hooks = dev_get_platdata(&pdev->dev); + if (up->platform_hooks && up->platform_hooks->probe) + up->platform_hooks->probe(pdev); + port = &up->port; mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -710,6 +716,7 @@ static int ar933x_uart_probe(struct plat goto err_disable_clk; platform_set_drvdata(pdev, up); + return 0; err_disable_clk: @@ -726,8 +733,9 @@ static int ar933x_uart_remove(struct pla if (up) { uart_remove_one_port(&ar933x_uart_driver, &up->port); clk_disable_unprepare(up->clk); + if (up->platform_hooks && up->platform_hooks->remove) + up->platform_hooks->remove(pdev); } - return 0; }