#include <linux/slab.h>
#include <linux/io.h>
#include <linux/irq.h>
+#include <linux/clk.h>
#include <asm/div64.h>
#include <asm/mach-ath79/ar933x_uart.h>
-#include <asm/mach-ath79/ar933x_uart_platform.h>
#define DRIVER_NAME "ar933x-uart"
unsigned int ier; /* shadow Interrupt Enable Register */
unsigned int min_baud;
unsigned int max_baud;
+ struct clk *clk;
};
static inline unsigned int ar933x_uart_read(struct ar933x_uart_port *up,
static int ar933x_uart_probe(struct platform_device *pdev)
{
- struct ar933x_uart_platform_data *pdata;
struct ar933x_uart_port *up;
struct uart_port *port;
struct resource *mem_res;
int id;
int ret;
- pdata = dev_get_platdata(&pdev->dev);
- if (!pdata)
- return -EINVAL;
-
id = pdev->id;
if (id == -1)
id = 0;
if (!up)
return -ENOMEM;
+ up->clk = devm_clk_get(&pdev->dev, "uart");
+ if (IS_ERR(up->clk)) {
+ dev_err(&pdev->dev, "unable to get UART clock\n");
+ return PTR_ERR(up->clk);
+ }
+
port = &up->port;
mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (IS_ERR(port->membase))
return PTR_ERR(port->membase);
+ ret = clk_prepare_enable(up->clk);
+ if (ret)
+ return ret;
+
+ port->uartclk = clk_get_rate(up->clk);
+ if (!port->uartclk) {
+ ret = -EINVAL;
+ goto err_disable_clk;
+ }
+
port->mapbase = mem_res->start;
port->line = id;
port->irq = irq_res->start;
port->dev = &pdev->dev;
port->type = PORT_AR933X;
port->iotype = UPIO_MEM32;
- port->uartclk = pdata->uartclk;
port->regshift = 2;
port->fifosize = AR933X_UART_FIFO_SIZE;
ret = uart_add_one_port(&ar933x_uart_driver, &up->port);
if (ret)
- return ret;
+ goto err_disable_clk;
platform_set_drvdata(pdev, up);
return 0;
+
+err_disable_clk:
+ clk_disable_unprepare(up->clk);
+ return ret;
}
static int ar933x_uart_remove(struct platform_device *pdev)
up = platform_get_drvdata(pdev);
- if (up)
+ if (up) {
uart_remove_one_port(&ar933x_uart_driver, &up->port);
+ clk_disable_unprepare(up->clk);
+ }
return 0;
}