blob: 45f8315d0a07d90312ff6965f4e736cf217a27c3 [file] [log] [blame]
Tom Rinidec7ea02024-05-20 13:35:03 -06001// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * (C) Copyright 2022 - Analog Devices, Inc.
4 *
5 * Written and/or maintained by Timesys Corporation
6 *
7 * Converted to driver model by Nathan Barrett-Morrison
8 *
9 * Contact: Nathan Barrett-Morrison <nathan.morrison@timesys.com>
10 * Contact: Greg Malysa <greg.malysa@timesys.com>
11 *
12 */
13
14#include <clk.h>
15#include <dm.h>
16#include <serial.h>
17#include <asm/io.h>
18#include <dm/device_compat.h>
19#include <linux/bitops.h>
20
21/*
22 * UART4 Masks
23 */
24
25/* UART_CONTROL */
26#define UEN BIT(0)
27#define LOOP_ENA BIT(1)
28#define UMOD (3 << 4)
29#define UMOD_UART (0 << 4)
30#define UMOD_MDB BIT(4)
31#define UMOD_IRDA BIT(4)
32#define WLS (3 << 8)
33#define WLS_5 (0 << 8)
34#define WLS_6 BIT(8)
35#define WLS_7 (2 << 8)
36#define WLS_8 (3 << 8)
37#define STB BIT(12)
38#define STBH BIT(13)
39#define PEN BIT(14)
40#define EPS BIT(15)
41#define STP BIT(16)
42#define FPE BIT(17)
43#define FFE BIT(18)
44#define SB BIT(19)
45#define FCPOL BIT(22)
46#define RPOLC BIT(23)
47#define TPOLC BIT(24)
48#define MRTS BIT(25)
49#define XOFF BIT(26)
50#define ARTS BIT(27)
51#define ACTS BIT(28)
52#define RFIT BIT(29)
53#define RFRT BIT(30)
54
55/* UART_STATUS */
56#define DR BIT(0)
57#define OE BIT(1)
58#define PE BIT(2)
59#define FE BIT(3)
60#define BI BIT(4)
61#define THRE BIT(5)
62#define TEMT BIT(7)
63#define TFI BIT(8)
64#define ASTKY BIT(9)
65#define ADDR BIT(10)
66#define RO BIT(11)
67#define SCTS BIT(12)
68#define CTS BIT(16)
69#define RFCS BIT(17)
70
71/* UART_EMASK */
72#define ERBFI BIT(0)
73#define ETBEI BIT(1)
74#define ELSI BIT(2)
75#define EDSSI BIT(3)
76#define EDTPTI BIT(4)
77#define ETFI BIT(5)
78#define ERFCI BIT(6)
79#define EAWI BIT(7)
80#define ERXS BIT(8)
81#define ETXS BIT(9)
82
83DECLARE_GLOBAL_DATA_PTR;
84
85struct uart4_reg {
86 u32 revid;
87 u32 control;
88 u32 status;
89 u32 scr;
90 u32 clock;
91 u32 emask;
92 u32 emaskst;
93 u32 emaskcl;
94 u32 rbr;
95 u32 thr;
96 u32 taip;
97 u32 tsr;
98 u32 rsr;
99 u32 txdiv_cnt;
100 u32 rxdiv_cnt;
101};
102
103struct adi_uart4_platdata {
104 // Hardware registers
105 struct uart4_reg *regs;
106
107 // Enable divide-by-one baud rate setting
108 bool edbo;
109};
110
111static int adi_uart4_set_brg(struct udevice *dev, int baudrate)
112{
113 struct adi_uart4_platdata *plat = dev_get_plat(dev);
114 struct uart4_reg *regs = plat->regs;
115 u32 divisor, uart_base_clk_rate;
116 struct clk uart_base_clk;
117
118 if (clk_get_by_index(dev, 0, &uart_base_clk)) {
119 dev_err(dev, "Could not get UART base clock\n");
120 return -1;
121 }
122
123 uart_base_clk_rate = clk_get_rate(&uart_base_clk);
124
125 if (plat->edbo) {
126 u16 divisor16 = (uart_base_clk_rate + (baudrate / 2)) / baudrate;
127
128 divisor = divisor16 | BIT(31);
129 } else {
130 // Divisor is only 16 bits
131 divisor = 0x0000ffff & ((uart_base_clk_rate + (baudrate * 8)) / (baudrate * 16));
132 }
133
134 writel(divisor, &regs->clock);
135 return 0;
136}
137
138static int adi_uart4_pending(struct udevice *dev, bool input)
139{
140 struct adi_uart4_platdata *plat = dev_get_plat(dev);
141 struct uart4_reg *regs = plat->regs;
142
143 if (input)
144 return (readl(&regs->status) & DR) ? 1 : 0;
145 else
146 return (readl(&regs->status) & THRE) ? 0 : 1;
147}
148
149static int adi_uart4_getc(struct udevice *dev)
150{
151 struct adi_uart4_platdata *plat = dev_get_plat(dev);
152 struct uart4_reg *regs = plat->regs;
153 int uart_rbr_val;
154
155 if (!adi_uart4_pending(dev, true))
156 return -EAGAIN;
157
158 uart_rbr_val = readl(&regs->rbr);
159 writel(-1, &regs->status);
160
161 return uart_rbr_val;
162}
163
164static int adi_uart4_putc(struct udevice *dev, const char ch)
165{
166 struct adi_uart4_platdata *plat = dev_get_plat(dev);
167 struct uart4_reg *regs = plat->regs;
168
169 if (adi_uart4_pending(dev, false))
170 return -EAGAIN;
171
172 writel(ch, &regs->thr);
173 return 0;
174}
175
176static const struct dm_serial_ops adi_uart4_serial_ops = {
177 .setbrg = adi_uart4_set_brg,
178 .getc = adi_uart4_getc,
179 .putc = adi_uart4_putc,
180 .pending = adi_uart4_pending,
181};
182
183static int adi_uart4_of_to_plat(struct udevice *dev)
184{
185 struct adi_uart4_platdata *plat = dev_get_plat(dev);
186 fdt_addr_t addr;
187
188 addr = dev_read_addr(dev);
189 if (addr == FDT_ADDR_T_NONE)
190 return -EINVAL;
191
192 plat->regs = (struct uart4_reg *)addr;
193 plat->edbo = dev_read_bool(dev, "adi,enable-edbo");
194
195 return 0;
196}
197
198static int adi_uart4_probe(struct udevice *dev)
199{
200 struct adi_uart4_platdata *plat = dev_get_plat(dev);
201 struct uart4_reg *regs = plat->regs;
202
203 /* always enable UART to 8-bit mode */
204 writel(UEN | UMOD_UART | WLS_8, &regs->control);
205
206 writel(-1, &regs->status);
207
208 return 0;
209}
210
211static const struct udevice_id adi_uart4_serial_ids[] = {
212 { .compatible = "adi,uart4" },
213 { }
214};
215
216U_BOOT_DRIVER(serial_adi_uart4) = {
217 .name = "serial_adi_uart4",
218 .id = UCLASS_SERIAL,
219 .of_match = adi_uart4_serial_ids,
220 .of_to_plat = adi_uart4_of_to_plat,
221 .plat_auto = sizeof(struct adi_uart4_platdata),
222 .probe = adi_uart4_probe,
223 .ops = &adi_uart4_serial_ops,
224 .flags = DM_FLAG_PRE_RELOC,
225};