Changeset 3712


Ignore:
Timestamp:
2006-04-29T00:35:21+02:00 (10 years ago)
Author:
mbm
Message:

update sibyte kernel, fix a few remaining bugs

Location:
trunk/openwrt/target/linux
Files:
6 added
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/openwrt/target/linux/sibyte-2.6/Makefile

    r3701 r3712  
    11include $(TOPDIR)/rules.mk 
    22 
    3 LINUX_VERSION:=2.6.16.4 
     3LINUX_VERSION:=2.6.16.7 
    44LINUX_RELEASE:=1 
    5 LINUX_KERNEL_MD5SUM:=cb675279c9711237a06ebb8379a4da27 
     5LINUX_KERNEL_MD5SUM:=9682b2bd6e02f3087982d7c3f5ba824e 
    66 
    77include ../rules.mk 
  • trunk/openwrt/target/linux/sibyte-2.6/patches/000-DUART.patch

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