OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [char/] [sb1250_duart.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation
3
 *
4
 * This program is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU General Public License
6
 * as published by the Free Software Foundation; either version 2
7
 * of the License, or (at your option) any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software
16
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17
 */
18
 
19
/*
20
 * Driver support for the on-chip sb1250 dual-channel serial port,
21
 * running in asynchronous mode.  Also, support for doing a serial console
22
 * on one of those ports
23
 */
24
#include <linux/config.h>
25
#include <linux/types.h>
26
#include <linux/serial.h>
27
#include <linux/module.h>
28
#include <linux/console.h>
29
#include <linux/kdev_t.h>
30
#include <linux/major.h>
31
#include <linux/termios.h>
32
#include <linux/spinlock.h>
33
#include <linux/irq.h>
34
#include <linux/errno.h>
35
#include <linux/tty.h>
36
#include <linux/sched.h>
37
#include <linux/tty_flip.h>
38
#include <linux/timer.h>
39
#include <linux/init.h>
40
#include <linux/mm.h>
41
#include <asm/delay.h>
42
#include <asm/io.h>
43
#include <asm/uaccess.h>
44
#include <asm/sibyte/swarm.h>
45
#include <asm/sibyte/sb1250_regs.h>
46
#include <asm/sibyte/sb1250_uart.h>
47
#include <asm/sibyte/sb1250_int.h>
48
#include <asm/sibyte/sb1250.h>
49
#include <asm/sibyte/64bit.h>
50
#include <asm/war.h>
51
 
52
/* Toggle spewing of debugging output */
53
#undef DUART_SPEW
54
 
55
#define DEFAULT_CFLAGS          (CS8 | B115200)
56
 
57
#define TX_INTEN          1
58
#define DUART_INITIALIZED 2
59
 
60
#ifndef MIN
61
#define MIN(a,b)        ((a) < (b) ? (a) : (b))
62
#endif
63
 
64
#define DUART_MAX_LINE 2
65
char sb1250_duart_present[DUART_MAX_LINE] = {1,1};
66
 
67
/*
68
 * Still not sure what the termios structures set up here are for,
69
 *  but we have to supply pointers to them to register the tty driver
70
 */
71
static struct tty_driver sb1250_duart_driver, sb1250_duart_callout_driver;
72
static int duart_refcount;
73
static struct tty_struct *duart_table[DUART_MAX_LINE];
74
static struct termios    *duart_termios[DUART_MAX_LINE];
75
static struct termios    *duart_termios_locked[DUART_MAX_LINE];
76
 
77
/*
78
 * This lock protects both the open flags for all the uart states as
79
 * well as the reference count for the module
80
 */
81
static spinlock_t          open_lock = SPIN_LOCK_UNLOCKED;
82
 
83
typedef struct {
84
        unsigned char       outp_buf[SERIAL_XMIT_SIZE];
85
        unsigned int        outp_head;
86
        unsigned int        outp_tail;
87
        unsigned int        outp_count;
88
        spinlock_t          outp_lock;
89
        unsigned int        open;
90
        unsigned int        line;
91
        unsigned int        last_cflags;
92
        unsigned long       flags;
93
        struct tty_struct   *tty;
94
        /* CSR addresses */
95
        u32                 *status;
96
        u32                 *imr;
97
        u32                 *tx_hold;
98
        u32                 *rx_hold;
99
        u32                 *mode_1;
100
        u32                 *mode_2;
101
        u32                 *clk_sel;
102
        u32                 *cmd;
103
} uart_state_t;
104
 
105
static uart_state_t uart_states[DUART_MAX_LINE];
106
 
107
/*
108
 * Inline functions local to this module
109
 */
110
 
111
/*
112
 * In bug 1956, we get glitches that can mess up uart registers.  This
113
 * "write-mode-1 after any register access" is the accepted
114
 * workaround.
115
 */
116
#if SIBYTE_1956_WAR
117
static unsigned int last_mode1[DUART_MAX_LINE];
118
#endif
119
 
120
static inline u32 READ_SERCSR(u32 *addr, int line)
121
{
122
        u32 val = csr_in32(addr);
123
#if SIBYTE_1956_WAR
124
        csr_out32(last_mode1[line], uart_states[line].mode_1);
125
#endif
126
        return val;
127
}
128
 
129
static inline void WRITE_SERCSR(u32 val, u32 *addr, int line)
130
{
131
        csr_out32(val, addr);
132
#if SIBYTE_1956_WAR
133
        csr_out32(last_mode1[line], uart_states[line].mode_1);
134
#endif
135
}
136
 
137
static void init_duart_port(uart_state_t *port, int line)
138
{
139
        if (!(port->flags & DUART_INITIALIZED)) {
140
                port->line = line;
141
                port->status = (u32 *)(IO_SPACE_BASE | A_DUART_CHANREG(line, R_DUART_STATUS));
142
                port->imr = (u32 *)(IO_SPACE_BASE | A_DUART_IMRREG(line));
143
                port->tx_hold = (u32 *)(IO_SPACE_BASE | A_DUART_CHANREG(line, R_DUART_TX_HOLD));
144
                port->rx_hold = (u32 *)(IO_SPACE_BASE | A_DUART_CHANREG(line, R_DUART_RX_HOLD));
145
                port->mode_1 = (u32 *)(IO_SPACE_BASE | A_DUART_CHANREG(line, R_DUART_MODE_REG_1));
146
                port->mode_2 = (u32 *)(IO_SPACE_BASE | A_DUART_CHANREG(line, R_DUART_MODE_REG_2));
147
                port->clk_sel = (u32 *)(IO_SPACE_BASE | A_DUART_CHANREG(line, R_DUART_CLK_SEL));
148
                port->cmd = (u32 *)(IO_SPACE_BASE | A_DUART_CHANREG(line, R_DUART_CMD));
149
                port->flags |= DUART_INITIALIZED;
150
        }
151
}
152
 
153
/*
154
 * Mask out the passed interrupt lines at the duart level.  This should be
155
 * called while holding the associated outp_lock.
156
 */
157
static inline void duart_mask_ints(unsigned int line, unsigned int mask)
158
{
159
        uart_state_t *port = uart_states + line;
160
        u64 tmp = READ_SERCSR(port->imr, line);
161
        WRITE_SERCSR(tmp & ~mask, port->imr, line);
162
}
163
 
164
 
165
/* Unmask the passed interrupt lines at the duart level */
166
static inline void duart_unmask_ints(unsigned int line, unsigned int mask)
167
{
168
        uart_state_t *port = uart_states + line;
169
        u64 tmp = READ_SERCSR(port->imr, line);
170
        WRITE_SERCSR(tmp | mask, port->imr, line);
171
}
172
 
173
static inline void transmit_char_pio(uart_state_t *us)
174
{
175
        struct tty_struct *tty = us->tty;
176
        int blocked = 0;
177
 
178
        if (spin_trylock(&us->outp_lock)) {
179
                for (;;) {
180
                        if (!(READ_SERCSR(us->status, us->line) & M_DUART_TX_RDY))
181
                                break;
182
                        if (us->outp_count <= 0 || tty->stopped || tty->hw_stopped) {
183
                                break;
184
                        } else {
185
                                WRITE_SERCSR(us->outp_buf[us->outp_head],
186
                                             us->tx_hold, us->line);
187
                                us->outp_head = (us->outp_head + 1) & (SERIAL_XMIT_SIZE-1);
188
                                if (--us->outp_count <= 0)
189
                                        break;
190
                        }
191
                        udelay(10);
192
                }
193
                spin_unlock(&us->outp_lock);
194
        } else {
195
                blocked = 1;
196
        }
197
 
198
        if (!us->outp_count || tty->stopped ||
199
            tty->hw_stopped || blocked) {
200
                us->flags &= ~TX_INTEN;
201
                duart_mask_ints(us->line, M_DUART_IMR_TX);
202
        }
203
 
204
        if (us->open &&
205
            (us->outp_count < (SERIAL_XMIT_SIZE/2))) {
206
                /*
207
                 * We told the discipline at one point that we had no
208
                 * space, so it went to sleep.  Wake it up when we hit
209
                 * half empty
210
                 */
211
                if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
212
                    tty->ldisc.write_wakeup)
213
                        tty->ldisc.write_wakeup(tty);
214
                wake_up_interruptible(&tty->write_wait);
215
        }
216
}
217
 
218
/*
219
 * Generic interrupt handler for both channels.  dev_id is a pointer
220
 * to the proper uart_states structure, so from that we can derive
221
 * which port interrupted
222
 */
223
 
224
static void duart_int(int irq, void *dev_id, struct pt_regs *regs)
225
{
226
        uart_state_t *us = (uart_state_t *)dev_id;
227
        struct tty_struct *tty = us->tty;
228
        unsigned int status = READ_SERCSR(us->status, us->line);
229
 
230
#ifdef DUART_SPEW
231
        printk("DUART INT\n");
232
#endif
233
 
234
        if (status & M_DUART_RX_RDY) {
235
                int counter = 2048;
236
                unsigned int ch;
237
 
238
                if (status & M_DUART_OVRUN_ERR)
239
                        tty_insert_flip_char(tty, 0, TTY_OVERRUN);
240
                if (status & M_DUART_PARITY_ERR) {
241
                        printk("Parity error!\n");
242
                } else if (status & M_DUART_FRM_ERR) {
243
                        printk("Frame error!\n");
244
                }
245
 
246
                while (counter > 0) {
247
                        if (!(READ_SERCSR(us->status, us->line) & M_DUART_RX_RDY))
248
                                break;
249
                        ch = READ_SERCSR(us->rx_hold, us->line);
250
                        if (tty->flip.count < TTY_FLIPBUF_SIZE) {
251
                                *tty->flip.char_buf_ptr++ = ch;
252
                                *tty->flip.flag_buf_ptr++ = 0;
253
                                tty->flip.count++;
254
                        }
255
                        udelay(1);
256
                        counter--;
257
                }
258
                tty_flip_buffer_push(tty);
259
        }
260
 
261
        if (status & M_DUART_TX_RDY) {
262
                transmit_char_pio(us);
263
        }
264
}
265
 
266
/*
267
 *  Actual driver functions
268
 */
269
 
270
/* Return the number of characters we can accomodate in a write at this instant */
271
static int duart_write_room(struct tty_struct *tty)
272
{
273
        uart_state_t *us = (uart_state_t *) tty->driver_data;
274
        int retval;
275
 
276
        retval = SERIAL_XMIT_SIZE - us->outp_count;
277
 
278
#ifdef DUART_SPEW
279
        printk("duart_write_room called, returning %i\n", retval);
280
#endif
281
 
282
        return retval;
283
}
284
 
285
/* memcpy the data from src to destination, but take extra care if the
286
   data is coming from user space */
287
static inline int copy_buf(char *dest, const char *src, int size, int from_user)
288
{
289
        if (from_user) {
290
                (void) copy_from_user(dest, src, size);
291
        } else {
292
                memcpy(dest, src, size);
293
        }
294
        return size;
295
}
296
 
297
/*
298
 * Buffer up to count characters from buf to be written.  If we don't have
299
 * other characters buffered, enable the tx interrupt to start sending
300
 */
301
static int duart_write(struct tty_struct * tty, int from_user,
302
        const unsigned char *buf, int count)
303
{
304
        uart_state_t *us;
305
        int c, t, total = 0;
306
        unsigned long flags;
307
 
308
        if (!tty) return 0;
309
 
310
        us = tty->driver_data;
311
        if (!us) return 0;
312
 
313
#ifdef DUART_SPEW
314
        printk("duart_write called for %i chars by %i (%s)\n", count, current->pid, current->comm);
315
#endif
316
 
317
        spin_lock_irqsave(&us->outp_lock, flags);
318
 
319
        for (;;) {
320
                c = count;
321
 
322
                t = SERIAL_XMIT_SIZE - us->outp_tail;
323
                if (t < c) c = t;
324
 
325
                t = SERIAL_XMIT_SIZE - 1 - us->outp_count;
326
                if (t < c) c = t;
327
 
328
                if (c <= 0) break;
329
 
330
                if (from_user) {
331
                        if (copy_from_user(us->outp_buf + us->outp_tail, buf, c)) {
332
                                spin_unlock_irqrestore(&us->outp_lock, flags);
333
                                return -EFAULT;
334
                        }
335
                } else {
336
                        memcpy(us->outp_buf + us->outp_tail, buf, c);
337
                }
338
 
339
                us->outp_count += c;
340
                us->outp_tail = (us->outp_tail + c) & (SERIAL_XMIT_SIZE - 1);
341
                buf += c;
342
                count -= c;
343
                total += c;
344
        }
345
 
346
        spin_unlock_irqrestore(&us->outp_lock, flags);
347
 
348
        if (us->outp_count && !tty->stopped &&
349
            !tty->hw_stopped && !(us->flags & TX_INTEN)) {
350
                us->flags |= TX_INTEN;
351
                duart_unmask_ints(us->line, M_DUART_IMR_TX);
352
        }
353
 
354
        return total;
355
}
356
 
357
 
358
/* Buffer one character to be written.  If there's not room for it, just drop
359
   it on the floor.  This is used for echo, among other things */
360
static void duart_put_char(struct tty_struct *tty, u_char ch)
361
{
362
        uart_state_t *us = (uart_state_t *) tty->driver_data;
363
        unsigned long flags;
364
 
365
#ifdef DUART_SPEW
366
        printk("duart_put_char called.  Char is %x (%c)\n", (int)ch, ch);
367
#endif
368
 
369
        spin_lock_irqsave(&us->outp_lock, flags);
370
 
371
        if (us->outp_count == SERIAL_XMIT_SIZE) {
372
                spin_unlock_irqrestore(&us->outp_lock, flags);
373
                return;
374
        }
375
 
376
        us->outp_buf[us->outp_tail] = ch;
377
        us->outp_tail = (us->outp_tail + 1) &(SERIAL_XMIT_SIZE-1);
378
        us->outp_count++;
379
 
380
        spin_unlock_irqrestore(&us->outp_lock, flags);
381
}
382
 
383
static void duart_flush_chars(struct tty_struct * tty)
384
{
385
        uart_state_t *port;
386
 
387
        if (!tty) return;
388
 
389
        port = tty->driver_data;
390
 
391
        if (!port) return;
392
 
393
        if (port->outp_count <= 0 || tty->stopped || tty->hw_stopped) {
394
                return;
395
        }
396
 
397
        port->flags |= TX_INTEN;
398
        duart_unmask_ints(port->line, M_DUART_IMR_TX);
399
}
400
 
401
/* Return the number of characters in the output buffer that have yet to be
402
   written */
403
static int duart_chars_in_buffer(struct tty_struct *tty)
404
{
405
        uart_state_t *us = (uart_state_t *) tty->driver_data;
406
        int retval;
407
 
408
        retval = us->outp_count;
409
 
410
#ifdef DUART_SPEW
411
        printk("duart_chars_in_buffer returning %i\n", retval);
412
#endif
413
        return retval;
414
}
415
 
416
/* Kill everything we haven't yet shoved into the FIFO.  Turn off the
417
   transmit interrupt since we've nothing more to transmit */
418
static void duart_flush_buffer(struct tty_struct *tty)
419
{
420
        uart_state_t *us = (uart_state_t *) tty->driver_data;
421
        unsigned long flags;
422
 
423
#ifdef DUART_SPEW
424
        printk("duart_flush_buffer called\n");
425
#endif
426
        spin_lock_irqsave(&us->outp_lock, flags);
427
        us->outp_head = us->outp_tail = us->outp_count = 0;
428
        spin_unlock_irqrestore(&us->outp_lock, flags);
429
 
430
        wake_up_interruptible(&us->tty->write_wait);
431
        if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
432
            tty->ldisc.write_wakeup)
433
                tty->ldisc.write_wakeup(tty);
434
}
435
 
436
 
437
/* See sb1250 user manual for details on these registers */
438
static inline void duart_set_cflag(unsigned int line, unsigned int cflag)
439
{
440
        unsigned int mode_reg1 = 0, mode_reg2 = 0;
441
        unsigned int clk_divisor;
442
        uart_state_t *port = uart_states + line;
443
 
444
        switch (cflag & CSIZE) {
445
        case CS7:
446
                mode_reg1 |= V_DUART_BITS_PER_CHAR_7;
447
 
448
        default:
449
                /* We don't handle CS5 or CS6...is there a way we're supposed to flag this?
450
                   right now we just force them to CS8 */
451
                mode_reg1 |= 0x0;
452
                break;
453
        }
454
        if (cflag & CSTOPB) {
455
                mode_reg2 |= M_DUART_STOP_BIT_LEN_2;
456
        }
457
        if (!(cflag & PARENB)) {
458
                mode_reg1 |= V_DUART_PARITY_MODE_NONE;
459
        }
460
        if (cflag & PARODD) {
461
                mode_reg1 |= M_DUART_PARITY_TYPE_ODD;
462
        }
463
 
464
        /* Formula for this is (5000000/baud)-1, but we saturate
465
           at 12 bits, which means we can't actually do anything less
466
           that 1200 baud */
467
        switch (cflag & CBAUD) {
468
        case B200:
469
        case B300:
470
        case B1200:     clk_divisor = 4095;             break;
471
        case B1800:     clk_divisor = 2776;             break;
472
        case B2400:     clk_divisor = 2082;             break;
473
        case B4800:     clk_divisor = 1040;             break;
474
        default:
475
        case B9600:     clk_divisor = 519;              break;
476
        case B19200:    clk_divisor = 259;              break;
477
        case B38400:    clk_divisor = 129;              break;
478
        case B57600:    clk_divisor = 85;               break;
479
        case B115200:   clk_divisor = 42;               break;
480
        }
481
        WRITE_SERCSR(mode_reg1, port->mode_1, port->line);
482
        WRITE_SERCSR(mode_reg2, port->mode_2, port->line);
483
        WRITE_SERCSR(clk_divisor, port->clk_sel, port->line);
484
        port->last_cflags = cflag;
485
}
486
 
487
 
488
/* Handle notification of a termios change.  */
489
static void duart_set_termios(struct tty_struct *tty, struct termios *old)
490
{
491
        uart_state_t *us = (uart_state_t *) tty->driver_data;
492
 
493
#ifdef DUART_SPEW 
494
        printk("duart_set_termios called by %i (%s)\n", current->pid, current->comm);
495
#endif
496
        if (old && tty->termios->c_cflag == old->c_cflag)
497
                return;
498
        duart_set_cflag(us->line, tty->termios->c_cflag);
499
}
500
 
501
static int duart_ioctl(struct tty_struct *tty, struct file * file,
502
                       unsigned int cmd, unsigned long arg)
503
{
504
/*      if (serial_paranoia_check(info, tty->device, "rs_ioctl"))
505
        return -ENODEV;*/
506
        switch (cmd) {
507
        case TIOCMGET:
508
                printk("Ignoring TIOCMGET\n");
509
                break;
510
        case TIOCMBIS:
511
                printk("Ignoring TIOCMBIS\n");
512
                break;
513
        case TIOCMBIC:
514
                printk("Ignoring TIOCMBIC\n");
515
                break;
516
        case TIOCMSET:
517
                printk("Ignoring TIOCMSET\n");
518
                break;
519
        case TIOCGSERIAL:
520
                printk("Ignoring TIOCGSERIAL\n");
521
                break;
522
        case TIOCSSERIAL:
523
                printk("Ignoring TIOCSSERIAL\n");
524
                break;
525
        case TIOCSERCONFIG:
526
                printk("Ignoring TIOCSERCONFIG\n");
527
                break;
528
        case TIOCSERGETLSR: /* Get line status register */
529
                printk("Ignoring TIOCSERGETLSR\n");
530
                break;
531
        case TIOCSERGSTRUCT:
532
                printk("Ignoring TIOCSERGSTRUCT\n");
533
                break;
534
        case TIOCMIWAIT:
535
                printk("Ignoring TIOCMIWAIT\n");
536
                break;
537
        case TIOCGICOUNT:
538
                printk("Ignoring TIOCGICOUNT\n");
539
                break;
540
        case TIOCSERGWILD:
541
                printk("Ignoring TIOCSERGWILD\n");
542
                break;
543
        case TIOCSERSWILD:
544
                printk("Ignoring TIOCSERSWILD\n");
545
                break;
546
        default:
547
                break;
548
        }
549
//      printk("Ignoring IOCTL %x from pid %i (%s)\n", cmd, current->pid, current->comm);
550
        return -ENOIOCTLCMD;
551
#if 0
552
        if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
553
            (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
554
            (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
555
                if (tty->flags & (1 << TTY_IO_ERROR))
556
                        return -EIO;
557
        }
558
 
559
        switch (cmd) {
560
        case TIOCMGET:
561
        case TIOCMBIS:
562
        case TIOCMBIC:
563
        case TIOCMSET:
564
        case TIOCGSERIAL:
565
        case TIOCSSERIAL:
566
        case TIOCSERCONFIG:
567
        case TIOCSERGETLSR: /* Get line status register */
568
        case TIOCSERGSTRUCT:
569
        case TIOCMIWAIT:
570
        case TIOCGICOUNT:
571
        case TIOCSERGWILD:
572
        case TIOCSERSWILD:
573
                /* XXX Implement me! */
574
                printk("IOCTL needs implementing: %x\n", cmd);
575
 
576
        default:
577
                printk("Unknown ioctl: %x\n", cmd);
578
        }
579
#endif
580
        return 0;
581
}
582
 
583
/* XXXKW locking? */
584
static void duart_start(struct tty_struct *tty)
585
{
586
        uart_state_t *us = (uart_state_t *) tty->driver_data;
587
 
588
#ifdef DUART_SPEW
589
        printk("duart_start called\n");
590
#endif
591
 
592
        if (us->outp_count && !(us->flags & TX_INTEN)) {
593
                us->flags |= TX_INTEN;
594
                duart_unmask_ints(us->line, M_DUART_IMR_TX);
595
        }
596
}
597
 
598
/* XXXKW locking? */
599
static void duart_stop(struct tty_struct *tty)
600
{
601
        uart_state_t *us = (uart_state_t *) tty->driver_data;
602
 
603
#ifdef DUART_SPEW
604
        printk("duart_stop called\n");
605
#endif
606
 
607
        if (us->outp_count && (us->flags & TX_INTEN)) {
608
                us->flags &= ~TX_INTEN;
609
                duart_mask_ints(us->line, M_DUART_IMR_TX);
610
        }
611
}
612
 
613
/* Not sure on the semantics of this; are we supposed to wait until the stuff
614
   already in the hardware FIFO drains, or are we supposed to wait until
615
   we've drained the output buffer, too?  I'm assuming the former, 'cause thats
616
   what the other drivers seem to assume
617
*/
618
 
619
static void duart_wait_until_sent(struct tty_struct *tty, int timeout)
620
{
621
        uart_state_t *us = (uart_state_t *) tty->driver_data;
622
        unsigned long orig_jiffies;
623
 
624
        orig_jiffies = jiffies;
625
#ifdef DUART_SPEW
626
        printk("duart_wait_until_sent(%d)+\n", timeout);
627
#endif
628
        while (!(READ_SERCSR(us->status, us->line) & M_DUART_TX_EMT)) {
629
                set_current_state(TASK_INTERRUPTIBLE);
630
                schedule_timeout(1);
631
                if (signal_pending(current))
632
                        break;
633
                if (timeout && time_after(jiffies, orig_jiffies + timeout))
634
                        break;
635
        }
636
#ifdef DUART_SPEW
637
        printk("duart_wait_until_sent()-\n");
638
#endif
639
}
640
 
641
/*
642
 * duart_hangup() --- called by tty_hangup() when a hangup is signaled.
643
 */
644
static void duart_hangup(struct tty_struct *tty)
645
{
646
        uart_state_t *us = (uart_state_t *) tty->driver_data;
647
 
648
        duart_flush_buffer(tty);
649
        us->open = 0;
650
        us->tty = 0;
651
}
652
 
653
/*
654
 * Open a tty line.  Note that this can be called multiple times, so ->open can
655
 * be >1.  Only set up the tty struct if this is a "new" open, e.g. ->open was
656
 * zero
657
 */
658
static int duart_open(struct tty_struct *tty, struct file *filp)
659
{
660
        uart_state_t *us;
661
        unsigned int line = MINOR(tty->device) - tty->driver.minor_start;
662
        unsigned long flags;
663
 
664
        MOD_INC_USE_COUNT;
665
 
666
        if ((line < 0) || (line >= DUART_MAX_LINE) || !sb1250_duart_present[line]) {
667
                MOD_DEC_USE_COUNT;
668
                return -ENODEV;
669
        }
670
 
671
#ifdef DUART_SPEW
672
        printk("duart_open called by %i (%s), tty is %p, rw is %p, ww is %p\n",
673
               current->pid, current->comm, tty, tty->read_wait,
674
               tty->write_wait);
675
#endif
676
 
677
        us = uart_states + line;
678
        tty->driver_data = us;
679
 
680
        spin_lock_irqsave(&open_lock, flags);
681
        if (!us->open) {
682
                us->tty = tty;
683
                us->tty->termios->c_cflag = us->last_cflags;
684
        }
685
        us->open++;
686
        us->flags &= ~TX_INTEN;
687
        duart_unmask_ints(line, M_DUART_IMR_RX);
688
        spin_unlock_irqrestore(&open_lock, flags);
689
 
690
        return 0;
691
}
692
 
693
 
694
/*
695
 * Close a reference count out.  If reference count hits zero, null the
696
 * tty, kill the interrupts.  The tty_io driver is responsible for making
697
 * sure we've cleared out our internal buffers before calling close()
698
 */
699
static void duart_close(struct tty_struct *tty, struct file *filp)
700
{
701
        uart_state_t *us = (uart_state_t *) tty->driver_data;
702
        unsigned long flags;
703
 
704
#ifdef DUART_SPEW
705
        printk("duart_close called by %i (%s)\n", current->pid, current->comm);
706
#endif
707
 
708
        if (!us || !us->open)
709
                return;
710
 
711
        spin_lock_irqsave(&open_lock, flags);
712
        if (tty_hung_up_p(filp)) {
713
                MOD_DEC_USE_COUNT;
714
                spin_unlock_irqrestore(&open_lock, flags);
715
                return;
716
        }
717
 
718
        if (--us->open < 0) {
719
                us->open = 0;
720
                printk(KERN_ERR "duart: bad open count: %d\n", us->open);
721
        }
722
        if (us->open) {
723
                spin_unlock_irqrestore(&open_lock, flags);
724
                return;
725
        }
726
 
727
        spin_unlock_irqrestore(&open_lock, flags);
728
 
729
        tty->closing = 1;
730
 
731
        /* Stop accepting input */
732
        duart_mask_ints(us->line, M_DUART_IMR_RX);
733
        /* Wait for FIFO to drain */
734
        while (!(READ_SERCSR(us->status, us->line) & M_DUART_TX_EMT))
735
                ;
736
 
737
        if (tty->driver.flush_buffer)
738
                tty->driver.flush_buffer(tty);
739
        if (tty->ldisc.flush_buffer)
740
                tty->ldisc.flush_buffer(tty);
741
        tty->closing = 0;
742
 
743
        MOD_DEC_USE_COUNT;
744
}
745
 
746
 
747
/* Set up the driver and register it, register the 2 1250 UART interrupts.  This
748
   is called from tty_init, or as a part of the module init */
749
static int __init sb1250_duart_init(void)
750
{
751
        int i;
752
 
753
        sb1250_duart_driver.magic            = TTY_DRIVER_MAGIC;
754
        sb1250_duart_driver.driver_name      = "serial";
755
#ifdef CONFIG_DEVFS_FS
756
        sb1250_duart_driver.name             = "tts/%d";
757
#else
758
        sb1250_duart_driver.name             = "ttyS";
759
#endif
760
        sb1250_duart_driver.major            = TTY_MAJOR;
761
        sb1250_duart_driver.minor_start      = SB1250_DUART_MINOR_BASE;
762
        sb1250_duart_driver.num              = DUART_MAX_LINE;
763
        sb1250_duart_driver.type             = TTY_DRIVER_TYPE_SERIAL;
764
        sb1250_duart_driver.subtype          = SERIAL_TYPE_NORMAL;
765
        sb1250_duart_driver.init_termios     = tty_std_termios;
766
        sb1250_duart_driver.flags            = TTY_DRIVER_REAL_RAW;
767
        sb1250_duart_driver.refcount         = &duart_refcount;
768
        sb1250_duart_driver.table            = duart_table;
769
        sb1250_duart_driver.termios          = duart_termios;
770
        sb1250_duart_driver.termios_locked   = duart_termios_locked;
771
 
772
        sb1250_duart_driver.open             = duart_open;
773
        sb1250_duart_driver.close            = duart_close;
774
        sb1250_duart_driver.write            = duart_write;
775
        sb1250_duart_driver.put_char         = duart_put_char;
776
        sb1250_duart_driver.write_room       = duart_write_room;
777
        sb1250_duart_driver.flush_chars      = duart_flush_chars;
778
        sb1250_duart_driver.chars_in_buffer  = duart_chars_in_buffer;
779
        sb1250_duart_driver.flush_buffer     = duart_flush_buffer;
780
        sb1250_duart_driver.ioctl            = duart_ioctl;
781
        sb1250_duart_driver.set_termios      = duart_set_termios;
782
        sb1250_duart_driver.stop             = duart_stop;
783
        sb1250_duart_driver.start            = duart_start;
784
        sb1250_duart_driver.hangup           = duart_hangup;
785
        sb1250_duart_driver.wait_until_sent  = duart_wait_until_sent;
786
 
787
        sb1250_duart_callout_driver          = sb1250_duart_driver;
788
#ifdef CONFIG_DEVFS_FS
789
        sb1250_duart_callout_driver.name     = "cua/%d";
790
#else
791
        sb1250_duart_callout_driver.name     = "cua";
792
#endif
793
        sb1250_duart_callout_driver.major    = TTYAUX_MAJOR;
794
        sb1250_duart_callout_driver.subtype  = SERIAL_TYPE_CALLOUT;
795
 
796
        for (i=0; i<DUART_MAX_LINE; i++) {
797
                uart_state_t *port = uart_states + i;
798
 
799
                if (!sb1250_duart_present[i])
800
                        continue;
801
 
802
                init_duart_port(port, i);
803
                spin_lock_init(&port->outp_lock);
804
                duart_mask_ints(i, M_DUART_IMR_ALL);
805
                if (request_irq(K_INT_UART_0+i, duart_int, 0, "uart", port)) {
806
                        panic("Couldn't get uart0 interrupt line");
807
                }
808
                out64(M_DUART_RX_EN|M_DUART_TX_EN,
809
                      IO_SPACE_BASE | A_DUART_CHANREG(i, R_DUART_CMD));
810
                duart_set_cflag(i, DEFAULT_CFLAGS);
811
        }
812
 
813
        /* Interrupts are now active, our ISR can be called. */
814
 
815
        if (tty_register_driver(&sb1250_duart_driver)) {
816
                printk(KERN_ERR "Couldn't register sb1250 duart serial driver\n");
817
        }
818
        if (tty_register_driver(&sb1250_duart_callout_driver)) {
819
                printk(KERN_ERR "Couldn't register sb1250 duart callout driver\n");
820
        }
821
        return 0;
822
}
823
 
824
/* Unload the driver.  Unregister stuff, get ready to go away */
825
static void __exit sb1250_duart_fini(void)
826
{
827
        unsigned long flags;
828
        int i;
829
        int ret;
830
 
831
        save_and_cli(flags);
832
        ret = tty_unregister_driver(&sb1250_duart_callout_driver);
833
        if (ret) {
834
                printk(KERN_ERR "Unable to unregister sb1250 duart callout driver (%d)\n", ret);
835
        }
836
        ret = tty_unregister_driver(&sb1250_duart_driver);
837
        if (ret) {
838
                printk(KERN_ERR "Unable to unregister sb1250 duart serial driver (%d)\n", ret);
839
        }
840
        for (i=0; i<DUART_MAX_LINE; i++) {
841
                if (!sb1250_duart_present[i])
842
                        continue;
843
                free_irq(K_INT_UART_0+i, &uart_states[i]);
844
                disable_irq(K_INT_UART_0+i);
845
        }
846
        restore_flags(flags);
847
}
848
 
849
module_init(sb1250_duart_init);
850
module_exit(sb1250_duart_fini);
851
MODULE_DESCRIPTION("SB1250 Duart serial driver");
852
MODULE_AUTHOR("Justin Carlson, Broadcom Corp.");
853
 
854
#ifdef CONFIG_SIBYTE_SB1250_DUART_CONSOLE
855
 
856
/*
857
 * Serial console stuff.  Very basic, polling driver for doing serial
858
 * console output.  The console_sem is held by the caller, so we
859
 * shouldn't be interrupted for more console activity.
860
 * XXXKW What about getting interrupted by uart driver activity?
861
 */
862
 
863
void serial_outc(unsigned char c, int line)
864
{
865
        uart_state_t *port = uart_states + line;
866
        while (!(READ_SERCSR(port->status, line) & M_DUART_TX_RDY)) ;
867
        WRITE_SERCSR(c, port->tx_hold, line);
868
        while (!(READ_SERCSR(port->status, port->line) & M_DUART_TX_EMT)) ;
869
}
870
 
871
static void ser_console_write(struct console *cons, const char *s,
872
        unsigned int count)
873
{
874
        int line = cons->index;
875
        uart_state_t *port = uart_states + line;
876
        u32 imr;
877
 
878
        imr = READ_SERCSR(port->imr, line);
879
        WRITE_SERCSR(0, port->imr, line);
880
        while (count--) {
881
                if (*s == '\n')
882
                        serial_outc('\r', line);
883
                serial_outc(*s++, line);
884
        }
885
        WRITE_SERCSR(imr, port->imr, line);
886
}
887
 
888
static kdev_t ser_console_device(struct console *c)
889
{
890
        return MKDEV(TTY_MAJOR, SB1250_DUART_MINOR_BASE + c->index);
891
}
892
 
893
static int ser_console_setup(struct console *cons, char *str)
894
{
895
        int i;
896
 
897
        for (i=0; i<DUART_MAX_LINE; i++) {
898
                uart_state_t *port = uart_states + i;
899
 
900
                if (!sb1250_duart_present[i])
901
                        continue;
902
 
903
                init_duart_port(port, i);
904
#if SIBYTE_1956_WAR
905
                last_mode1[i] = V_DUART_PARITY_MODE_NONE|V_DUART_BITS_PER_CHAR_8;
906
#endif
907
                WRITE_SERCSR(V_DUART_PARITY_MODE_NONE|V_DUART_BITS_PER_CHAR_8,
908
                             port->mode_1, i);
909
                WRITE_SERCSR(M_DUART_STOP_BIT_LEN_1,
910
                             port->mode_2, i);
911
                WRITE_SERCSR(V_DUART_BAUD_RATE(115200),
912
                             port->clk_sel, i);
913
                WRITE_SERCSR(M_DUART_RX_EN|M_DUART_TX_EN,
914
                             port->cmd, i);
915
        }
916
        return 0;
917
}
918
 
919
static struct console sb1250_ser_cons = {
920
        name:           "duart",
921
        write:          ser_console_write,
922
        device:         ser_console_device,
923
        setup:          ser_console_setup,
924
        flags:          CON_PRINTBUFFER,
925
        index:          -1,
926
};
927
 
928
void __init sb1250_serial_console_init(void)
929
{
930
        register_console(&sb1250_ser_cons);
931
}
932
 
933
#endif /* CONFIG_SIBYTE_SB1250_DUART_CONSOLE */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.