]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
c9d4f46b SM |
2 | /* |
3 | * (C) Copyright 2004, Psyent Corporation <www.psyent.com> | |
4 | * Scott McNutt <[email protected]> | |
c9d4f46b SM |
5 | */ |
6 | ||
7 | #include <common.h> | |
220e8021 TC |
8 | #include <dm.h> |
9 | #include <errno.h> | |
8c085757 | 10 | #include <serial.h> |
315acd08 | 11 | #include <asm/io.h> |
cd93d625 | 12 | #include <linux/bitops.h> |
c9d4f46b | 13 | |
86450710 | 14 | /* data register */ |
886161a4 | 15 | #define ALTERA_JTAG_RVALID BIT(15) /* Read valid */ |
86450710 TC |
16 | |
17 | /* control register */ | |
886161a4 TC |
18 | #define ALTERA_JTAG_AC BIT(10) /* activity indicator */ |
19 | #define ALTERA_JTAG_RRDY BIT(12) /* read available */ | |
315acd08 | 20 | #define ALTERA_JTAG_WSPACE(d) ((d) >> 16) /* Write space avail */ |
220e8021 TC |
21 | /* Write fifo size. FIXME: this should be extracted with sopc2dts */ |
22 | #define ALTERA_JTAG_WRITE_DEPTH 64 | |
86450710 | 23 | |
315acd08 TC |
24 | struct altera_jtaguart_regs { |
25 | u32 data; /* Data register */ | |
26 | u32 control; /* Control register */ | |
27 | }; | |
28 | ||
29 | struct altera_jtaguart_platdata { | |
30 | struct altera_jtaguart_regs *regs; | |
31 | }; | |
c9d4f46b | 32 | |
220e8021 | 33 | static int altera_jtaguart_setbrg(struct udevice *dev, int baudrate) |
8c085757 | 34 | { |
220e8021 | 35 | return 0; |
8c085757 MV |
36 | } |
37 | ||
220e8021 | 38 | static int altera_jtaguart_putc(struct udevice *dev, const char ch) |
8c085757 | 39 | { |
220e8021 TC |
40 | struct altera_jtaguart_platdata *plat = dev->platdata; |
41 | struct altera_jtaguart_regs *const regs = plat->regs; | |
42 | u32 st = readl(®s->control); | |
43 | ||
44 | #ifdef CONFIG_ALTERA_JTAG_UART_BYPASS | |
45 | if (!(st & ALTERA_JTAG_AC)) /* no connection yet */ | |
46 | return -ENETUNREACH; | |
47 | #endif | |
48 | ||
49 | if (ALTERA_JTAG_WSPACE(st) == 0) | |
50 | return -EAGAIN; | |
51 | ||
52 | writel(ch, ®s->data); | |
53 | ||
8c085757 MV |
54 | return 0; |
55 | } | |
c9d4f46b | 56 | |
220e8021 | 57 | static int altera_jtaguart_pending(struct udevice *dev, bool input) |
c9d4f46b | 58 | { |
220e8021 TC |
59 | struct altera_jtaguart_platdata *plat = dev->platdata; |
60 | struct altera_jtaguart_regs *const regs = plat->regs; | |
61 | u32 st = readl(®s->control); | |
62 | ||
63 | if (input) | |
64 | return st & ALTERA_JTAG_RRDY ? 1 : 0; | |
65 | else | |
66 | return !(ALTERA_JTAG_WSPACE(st) == ALTERA_JTAG_WRITE_DEPTH); | |
c9d4f46b SM |
67 | } |
68 | ||
220e8021 | 69 | static int altera_jtaguart_getc(struct udevice *dev) |
c9d4f46b | 70 | { |
220e8021 TC |
71 | struct altera_jtaguart_platdata *plat = dev->platdata; |
72 | struct altera_jtaguart_regs *const regs = plat->regs; | |
73 | u32 val; | |
74 | ||
75 | val = readl(®s->data); | |
76 | ||
77 | if (!(val & ALTERA_JTAG_RVALID)) | |
78 | return -EAGAIN; | |
79 | ||
80 | return val & 0xff; | |
c9d4f46b SM |
81 | } |
82 | ||
220e8021 | 83 | static int altera_jtaguart_probe(struct udevice *dev) |
c9d4f46b | 84 | { |
220e8021 TC |
85 | #ifdef CONFIG_ALTERA_JTAG_UART_BYPASS |
86 | struct altera_jtaguart_platdata *plat = dev->platdata; | |
87 | struct altera_jtaguart_regs *const regs = plat->regs; | |
c9d4f46b | 88 | |
220e8021 TC |
89 | writel(ALTERA_JTAG_AC, ®s->control); /* clear AC flag */ |
90 | #endif | |
91 | return 0; | |
92 | } | |
93 | ||
94 | static int altera_jtaguart_ofdata_to_platdata(struct udevice *dev) | |
95 | { | |
96 | struct altera_jtaguart_platdata *plat = dev_get_platdata(dev); | |
97 | ||
2548493a | 98 | plat->regs = map_physmem(dev_read_addr(dev), |
18c3f270 TC |
99 | sizeof(struct altera_jtaguart_regs), |
100 | MAP_NOCACHE); | |
220e8021 TC |
101 | |
102 | return 0; | |
c9d4f46b | 103 | } |
8c085757 | 104 | |
220e8021 TC |
105 | static const struct dm_serial_ops altera_jtaguart_ops = { |
106 | .putc = altera_jtaguart_putc, | |
107 | .pending = altera_jtaguart_pending, | |
108 | .getc = altera_jtaguart_getc, | |
109 | .setbrg = altera_jtaguart_setbrg, | |
110 | }; | |
111 | ||
112 | static const struct udevice_id altera_jtaguart_ids[] = { | |
315acd08 TC |
113 | { .compatible = "altr,juart-1.0" }, |
114 | {} | |
220e8021 TC |
115 | }; |
116 | ||
117 | U_BOOT_DRIVER(altera_jtaguart) = { | |
118 | .name = "altera_jtaguart", | |
119 | .id = UCLASS_SERIAL, | |
120 | .of_match = altera_jtaguart_ids, | |
121 | .ofdata_to_platdata = altera_jtaguart_ofdata_to_platdata, | |
41575d8e | 122 | .platdata_auto = sizeof(struct altera_jtaguart_platdata), |
220e8021 TC |
123 | .probe = altera_jtaguart_probe, |
124 | .ops = &altera_jtaguart_ops, | |
8c085757 MV |
125 | }; |
126 | ||
220e8021 TC |
127 | #ifdef CONFIG_DEBUG_UART_ALTERA_JTAGUART |
128 | ||
129 | #include <debug_uart.h> | |
130 | ||
933529ce | 131 | static inline void _debug_uart_init(void) |
8c085757 | 132 | { |
8c085757 MV |
133 | } |
134 | ||
220e8021 | 135 | static inline void _debug_uart_putc(int ch) |
8c085757 | 136 | { |
220e8021 TC |
137 | struct altera_jtaguart_regs *regs = (void *)CONFIG_DEBUG_UART_BASE; |
138 | ||
139 | while (1) { | |
140 | u32 st = readl(®s->control); | |
141 | ||
142 | if (ALTERA_JTAG_WSPACE(st)) | |
143 | break; | |
144 | } | |
145 | ||
146 | writel(ch, ®s->data); | |
8c085757 | 147 | } |
220e8021 TC |
148 | |
149 | DEBUG_UART_FUNCS | |
150 | ||
151 | #endif |