1 /*
2  * (C) Copyright 2003
3  *
4  * Thomas Frieden (ThomasF@hyperion-entertainment.com)
5  *
6  * See file CREDITS for list of people who contributed to this
7  * project.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation; either version 2 of
12  * the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22  * MA 02111-1307 USA
23  *
24  */
25 #include <common.h>
26 #include <asm/processor.h>
27 #include <asm/string.h>
28 #include <devices.h>
29 #include <pci.h>
30 #include "memio.h"
31 #include "catweasel.h"
32 #include "cw4.h"
33 #include "../menu/menu.h"
34 
35 #define CATW_PCI_VENDOR		0xe159
36 #define CATW_PCI_PRODUCT	0x0001
37 
38 #define CATW4_SUBSYS_VENDOR	0x5213
39 #define CATW4_SUBSYS_ID1	0x0002
40 #define CATW4_SUBSYS_ID2	0x0003
41 
42 #define CATW_KEY_DATA		0xd0
43 #define CATW_KEY_STATUS		0xd4
44 
45 #define CATW_KS_READY		0x80
46 
47 #define CATW_NAME			"amikbd"
48 
49 #define CATW4_FILEID		FileID('C','A','T','4')
50 
51 #undef CATW_DEBUG
52 #ifdef	CATW_DEBUG
53 #define	dprintf(fmt,args...)	printf (fmt ,##args)
54 #else
55 #define dprintf(fmt,args...)
56 #endif
57 
58 int catw_getc(void);
59 int catw_testc(void);
60 
61 static int catw_pci = -1;
62 static unsigned long catw_iobase = 0;
63 
64 static int catw_poll_delay = 20000;
65 
66 static char catw_shift_state = 0;
67 
68 static unsigned char catw_normal_xlate[0x70] =
69 {          /*  0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F */
70 /* 00 - 0F */ '`','1','2','3','4','5','6','7','8','9','0','�','\'','\\',0, '0',
71 /* 10 - 1F */ 'q','w','e','r','t','z','u','i','o','p','�','+', 0 ,'1','2','3',
72 /* 20 - 2F */ 'a','s','d','f','g','h','j','k','l','�','�','#', 0 ,'4','5','6',
73 /* 30 - 3F */ '<','y','x','c','v','b','n','m',',','.','-', 0 , 0 ,'7','8','9',
74 /* 40 - 4F */ ' ', 8 , 9 , 13, 13, 27,127, 0 , 0 , 0 ,'-', 0 , 0 , 0 , 0 , 0 ,
75 /* 50 - 5F */  0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,'[',']','/','*','+', 0 ,
76 /* 60 - 6F */  0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
77 };
78 
79 static unsigned char catw_shifted_xlate[0x70] =
80 {          /*  0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F */
81 /* 00 - 0F */ '~','!','"','�','$','%','&','/','(',')','=','?','`','|', 0, '0',
82 /* 10 - 1F */ 'Q','W','E','R','T','Z','U','I','O','P','�','*', 0 ,'1','2','3',
83 /* 20 - 2F */ 'A','S','D','F','G','H','J','K','L','�','�','^', 0 ,'4','5','6',
84 /* 30 - 3F */ '>','Y','X','C','V','B','N','M',';',':','_', 0 , 0 ,'7','8','9',
85 /* 40 - 4F */ ' ', 8 , 9 , 13, 13, 27,127, 0 , 0 , 0 ,'-', 0 , 0 , 0 , 0 , 0 ,
86 /* 50 - 5F */  0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,'{','}','/','*','+', 0 ,
87 /* 60 - 6F */  0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
88 };
89 
90 //"
91 
92 #define CATW_BUFFER_SIZE 20
93 static unsigned char catw_buffer[CATW_BUFFER_SIZE];
94 static int catw_inptr = 0, catw_outptr = 0;
95 
catw_handle(int c)96 void catw_handle(int c)
97 {
98 	int kup = (c&0x80);
99 	int key = (c&0x7f);
100 
101 	switch (key)
102 	{
103 		case 0x60:
104 		case 0x61:
105 		case 0x62:
106 			if (kup)
107 				catw_shift_state = 0;
108 			else
109 				catw_shift_state = 1;
110 			break;
111 		case 0x78:
112 			/* Reset */
113 			dprintf("Reset!\n");
114 			break;
115 	}
116 }
117 
catw_xlate(int c)118 int catw_xlate(int c)
119 {
120 	c &= 0x7f;
121 
122 	switch(c)
123 	{
124 	case 0x4C:
125 		return KEY_PREV_ITEM;
126 	case 0x4D:
127 		return KEY_NEXT_ITEM;
128 	case 0x4E:
129 		return KEY_NEXT_OPTION;
130 	case 0x4F:
131 		return KEY_PREV_OPTION;
132 	default:
133 		if (catw_shift_state)
134 			return catw_shifted_xlate[c];
135 		else
136 			return catw_normal_xlate[c];
137 	}
138 }
139 
catw_fpga_ready(void)140 static int catw_fpga_ready(void)
141 {
142 	if ((in_byte(catw_iobase + 0x07) & 8) == 8) return 1;
143 	else return 0;
144 }
145 
catw_config_done(void)146 static int catw_config_done(void)
147 {
148 	if ((in_byte(catw_iobase + 0x07) & 4) == 4) return 1;
149 	else return 0;
150 }
151 
catw_reset_fpga(void)152 static void catw_reset_fpga(void)
153 {
154 	dprintf("Resetting fpga...\n");
155 	out_byte(catw_iobase + 0x02, 227);
156 	out_byte(catw_iobase + 0x03, 0);
157 	udelay(1000);
158 	out_byte(catw_iobase + 0x03, 65);
159 	dprintf("Done\n");
160 }
161 
catw_get_config(uint32 * size)162 static void *catw_get_config(uint32 *size)
163 {
164 	*size = 59215;
165 	return &cw4[0];
166 }
167 
catw_program_fpga_config(void)168 static int catw_program_fpga_config(void)
169 {
170 	uint32 length;
171 	uint8 b;
172 	int i;
173 	int try;
174 	uint8 *config = (uint8*)catw_get_config(&length);
175 
176 	if (!config)
177 	{
178 		dprintf("Couldn't find core config\n");
179 		return 0;
180 	}
181 
182 	#ifdef CATW_DEBUG
183 	dprintf("Found a config string of %d bytes\n", length);
184 	dprintf("starting with...\n");
185 	{
186 		int i;
187 		for (i=0; i<40; i++)
188 		{
189 			dprintf("%02x ", *(config+i));
190 		}
191 		dprintf("\n");
192 		dprintf("...\n");
193 
194 		for (i=0; i<40; i++)
195 		{
196 			dprintf("%02x ", *(config+length-40+i));
197 		}
198 		dprintf("\n");
199 	}
200 	#endif
201 
202 	for (i=0; i<length-1; i++)
203 	{
204 		b = *(config+i);
205 		try = 0;
206 
207 		if ((b & 0x01) == 0x01)
208 			out_byte(catw_iobase + 0x03, 0x43);
209 		else
210 			out_byte(catw_iobase + 0x03, 0x41);
211 
212 		while (catw_fpga_ready() == 0)
213 		{
214 			udelay(2000);
215 			try++;
216 			dprintf("waiting for FPGA (try = %d)\n", try);
217 			if (try == 10)
218 			{
219 				dprintf("PANIC: FPGA failed on catw_fpga_ready()\n");
220 				dprintf("at byte offset %d\n", i);
221 				dprintf("byte written was %02x\n", b);
222 				return 0;
223 			}
224 		}
225 
226 		out_byte(catw_iobase + 0xc0, b);
227 	}
228 
229 	return 1;
230 }
231 
232 
catw_kb_init(void)233 int catw_kb_init(void)
234 {
235 	int i;
236 	device_t catw_kbddev;
237 	int error;
238 	char *s;
239 	uint16 subsys_vendor, subsys_device;
240 
241 	/* Some init */
242 	catw_shift_state = 0;
243 
244 	/* Find the device */
245 	catw_pci = pci_find_device(CATW_PCI_VENDOR, CATW_PCI_PRODUCT, 0);
246 	if (catw_pci == -1)
247 	{
248 		dprintf("No Catweasel controller (0x%0x4, 0x%04x) attached\n", CATW_PCI_VENDOR, CATW_PCI_PRODUCT);
249 		return -1;
250 	}
251 
252 	/* Get IO base */
253 	for (i = 0; i < 6; i++)
254 	{
255 		pci_read_config_dword(catw_pci, PCI_BASE_ADDRESS_0+4*i, (u32 *)&catw_iobase);
256 		if (catw_iobase & 1)
257 		{
258 			/* Found the IO base */
259 			break;
260 		}
261 	}
262 
263 	/* Check the iobase */
264 	if (catw_iobase & 1)
265 	{
266 		catw_iobase &= ~1;
267 		dprintf("I/O base: %p\n", (u32 *)catw_iobase);
268 	}
269 	else
270 	{
271 		printf("Error: Unable to find I/O address range\n");
272 		return -1;
273 	}
274 
275 	pci_read_config_word(catw_pci, PCI_SUBSYSTEM_VENDOR_ID, &subsys_vendor);
276 	pci_read_config_word(catw_pci, PCI_SUBSYSTEM_ID, &subsys_device);
277 
278 	if (subsys_vendor == CATW4_SUBSYS_VENDOR &&
279 	   ((subsys_device == CATW4_SUBSYS_ID1) || (subsys_device == CATW4_SUBSYS_ID1)))
280 	{
281 		dprintf("Catweasel Mark IV detected\n");
282 		/* Send Mark IV initialisation sequence */
283 		out_byte(catw_iobase + 0x00, 0xF1);
284 		out_byte(catw_iobase + 0x01, 0x00);
285 		out_byte(catw_iobase + 0x02, 0xE3);
286 		out_byte(catw_iobase + 0x03, 0x41);
287 		out_byte(catw_iobase + 0x04, 0x00);
288 		out_byte(catw_iobase + 0x05, 0x00);
289 		out_byte(catw_iobase + 0x29, 0x00);
290 		out_byte(catw_iobase + 0x2B, 0x00);
291 
292 		#ifdef CATW_DEBUG
293 		if (catw_config_done())
294 			dprintf("FPGA already configured\n");
295 		else
296 			dprintf("FPGA Empty\n");
297 		#endif
298 
299 		catw_reset_fpga();
300 		if (catw_config_done())
301 		{
302 			printf("**PANIC** FPGA reset failed\n");
303 			return -1;
304 		}
305 		#ifdef CATW_DEBUG
306 		else
307 		{
308 			dprintf("FPGA reset OK\n");
309 		}
310 		#endif
311 
312 		if (0 == catw_program_fpga_config())
313 		{
314 			printf("**ERROR** FPGA Programming failed\n");
315 			return -1;
316 		}
317 
318 		if (catw_config_done())
319 		{
320 			printf("Catweasel Mark IV configured\n\n");
321 		}
322 		else
323 		{
324 			printf("**ERROR** Catweasel Mark IV configuration failed\n");
325 			return -1;
326 		}
327 		udelay(1000);
328 	}
329 	/* Catweasel mark III cannot work on Sam
330 	 * it's a +5V only PCI card...
331 	else
332 	{
333 		dprintf("Catweasel Mark III detected\n");
334 		// Send initialisation sequence for Mark III
335 		out_byte(catw_iobase + 0x00, 0xf1);
336 		out_byte(catw_iobase + 0x01, 0x00);
337 		out_byte(catw_iobase + 0x02, 0x00);
338 		out_byte(catw_iobase + 0x04, 0x00);
339 		out_byte(catw_iobase + 0x05, 0x00);
340 		out_byte(catw_iobase + 0x29, 0x00);
341 		out_byte(catw_iobase + 0x2b, 0x00);
342 	}
343 	*/
344 
345 	out_byte(catw_iobase + CATW_KEY_DATA, 0);
346 
347 	/* Register us as a possible keyboard device */
348 	memset(&catw_kbddev, 0, sizeof(catw_kbddev));
349 	strcpy(catw_kbddev.name, CATW_NAME);
350 	catw_kbddev.flags =  DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
351   	catw_kbddev.putc = NULL;
352 	catw_kbddev.puts = NULL;
353 	catw_kbddev.getc = catw_getc;
354 	catw_kbddev.tstc = catw_testc;
355 
356 	s = getenv("catw_poll_delay");
357 	if (s)
358 	{
359 		catw_poll_delay = simple_strtol(s, NULL, 0) * 1000;
360 	}
361 
362 	error = device_register(&catw_kbddev);
363 	if (0 == error )
364 	{
365 		/* Check if we are stdin */
366 		if (0 == strcmp(getenv("stdin"), CATW_NAME))
367 		{
368 			if (overwrite_console())
369 				return 1;
370 
371 			error = console_assign(stdin,CATW_NAME);
372 			if (0 == error)
373 			{
374 				dprintf("Catweasel keyboard initialized 1\n");
375 				return 1;
376 			}
377 			else
378 			{
379 				dprintf("Catweasel keyboard initialized 2\n");
380 				return error;
381 			}
382 		}
383 
384 		dprintf("Catweasel keyboard initialized 3\n");
385 		return 1;
386 	}
387 
388 	return error;
389 }
390 
catw_push(unsigned char c)391 static void catw_push(unsigned char c)
392 {
393 	if (catw_inptr == CATW_BUFFER_SIZE-1)
394 	{
395 		if (catw_outptr == 0) return;
396 		catw_inptr = 0;
397 	}
398 	else if (catw_inptr + 1 == catw_outptr)
399 	{
400 		return;
401 	}
402 
403 	catw_buffer[++catw_inptr] = c;
404 }
405 
catw_pop(void)406 static int catw_pop(void)
407 {
408 	if (catw_inptr == catw_outptr) return -1;
409 	if (catw_outptr >= CATW_BUFFER_SIZE-1)
410 		catw_outptr = 0;
411 	else
412 		++catw_outptr;
413 
414 	return (int)catw_buffer[catw_outptr];
415 }
416 
catw_poll(void)417 static void catw_poll(void)
418 {
419 	int x;
420 
421 	x = in_byte(catw_iobase + CATW_KEY_STATUS);
422 
423 	if (x & CATW_KS_READY)
424 	{
425 		x = in_byte(catw_iobase + CATW_KEY_DATA);
426 		dprintf("got char: %x\n", x);
427 		catw_handle(x);
428 
429 		if (!(x&0x80))
430 		{
431 			x = catw_xlate(x);
432 			if (x)
433 			{
434 				dprintf("xlate: %x\n", x);
435 				catw_push((unsigned char)x);
436 			}
437 		}
438 		udelay(1000);
439 		out_byte(catw_iobase + CATW_KEY_DATA, 0);
440 	}
441 }
442 
catw_getc(void)443 int catw_getc(void)
444 {
445 	int c;
446 
447 	do
448 	{
449 		udelay(catw_poll_delay);
450 		catw_poll();
451 		c = catw_pop();
452 	} while (c == -1);
453 
454 	return c;
455 }
456 
457 unsigned long long get_ticks(void);
458 unsigned long ticks2usec(unsigned long ticks);
459 
catw_testc(void)460 int catw_testc(void)
461 {
462 	catw_poll();
463 	if (catw_inptr == catw_outptr) return 0;
464 	else return 1;
465 }
466