Skip to content

Commit 7282bee

Browse files
Chris ZankelLinus Torvalds
authored andcommitted
[PATCH] xtensa: Architecture support for Tensilica Xtensa Part 8
The attached patches provides part 8 of an architecture implementation for the Tensilica Xtensa CPU series. Signed-off-by: Chris Zankel <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent e344b63 commit 7282bee

File tree

8 files changed

+1967
-0
lines changed

8 files changed

+1967
-0
lines changed

arch/xtensa/configs/iss_defconfig

Lines changed: 531 additions & 0 deletions
Large diffs are not rendered by default.

arch/xtensa/platform-iss/Makefile

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# $Id: Makefile,v 1.1.1.1 2002/08/28 16:10:14 aroll Exp $
2+
#
3+
# Makefile for the Xtensa Instruction Set Simulator (ISS)
4+
# "prom monitor" library routines under Linux.
5+
#
6+
# Note! Dependencies are done automagically by 'make dep', which also
7+
# removes any old dependencies. DON'T put your own dependencies here
8+
# unless it's something special (ie not a .c file).
9+
#
10+
# Note 2! The CFLAGS definitions are in the main makefile...
11+
12+
obj-y = io.o console.o setup.o network.o
13+

arch/xtensa/platform-iss/console.c

Lines changed: 303 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,303 @@
1+
/*
2+
* arch/xtensa/platform-iss/console.c
3+
*
4+
* This file is subject to the terms and conditions of the GNU General Public
5+
* License. See the file "COPYING" in the main directory of this archive
6+
* for more details.
7+
*
8+
* Copyright (C) 2001-2005 Tensilica Inc.
9+
* Authors Christian Zankel, Joe Taylor
10+
*/
11+
12+
#include <linux/module.h>
13+
#include <linux/config.h>
14+
#include <linux/kernel.h>
15+
#include <linux/sched.h>
16+
#include <linux/console.h>
17+
#include <linux/init.h>
18+
#include <linux/slab.h>
19+
#include <linux/mm.h>
20+
#include <linux/major.h>
21+
#include <linux/param.h>
22+
#include <linux/serial.h>
23+
#include <linux/serialP.h>
24+
#include <linux/console.h>
25+
26+
#include <asm/uaccess.h>
27+
#include <asm/irq.h>
28+
29+
#include <xtensa/simcall.h>
30+
31+
#include <linux/tty.h>
32+
#include <linux/tty_flip.h>
33+
34+
#ifdef SERIAL_INLINE
35+
#define _INLINE_ inline
36+
#endif
37+
38+
#define SERIAL_MAX_NUM_LINES 1
39+
#define SERIAL_TIMER_VALUE (20 * HZ)
40+
41+
static struct tty_driver *serial_driver;
42+
static struct timer_list serial_timer;
43+
44+
static DEFINE_SPINLOCK(timer_lock);
45+
46+
int errno;
47+
48+
static int __simc (int a, int b, int c, int d, int e, int f)
49+
{
50+
int ret;
51+
__asm__ __volatile__ ("simcall\n"
52+
"mov %0, a2\n"
53+
"mov %1, a3\n" : "=a" (ret), "=a" (errno)
54+
: : "a2", "a3");
55+
return ret;
56+
}
57+
58+
static char *serial_version = "0.1";
59+
static char *serial_name = "ISS serial driver";
60+
61+
/*
62+
* This routine is called whenever a serial port is opened. It
63+
* enables interrupts for a serial port, linking in its async structure into
64+
* the IRQ chain. It also performs the serial-specific
65+
* initialization for the tty structure.
66+
*/
67+
68+
static void rs_poll(unsigned long);
69+
70+
static int rs_open(struct tty_struct *tty, struct file * filp)
71+
{
72+
int line = tty->index;
73+
74+
if ((line < 0) || (line >= SERIAL_MAX_NUM_LINES))
75+
return -ENODEV;
76+
77+
spin_lock(&timer_lock);
78+
79+
if (tty->count == 1) {
80+
init_timer(&serial_timer);
81+
serial_timer.data = (unsigned long) tty;
82+
serial_timer.function = rs_poll;
83+
mod_timer(&serial_timer, jiffies + SERIAL_TIMER_VALUE);
84+
}
85+
spin_unlock(&timer_lock);
86+
87+
return 0;
88+
}
89+
90+
91+
/*
92+
* ------------------------------------------------------------
93+
* iss_serial_close()
94+
*
95+
* This routine is called when the serial port gets closed. First, we
96+
* wait for the last remaining data to be sent. Then, we unlink its
97+
* async structure from the interrupt chain if necessary, and we free
98+
* that IRQ if nothing is left in the chain.
99+
* ------------------------------------------------------------
100+
*/
101+
static void rs_close(struct tty_struct *tty, struct file * filp)
102+
{
103+
spin_lock(&timer_lock);
104+
if (tty->count == 1)
105+
del_timer_sync(&serial_timer);
106+
spin_unlock(&timer_lock);
107+
}
108+
109+
110+
static int rs_write(struct tty_struct * tty,
111+
const unsigned char *buf, int count)
112+
{
113+
/* see drivers/char/serialX.c to reference original version */
114+
115+
__simc (SYS_write, 1, (unsigned long)buf, count, 0, 0);
116+
return count;
117+
}
118+
119+
static void rs_poll(unsigned long priv)
120+
{
121+
struct tty_struct* tty = (struct tty_struct*) priv;
122+
123+
struct timeval tv = { .tv_sec = 0, .tv_usec = 0 };
124+
int i = 0;
125+
unsigned char c;
126+
127+
spin_lock(&timer_lock);
128+
129+
while (__simc(SYS_select_one, 0, XTISS_SELECT_ONE_READ, (int)&tv,0,0)){
130+
__simc (SYS_read, 0, (unsigned long)&c, 1, 0, 0);
131+
tty->flip.count++;
132+
*tty->flip.char_buf_ptr++ = c;
133+
*tty->flip.flag_buf_ptr++ = TTY_NORMAL;
134+
i++;
135+
}
136+
137+
if (i)
138+
tty_flip_buffer_push(tty);
139+
140+
141+
mod_timer(&serial_timer, jiffies + SERIAL_TIMER_VALUE);
142+
spin_unlock(&timer_lock);
143+
}
144+
145+
146+
static void rs_put_char(struct tty_struct *tty, unsigned char ch)
147+
{
148+
char buf[2];
149+
150+
if (!tty)
151+
return;
152+
153+
buf[0] = ch;
154+
buf[1] = '\0'; /* Is this NULL necessary? */
155+
__simc (SYS_write, 1, (unsigned long) buf, 1, 0, 0);
156+
}
157+
158+
static void rs_flush_chars(struct tty_struct *tty)
159+
{
160+
}
161+
162+
static int rs_write_room(struct tty_struct *tty)
163+
{
164+
/* Let's say iss can always accept 2K characters.. */
165+
return 2 * 1024;
166+
}
167+
168+
static int rs_chars_in_buffer(struct tty_struct *tty)
169+
{
170+
/* the iss doesn't buffer characters */
171+
return 0;
172+
}
173+
174+
static void rs_hangup(struct tty_struct *tty)
175+
{
176+
/* Stub, once again.. */
177+
}
178+
179+
static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
180+
{
181+
/* Stub, once again.. */
182+
}
183+
184+
static int rs_read_proc(char *page, char **start, off_t off, int count,
185+
int *eof, void *data)
186+
{
187+
int len = 0;
188+
off_t begin = 0;
189+
190+
len += sprintf(page, "serinfo:1.0 driver:%s\n", serial_version);
191+
*eof = 1;
192+
193+
if (off >= len + begin)
194+
return 0;
195+
196+
*start = page + (off - begin);
197+
return ((count < begin + len - off) ? count : begin + len - off);
198+
}
199+
200+
201+
int register_serial(struct serial_struct*);
202+
void unregister_serial(int);
203+
204+
static struct tty_operations serial_ops = {
205+
.open = rs_open,
206+
.close = rs_close,
207+
.write = rs_write,
208+
.put_char = rs_put_char,
209+
.flush_chars = rs_flush_chars,
210+
.write_room = rs_write_room,
211+
.chars_in_buffer = rs_chars_in_buffer,
212+
.hangup = rs_hangup,
213+
.wait_until_sent = rs_wait_until_sent,
214+
.read_proc = rs_read_proc
215+
};
216+
217+
int __init rs_init(void)
218+
{
219+
serial_driver = alloc_tty_driver(1);
220+
221+
printk ("%s %s\n", serial_name, serial_version);
222+
223+
/* Initialize the tty_driver structure */
224+
225+
serial_driver->owner = THIS_MODULE;
226+
serial_driver->driver_name = "iss_serial";
227+
serial_driver->name = "ttyS";
228+
serial_driver->major = TTY_MAJOR;
229+
serial_driver->minor_start = 64;
230+
serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
231+
serial_driver->subtype = SERIAL_TYPE_NORMAL;
232+
serial_driver->init_termios = tty_std_termios;
233+
serial_driver->init_termios.c_cflag =
234+
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
235+
serial_driver->flags = TTY_DRIVER_REAL_RAW;
236+
237+
tty_set_operations(serial_driver, &serial_ops);
238+
239+
if (tty_register_driver(serial_driver))
240+
panic("Couldn't register serial driver\n");
241+
return 0;
242+
}
243+
244+
245+
static __exit void rs_exit(void)
246+
{
247+
int error;
248+
249+
if ((error = tty_unregister_driver(serial_driver)))
250+
printk("ISS_SERIAL: failed to unregister serial driver (%d)\n",
251+
error);
252+
put_tty_driver(serial_driver);
253+
}
254+
255+
256+
/* We use `late_initcall' instead of just `__initcall' as a workaround for
257+
* the fact that (1) simcons_tty_init can't be called before tty_init,
258+
* (2) tty_init is called via `module_init', (3) if statically linked,
259+
* module_init == device_init, and (4) there's no ordering of init lists.
260+
* We can do this easily because simcons is always statically linked, but
261+
* other tty drivers that depend on tty_init and which must use
262+
* `module_init' to declare their init routines are likely to be broken.
263+
*/
264+
265+
late_initcall(rs_init);
266+
267+
268+
#ifdef CONFIG_SERIAL_CONSOLE
269+
270+
static void iss_console_write(struct console *co, const char *s, unsigned count)
271+
{
272+
int len = strlen(s);
273+
274+
if (s != 0 && *s != 0)
275+
__simc (SYS_write, 1, (unsigned long)s,
276+
count < len ? count : len,0,0);
277+
}
278+
279+
static struct tty_driver* iss_console_device(struct console *c, int *index)
280+
{
281+
*index = c->index;
282+
return serial_driver;
283+
}
284+
285+
286+
static struct console sercons = {
287+
.name = "ttyS",
288+
.write = iss_console_write,
289+
.device = iss_console_device,
290+
.flags = CON_PRINTBUFFER,
291+
.index = -1
292+
};
293+
294+
static int __init iss_console_init(void)
295+
{
296+
register_console(&sercons);
297+
return 0;
298+
}
299+
300+
console_initcall(iss_console_init);
301+
302+
#endif /* CONFIG_SERIAL_CONSOLE */
303+

arch/xtensa/platform-iss/io.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/* This file isn't really needed right now. */
2+
3+
#if 0
4+
5+
#include <asm/io.h>
6+
#include <xtensa/simcall.h>
7+
8+
extern int __simc ();
9+
10+
11+
char iss_serial_getc()
12+
{
13+
char c;
14+
__simc( SYS_read, 0, &c, 1 );
15+
return c;
16+
}
17+
18+
void iss_serial_putc( char c )
19+
{
20+
__simc( SYS_write, 1, &c, 1 );
21+
}
22+
23+
void iss_serial_puts( char *s )
24+
{
25+
if( s != 0 && *s != 0 )
26+
__simc( SYS_write, 1, s, strlen(s) );
27+
}
28+
29+
/*#error Need I/O ports to specific hardware!*/
30+
31+
#endif
32+

0 commit comments

Comments
 (0)