1*16b195c8SJean-Christophe PLAGNIOL-VILLARD /*********************************************************************** 2*16b195c8SJean-Christophe PLAGNIOL-VILLARD * 3*16b195c8SJean-Christophe PLAGNIOL-VILLARD * (C) Copyright 2004 4*16b195c8SJean-Christophe PLAGNIOL-VILLARD * DENX Software Engineering 5*16b195c8SJean-Christophe PLAGNIOL-VILLARD * Wolfgang Denk, wd@denx.de 6*16b195c8SJean-Christophe PLAGNIOL-VILLARD * All rights reserved. 7*16b195c8SJean-Christophe PLAGNIOL-VILLARD * 8*16b195c8SJean-Christophe PLAGNIOL-VILLARD * Simple 16550A serial driver 9*16b195c8SJean-Christophe PLAGNIOL-VILLARD * 10*16b195c8SJean-Christophe PLAGNIOL-VILLARD * Originally from linux source (drivers/char/ps2ser.c) 11*16b195c8SJean-Christophe PLAGNIOL-VILLARD * 12*16b195c8SJean-Christophe PLAGNIOL-VILLARD * Used by the PS/2 multiplexer driver (ps2mult.c) 13*16b195c8SJean-Christophe PLAGNIOL-VILLARD * 14*16b195c8SJean-Christophe PLAGNIOL-VILLARD ***********************************************************************/ 15*16b195c8SJean-Christophe PLAGNIOL-VILLARD 16*16b195c8SJean-Christophe PLAGNIOL-VILLARD #include <common.h> 17*16b195c8SJean-Christophe PLAGNIOL-VILLARD 18*16b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_PS2SERIAL 19*16b195c8SJean-Christophe PLAGNIOL-VILLARD 20*16b195c8SJean-Christophe PLAGNIOL-VILLARD #include <asm/io.h> 21*16b195c8SJean-Christophe PLAGNIOL-VILLARD #include <asm/atomic.h> 22*16b195c8SJean-Christophe PLAGNIOL-VILLARD #include <ps2mult.h> 23*16b195c8SJean-Christophe PLAGNIOL-VILLARD #if defined(CFG_NS16550) || defined(CONFIG_MPC85xx) 24*16b195c8SJean-Christophe PLAGNIOL-VILLARD #include <ns16550.h> 25*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 26*16b195c8SJean-Christophe PLAGNIOL-VILLARD 27*16b195c8SJean-Christophe PLAGNIOL-VILLARD DECLARE_GLOBAL_DATA_PTR; 28*16b195c8SJean-Christophe PLAGNIOL-VILLARD 29*16b195c8SJean-Christophe PLAGNIOL-VILLARD /* #define DEBUG */ 30*16b195c8SJean-Christophe PLAGNIOL-VILLARD 31*16b195c8SJean-Christophe PLAGNIOL-VILLARD #define PS2SER_BAUD 57600 32*16b195c8SJean-Christophe PLAGNIOL-VILLARD 33*16b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC5xxx 34*16b195c8SJean-Christophe PLAGNIOL-VILLARD #if CONFIG_PS2SERIAL == 1 35*16b195c8SJean-Christophe PLAGNIOL-VILLARD #define PSC_BASE MPC5XXX_PSC1 36*16b195c8SJean-Christophe PLAGNIOL-VILLARD #elif CONFIG_PS2SERIAL == 2 37*16b195c8SJean-Christophe PLAGNIOL-VILLARD #define PSC_BASE MPC5XXX_PSC2 38*16b195c8SJean-Christophe PLAGNIOL-VILLARD #elif CONFIG_PS2SERIAL == 3 39*16b195c8SJean-Christophe PLAGNIOL-VILLARD #define PSC_BASE MPC5XXX_PSC3 40*16b195c8SJean-Christophe PLAGNIOL-VILLARD #elif defined(CONFIG_MGT5100) 41*16b195c8SJean-Christophe PLAGNIOL-VILLARD #error CONFIG_PS2SERIAL must be in 1, 2 or 3 42*16b195c8SJean-Christophe PLAGNIOL-VILLARD #elif CONFIG_PS2SERIAL == 4 43*16b195c8SJean-Christophe PLAGNIOL-VILLARD #define PSC_BASE MPC5XXX_PSC4 44*16b195c8SJean-Christophe PLAGNIOL-VILLARD #elif CONFIG_PS2SERIAL == 5 45*16b195c8SJean-Christophe PLAGNIOL-VILLARD #define PSC_BASE MPC5XXX_PSC5 46*16b195c8SJean-Christophe PLAGNIOL-VILLARD #elif CONFIG_PS2SERIAL == 6 47*16b195c8SJean-Christophe PLAGNIOL-VILLARD #define PSC_BASE MPC5XXX_PSC6 48*16b195c8SJean-Christophe PLAGNIOL-VILLARD #else 49*16b195c8SJean-Christophe PLAGNIOL-VILLARD #error CONFIG_PS2SERIAL must be in 1 ... 6 50*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 51*16b195c8SJean-Christophe PLAGNIOL-VILLARD 52*16b195c8SJean-Christophe PLAGNIOL-VILLARD #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || defined(CONFIG_MPC8555) 53*16b195c8SJean-Christophe PLAGNIOL-VILLARD 54*16b195c8SJean-Christophe PLAGNIOL-VILLARD #if CONFIG_PS2SERIAL == 1 55*16b195c8SJean-Christophe PLAGNIOL-VILLARD #define COM_BASE (CFG_CCSRBAR+0x4500) 56*16b195c8SJean-Christophe PLAGNIOL-VILLARD #elif CONFIG_PS2SERIAL == 2 57*16b195c8SJean-Christophe PLAGNIOL-VILLARD #define COM_BASE (CFG_CCSRBAR+0x4600) 58*16b195c8SJean-Christophe PLAGNIOL-VILLARD #else 59*16b195c8SJean-Christophe PLAGNIOL-VILLARD #error CONFIG_PS2SERIAL must be in 1 ... 2 60*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 61*16b195c8SJean-Christophe PLAGNIOL-VILLARD 62*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif /* CONFIG_MPC5xxx / CONFIG_MPC8540 / other */ 63*16b195c8SJean-Christophe PLAGNIOL-VILLARD 64*16b195c8SJean-Christophe PLAGNIOL-VILLARD static int ps2ser_getc_hw(void); 65*16b195c8SJean-Christophe PLAGNIOL-VILLARD static void ps2ser_interrupt(void *dev_id); 66*16b195c8SJean-Christophe PLAGNIOL-VILLARD 67*16b195c8SJean-Christophe PLAGNIOL-VILLARD extern struct serial_state rs_table[]; /* in serial.c */ 68*16b195c8SJean-Christophe PLAGNIOL-VILLARD #if !defined(CONFIG_MPC5xxx) && !defined(CONFIG_MPC8540) && !defined(CONFIG_MPC8541) && !defined(CONFIG_MPC8555) 69*16b195c8SJean-Christophe PLAGNIOL-VILLARD static struct serial_state *state; 70*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 71*16b195c8SJean-Christophe PLAGNIOL-VILLARD 72*16b195c8SJean-Christophe PLAGNIOL-VILLARD static u_char ps2buf[PS2BUF_SIZE]; 73*16b195c8SJean-Christophe PLAGNIOL-VILLARD static atomic_t ps2buf_cnt; 74*16b195c8SJean-Christophe PLAGNIOL-VILLARD static int ps2buf_in_idx; 75*16b195c8SJean-Christophe PLAGNIOL-VILLARD static int ps2buf_out_idx; 76*16b195c8SJean-Christophe PLAGNIOL-VILLARD 77*16b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC5xxx 78*16b195c8SJean-Christophe PLAGNIOL-VILLARD int ps2ser_init(void) 79*16b195c8SJean-Christophe PLAGNIOL-VILLARD { 80*16b195c8SJean-Christophe PLAGNIOL-VILLARD volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE; 81*16b195c8SJean-Christophe PLAGNIOL-VILLARD unsigned long baseclk; 82*16b195c8SJean-Christophe PLAGNIOL-VILLARD int div; 83*16b195c8SJean-Christophe PLAGNIOL-VILLARD 84*16b195c8SJean-Christophe PLAGNIOL-VILLARD /* reset PSC */ 85*16b195c8SJean-Christophe PLAGNIOL-VILLARD psc->command = PSC_SEL_MODE_REG_1; 86*16b195c8SJean-Christophe PLAGNIOL-VILLARD 87*16b195c8SJean-Christophe PLAGNIOL-VILLARD /* select clock sources */ 88*16b195c8SJean-Christophe PLAGNIOL-VILLARD #if defined(CONFIG_MGT5100) 89*16b195c8SJean-Christophe PLAGNIOL-VILLARD psc->psc_clock_select = 0xdd00; 90*16b195c8SJean-Christophe PLAGNIOL-VILLARD baseclk = (CFG_MPC5XXX_CLKIN + 16) / 32; 91*16b195c8SJean-Christophe PLAGNIOL-VILLARD #elif defined(CONFIG_MPC5200) 92*16b195c8SJean-Christophe PLAGNIOL-VILLARD psc->psc_clock_select = 0; 93*16b195c8SJean-Christophe PLAGNIOL-VILLARD baseclk = (gd->ipb_clk + 16) / 32; 94*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 95*16b195c8SJean-Christophe PLAGNIOL-VILLARD 96*16b195c8SJean-Christophe PLAGNIOL-VILLARD /* switch to UART mode */ 97*16b195c8SJean-Christophe PLAGNIOL-VILLARD psc->sicr = 0; 98*16b195c8SJean-Christophe PLAGNIOL-VILLARD 99*16b195c8SJean-Christophe PLAGNIOL-VILLARD /* configure parity, bit length and so on */ 100*16b195c8SJean-Christophe PLAGNIOL-VILLARD #if defined(CONFIG_MGT5100) 101*16b195c8SJean-Christophe PLAGNIOL-VILLARD psc->mode = PSC_MODE_ERR | PSC_MODE_8_BITS | PSC_MODE_PARNONE; 102*16b195c8SJean-Christophe PLAGNIOL-VILLARD #elif defined(CONFIG_MPC5200) 103*16b195c8SJean-Christophe PLAGNIOL-VILLARD psc->mode = PSC_MODE_8_BITS | PSC_MODE_PARNONE; 104*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 105*16b195c8SJean-Christophe PLAGNIOL-VILLARD psc->mode = PSC_MODE_ONE_STOP; 106*16b195c8SJean-Christophe PLAGNIOL-VILLARD 107*16b195c8SJean-Christophe PLAGNIOL-VILLARD /* set up UART divisor */ 108*16b195c8SJean-Christophe PLAGNIOL-VILLARD div = (baseclk + (PS2SER_BAUD/2)) / PS2SER_BAUD; 109*16b195c8SJean-Christophe PLAGNIOL-VILLARD psc->ctur = (div >> 8) & 0xff; 110*16b195c8SJean-Christophe PLAGNIOL-VILLARD psc->ctlr = div & 0xff; 111*16b195c8SJean-Christophe PLAGNIOL-VILLARD 112*16b195c8SJean-Christophe PLAGNIOL-VILLARD /* disable all interrupts */ 113*16b195c8SJean-Christophe PLAGNIOL-VILLARD psc->psc_imr = 0; 114*16b195c8SJean-Christophe PLAGNIOL-VILLARD 115*16b195c8SJean-Christophe PLAGNIOL-VILLARD /* reset and enable Rx/Tx */ 116*16b195c8SJean-Christophe PLAGNIOL-VILLARD psc->command = PSC_RST_RX; 117*16b195c8SJean-Christophe PLAGNIOL-VILLARD psc->command = PSC_RST_TX; 118*16b195c8SJean-Christophe PLAGNIOL-VILLARD psc->command = PSC_RX_ENABLE | PSC_TX_ENABLE; 119*16b195c8SJean-Christophe PLAGNIOL-VILLARD 120*16b195c8SJean-Christophe PLAGNIOL-VILLARD return (0); 121*16b195c8SJean-Christophe PLAGNIOL-VILLARD } 122*16b195c8SJean-Christophe PLAGNIOL-VILLARD 123*16b195c8SJean-Christophe PLAGNIOL-VILLARD #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || defined(CONFIG_MPC8555) 124*16b195c8SJean-Christophe PLAGNIOL-VILLARD int ps2ser_init(void) 125*16b195c8SJean-Christophe PLAGNIOL-VILLARD { 126*16b195c8SJean-Christophe PLAGNIOL-VILLARD NS16550_t com_port = (NS16550_t)COM_BASE; 127*16b195c8SJean-Christophe PLAGNIOL-VILLARD 128*16b195c8SJean-Christophe PLAGNIOL-VILLARD com_port->ier = 0x00; 129*16b195c8SJean-Christophe PLAGNIOL-VILLARD com_port->lcr = LCR_BKSE | LCR_8N1; 130*16b195c8SJean-Christophe PLAGNIOL-VILLARD com_port->dll = (CFG_NS16550_CLK / 16 / PS2SER_BAUD) & 0xff; 131*16b195c8SJean-Christophe PLAGNIOL-VILLARD com_port->dlm = ((CFG_NS16550_CLK / 16 / PS2SER_BAUD) >> 8) & 0xff; 132*16b195c8SJean-Christophe PLAGNIOL-VILLARD com_port->lcr = LCR_8N1; 133*16b195c8SJean-Christophe PLAGNIOL-VILLARD com_port->mcr = (MCR_DTR | MCR_RTS); 134*16b195c8SJean-Christophe PLAGNIOL-VILLARD com_port->fcr = (FCR_FIFO_EN | FCR_RXSR | FCR_TXSR); 135*16b195c8SJean-Christophe PLAGNIOL-VILLARD 136*16b195c8SJean-Christophe PLAGNIOL-VILLARD return (0); 137*16b195c8SJean-Christophe PLAGNIOL-VILLARD } 138*16b195c8SJean-Christophe PLAGNIOL-VILLARD 139*16b195c8SJean-Christophe PLAGNIOL-VILLARD #else /* !CONFIG_MPC5xxx && !CONFIG_MPC8540 / other */ 140*16b195c8SJean-Christophe PLAGNIOL-VILLARD 141*16b195c8SJean-Christophe PLAGNIOL-VILLARD static inline unsigned int ps2ser_in(int offset) 142*16b195c8SJean-Christophe PLAGNIOL-VILLARD { 143*16b195c8SJean-Christophe PLAGNIOL-VILLARD return readb((unsigned long) state->iomem_base + offset); 144*16b195c8SJean-Christophe PLAGNIOL-VILLARD } 145*16b195c8SJean-Christophe PLAGNIOL-VILLARD 146*16b195c8SJean-Christophe PLAGNIOL-VILLARD static inline void ps2ser_out(int offset, int value) 147*16b195c8SJean-Christophe PLAGNIOL-VILLARD { 148*16b195c8SJean-Christophe PLAGNIOL-VILLARD writeb(value, (unsigned long) state->iomem_base + offset); 149*16b195c8SJean-Christophe PLAGNIOL-VILLARD } 150*16b195c8SJean-Christophe PLAGNIOL-VILLARD 151*16b195c8SJean-Christophe PLAGNIOL-VILLARD int ps2ser_init(void) 152*16b195c8SJean-Christophe PLAGNIOL-VILLARD { 153*16b195c8SJean-Christophe PLAGNIOL-VILLARD int quot; 154*16b195c8SJean-Christophe PLAGNIOL-VILLARD unsigned cval; 155*16b195c8SJean-Christophe PLAGNIOL-VILLARD 156*16b195c8SJean-Christophe PLAGNIOL-VILLARD state = rs_table + CONFIG_PS2SERIAL; 157*16b195c8SJean-Christophe PLAGNIOL-VILLARD 158*16b195c8SJean-Christophe PLAGNIOL-VILLARD quot = state->baud_base / PS2SER_BAUD; 159*16b195c8SJean-Christophe PLAGNIOL-VILLARD cval = 0x3; /* 8N1 - 8 data bits, no parity bits, 1 stop bit */ 160*16b195c8SJean-Christophe PLAGNIOL-VILLARD 161*16b195c8SJean-Christophe PLAGNIOL-VILLARD /* Set speed, enable interrupts, enable FIFO 162*16b195c8SJean-Christophe PLAGNIOL-VILLARD */ 163*16b195c8SJean-Christophe PLAGNIOL-VILLARD ps2ser_out(UART_LCR, cval | UART_LCR_DLAB); 164*16b195c8SJean-Christophe PLAGNIOL-VILLARD ps2ser_out(UART_DLL, quot & 0xff); 165*16b195c8SJean-Christophe PLAGNIOL-VILLARD ps2ser_out(UART_DLM, quot >> 8); 166*16b195c8SJean-Christophe PLAGNIOL-VILLARD ps2ser_out(UART_LCR, cval); 167*16b195c8SJean-Christophe PLAGNIOL-VILLARD ps2ser_out(UART_IER, UART_IER_RDI); 168*16b195c8SJean-Christophe PLAGNIOL-VILLARD ps2ser_out(UART_MCR, UART_MCR_OUT2 | UART_MCR_DTR | UART_MCR_RTS); 169*16b195c8SJean-Christophe PLAGNIOL-VILLARD ps2ser_out(UART_FCR, 170*16b195c8SJean-Christophe PLAGNIOL-VILLARD UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); 171*16b195c8SJean-Christophe PLAGNIOL-VILLARD 172*16b195c8SJean-Christophe PLAGNIOL-VILLARD /* If we read 0xff from the LSR, there is no UART here 173*16b195c8SJean-Christophe PLAGNIOL-VILLARD */ 174*16b195c8SJean-Christophe PLAGNIOL-VILLARD if (ps2ser_in(UART_LSR) == 0xff) { 175*16b195c8SJean-Christophe PLAGNIOL-VILLARD printf ("ps2ser.c: no UART found\n"); 176*16b195c8SJean-Christophe PLAGNIOL-VILLARD return -1; 177*16b195c8SJean-Christophe PLAGNIOL-VILLARD } 178*16b195c8SJean-Christophe PLAGNIOL-VILLARD 179*16b195c8SJean-Christophe PLAGNIOL-VILLARD irq_install_handler(state->irq, ps2ser_interrupt, NULL); 180*16b195c8SJean-Christophe PLAGNIOL-VILLARD 181*16b195c8SJean-Christophe PLAGNIOL-VILLARD return 0; 182*16b195c8SJean-Christophe PLAGNIOL-VILLARD } 183*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif /* CONFIG_MPC5xxx / CONFIG_MPC8540 / other */ 184*16b195c8SJean-Christophe PLAGNIOL-VILLARD 185*16b195c8SJean-Christophe PLAGNIOL-VILLARD void ps2ser_putc(int chr) 186*16b195c8SJean-Christophe PLAGNIOL-VILLARD { 187*16b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC5xxx 188*16b195c8SJean-Christophe PLAGNIOL-VILLARD volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE; 189*16b195c8SJean-Christophe PLAGNIOL-VILLARD #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || defined(CONFIG_MPC8555) 190*16b195c8SJean-Christophe PLAGNIOL-VILLARD NS16550_t com_port = (NS16550_t)COM_BASE; 191*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 192*16b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG 193*16b195c8SJean-Christophe PLAGNIOL-VILLARD printf(">>>> 0x%02x\n", chr); 194*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 195*16b195c8SJean-Christophe PLAGNIOL-VILLARD 196*16b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC5xxx 197*16b195c8SJean-Christophe PLAGNIOL-VILLARD while (!(psc->psc_status & PSC_SR_TXRDY)); 198*16b195c8SJean-Christophe PLAGNIOL-VILLARD 199*16b195c8SJean-Christophe PLAGNIOL-VILLARD psc->psc_buffer_8 = chr; 200*16b195c8SJean-Christophe PLAGNIOL-VILLARD #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || defined(CONFIG_MPC8555) 201*16b195c8SJean-Christophe PLAGNIOL-VILLARD while ((com_port->lsr & LSR_THRE) == 0); 202*16b195c8SJean-Christophe PLAGNIOL-VILLARD com_port->thr = chr; 203*16b195c8SJean-Christophe PLAGNIOL-VILLARD #else 204*16b195c8SJean-Christophe PLAGNIOL-VILLARD while (!(ps2ser_in(UART_LSR) & UART_LSR_THRE)); 205*16b195c8SJean-Christophe PLAGNIOL-VILLARD 206*16b195c8SJean-Christophe PLAGNIOL-VILLARD ps2ser_out(UART_TX, chr); 207*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 208*16b195c8SJean-Christophe PLAGNIOL-VILLARD } 209*16b195c8SJean-Christophe PLAGNIOL-VILLARD 210*16b195c8SJean-Christophe PLAGNIOL-VILLARD static int ps2ser_getc_hw(void) 211*16b195c8SJean-Christophe PLAGNIOL-VILLARD { 212*16b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC5xxx 213*16b195c8SJean-Christophe PLAGNIOL-VILLARD volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE; 214*16b195c8SJean-Christophe PLAGNIOL-VILLARD #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || defined(CONFIG_MPC8555) 215*16b195c8SJean-Christophe PLAGNIOL-VILLARD NS16550_t com_port = (NS16550_t)COM_BASE; 216*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 217*16b195c8SJean-Christophe PLAGNIOL-VILLARD int res = -1; 218*16b195c8SJean-Christophe PLAGNIOL-VILLARD 219*16b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC5xxx 220*16b195c8SJean-Christophe PLAGNIOL-VILLARD if (psc->psc_status & PSC_SR_RXRDY) { 221*16b195c8SJean-Christophe PLAGNIOL-VILLARD res = (psc->psc_buffer_8); 222*16b195c8SJean-Christophe PLAGNIOL-VILLARD } 223*16b195c8SJean-Christophe PLAGNIOL-VILLARD #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || defined(CONFIG_MPC8555) 224*16b195c8SJean-Christophe PLAGNIOL-VILLARD if (com_port->lsr & LSR_DR) { 225*16b195c8SJean-Christophe PLAGNIOL-VILLARD res = com_port->rbr; 226*16b195c8SJean-Christophe PLAGNIOL-VILLARD } 227*16b195c8SJean-Christophe PLAGNIOL-VILLARD #else 228*16b195c8SJean-Christophe PLAGNIOL-VILLARD if (ps2ser_in(UART_LSR) & UART_LSR_DR) { 229*16b195c8SJean-Christophe PLAGNIOL-VILLARD res = (ps2ser_in(UART_RX)); 230*16b195c8SJean-Christophe PLAGNIOL-VILLARD } 231*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 232*16b195c8SJean-Christophe PLAGNIOL-VILLARD 233*16b195c8SJean-Christophe PLAGNIOL-VILLARD return res; 234*16b195c8SJean-Christophe PLAGNIOL-VILLARD } 235*16b195c8SJean-Christophe PLAGNIOL-VILLARD 236*16b195c8SJean-Christophe PLAGNIOL-VILLARD int ps2ser_getc(void) 237*16b195c8SJean-Christophe PLAGNIOL-VILLARD { 238*16b195c8SJean-Christophe PLAGNIOL-VILLARD volatile int chr; 239*16b195c8SJean-Christophe PLAGNIOL-VILLARD int flags; 240*16b195c8SJean-Christophe PLAGNIOL-VILLARD 241*16b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG 242*16b195c8SJean-Christophe PLAGNIOL-VILLARD printf("<< "); 243*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 244*16b195c8SJean-Christophe PLAGNIOL-VILLARD 245*16b195c8SJean-Christophe PLAGNIOL-VILLARD flags = disable_interrupts(); 246*16b195c8SJean-Christophe PLAGNIOL-VILLARD 247*16b195c8SJean-Christophe PLAGNIOL-VILLARD do { 248*16b195c8SJean-Christophe PLAGNIOL-VILLARD if (atomic_read(&ps2buf_cnt) != 0) { 249*16b195c8SJean-Christophe PLAGNIOL-VILLARD chr = ps2buf[ps2buf_out_idx++]; 250*16b195c8SJean-Christophe PLAGNIOL-VILLARD ps2buf_out_idx &= (PS2BUF_SIZE - 1); 251*16b195c8SJean-Christophe PLAGNIOL-VILLARD atomic_dec(&ps2buf_cnt); 252*16b195c8SJean-Christophe PLAGNIOL-VILLARD } else { 253*16b195c8SJean-Christophe PLAGNIOL-VILLARD chr = ps2ser_getc_hw(); 254*16b195c8SJean-Christophe PLAGNIOL-VILLARD } 255*16b195c8SJean-Christophe PLAGNIOL-VILLARD } 256*16b195c8SJean-Christophe PLAGNIOL-VILLARD while (chr < 0); 257*16b195c8SJean-Christophe PLAGNIOL-VILLARD 258*16b195c8SJean-Christophe PLAGNIOL-VILLARD if (flags) enable_interrupts(); 259*16b195c8SJean-Christophe PLAGNIOL-VILLARD 260*16b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG 261*16b195c8SJean-Christophe PLAGNIOL-VILLARD printf("0x%02x\n", chr); 262*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 263*16b195c8SJean-Christophe PLAGNIOL-VILLARD 264*16b195c8SJean-Christophe PLAGNIOL-VILLARD return chr; 265*16b195c8SJean-Christophe PLAGNIOL-VILLARD } 266*16b195c8SJean-Christophe PLAGNIOL-VILLARD 267*16b195c8SJean-Christophe PLAGNIOL-VILLARD int ps2ser_check(void) 268*16b195c8SJean-Christophe PLAGNIOL-VILLARD { 269*16b195c8SJean-Christophe PLAGNIOL-VILLARD int flags; 270*16b195c8SJean-Christophe PLAGNIOL-VILLARD 271*16b195c8SJean-Christophe PLAGNIOL-VILLARD flags = disable_interrupts(); 272*16b195c8SJean-Christophe PLAGNIOL-VILLARD ps2ser_interrupt(NULL); 273*16b195c8SJean-Christophe PLAGNIOL-VILLARD if (flags) enable_interrupts(); 274*16b195c8SJean-Christophe PLAGNIOL-VILLARD 275*16b195c8SJean-Christophe PLAGNIOL-VILLARD return atomic_read(&ps2buf_cnt); 276*16b195c8SJean-Christophe PLAGNIOL-VILLARD } 277*16b195c8SJean-Christophe PLAGNIOL-VILLARD 278*16b195c8SJean-Christophe PLAGNIOL-VILLARD static void ps2ser_interrupt(void *dev_id) 279*16b195c8SJean-Christophe PLAGNIOL-VILLARD { 280*16b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC5xxx 281*16b195c8SJean-Christophe PLAGNIOL-VILLARD volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE; 282*16b195c8SJean-Christophe PLAGNIOL-VILLARD #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || defined(CONFIG_MPC8555) 283*16b195c8SJean-Christophe PLAGNIOL-VILLARD NS16550_t com_port = (NS16550_t)COM_BASE; 284*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 285*16b195c8SJean-Christophe PLAGNIOL-VILLARD int chr; 286*16b195c8SJean-Christophe PLAGNIOL-VILLARD int status; 287*16b195c8SJean-Christophe PLAGNIOL-VILLARD 288*16b195c8SJean-Christophe PLAGNIOL-VILLARD do { 289*16b195c8SJean-Christophe PLAGNIOL-VILLARD chr = ps2ser_getc_hw(); 290*16b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC5xxx 291*16b195c8SJean-Christophe PLAGNIOL-VILLARD status = psc->psc_status; 292*16b195c8SJean-Christophe PLAGNIOL-VILLARD #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || defined(CONFIG_MPC8555) 293*16b195c8SJean-Christophe PLAGNIOL-VILLARD status = com_port->lsr; 294*16b195c8SJean-Christophe PLAGNIOL-VILLARD #else 295*16b195c8SJean-Christophe PLAGNIOL-VILLARD status = ps2ser_in(UART_IIR); 296*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 297*16b195c8SJean-Christophe PLAGNIOL-VILLARD if (chr < 0) continue; 298*16b195c8SJean-Christophe PLAGNIOL-VILLARD 299*16b195c8SJean-Christophe PLAGNIOL-VILLARD if (atomic_read(&ps2buf_cnt) < PS2BUF_SIZE) { 300*16b195c8SJean-Christophe PLAGNIOL-VILLARD ps2buf[ps2buf_in_idx++] = chr; 301*16b195c8SJean-Christophe PLAGNIOL-VILLARD ps2buf_in_idx &= (PS2BUF_SIZE - 1); 302*16b195c8SJean-Christophe PLAGNIOL-VILLARD atomic_inc(&ps2buf_cnt); 303*16b195c8SJean-Christophe PLAGNIOL-VILLARD } else { 304*16b195c8SJean-Christophe PLAGNIOL-VILLARD printf ("ps2ser.c: buffer overflow\n"); 305*16b195c8SJean-Christophe PLAGNIOL-VILLARD } 306*16b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC5xxx 307*16b195c8SJean-Christophe PLAGNIOL-VILLARD } while (status & PSC_SR_RXRDY); 308*16b195c8SJean-Christophe PLAGNIOL-VILLARD #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || defined(CONFIG_MPC8555) 309*16b195c8SJean-Christophe PLAGNIOL-VILLARD } while (status & LSR_DR); 310*16b195c8SJean-Christophe PLAGNIOL-VILLARD #else 311*16b195c8SJean-Christophe PLAGNIOL-VILLARD } while (status & UART_IIR_RDI); 312*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 313*16b195c8SJean-Christophe PLAGNIOL-VILLARD 314*16b195c8SJean-Christophe PLAGNIOL-VILLARD if (atomic_read(&ps2buf_cnt)) { 315*16b195c8SJean-Christophe PLAGNIOL-VILLARD ps2mult_callback(atomic_read(&ps2buf_cnt)); 316*16b195c8SJean-Christophe PLAGNIOL-VILLARD } 317*16b195c8SJean-Christophe PLAGNIOL-VILLARD } 318*16b195c8SJean-Christophe PLAGNIOL-VILLARD 319*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif /* CONFIG_PS2SERIAL */ 320