Index: psc.c =================================================================== --- psc.c (.../kernel/linux/arch/ppc/5xxx_io/psc.c) (Revision 777) +++ psc.c (.../firmware/kernel/linux/arch/ppc/5xxx_io/psc.c) (Arbeitskopie) @@ -29,6 +29,7 @@ #include #include #include +#include #ifdef CONFIG_UBOOT #include #endif @@ -37,7 +38,7 @@ * This driver can spew a whole lot of debugging output at you. If you * need maximum performance, you should disable the DEBUG define. */ -#undef MPC5xxx_PSC_DEBUG +#undef MPC5xxx_PSC_DEBUG #ifdef MPC5xxx_PSC_DEBUG #define MPC5xxx_PSC_DEBUG_OPEN 0x00000001 @@ -55,6 +56,7 @@ #define MPC5xxx_PSC_DEBUG_FIRMWARE 0x00001000 #define MPC5xxx_PSC_DEBUG_MEMTEST 0x00002000 #define MPC5xxx_PSC_DEBUG_THROTTLE 0x00004000 +#define MPC5xxx_PSC_DEBUG_CLEARERR 0x00008000 #define MPC5xxx_PSC_DEBUG_ALL 0xffffffff int rs_debug = MPC5xxx_PSC_DEBUG_ALL & ~MPC5xxx_PSC_DEBUG_TRANSMIT; @@ -150,13 +152,23 @@ int rs_refcount; int rs_initialized = 0; + /* + * proc stuff + */ +static int sio_read_info(char * buf, char ** start, off_t offset, int count, int *eof, void * data ); +static int sio_clear_err(struct file *file, const char *buffer, unsigned long count, void *data); +static struct proc_dir_entry *pProcEntry = NULL; + + +void clear_err(struct mpc5xxx_psc * psc); +/* * ---------------------------------------------------------------------- * * Here starts the interrupt handling routines. All of the following * subroutines are declared as inline and are folded into * rs_interrupt(). They were separated out for readability's sake. - * + *MPC5xxx_PSC_DEBUG_RECEIVE * Note: rs_interrupt() is a "fast" interrupt, which means that it * runs with interrupts turned off. People who may want to modify * rs_interrupt() should try to keep the interrupt handler as fast as @@ -294,19 +306,36 @@ static void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs) { - struct rs_port * port; + struct rs_port * port = (struct rs_port *)dev_id; + struct mpc5xxx_psc *psc = port->psc; unsigned long flags; + u16 status; spin_lock_irqsave(&mpc5xxx_serial_lock, flags); - port = (struct rs_port *)dev_id; + rs_dprintk(MPC5xxx_PSC_DEBUG_INTERRUPTS, "rs_interrupt (port %p)...", port); + if (!port || !port->gs.tty) { + printk( KERN_DEBUG"%s(%d): port=%p tty=%p\n", __FUNCTION__, __LINE__, + port, port?port->gs.tty:NULL ); + goto out; + } + + status = in_be16(&psc->mpc5xxx_psc_status); + /* RB-Bit is set ? */ + if(status & MPC5xxx_PSC_SR_RB) + { + clear_err(psc); + rs_dprintk(MPC5xxx_PSC_DEBUG_INTERRUPTS, "clear err in isr nach status %d.\n", status); + goto out; + } + receive_char(port); transmit_char(port); - +out: spin_unlock_irqrestore(&mpc5xxx_serial_lock, flags); rs_dprintk(MPC5xxx_PSC_DEBUG_INTERRUPTS, "end.\n"); @@ -318,7 +347,7 @@ * interface with the generic_serial driver * ************************************************************************ */ -static void rs_disable_tx_interrupts(void * ptr) +static void rs_disable_tx_interrupts(void * ptr) { struct rs_port *port = ptr; struct mpc5xxx_psc *psc = port->psc; @@ -360,7 +389,7 @@ port->imr &= ~MPC5xxx_PSC_IMR_RXRDY; out_be16(&psc->mpc5xxx_psc_imr, port->imr); - + rs_dprintk(MPC5xxx_PSC_DEBUG_RECEIVE,"disable RxInt\n"); spin_unlock_irqrestore(&mpc5xxx_serial_lock, flags); } @@ -382,7 +411,7 @@ * while (in_be16(&psc->mpc5xxx_psc_status) & MPC5xxx_PSC_SR_RXRDY) * in_8(&psc->mpc5xxx_psc_buffer_8); */ - + rs_dprintk(MPC5xxx_PSC_DEBUG_RECEIVE,"enable RxInt\n"); spin_unlock_irqrestore(&mpc5xxx_serial_lock, flags); } @@ -442,9 +471,15 @@ val32 |= (MPC5xxx_GPIO_PSC_CONFIG_UART_WITHOUT_CD << (4*line)); out_be32(&gpio->port_config, val32); /* reset and enable PSC */ - out_8(&psc->command, MPC5xxx_PSC_RST_TX - | MPC5xxx_PSC_RX_DISABLE | MPC5xxx_PSC_TX_ENABLE); - out_8(&psc->command, MPC5xxx_PSC_RST_RX); +// out_8(&psc->command, MPC5xxx_PSC_RST_TX +// | MPC5xxx_PSC_RX_DISABLE | MPC5xxx_PSC_TX_ENABLE); +// out_8(&psc->command, MPC5xxx_PSC_RST_RX); + + /* neu */ + /* reset and enable PSC */ + out_8(&psc->command, MPC5xxx_PSC_RST_TX | MPC5xxx_PSC_TX_ENABLE); + //out_8(&psc->command, MPC5xxx_PSC_RST_RX); + /* ende neu*/ /* Set PSC operation mode as 'UART, DCD ignored' */ out_be32(&psc->sicr, 0x0); /* Set clocking */ @@ -539,7 +574,7 @@ line = minor(tty->device) - tty->driver.minor_start; rs_dprintk(MPC5xxx_PSC_DEBUG_OPEN, - "%d: opening line %d. tty=%p ctty=%p)\n", + "%d: opening line %d. tty=%p ctty=%p)\n", (int) current->pid, line, tty, current->tty); if ((line < 0) || (line >= RS_TABLE_SIZE)) @@ -813,6 +848,7 @@ #endif rs_dprintk(MPC5xxx_PSC_DEBUG_INIT, "psc base 0x%08lx\n", (unsigned long)port->psc); + clear_err(port->psc); port++; } @@ -878,6 +914,11 @@ return 1; } + //pProcEntry = create_proc_read_entry("driver/sio0",0444,NULL,sio_read_info,NULL); + pProcEntry = create_proc_entry("driver/sio0",0444,NULL); + pProcEntry->read_proc = sio_read_info; + pProcEntry->write_proc = sio_clear_err; + pProcEntry->owner = THIS_MODULE; func_exit(); return 0; } @@ -1094,3 +1135,61 @@ } #endif +static int sio_read_info(char * buf, char ** start, off_t offset, int count, int *eof, void * data ) +{ + + int len = 0; + struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *) MPC5xxx_PSC1; + u16 nStat; + + *eof = 1; + *buf = 0; + nStat = in_be16(&psc->mpc5xxx_psc_status); + if(count > len + 120) + { + len += sprintf(buf+len, "\n Status PSC 1: %d",nStat); + len += sprintf(buf+len, "\n RB: %d",(nStat & MPC5xxx_PSC_SR_RB) ? 1 : 0); + len += sprintf(buf+len, "\n FE: %d",(nStat & MPC5xxx_PSC_SR_FE) ? 1 : 0); + len += sprintf(buf+len, "\n PE: %d",(nStat & MPC5xxx_PSC_SR_PE) ? 1 : 0); + len += sprintf(buf+len, "\n OR: %d",(nStat & MPC5xxx_PSC_SR_OE) ? 1 : 0); + len += sprintf(buf+len, "\n TxEMP: %d",(nStat & MPC5xxx_PSC_SR_TXEMP) ? 1 : 0); + len += sprintf(buf+len, "\n TxRDY: %d",(nStat & MPC5xxx_PSC_SR_TXRDY) ? 1 : 0); + len += sprintf(buf+len, "\n RXFULL: %d",(nStat & MPC5xxx_PSC_SR_RXFULL) ? 1 : 0); + len += sprintf(buf+len, "\n RxRDY: %d",(nStat & MPC5xxx_PSC_SR_RXRDY) ? 1 : 0); + len += sprintf(buf+len, "\n CDE: %d\n",(nStat & MPC5xxx_PSC_SR_CDE) ? 1 : 0); + + } + return len; + +} +static int sio_clear_err(struct file *file, const char *buffer, unsigned long count, void *data) +{ + + struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *) MPC5xxx_PSC1; + + clear_err(psc); + return (int)count; +} + +void clear_err(struct mpc5xxx_psc * psc) +{ + u8 byCmd; + u16 i; + unsigned int status, nBytes; + + nBytes = in_be16(&psc->rfnum) & MPC5xxx_PSC_RFNUM_MASK; + for(i=0; i< nBytes;i++) + { + byCmd = in_8(&psc->mpc5xxx_psc_buffer_8); + rs_dprintk(MPC5xxx_PSC_DEBUG_CLEARERR,"loesche Byte %d von %d Bytes\n",i+1,nBytes); + } + status = in_be16(&psc->mpc5xxx_psc_status); + rs_dprintk(MPC5xxx_PSC_DEBUG_CLEARERR,"status Start %d\n",status); + byCmd = (u8) MPC5xxx_PSC_RST_ERR_STAT; + out_8(&psc->command, byCmd); + wmb(); + status = in_be16(&psc->mpc5xxx_psc_status); + rmb(); + rs_dprintk(MPC5xxx_PSC_DEBUG_CLEARERR,"status clear %d\n",status); +} +