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