116b195c8SJean-Christophe PLAGNIOL-VILLARD /*********************************************************************** 216b195c8SJean-Christophe PLAGNIOL-VILLARD * 316b195c8SJean-Christophe PLAGNIOL-VILLARD * (C) Copyright 2004 416b195c8SJean-Christophe PLAGNIOL-VILLARD * DENX Software Engineering 516b195c8SJean-Christophe PLAGNIOL-VILLARD * Wolfgang Denk, wd@denx.de 616b195c8SJean-Christophe PLAGNIOL-VILLARD * All rights reserved. 716b195c8SJean-Christophe PLAGNIOL-VILLARD * 816b195c8SJean-Christophe PLAGNIOL-VILLARD * Simple 16550A serial driver 916b195c8SJean-Christophe PLAGNIOL-VILLARD * 1016b195c8SJean-Christophe PLAGNIOL-VILLARD * Originally from linux source (drivers/char/ps2ser.c) 1116b195c8SJean-Christophe PLAGNIOL-VILLARD * 1216b195c8SJean-Christophe PLAGNIOL-VILLARD * Used by the PS/2 multiplexer driver (ps2mult.c) 1316b195c8SJean-Christophe PLAGNIOL-VILLARD * 1416b195c8SJean-Christophe PLAGNIOL-VILLARD ***********************************************************************/ 1516b195c8SJean-Christophe PLAGNIOL-VILLARD 1616b195c8SJean-Christophe PLAGNIOL-VILLARD #include <common.h> 1716b195c8SJean-Christophe PLAGNIOL-VILLARD 1816b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_PS2SERIAL 1916b195c8SJean-Christophe PLAGNIOL-VILLARD 2016b195c8SJean-Christophe PLAGNIOL-VILLARD #include <asm/io.h> 2116b195c8SJean-Christophe PLAGNIOL-VILLARD #include <asm/atomic.h> 2216b195c8SJean-Christophe PLAGNIOL-VILLARD #include <ps2mult.h> 2316b195c8SJean-Christophe PLAGNIOL-VILLARD #if defined(CFG_NS16550) || defined(CONFIG_MPC85xx) 2416b195c8SJean-Christophe PLAGNIOL-VILLARD #include <ns16550.h> 2516b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 2616b195c8SJean-Christophe PLAGNIOL-VILLARD 2716b195c8SJean-Christophe PLAGNIOL-VILLARD DECLARE_GLOBAL_DATA_PTR; 2816b195c8SJean-Christophe PLAGNIOL-VILLARD 2916b195c8SJean-Christophe PLAGNIOL-VILLARD /* #define DEBUG */ 3016b195c8SJean-Christophe PLAGNIOL-VILLARD 3116b195c8SJean-Christophe PLAGNIOL-VILLARD #define PS2SER_BAUD 57600 3216b195c8SJean-Christophe PLAGNIOL-VILLARD 3316b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC5xxx 3416b195c8SJean-Christophe PLAGNIOL-VILLARD #if CONFIG_PS2SERIAL == 1 3516b195c8SJean-Christophe PLAGNIOL-VILLARD #define PSC_BASE MPC5XXX_PSC1 3616b195c8SJean-Christophe PLAGNIOL-VILLARD #elif CONFIG_PS2SERIAL == 2 3716b195c8SJean-Christophe PLAGNIOL-VILLARD #define PSC_BASE MPC5XXX_PSC2 3816b195c8SJean-Christophe PLAGNIOL-VILLARD #elif CONFIG_PS2SERIAL == 3 3916b195c8SJean-Christophe PLAGNIOL-VILLARD #define PSC_BASE MPC5XXX_PSC3 4016b195c8SJean-Christophe PLAGNIOL-VILLARD #elif defined(CONFIG_MGT5100) 4116b195c8SJean-Christophe PLAGNIOL-VILLARD #error CONFIG_PS2SERIAL must be in 1, 2 or 3 4216b195c8SJean-Christophe PLAGNIOL-VILLARD #elif CONFIG_PS2SERIAL == 4 4316b195c8SJean-Christophe PLAGNIOL-VILLARD #define PSC_BASE MPC5XXX_PSC4 4416b195c8SJean-Christophe PLAGNIOL-VILLARD #elif CONFIG_PS2SERIAL == 5 4516b195c8SJean-Christophe PLAGNIOL-VILLARD #define PSC_BASE MPC5XXX_PSC5 4616b195c8SJean-Christophe PLAGNIOL-VILLARD #elif CONFIG_PS2SERIAL == 6 4716b195c8SJean-Christophe PLAGNIOL-VILLARD #define PSC_BASE MPC5XXX_PSC6 4816b195c8SJean-Christophe PLAGNIOL-VILLARD #else 4916b195c8SJean-Christophe PLAGNIOL-VILLARD #error CONFIG_PS2SERIAL must be in 1 ... 6 5016b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 5116b195c8SJean-Christophe PLAGNIOL-VILLARD 52*1287e0c5SWolfgang Grandegger #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \ 53*1287e0c5SWolfgang Grandegger defined(CONFIG_MPC8548) || defined(CONFIG_MPC8555) 5416b195c8SJean-Christophe PLAGNIOL-VILLARD 5516b195c8SJean-Christophe PLAGNIOL-VILLARD #if CONFIG_PS2SERIAL == 1 5616b195c8SJean-Christophe PLAGNIOL-VILLARD #define COM_BASE (CFG_CCSRBAR+0x4500) 5716b195c8SJean-Christophe PLAGNIOL-VILLARD #elif CONFIG_PS2SERIAL == 2 5816b195c8SJean-Christophe PLAGNIOL-VILLARD #define COM_BASE (CFG_CCSRBAR+0x4600) 5916b195c8SJean-Christophe PLAGNIOL-VILLARD #else 6016b195c8SJean-Christophe PLAGNIOL-VILLARD #error CONFIG_PS2SERIAL must be in 1 ... 2 6116b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 6216b195c8SJean-Christophe PLAGNIOL-VILLARD 6316b195c8SJean-Christophe PLAGNIOL-VILLARD #endif /* CONFIG_MPC5xxx / CONFIG_MPC8540 / other */ 6416b195c8SJean-Christophe PLAGNIOL-VILLARD 6516b195c8SJean-Christophe PLAGNIOL-VILLARD static int ps2ser_getc_hw(void); 6616b195c8SJean-Christophe PLAGNIOL-VILLARD static void ps2ser_interrupt(void *dev_id); 6716b195c8SJean-Christophe PLAGNIOL-VILLARD 6816b195c8SJean-Christophe PLAGNIOL-VILLARD extern struct serial_state rs_table[]; /* in serial.c */ 69*1287e0c5SWolfgang Grandegger #if !defined(CONFIG_MPC5xxx) && !defined(CONFIG_MPC8540) && \ 70*1287e0c5SWolfgang Grandegger !defined(CONFIG_MPC8541) && !defined(CONFIG_MPC8548) && \ 71*1287e0c5SWolfgang Grandegger !defined(CONFIG_MPC8555) 7216b195c8SJean-Christophe PLAGNIOL-VILLARD static struct serial_state *state; 7316b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 7416b195c8SJean-Christophe PLAGNIOL-VILLARD 7516b195c8SJean-Christophe PLAGNIOL-VILLARD static u_char ps2buf[PS2BUF_SIZE]; 7616b195c8SJean-Christophe PLAGNIOL-VILLARD static atomic_t ps2buf_cnt; 7716b195c8SJean-Christophe PLAGNIOL-VILLARD static int ps2buf_in_idx; 7816b195c8SJean-Christophe PLAGNIOL-VILLARD static int ps2buf_out_idx; 7916b195c8SJean-Christophe PLAGNIOL-VILLARD 8016b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC5xxx 8116b195c8SJean-Christophe PLAGNIOL-VILLARD int ps2ser_init(void) 8216b195c8SJean-Christophe PLAGNIOL-VILLARD { 8316b195c8SJean-Christophe PLAGNIOL-VILLARD volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE; 8416b195c8SJean-Christophe PLAGNIOL-VILLARD unsigned long baseclk; 8516b195c8SJean-Christophe PLAGNIOL-VILLARD int div; 8616b195c8SJean-Christophe PLAGNIOL-VILLARD 8716b195c8SJean-Christophe PLAGNIOL-VILLARD /* reset PSC */ 8816b195c8SJean-Christophe PLAGNIOL-VILLARD psc->command = PSC_SEL_MODE_REG_1; 8916b195c8SJean-Christophe PLAGNIOL-VILLARD 9016b195c8SJean-Christophe PLAGNIOL-VILLARD /* select clock sources */ 9116b195c8SJean-Christophe PLAGNIOL-VILLARD #if defined(CONFIG_MGT5100) 9216b195c8SJean-Christophe PLAGNIOL-VILLARD psc->psc_clock_select = 0xdd00; 9316b195c8SJean-Christophe PLAGNIOL-VILLARD baseclk = (CFG_MPC5XXX_CLKIN + 16) / 32; 9416b195c8SJean-Christophe PLAGNIOL-VILLARD #elif defined(CONFIG_MPC5200) 9516b195c8SJean-Christophe PLAGNIOL-VILLARD psc->psc_clock_select = 0; 9616b195c8SJean-Christophe PLAGNIOL-VILLARD baseclk = (gd->ipb_clk + 16) / 32; 9716b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 9816b195c8SJean-Christophe PLAGNIOL-VILLARD 9916b195c8SJean-Christophe PLAGNIOL-VILLARD /* switch to UART mode */ 10016b195c8SJean-Christophe PLAGNIOL-VILLARD psc->sicr = 0; 10116b195c8SJean-Christophe PLAGNIOL-VILLARD 10216b195c8SJean-Christophe PLAGNIOL-VILLARD /* configure parity, bit length and so on */ 10316b195c8SJean-Christophe PLAGNIOL-VILLARD #if defined(CONFIG_MGT5100) 10416b195c8SJean-Christophe PLAGNIOL-VILLARD psc->mode = PSC_MODE_ERR | PSC_MODE_8_BITS | PSC_MODE_PARNONE; 10516b195c8SJean-Christophe PLAGNIOL-VILLARD #elif defined(CONFIG_MPC5200) 10616b195c8SJean-Christophe PLAGNIOL-VILLARD psc->mode = PSC_MODE_8_BITS | PSC_MODE_PARNONE; 10716b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 10816b195c8SJean-Christophe PLAGNIOL-VILLARD psc->mode = PSC_MODE_ONE_STOP; 10916b195c8SJean-Christophe PLAGNIOL-VILLARD 11016b195c8SJean-Christophe PLAGNIOL-VILLARD /* set up UART divisor */ 11116b195c8SJean-Christophe PLAGNIOL-VILLARD div = (baseclk + (PS2SER_BAUD/2)) / PS2SER_BAUD; 11216b195c8SJean-Christophe PLAGNIOL-VILLARD psc->ctur = (div >> 8) & 0xff; 11316b195c8SJean-Christophe PLAGNIOL-VILLARD psc->ctlr = div & 0xff; 11416b195c8SJean-Christophe PLAGNIOL-VILLARD 11516b195c8SJean-Christophe PLAGNIOL-VILLARD /* disable all interrupts */ 11616b195c8SJean-Christophe PLAGNIOL-VILLARD psc->psc_imr = 0; 11716b195c8SJean-Christophe PLAGNIOL-VILLARD 11816b195c8SJean-Christophe PLAGNIOL-VILLARD /* reset and enable Rx/Tx */ 11916b195c8SJean-Christophe PLAGNIOL-VILLARD psc->command = PSC_RST_RX; 12016b195c8SJean-Christophe PLAGNIOL-VILLARD psc->command = PSC_RST_TX; 12116b195c8SJean-Christophe PLAGNIOL-VILLARD psc->command = PSC_RX_ENABLE | PSC_TX_ENABLE; 12216b195c8SJean-Christophe PLAGNIOL-VILLARD 12316b195c8SJean-Christophe PLAGNIOL-VILLARD return (0); 12416b195c8SJean-Christophe PLAGNIOL-VILLARD } 12516b195c8SJean-Christophe PLAGNIOL-VILLARD 126*1287e0c5SWolfgang Grandegger #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \ 127*1287e0c5SWolfgang Grandegger defined(CONFIG_MPC8548) || defined(CONFIG_MPC8555) 12816b195c8SJean-Christophe PLAGNIOL-VILLARD int ps2ser_init(void) 12916b195c8SJean-Christophe PLAGNIOL-VILLARD { 13016b195c8SJean-Christophe PLAGNIOL-VILLARD NS16550_t com_port = (NS16550_t)COM_BASE; 13116b195c8SJean-Christophe PLAGNIOL-VILLARD 13216b195c8SJean-Christophe PLAGNIOL-VILLARD com_port->ier = 0x00; 13316b195c8SJean-Christophe PLAGNIOL-VILLARD com_port->lcr = LCR_BKSE | LCR_8N1; 13416b195c8SJean-Christophe PLAGNIOL-VILLARD com_port->dll = (CFG_NS16550_CLK / 16 / PS2SER_BAUD) & 0xff; 13516b195c8SJean-Christophe PLAGNIOL-VILLARD com_port->dlm = ((CFG_NS16550_CLK / 16 / PS2SER_BAUD) >> 8) & 0xff; 13616b195c8SJean-Christophe PLAGNIOL-VILLARD com_port->lcr = LCR_8N1; 13716b195c8SJean-Christophe PLAGNIOL-VILLARD com_port->mcr = (MCR_DTR | MCR_RTS); 13816b195c8SJean-Christophe PLAGNIOL-VILLARD com_port->fcr = (FCR_FIFO_EN | FCR_RXSR | FCR_TXSR); 13916b195c8SJean-Christophe PLAGNIOL-VILLARD 14016b195c8SJean-Christophe PLAGNIOL-VILLARD return (0); 14116b195c8SJean-Christophe PLAGNIOL-VILLARD } 14216b195c8SJean-Christophe PLAGNIOL-VILLARD 14316b195c8SJean-Christophe PLAGNIOL-VILLARD #else /* !CONFIG_MPC5xxx && !CONFIG_MPC8540 / other */ 14416b195c8SJean-Christophe PLAGNIOL-VILLARD 14516b195c8SJean-Christophe PLAGNIOL-VILLARD static inline unsigned int ps2ser_in(int offset) 14616b195c8SJean-Christophe PLAGNIOL-VILLARD { 14716b195c8SJean-Christophe PLAGNIOL-VILLARD return readb((unsigned long) state->iomem_base + offset); 14816b195c8SJean-Christophe PLAGNIOL-VILLARD } 14916b195c8SJean-Christophe PLAGNIOL-VILLARD 15016b195c8SJean-Christophe PLAGNIOL-VILLARD static inline void ps2ser_out(int offset, int value) 15116b195c8SJean-Christophe PLAGNIOL-VILLARD { 15216b195c8SJean-Christophe PLAGNIOL-VILLARD writeb(value, (unsigned long) state->iomem_base + offset); 15316b195c8SJean-Christophe PLAGNIOL-VILLARD } 15416b195c8SJean-Christophe PLAGNIOL-VILLARD 15516b195c8SJean-Christophe PLAGNIOL-VILLARD int ps2ser_init(void) 15616b195c8SJean-Christophe PLAGNIOL-VILLARD { 15716b195c8SJean-Christophe PLAGNIOL-VILLARD int quot; 15816b195c8SJean-Christophe PLAGNIOL-VILLARD unsigned cval; 15916b195c8SJean-Christophe PLAGNIOL-VILLARD 16016b195c8SJean-Christophe PLAGNIOL-VILLARD state = rs_table + CONFIG_PS2SERIAL; 16116b195c8SJean-Christophe PLAGNIOL-VILLARD 16216b195c8SJean-Christophe PLAGNIOL-VILLARD quot = state->baud_base / PS2SER_BAUD; 16316b195c8SJean-Christophe PLAGNIOL-VILLARD cval = 0x3; /* 8N1 - 8 data bits, no parity bits, 1 stop bit */ 16416b195c8SJean-Christophe PLAGNIOL-VILLARD 16516b195c8SJean-Christophe PLAGNIOL-VILLARD /* Set speed, enable interrupts, enable FIFO 16616b195c8SJean-Christophe PLAGNIOL-VILLARD */ 16716b195c8SJean-Christophe PLAGNIOL-VILLARD ps2ser_out(UART_LCR, cval | UART_LCR_DLAB); 16816b195c8SJean-Christophe PLAGNIOL-VILLARD ps2ser_out(UART_DLL, quot & 0xff); 16916b195c8SJean-Christophe PLAGNIOL-VILLARD ps2ser_out(UART_DLM, quot >> 8); 17016b195c8SJean-Christophe PLAGNIOL-VILLARD ps2ser_out(UART_LCR, cval); 17116b195c8SJean-Christophe PLAGNIOL-VILLARD ps2ser_out(UART_IER, UART_IER_RDI); 17216b195c8SJean-Christophe PLAGNIOL-VILLARD ps2ser_out(UART_MCR, UART_MCR_OUT2 | UART_MCR_DTR | UART_MCR_RTS); 17316b195c8SJean-Christophe PLAGNIOL-VILLARD ps2ser_out(UART_FCR, 17416b195c8SJean-Christophe PLAGNIOL-VILLARD UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); 17516b195c8SJean-Christophe PLAGNIOL-VILLARD 17616b195c8SJean-Christophe PLAGNIOL-VILLARD /* If we read 0xff from the LSR, there is no UART here 17716b195c8SJean-Christophe PLAGNIOL-VILLARD */ 17816b195c8SJean-Christophe PLAGNIOL-VILLARD if (ps2ser_in(UART_LSR) == 0xff) { 17916b195c8SJean-Christophe PLAGNIOL-VILLARD printf ("ps2ser.c: no UART found\n"); 18016b195c8SJean-Christophe PLAGNIOL-VILLARD return -1; 18116b195c8SJean-Christophe PLAGNIOL-VILLARD } 18216b195c8SJean-Christophe PLAGNIOL-VILLARD 18316b195c8SJean-Christophe PLAGNIOL-VILLARD irq_install_handler(state->irq, ps2ser_interrupt, NULL); 18416b195c8SJean-Christophe PLAGNIOL-VILLARD 18516b195c8SJean-Christophe PLAGNIOL-VILLARD return 0; 18616b195c8SJean-Christophe PLAGNIOL-VILLARD } 18716b195c8SJean-Christophe PLAGNIOL-VILLARD #endif /* CONFIG_MPC5xxx / CONFIG_MPC8540 / other */ 18816b195c8SJean-Christophe PLAGNIOL-VILLARD 18916b195c8SJean-Christophe PLAGNIOL-VILLARD void ps2ser_putc(int chr) 19016b195c8SJean-Christophe PLAGNIOL-VILLARD { 19116b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC5xxx 19216b195c8SJean-Christophe PLAGNIOL-VILLARD volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE; 193*1287e0c5SWolfgang Grandegger #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \ 194*1287e0c5SWolfgang Grandegger defined(CONFIG_MPC8548) || defined(CONFIG_MPC8555) 19516b195c8SJean-Christophe PLAGNIOL-VILLARD NS16550_t com_port = (NS16550_t)COM_BASE; 19616b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 19716b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG 19816b195c8SJean-Christophe PLAGNIOL-VILLARD printf(">>>> 0x%02x\n", chr); 19916b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 20016b195c8SJean-Christophe PLAGNIOL-VILLARD 20116b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC5xxx 20216b195c8SJean-Christophe PLAGNIOL-VILLARD while (!(psc->psc_status & PSC_SR_TXRDY)); 20316b195c8SJean-Christophe PLAGNIOL-VILLARD 20416b195c8SJean-Christophe PLAGNIOL-VILLARD psc->psc_buffer_8 = chr; 205*1287e0c5SWolfgang Grandegger #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \ 206*1287e0c5SWolfgang Grandegger defined(CONFIG_MPC8548) || defined(CONFIG_MPC8555) 20716b195c8SJean-Christophe PLAGNIOL-VILLARD while ((com_port->lsr & LSR_THRE) == 0); 20816b195c8SJean-Christophe PLAGNIOL-VILLARD com_port->thr = chr; 20916b195c8SJean-Christophe PLAGNIOL-VILLARD #else 21016b195c8SJean-Christophe PLAGNIOL-VILLARD while (!(ps2ser_in(UART_LSR) & UART_LSR_THRE)); 21116b195c8SJean-Christophe PLAGNIOL-VILLARD 21216b195c8SJean-Christophe PLAGNIOL-VILLARD ps2ser_out(UART_TX, chr); 21316b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 21416b195c8SJean-Christophe PLAGNIOL-VILLARD } 21516b195c8SJean-Christophe PLAGNIOL-VILLARD 21616b195c8SJean-Christophe PLAGNIOL-VILLARD static int ps2ser_getc_hw(void) 21716b195c8SJean-Christophe PLAGNIOL-VILLARD { 21816b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC5xxx 21916b195c8SJean-Christophe PLAGNIOL-VILLARD volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE; 220*1287e0c5SWolfgang Grandegger #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \ 221*1287e0c5SWolfgang Grandegger defined(CONFIG_MPC8548) || defined(CONFIG_MPC8555) 22216b195c8SJean-Christophe PLAGNIOL-VILLARD NS16550_t com_port = (NS16550_t)COM_BASE; 22316b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 22416b195c8SJean-Christophe PLAGNIOL-VILLARD int res = -1; 22516b195c8SJean-Christophe PLAGNIOL-VILLARD 22616b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC5xxx 22716b195c8SJean-Christophe PLAGNIOL-VILLARD if (psc->psc_status & PSC_SR_RXRDY) { 22816b195c8SJean-Christophe PLAGNIOL-VILLARD res = (psc->psc_buffer_8); 22916b195c8SJean-Christophe PLAGNIOL-VILLARD } 230*1287e0c5SWolfgang Grandegger #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \ 231*1287e0c5SWolfgang Grandegger defined(CONFIG_MPC8548) || defined(CONFIG_MPC8555) 23216b195c8SJean-Christophe PLAGNIOL-VILLARD if (com_port->lsr & LSR_DR) { 23316b195c8SJean-Christophe PLAGNIOL-VILLARD res = com_port->rbr; 23416b195c8SJean-Christophe PLAGNIOL-VILLARD } 23516b195c8SJean-Christophe PLAGNIOL-VILLARD #else 23616b195c8SJean-Christophe PLAGNIOL-VILLARD if (ps2ser_in(UART_LSR) & UART_LSR_DR) { 23716b195c8SJean-Christophe PLAGNIOL-VILLARD res = (ps2ser_in(UART_RX)); 23816b195c8SJean-Christophe PLAGNIOL-VILLARD } 23916b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 24016b195c8SJean-Christophe PLAGNIOL-VILLARD 24116b195c8SJean-Christophe PLAGNIOL-VILLARD return res; 24216b195c8SJean-Christophe PLAGNIOL-VILLARD } 24316b195c8SJean-Christophe PLAGNIOL-VILLARD 24416b195c8SJean-Christophe PLAGNIOL-VILLARD int ps2ser_getc(void) 24516b195c8SJean-Christophe PLAGNIOL-VILLARD { 24616b195c8SJean-Christophe PLAGNIOL-VILLARD volatile int chr; 24716b195c8SJean-Christophe PLAGNIOL-VILLARD int flags; 24816b195c8SJean-Christophe PLAGNIOL-VILLARD 24916b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG 25016b195c8SJean-Christophe PLAGNIOL-VILLARD printf("<< "); 25116b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 25216b195c8SJean-Christophe PLAGNIOL-VILLARD 25316b195c8SJean-Christophe PLAGNIOL-VILLARD flags = disable_interrupts(); 25416b195c8SJean-Christophe PLAGNIOL-VILLARD 25516b195c8SJean-Christophe PLAGNIOL-VILLARD do { 25616b195c8SJean-Christophe PLAGNIOL-VILLARD if (atomic_read(&ps2buf_cnt) != 0) { 25716b195c8SJean-Christophe PLAGNIOL-VILLARD chr = ps2buf[ps2buf_out_idx++]; 25816b195c8SJean-Christophe PLAGNIOL-VILLARD ps2buf_out_idx &= (PS2BUF_SIZE - 1); 25916b195c8SJean-Christophe PLAGNIOL-VILLARD atomic_dec(&ps2buf_cnt); 26016b195c8SJean-Christophe PLAGNIOL-VILLARD } else { 26116b195c8SJean-Christophe PLAGNIOL-VILLARD chr = ps2ser_getc_hw(); 26216b195c8SJean-Christophe PLAGNIOL-VILLARD } 26316b195c8SJean-Christophe PLAGNIOL-VILLARD } 26416b195c8SJean-Christophe PLAGNIOL-VILLARD while (chr < 0); 26516b195c8SJean-Christophe PLAGNIOL-VILLARD 26616b195c8SJean-Christophe PLAGNIOL-VILLARD if (flags) enable_interrupts(); 26716b195c8SJean-Christophe PLAGNIOL-VILLARD 26816b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG 26916b195c8SJean-Christophe PLAGNIOL-VILLARD printf("0x%02x\n", chr); 27016b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 27116b195c8SJean-Christophe PLAGNIOL-VILLARD 27216b195c8SJean-Christophe PLAGNIOL-VILLARD return chr; 27316b195c8SJean-Christophe PLAGNIOL-VILLARD } 27416b195c8SJean-Christophe PLAGNIOL-VILLARD 27516b195c8SJean-Christophe PLAGNIOL-VILLARD int ps2ser_check(void) 27616b195c8SJean-Christophe PLAGNIOL-VILLARD { 27716b195c8SJean-Christophe PLAGNIOL-VILLARD int flags; 27816b195c8SJean-Christophe PLAGNIOL-VILLARD 27916b195c8SJean-Christophe PLAGNIOL-VILLARD flags = disable_interrupts(); 28016b195c8SJean-Christophe PLAGNIOL-VILLARD ps2ser_interrupt(NULL); 28116b195c8SJean-Christophe PLAGNIOL-VILLARD if (flags) enable_interrupts(); 28216b195c8SJean-Christophe PLAGNIOL-VILLARD 28316b195c8SJean-Christophe PLAGNIOL-VILLARD return atomic_read(&ps2buf_cnt); 28416b195c8SJean-Christophe PLAGNIOL-VILLARD } 28516b195c8SJean-Christophe PLAGNIOL-VILLARD 28616b195c8SJean-Christophe PLAGNIOL-VILLARD static void ps2ser_interrupt(void *dev_id) 28716b195c8SJean-Christophe PLAGNIOL-VILLARD { 28816b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC5xxx 28916b195c8SJean-Christophe PLAGNIOL-VILLARD volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE; 290*1287e0c5SWolfgang Grandegger #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \ 291*1287e0c5SWolfgang Grandegger defined(CONFIG_MPC8548) || defined(CONFIG_MPC8555) 29216b195c8SJean-Christophe PLAGNIOL-VILLARD NS16550_t com_port = (NS16550_t)COM_BASE; 29316b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 29416b195c8SJean-Christophe PLAGNIOL-VILLARD int chr; 29516b195c8SJean-Christophe PLAGNIOL-VILLARD int status; 29616b195c8SJean-Christophe PLAGNIOL-VILLARD 29716b195c8SJean-Christophe PLAGNIOL-VILLARD do { 29816b195c8SJean-Christophe PLAGNIOL-VILLARD chr = ps2ser_getc_hw(); 29916b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC5xxx 30016b195c8SJean-Christophe PLAGNIOL-VILLARD status = psc->psc_status; 301*1287e0c5SWolfgang Grandegger #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \ 302*1287e0c5SWolfgang Grandegger defined(CONFIG_MPC8548) || defined(CONFIG_MPC8555) 30316b195c8SJean-Christophe PLAGNIOL-VILLARD status = com_port->lsr; 30416b195c8SJean-Christophe PLAGNIOL-VILLARD #else 30516b195c8SJean-Christophe PLAGNIOL-VILLARD status = ps2ser_in(UART_IIR); 30616b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 30716b195c8SJean-Christophe PLAGNIOL-VILLARD if (chr < 0) continue; 30816b195c8SJean-Christophe PLAGNIOL-VILLARD 30916b195c8SJean-Christophe PLAGNIOL-VILLARD if (atomic_read(&ps2buf_cnt) < PS2BUF_SIZE) { 31016b195c8SJean-Christophe PLAGNIOL-VILLARD ps2buf[ps2buf_in_idx++] = chr; 31116b195c8SJean-Christophe PLAGNIOL-VILLARD ps2buf_in_idx &= (PS2BUF_SIZE - 1); 31216b195c8SJean-Christophe PLAGNIOL-VILLARD atomic_inc(&ps2buf_cnt); 31316b195c8SJean-Christophe PLAGNIOL-VILLARD } else { 31416b195c8SJean-Christophe PLAGNIOL-VILLARD printf ("ps2ser.c: buffer overflow\n"); 31516b195c8SJean-Christophe PLAGNIOL-VILLARD } 31616b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC5xxx 31716b195c8SJean-Christophe PLAGNIOL-VILLARD } while (status & PSC_SR_RXRDY); 318*1287e0c5SWolfgang Grandegger #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \ 319*1287e0c5SWolfgang Grandegger defined(CONFIG_MPC8548) || defined(CONFIG_MPC8555) 32016b195c8SJean-Christophe PLAGNIOL-VILLARD } while (status & LSR_DR); 32116b195c8SJean-Christophe PLAGNIOL-VILLARD #else 32216b195c8SJean-Christophe PLAGNIOL-VILLARD } while (status & UART_IIR_RDI); 32316b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 32416b195c8SJean-Christophe PLAGNIOL-VILLARD 32516b195c8SJean-Christophe PLAGNIOL-VILLARD if (atomic_read(&ps2buf_cnt)) { 32616b195c8SJean-Christophe PLAGNIOL-VILLARD ps2mult_callback(atomic_read(&ps2buf_cnt)); 32716b195c8SJean-Christophe PLAGNIOL-VILLARD } 32816b195c8SJean-Christophe PLAGNIOL-VILLARD } 32916b195c8SJean-Christophe PLAGNIOL-VILLARD 33016b195c8SJean-Christophe PLAGNIOL-VILLARD #endif /* CONFIG_PS2SERIAL */ 331