1
2
3
4
5
6
7
8
9
10#include <mm/mmu_decl.h>
11
12#include <asm/io.h>
13#include <asm/prom.h>
14#include <asm/udbg.h>
15#include <asm/fixmap.h>
16
17#include "usbgecko_udbg.h"
18
19
20#define EXI_CLK_32MHZ 5
21
22#define EXI_CSR 0x00
23#define EXI_CSR_CLKMASK (0x7<<4)
24#define EXI_CSR_CLK_32MHZ (EXI_CLK_32MHZ<<4)
25#define EXI_CSR_CSMASK (0x7<<7)
26#define EXI_CSR_CS_0 (0x1<<7)
27
28#define EXI_CR 0x0c
29#define EXI_CR_TSTART (1<<0)
30#define EXI_CR_WRITE (1<<2)
31#define EXI_CR_READ_WRITE (2<<2)
32#define EXI_CR_TLEN(len) (((len)-1)<<4)
33
34#define EXI_DATA 0x10
35
36#define UG_READ_ATTEMPTS 100
37#define UG_WRITE_ATTEMPTS 100
38
39
40static void __iomem *ug_io_base;
41
42
43
44
45static u32 ug_io_transaction(u32 in)
46{
47 u32 __iomem *csr_reg = ug_io_base + EXI_CSR;
48 u32 __iomem *data_reg = ug_io_base + EXI_DATA;
49 u32 __iomem *cr_reg = ug_io_base + EXI_CR;
50 u32 csr, data, cr;
51
52
53 csr = EXI_CSR_CLK_32MHZ | EXI_CSR_CS_0;
54 out_be32(csr_reg, csr);
55
56
57 data = in;
58 out_be32(data_reg, data);
59 cr = EXI_CR_TLEN(2) | EXI_CR_READ_WRITE | EXI_CR_TSTART;
60 out_be32(cr_reg, cr);
61
62 while (in_be32(cr_reg) & EXI_CR_TSTART)
63 barrier();
64
65
66 out_be32(csr_reg, 0);
67
68
69 data = in_be32(data_reg);
70
71 return data;
72}
73
74
75
76
77static int ug_is_adapter_present(void)
78{
79 if (!ug_io_base)
80 return 0;
81
82 return ug_io_transaction(0x90000000) == 0x04700000;
83}
84
85
86
87
88static int ug_is_txfifo_ready(void)
89{
90 return ug_io_transaction(0xc0000000) & 0x04000000;
91}
92
93
94
95
96
97static void ug_raw_putc(char ch)
98{
99 ug_io_transaction(0xb0000000 | (ch << 20));
100}
101
102
103
104
105
106static void ug_putc(char ch)
107{
108 int count = UG_WRITE_ATTEMPTS;
109
110 if (!ug_io_base)
111 return;
112
113 if (ch == '\n')
114 ug_putc('\r');
115
116 while (!ug_is_txfifo_ready() && count--)
117 barrier();
118 if (count >= 0)
119 ug_raw_putc(ch);
120}
121
122
123
124
125static int ug_is_rxfifo_ready(void)
126{
127 return ug_io_transaction(0xd0000000) & 0x04000000;
128}
129
130
131
132
133
134static int ug_raw_getc(void)
135{
136 u32 data = ug_io_transaction(0xa0000000);
137 if (data & 0x08000000)
138 return (data >> 16) & 0xff;
139 else
140 return -1;
141}
142
143
144
145
146
147static int ug_getc(void)
148{
149 int count = UG_READ_ATTEMPTS;
150
151 if (!ug_io_base)
152 return -1;
153
154 while (!ug_is_rxfifo_ready() && count--)
155 barrier();
156 return ug_raw_getc();
157}
158
159
160
161
162
163
164
165
166
167static void ug_udbg_putc(char ch)
168{
169 ug_putc(ch);
170}
171
172
173
174
175static int ug_udbg_getc(void)
176{
177 int ch;
178
179 while ((ch = ug_getc()) == -1)
180 barrier();
181 return ch;
182}
183
184
185
186
187static int ug_udbg_getc_poll(void)
188{
189 if (!ug_is_rxfifo_ready())
190 return -1;
191 return ug_getc();
192}
193
194
195
196
197static void __iomem *ug_udbg_setup_exi_io_base(struct device_node *np)
198{
199 void __iomem *exi_io_base = NULL;
200 phys_addr_t paddr;
201 const unsigned int *reg;
202
203 reg = of_get_property(np, "reg", NULL);
204 if (reg) {
205 paddr = of_translate_address(np, reg);
206 if (paddr)
207 exi_io_base = ioremap(paddr, reg[1]);
208 }
209 return exi_io_base;
210}
211
212
213
214
215static void __iomem *ug_udbg_probe(void __iomem *exi_io_base)
216{
217 int i;
218
219
220 for (i = 0; i < 2; i++) {
221 ug_io_base = exi_io_base + 0x14 * i;
222 if (ug_is_adapter_present())
223 break;
224 }
225 if (i == 2)
226 ug_io_base = NULL;
227 return ug_io_base;
228
229}
230
231
232
233
234void __init ug_udbg_init(void)
235{
236 struct device_node *np;
237 void __iomem *exi_io_base;
238
239 if (ug_io_base)
240 udbg_printf("%s: early -> final\n", __func__);
241
242 np = of_find_compatible_node(NULL, NULL, "nintendo,flipper-exi");
243 if (!np) {
244 udbg_printf("%s: EXI node not found\n", __func__);
245 goto out;
246 }
247
248 exi_io_base = ug_udbg_setup_exi_io_base(np);
249 if (!exi_io_base) {
250 udbg_printf("%s: failed to setup EXI io base\n", __func__);
251 goto done;
252 }
253
254 if (!ug_udbg_probe(exi_io_base)) {
255 udbg_printf("usbgecko_udbg: not found\n");
256 iounmap(exi_io_base);
257 } else {
258 udbg_putc = ug_udbg_putc;
259 udbg_getc = ug_udbg_getc;
260 udbg_getc_poll = ug_udbg_getc_poll;
261 udbg_printf("usbgecko_udbg: ready\n");
262 }
263
264done:
265 of_node_put(np);
266out:
267 return;
268}
269
270#ifdef CONFIG_PPC_EARLY_DEBUG_USBGECKO
271
272static phys_addr_t __init ug_early_grab_io_addr(void)
273{
274#if defined(CONFIG_GAMECUBE)
275 return 0x0c000000;
276#elif defined(CONFIG_WII)
277 return 0x0d000000;
278#else
279#error Invalid platform for USB Gecko based early debugging.
280#endif
281}
282
283
284
285
286void __init udbg_init_usbgecko(void)
287{
288 void __iomem *early_debug_area;
289 void __iomem *exi_io_base;
290
291
292
293
294
295
296
297
298
299 early_debug_area = (void __iomem *)__fix_to_virt(FIX_EARLY_DEBUG_BASE);
300 exi_io_base = early_debug_area + 0x00006800;
301
302
303 if (!ug_udbg_probe(exi_io_base))
304 return;
305
306
307 udbg_putc = ug_udbg_putc;
308 udbg_getc = ug_udbg_getc;
309 udbg_getc_poll = ug_udbg_getc_poll;
310
311
312
313
314
315
316
317
318 setbat(1, (unsigned long)early_debug_area,
319 ug_early_grab_io_addr(), 128*1024, PAGE_KERNEL_NCG);
320}
321
322#endif
323
324