blob: a7e566bd23fbea3875f9e18eb85e3ec351ee915d [file] [log] [blame]
Alexey Brodkinc51eb112013-12-13 10:35:11 +04001/*
2 * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com)
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 */
9
Alexey Brodkine458cc12015-03-17 14:55:14 +030010#include <dm.h>
Alexey Brodkinc51eb112013-12-13 10:35:11 +040011#include <serial.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060012#include <asm/global_data.h>
Alexey Brodkinc51eb112013-12-13 10:35:11 +040013
14DECLARE_GLOBAL_DATA_PTR;
15
16struct arc_serial_regs {
17 unsigned int id0;
18 unsigned int id1;
19 unsigned int id2;
20 unsigned int id3;
21 unsigned int data;
22 unsigned int status;
23 unsigned int baudl;
24 unsigned int baudh;
25};
26
Simon Glassb75b15b2020-12-03 16:55:23 -070027struct arc_serial_plat {
Alexey Brodkine458cc12015-03-17 14:55:14 +030028 struct arc_serial_regs *reg;
29 unsigned int uartclk;
30};
31
Alexey Brodkinc51eb112013-12-13 10:35:11 +040032/* Bit definitions of STATUS register */
33#define UART_RXEMPTY (1 << 5)
34#define UART_OVERFLOW_ERR (1 << 1)
35#define UART_TXEMPTY (1 << 7)
36
Alexey Brodkine458cc12015-03-17 14:55:14 +030037static int arc_serial_setbrg(struct udevice *dev, int baudrate)
Alexey Brodkinc51eb112013-12-13 10:35:11 +040038{
Simon Glass95588622020-12-22 19:30:28 -070039 struct arc_serial_plat *plat = dev_get_plat(dev);
Alexey Brodkine458cc12015-03-17 14:55:14 +030040 struct arc_serial_regs *const regs = plat->reg;
41 int arc_console_baud = gd->cpu_clk / (baudrate * 4) - 1;
Alexey Brodkinc51eb112013-12-13 10:35:11 +040042
Alexey Brodkin326d8372014-02-08 10:10:02 +040043 writeb(arc_console_baud & 0xff, &regs->baudl);
Alexey Brodkin326d8372014-02-08 10:10:02 +040044 writeb((arc_console_baud & 0xff00) >> 8, &regs->baudh);
Alexey Brodkinc51eb112013-12-13 10:35:11 +040045
Alexey Brodkinc51eb112013-12-13 10:35:11 +040046 return 0;
47}
48
Alexey Brodkine458cc12015-03-17 14:55:14 +030049static int arc_serial_putc(struct udevice *dev, const char c)
Alexey Brodkinc51eb112013-12-13 10:35:11 +040050{
Simon Glass95588622020-12-22 19:30:28 -070051 struct arc_serial_plat *plat = dev_get_plat(dev);
Alexey Brodkine458cc12015-03-17 14:55:14 +030052 struct arc_serial_regs *const regs = plat->reg;
53
Pali Rohár241f12d2022-12-11 00:31:21 +010054 if (!(readb(&regs->status) & UART_TXEMPTY))
55 return -EAGAIN;
Alexey Brodkinc51eb112013-12-13 10:35:11 +040056
Alexey Brodkin326d8372014-02-08 10:10:02 +040057 writeb(c, &regs->data);
Alexey Brodkine458cc12015-03-17 14:55:14 +030058
59 return 0;
Alexey Brodkinc51eb112013-12-13 10:35:11 +040060}
61
Alexey Brodkine458cc12015-03-17 14:55:14 +030062static int arc_serial_tstc(struct arc_serial_regs *const regs)
Alexey Brodkinc51eb112013-12-13 10:35:11 +040063{
Alexey Brodkin326d8372014-02-08 10:10:02 +040064 return !(readb(&regs->status) & UART_RXEMPTY);
Alexey Brodkinc51eb112013-12-13 10:35:11 +040065}
66
Alexey Brodkine458cc12015-03-17 14:55:14 +030067static int arc_serial_pending(struct udevice *dev, bool input)
68{
Simon Glass95588622020-12-22 19:30:28 -070069 struct arc_serial_plat *plat = dev_get_plat(dev);
Alexey Brodkine458cc12015-03-17 14:55:14 +030070 struct arc_serial_regs *const regs = plat->reg;
71 uint32_t status = readb(&regs->status);
72
73 if (input)
74 return status & UART_RXEMPTY ? 0 : 1;
75 else
76 return status & UART_TXEMPTY ? 0 : 1;
77}
78
79static int arc_serial_getc(struct udevice *dev)
Alexey Brodkinc51eb112013-12-13 10:35:11 +040080{
Simon Glass95588622020-12-22 19:30:28 -070081 struct arc_serial_plat *plat = dev_get_plat(dev);
Alexey Brodkine458cc12015-03-17 14:55:14 +030082 struct arc_serial_regs *const regs = plat->reg;
83
Pali Rohár241f12d2022-12-11 00:31:21 +010084 if (!arc_serial_tstc(regs))
85 return -EAGAIN;
Alexey Brodkinc51eb112013-12-13 10:35:11 +040086
87 /* Check for overflow errors */
Alexey Brodkin326d8372014-02-08 10:10:02 +040088 if (readb(&regs->status) & UART_OVERFLOW_ERR)
Alexey Brodkinc51eb112013-12-13 10:35:11 +040089 return 0;
90
Alexey Brodkin326d8372014-02-08 10:10:02 +040091 return readb(&regs->data) & 0xFF;
Alexey Brodkinc51eb112013-12-13 10:35:11 +040092}
93
Alexey Brodkine458cc12015-03-17 14:55:14 +030094static int arc_serial_probe(struct udevice *dev)
Alexey Brodkinc51eb112013-12-13 10:35:11 +040095{
Alexey Brodkine458cc12015-03-17 14:55:14 +030096 return 0;
Alexey Brodkinc51eb112013-12-13 10:35:11 +040097}
98
Alexey Brodkine458cc12015-03-17 14:55:14 +030099static const struct dm_serial_ops arc_serial_ops = {
100 .putc = arc_serial_putc,
101 .pending = arc_serial_pending,
102 .getc = arc_serial_getc,
103 .setbrg = arc_serial_setbrg,
104};
105
106static const struct udevice_id arc_serial_ids[] = {
107 { .compatible = "snps,arc-uart" },
108 { }
109};
110
Simon Glassaad29ae2020-12-03 16:55:21 -0700111static int arc_serial_of_to_plat(struct udevice *dev)
Alexey Brodkinc51eb112013-12-13 10:35:11 +0400112{
Simon Glassb75b15b2020-12-03 16:55:23 -0700113 struct arc_serial_plat *plat = dev_get_plat(dev);
Alexey Brodkine458cc12015-03-17 14:55:14 +0300114 DECLARE_GLOBAL_DATA_PTR;
115
Masahiro Yamada1096ae12020-07-17 14:36:46 +0900116 plat->reg = dev_read_addr_ptr(dev);
Simon Glassdd79d6e2017-01-17 16:52:55 -0700117 plat->uartclk = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
Alexey Brodkine458cc12015-03-17 14:55:14 +0300118 "clock-frequency", 0);
119
120 return 0;
Alexey Brodkinc51eb112013-12-13 10:35:11 +0400121}
Alexey Brodkine458cc12015-03-17 14:55:14 +0300122
123U_BOOT_DRIVER(serial_arc) = {
124 .name = "serial_arc",
125 .id = UCLASS_SERIAL,
126 .of_match = arc_serial_ids,
Simon Glassaad29ae2020-12-03 16:55:21 -0700127 .of_to_plat = arc_serial_of_to_plat,
Simon Glassb75b15b2020-12-03 16:55:23 -0700128 .plat_auto = sizeof(struct arc_serial_plat),
Alexey Brodkine458cc12015-03-17 14:55:14 +0300129 .probe = arc_serial_probe,
130 .ops = &arc_serial_ops,
Alexey Brodkine458cc12015-03-17 14:55:14 +0300131};
Alexey Brodkineede1672018-05-21 16:42:07 +0300132
133#ifdef CONFIG_DEBUG_ARC_SERIAL
134#include <debug_uart.h>
135
136static inline void _debug_uart_init(void)
137{
Pali Rohár8864b352022-05-27 22:15:24 +0200138 struct arc_serial_regs *regs = (struct arc_serial_regs *)CONFIG_VAL(DEBUG_UART_BASE);
Alexey Brodkineede1672018-05-21 16:42:07 +0300139 int arc_console_baud = CONFIG_DEBUG_UART_CLOCK / (CONFIG_BAUDRATE * 4) - 1;
140
141 writeb(arc_console_baud & 0xff, &regs->baudl);
142 writeb((arc_console_baud & 0xff00) >> 8, &regs->baudh);
143}
144
145static inline void _debug_uart_putc(int c)
146{
Pali Rohár8864b352022-05-27 22:15:24 +0200147 struct arc_serial_regs *regs = (struct arc_serial_regs *)CONFIG_VAL(DEBUG_UART_BASE);
Alexey Brodkineede1672018-05-21 16:42:07 +0300148
149 while (!(readb(&regs->status) & UART_TXEMPTY))
150 ;
151
152 writeb(c, &regs->data);
153}
154
155DEBUG_UART_FUNCS
156
157#endif