1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * TI DaVinci serial driver
4 *
5 * Copyright (C) 2006 Texas Instruments.
6 */
7
8#include <linux/kernel.h>
9#include <linux/init.h>
10#include <linux/serial_8250.h>
11#include <linux/serial_reg.h>
12#include <linux/platform_device.h>
13#include <linux/delay.h>
14#include <linux/clk.h>
15#include <linux/io.h>
16
17#include <mach/serial.h>
18#include <mach/cputype.h>
19
20static inline void serial_write_reg(struct plat_serial8250_port *p, int offset,
21				    int value)
22{
23	offset <<= p->regshift;
24
25	WARN_ONCE(!p->membase, "unmapped write: uart[%d]\n", offset);
26
27	__raw_writel(value, p->membase + offset);
28}
29
30static void __init davinci_serial_reset(struct plat_serial8250_port *p)
31{
32	unsigned int pwremu = 0;
33
34	serial_write_reg(p, UART_IER, 0);  /* disable all interrupts */
35
36	/* reset both transmitter and receiver: bits 14,13 = UTRST, URRST */
37	serial_write_reg(p, UART_DAVINCI_PWREMU, pwremu);
38	mdelay(10);
39
40	pwremu |= (0x3 << 13);
41	pwremu |= 0x1;
42	serial_write_reg(p, UART_DAVINCI_PWREMU, pwremu);
43
44	if (cpu_is_davinci_dm646x())
45		serial_write_reg(p, UART_DM646X_SCR,
46				 UART_DM646X_SCR_TX_WATERMARK);
47}
48
49int __init davinci_serial_init(struct platform_device *serial_dev)
50{
51	int i, ret = 0;
52	struct device *dev;
53	struct plat_serial8250_port *p;
54	struct clk *clk;
55
56	/*
57	 * Make sure the serial ports are muxed on at this point.
58	 * You have to mux them off in device drivers later on if not needed.
59	 */
60	for (i = 0; serial_dev[i].dev.platform_data != NULL; i++) {
61		dev = &serial_dev[i].dev;
62		p = dev->platform_data;
63
64		ret = platform_device_register(&serial_dev[i]);
65		if (ret)
66			continue;
67
68		clk = clk_get(dev, NULL);
69		if (IS_ERR(clk)) {
70			pr_err("%s:%d: failed to get UART%d clock\n",
71			       __func__, __LINE__, i);
72			continue;
73		}
74
75		clk_prepare_enable(clk);
76
77		p->uartclk = clk_get_rate(clk);
78
79		if (!p->membase && p->mapbase) {
80			p->membase = ioremap(p->mapbase, SZ_4K);
81
82			if (p->membase)
83				p->flags &= ~UPF_IOREMAP;
84			else
85				pr_err("uart regs ioremap failed\n");
86		}
87
88		if (p->membase && p->type != PORT_AR7)
89			davinci_serial_reset(p);
90	}
91	return ret;
92}
93