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 #include <asm/io.h> 1916b195c8SJean-Christophe PLAGNIOL-VILLARD #include <asm/atomic.h> 2016b195c8SJean-Christophe PLAGNIOL-VILLARD #include <ps2mult.h> 21*6d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #if defined(CONFIG_SYS_NS16550) || defined(CONFIG_MPC85xx) 2216b195c8SJean-Christophe PLAGNIOL-VILLARD #include <ns16550.h> 2316b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 2416b195c8SJean-Christophe PLAGNIOL-VILLARD 2516b195c8SJean-Christophe PLAGNIOL-VILLARD DECLARE_GLOBAL_DATA_PTR; 2616b195c8SJean-Christophe PLAGNIOL-VILLARD 2716b195c8SJean-Christophe PLAGNIOL-VILLARD /* #define DEBUG */ 2816b195c8SJean-Christophe PLAGNIOL-VILLARD 2916b195c8SJean-Christophe PLAGNIOL-VILLARD #define PS2SER_BAUD 57600 3016b195c8SJean-Christophe PLAGNIOL-VILLARD 3116b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC5xxx 3216b195c8SJean-Christophe PLAGNIOL-VILLARD #if CONFIG_PS2SERIAL == 1 3316b195c8SJean-Christophe PLAGNIOL-VILLARD #define PSC_BASE MPC5XXX_PSC1 3416b195c8SJean-Christophe PLAGNIOL-VILLARD #elif CONFIG_PS2SERIAL == 2 3516b195c8SJean-Christophe PLAGNIOL-VILLARD #define PSC_BASE MPC5XXX_PSC2 3616b195c8SJean-Christophe PLAGNIOL-VILLARD #elif CONFIG_PS2SERIAL == 3 3716b195c8SJean-Christophe PLAGNIOL-VILLARD #define PSC_BASE MPC5XXX_PSC3 3816b195c8SJean-Christophe PLAGNIOL-VILLARD #elif defined(CONFIG_MGT5100) 3916b195c8SJean-Christophe PLAGNIOL-VILLARD #error CONFIG_PS2SERIAL must be in 1, 2 or 3 4016b195c8SJean-Christophe PLAGNIOL-VILLARD #elif CONFIG_PS2SERIAL == 4 4116b195c8SJean-Christophe PLAGNIOL-VILLARD #define PSC_BASE MPC5XXX_PSC4 4216b195c8SJean-Christophe PLAGNIOL-VILLARD #elif CONFIG_PS2SERIAL == 5 4316b195c8SJean-Christophe PLAGNIOL-VILLARD #define PSC_BASE MPC5XXX_PSC5 4416b195c8SJean-Christophe PLAGNIOL-VILLARD #elif CONFIG_PS2SERIAL == 6 4516b195c8SJean-Christophe PLAGNIOL-VILLARD #define PSC_BASE MPC5XXX_PSC6 4616b195c8SJean-Christophe PLAGNIOL-VILLARD #else 4716b195c8SJean-Christophe PLAGNIOL-VILLARD #error CONFIG_PS2SERIAL must be in 1 ... 6 4816b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 4916b195c8SJean-Christophe PLAGNIOL-VILLARD 501287e0c5SWolfgang Grandegger #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \ 511287e0c5SWolfgang Grandegger defined(CONFIG_MPC8548) || defined(CONFIG_MPC8555) 5216b195c8SJean-Christophe PLAGNIOL-VILLARD 5316b195c8SJean-Christophe PLAGNIOL-VILLARD #if CONFIG_PS2SERIAL == 1 54*6d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #define COM_BASE (CONFIG_SYS_CCSRBAR+0x4500) 5516b195c8SJean-Christophe PLAGNIOL-VILLARD #elif CONFIG_PS2SERIAL == 2 56*6d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #define COM_BASE (CONFIG_SYS_CCSRBAR+0x4600) 5716b195c8SJean-Christophe PLAGNIOL-VILLARD #else 5816b195c8SJean-Christophe PLAGNIOL-VILLARD #error CONFIG_PS2SERIAL must be in 1 ... 2 5916b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 6016b195c8SJean-Christophe PLAGNIOL-VILLARD 6116b195c8SJean-Christophe PLAGNIOL-VILLARD #endif /* CONFIG_MPC5xxx / CONFIG_MPC8540 / other */ 6216b195c8SJean-Christophe PLAGNIOL-VILLARD 6316b195c8SJean-Christophe PLAGNIOL-VILLARD static int ps2ser_getc_hw(void); 6416b195c8SJean-Christophe PLAGNIOL-VILLARD static void ps2ser_interrupt(void *dev_id); 6516b195c8SJean-Christophe PLAGNIOL-VILLARD 6616b195c8SJean-Christophe PLAGNIOL-VILLARD extern struct serial_state rs_table[]; /* in serial.c */ 671287e0c5SWolfgang Grandegger #if !defined(CONFIG_MPC5xxx) && !defined(CONFIG_MPC8540) && \ 681287e0c5SWolfgang Grandegger !defined(CONFIG_MPC8541) && !defined(CONFIG_MPC8548) && \ 691287e0c5SWolfgang Grandegger !defined(CONFIG_MPC8555) 7016b195c8SJean-Christophe PLAGNIOL-VILLARD static struct serial_state *state; 7116b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 7216b195c8SJean-Christophe PLAGNIOL-VILLARD 7316b195c8SJean-Christophe PLAGNIOL-VILLARD static u_char ps2buf[PS2BUF_SIZE]; 7416b195c8SJean-Christophe PLAGNIOL-VILLARD static atomic_t ps2buf_cnt; 7516b195c8SJean-Christophe PLAGNIOL-VILLARD static int ps2buf_in_idx; 7616b195c8SJean-Christophe PLAGNIOL-VILLARD static int ps2buf_out_idx; 7716b195c8SJean-Christophe PLAGNIOL-VILLARD 7816b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC5xxx 7916b195c8SJean-Christophe PLAGNIOL-VILLARD int ps2ser_init(void) 8016b195c8SJean-Christophe PLAGNIOL-VILLARD { 8116b195c8SJean-Christophe PLAGNIOL-VILLARD volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE; 8216b195c8SJean-Christophe PLAGNIOL-VILLARD unsigned long baseclk; 8316b195c8SJean-Christophe PLAGNIOL-VILLARD int div; 8416b195c8SJean-Christophe PLAGNIOL-VILLARD 8516b195c8SJean-Christophe PLAGNIOL-VILLARD /* reset PSC */ 8616b195c8SJean-Christophe PLAGNIOL-VILLARD psc->command = PSC_SEL_MODE_REG_1; 8716b195c8SJean-Christophe PLAGNIOL-VILLARD 8816b195c8SJean-Christophe PLAGNIOL-VILLARD /* select clock sources */ 8916b195c8SJean-Christophe PLAGNIOL-VILLARD #if defined(CONFIG_MGT5100) 9016b195c8SJean-Christophe PLAGNIOL-VILLARD psc->psc_clock_select = 0xdd00; 91*6d0f6bcfSJean-Christophe PLAGNIOL-VILLARD baseclk = (CONFIG_SYS_MPC5XXX_CLKIN + 16) / 32; 9216b195c8SJean-Christophe PLAGNIOL-VILLARD #elif defined(CONFIG_MPC5200) 9316b195c8SJean-Christophe PLAGNIOL-VILLARD psc->psc_clock_select = 0; 9416b195c8SJean-Christophe PLAGNIOL-VILLARD baseclk = (gd->ipb_clk + 16) / 32; 9516b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 9616b195c8SJean-Christophe PLAGNIOL-VILLARD 9716b195c8SJean-Christophe PLAGNIOL-VILLARD /* switch to UART mode */ 9816b195c8SJean-Christophe PLAGNIOL-VILLARD psc->sicr = 0; 9916b195c8SJean-Christophe PLAGNIOL-VILLARD 10016b195c8SJean-Christophe PLAGNIOL-VILLARD /* configure parity, bit length and so on */ 10116b195c8SJean-Christophe PLAGNIOL-VILLARD #if defined(CONFIG_MGT5100) 10216b195c8SJean-Christophe PLAGNIOL-VILLARD psc->mode = PSC_MODE_ERR | PSC_MODE_8_BITS | PSC_MODE_PARNONE; 10316b195c8SJean-Christophe PLAGNIOL-VILLARD #elif defined(CONFIG_MPC5200) 10416b195c8SJean-Christophe PLAGNIOL-VILLARD psc->mode = PSC_MODE_8_BITS | PSC_MODE_PARNONE; 10516b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 10616b195c8SJean-Christophe PLAGNIOL-VILLARD psc->mode = PSC_MODE_ONE_STOP; 10716b195c8SJean-Christophe PLAGNIOL-VILLARD 10816b195c8SJean-Christophe PLAGNIOL-VILLARD /* set up UART divisor */ 10916b195c8SJean-Christophe PLAGNIOL-VILLARD div = (baseclk + (PS2SER_BAUD/2)) / PS2SER_BAUD; 11016b195c8SJean-Christophe PLAGNIOL-VILLARD psc->ctur = (div >> 8) & 0xff; 11116b195c8SJean-Christophe PLAGNIOL-VILLARD psc->ctlr = div & 0xff; 11216b195c8SJean-Christophe PLAGNIOL-VILLARD 11316b195c8SJean-Christophe PLAGNIOL-VILLARD /* disable all interrupts */ 11416b195c8SJean-Christophe PLAGNIOL-VILLARD psc->psc_imr = 0; 11516b195c8SJean-Christophe PLAGNIOL-VILLARD 11616b195c8SJean-Christophe PLAGNIOL-VILLARD /* reset and enable Rx/Tx */ 11716b195c8SJean-Christophe PLAGNIOL-VILLARD psc->command = PSC_RST_RX; 11816b195c8SJean-Christophe PLAGNIOL-VILLARD psc->command = PSC_RST_TX; 11916b195c8SJean-Christophe PLAGNIOL-VILLARD psc->command = PSC_RX_ENABLE | PSC_TX_ENABLE; 12016b195c8SJean-Christophe PLAGNIOL-VILLARD 12116b195c8SJean-Christophe PLAGNIOL-VILLARD return (0); 12216b195c8SJean-Christophe PLAGNIOL-VILLARD } 12316b195c8SJean-Christophe PLAGNIOL-VILLARD 1241287e0c5SWolfgang Grandegger #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \ 1251287e0c5SWolfgang Grandegger defined(CONFIG_MPC8548) || defined(CONFIG_MPC8555) 12616b195c8SJean-Christophe PLAGNIOL-VILLARD int ps2ser_init(void) 12716b195c8SJean-Christophe PLAGNIOL-VILLARD { 12816b195c8SJean-Christophe PLAGNIOL-VILLARD NS16550_t com_port = (NS16550_t)COM_BASE; 12916b195c8SJean-Christophe PLAGNIOL-VILLARD 13016b195c8SJean-Christophe PLAGNIOL-VILLARD com_port->ier = 0x00; 13116b195c8SJean-Christophe PLAGNIOL-VILLARD com_port->lcr = LCR_BKSE | LCR_8N1; 132*6d0f6bcfSJean-Christophe PLAGNIOL-VILLARD com_port->dll = (CONFIG_SYS_NS16550_CLK / 16 / PS2SER_BAUD) & 0xff; 133*6d0f6bcfSJean-Christophe PLAGNIOL-VILLARD com_port->dlm = ((CONFIG_SYS_NS16550_CLK / 16 / PS2SER_BAUD) >> 8) & 0xff; 13416b195c8SJean-Christophe PLAGNIOL-VILLARD com_port->lcr = LCR_8N1; 13516b195c8SJean-Christophe PLAGNIOL-VILLARD com_port->mcr = (MCR_DTR | MCR_RTS); 13616b195c8SJean-Christophe PLAGNIOL-VILLARD com_port->fcr = (FCR_FIFO_EN | FCR_RXSR | FCR_TXSR); 13716b195c8SJean-Christophe PLAGNIOL-VILLARD 13816b195c8SJean-Christophe PLAGNIOL-VILLARD return (0); 13916b195c8SJean-Christophe PLAGNIOL-VILLARD } 14016b195c8SJean-Christophe PLAGNIOL-VILLARD 14116b195c8SJean-Christophe PLAGNIOL-VILLARD #else /* !CONFIG_MPC5xxx && !CONFIG_MPC8540 / other */ 14216b195c8SJean-Christophe PLAGNIOL-VILLARD 14316b195c8SJean-Christophe PLAGNIOL-VILLARD static inline unsigned int ps2ser_in(int offset) 14416b195c8SJean-Christophe PLAGNIOL-VILLARD { 14516b195c8SJean-Christophe PLAGNIOL-VILLARD return readb((unsigned long) state->iomem_base + offset); 14616b195c8SJean-Christophe PLAGNIOL-VILLARD } 14716b195c8SJean-Christophe PLAGNIOL-VILLARD 14816b195c8SJean-Christophe PLAGNIOL-VILLARD static inline void ps2ser_out(int offset, int value) 14916b195c8SJean-Christophe PLAGNIOL-VILLARD { 15016b195c8SJean-Christophe PLAGNIOL-VILLARD writeb(value, (unsigned long) state->iomem_base + offset); 15116b195c8SJean-Christophe PLAGNIOL-VILLARD } 15216b195c8SJean-Christophe PLAGNIOL-VILLARD 15316b195c8SJean-Christophe PLAGNIOL-VILLARD int ps2ser_init(void) 15416b195c8SJean-Christophe PLAGNIOL-VILLARD { 15516b195c8SJean-Christophe PLAGNIOL-VILLARD int quot; 15616b195c8SJean-Christophe PLAGNIOL-VILLARD unsigned cval; 15716b195c8SJean-Christophe PLAGNIOL-VILLARD 15816b195c8SJean-Christophe PLAGNIOL-VILLARD state = rs_table + CONFIG_PS2SERIAL; 15916b195c8SJean-Christophe PLAGNIOL-VILLARD 16016b195c8SJean-Christophe PLAGNIOL-VILLARD quot = state->baud_base / PS2SER_BAUD; 16116b195c8SJean-Christophe PLAGNIOL-VILLARD cval = 0x3; /* 8N1 - 8 data bits, no parity bits, 1 stop bit */ 16216b195c8SJean-Christophe PLAGNIOL-VILLARD 16316b195c8SJean-Christophe PLAGNIOL-VILLARD /* Set speed, enable interrupts, enable FIFO 16416b195c8SJean-Christophe PLAGNIOL-VILLARD */ 16516b195c8SJean-Christophe PLAGNIOL-VILLARD ps2ser_out(UART_LCR, cval | UART_LCR_DLAB); 16616b195c8SJean-Christophe PLAGNIOL-VILLARD ps2ser_out(UART_DLL, quot & 0xff); 16716b195c8SJean-Christophe PLAGNIOL-VILLARD ps2ser_out(UART_DLM, quot >> 8); 16816b195c8SJean-Christophe PLAGNIOL-VILLARD ps2ser_out(UART_LCR, cval); 16916b195c8SJean-Christophe PLAGNIOL-VILLARD ps2ser_out(UART_IER, UART_IER_RDI); 17016b195c8SJean-Christophe PLAGNIOL-VILLARD ps2ser_out(UART_MCR, UART_MCR_OUT2 | UART_MCR_DTR | UART_MCR_RTS); 17116b195c8SJean-Christophe PLAGNIOL-VILLARD ps2ser_out(UART_FCR, 17216b195c8SJean-Christophe PLAGNIOL-VILLARD UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); 17316b195c8SJean-Christophe PLAGNIOL-VILLARD 17416b195c8SJean-Christophe PLAGNIOL-VILLARD /* If we read 0xff from the LSR, there is no UART here 17516b195c8SJean-Christophe PLAGNIOL-VILLARD */ 17616b195c8SJean-Christophe PLAGNIOL-VILLARD if (ps2ser_in(UART_LSR) == 0xff) { 17716b195c8SJean-Christophe PLAGNIOL-VILLARD printf ("ps2ser.c: no UART found\n"); 17816b195c8SJean-Christophe PLAGNIOL-VILLARD return -1; 17916b195c8SJean-Christophe PLAGNIOL-VILLARD } 18016b195c8SJean-Christophe PLAGNIOL-VILLARD 18116b195c8SJean-Christophe PLAGNIOL-VILLARD irq_install_handler(state->irq, ps2ser_interrupt, NULL); 18216b195c8SJean-Christophe PLAGNIOL-VILLARD 18316b195c8SJean-Christophe PLAGNIOL-VILLARD return 0; 18416b195c8SJean-Christophe PLAGNIOL-VILLARD } 18516b195c8SJean-Christophe PLAGNIOL-VILLARD #endif /* CONFIG_MPC5xxx / CONFIG_MPC8540 / other */ 18616b195c8SJean-Christophe PLAGNIOL-VILLARD 18716b195c8SJean-Christophe PLAGNIOL-VILLARD void ps2ser_putc(int chr) 18816b195c8SJean-Christophe PLAGNIOL-VILLARD { 18916b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC5xxx 19016b195c8SJean-Christophe PLAGNIOL-VILLARD volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE; 1911287e0c5SWolfgang Grandegger #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \ 1921287e0c5SWolfgang Grandegger defined(CONFIG_MPC8548) || defined(CONFIG_MPC8555) 19316b195c8SJean-Christophe PLAGNIOL-VILLARD NS16550_t com_port = (NS16550_t)COM_BASE; 19416b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 19516b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG 19616b195c8SJean-Christophe PLAGNIOL-VILLARD printf(">>>> 0x%02x\n", chr); 19716b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 19816b195c8SJean-Christophe PLAGNIOL-VILLARD 19916b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC5xxx 20016b195c8SJean-Christophe PLAGNIOL-VILLARD while (!(psc->psc_status & PSC_SR_TXRDY)); 20116b195c8SJean-Christophe PLAGNIOL-VILLARD 20216b195c8SJean-Christophe PLAGNIOL-VILLARD psc->psc_buffer_8 = chr; 2031287e0c5SWolfgang Grandegger #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \ 2041287e0c5SWolfgang Grandegger defined(CONFIG_MPC8548) || defined(CONFIG_MPC8555) 20516b195c8SJean-Christophe PLAGNIOL-VILLARD while ((com_port->lsr & LSR_THRE) == 0); 20616b195c8SJean-Christophe PLAGNIOL-VILLARD com_port->thr = chr; 20716b195c8SJean-Christophe PLAGNIOL-VILLARD #else 20816b195c8SJean-Christophe PLAGNIOL-VILLARD while (!(ps2ser_in(UART_LSR) & UART_LSR_THRE)); 20916b195c8SJean-Christophe PLAGNIOL-VILLARD 21016b195c8SJean-Christophe PLAGNIOL-VILLARD ps2ser_out(UART_TX, chr); 21116b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 21216b195c8SJean-Christophe PLAGNIOL-VILLARD } 21316b195c8SJean-Christophe PLAGNIOL-VILLARD 21416b195c8SJean-Christophe PLAGNIOL-VILLARD static int ps2ser_getc_hw(void) 21516b195c8SJean-Christophe PLAGNIOL-VILLARD { 21616b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC5xxx 21716b195c8SJean-Christophe PLAGNIOL-VILLARD volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE; 2181287e0c5SWolfgang Grandegger #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \ 2191287e0c5SWolfgang Grandegger defined(CONFIG_MPC8548) || defined(CONFIG_MPC8555) 22016b195c8SJean-Christophe PLAGNIOL-VILLARD NS16550_t com_port = (NS16550_t)COM_BASE; 22116b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 22216b195c8SJean-Christophe PLAGNIOL-VILLARD int res = -1; 22316b195c8SJean-Christophe PLAGNIOL-VILLARD 22416b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC5xxx 22516b195c8SJean-Christophe PLAGNIOL-VILLARD if (psc->psc_status & PSC_SR_RXRDY) { 22616b195c8SJean-Christophe PLAGNIOL-VILLARD res = (psc->psc_buffer_8); 22716b195c8SJean-Christophe PLAGNIOL-VILLARD } 2281287e0c5SWolfgang Grandegger #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \ 2291287e0c5SWolfgang Grandegger defined(CONFIG_MPC8548) || defined(CONFIG_MPC8555) 23016b195c8SJean-Christophe PLAGNIOL-VILLARD if (com_port->lsr & LSR_DR) { 23116b195c8SJean-Christophe PLAGNIOL-VILLARD res = com_port->rbr; 23216b195c8SJean-Christophe PLAGNIOL-VILLARD } 23316b195c8SJean-Christophe PLAGNIOL-VILLARD #else 23416b195c8SJean-Christophe PLAGNIOL-VILLARD if (ps2ser_in(UART_LSR) & UART_LSR_DR) { 23516b195c8SJean-Christophe PLAGNIOL-VILLARD res = (ps2ser_in(UART_RX)); 23616b195c8SJean-Christophe PLAGNIOL-VILLARD } 23716b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 23816b195c8SJean-Christophe PLAGNIOL-VILLARD 23916b195c8SJean-Christophe PLAGNIOL-VILLARD return res; 24016b195c8SJean-Christophe PLAGNIOL-VILLARD } 24116b195c8SJean-Christophe PLAGNIOL-VILLARD 24216b195c8SJean-Christophe PLAGNIOL-VILLARD int ps2ser_getc(void) 24316b195c8SJean-Christophe PLAGNIOL-VILLARD { 24416b195c8SJean-Christophe PLAGNIOL-VILLARD volatile int chr; 24516b195c8SJean-Christophe PLAGNIOL-VILLARD int flags; 24616b195c8SJean-Christophe PLAGNIOL-VILLARD 24716b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG 24816b195c8SJean-Christophe PLAGNIOL-VILLARD printf("<< "); 24916b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 25016b195c8SJean-Christophe PLAGNIOL-VILLARD 25116b195c8SJean-Christophe PLAGNIOL-VILLARD flags = disable_interrupts(); 25216b195c8SJean-Christophe PLAGNIOL-VILLARD 25316b195c8SJean-Christophe PLAGNIOL-VILLARD do { 25416b195c8SJean-Christophe PLAGNIOL-VILLARD if (atomic_read(&ps2buf_cnt) != 0) { 25516b195c8SJean-Christophe PLAGNIOL-VILLARD chr = ps2buf[ps2buf_out_idx++]; 25616b195c8SJean-Christophe PLAGNIOL-VILLARD ps2buf_out_idx &= (PS2BUF_SIZE - 1); 25716b195c8SJean-Christophe PLAGNIOL-VILLARD atomic_dec(&ps2buf_cnt); 25816b195c8SJean-Christophe PLAGNIOL-VILLARD } else { 25916b195c8SJean-Christophe PLAGNIOL-VILLARD chr = ps2ser_getc_hw(); 26016b195c8SJean-Christophe PLAGNIOL-VILLARD } 26116b195c8SJean-Christophe PLAGNIOL-VILLARD } 26216b195c8SJean-Christophe PLAGNIOL-VILLARD while (chr < 0); 26316b195c8SJean-Christophe PLAGNIOL-VILLARD 26416b195c8SJean-Christophe PLAGNIOL-VILLARD if (flags) enable_interrupts(); 26516b195c8SJean-Christophe PLAGNIOL-VILLARD 26616b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG 26716b195c8SJean-Christophe PLAGNIOL-VILLARD printf("0x%02x\n", chr); 26816b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 26916b195c8SJean-Christophe PLAGNIOL-VILLARD 27016b195c8SJean-Christophe PLAGNIOL-VILLARD return chr; 27116b195c8SJean-Christophe PLAGNIOL-VILLARD } 27216b195c8SJean-Christophe PLAGNIOL-VILLARD 27316b195c8SJean-Christophe PLAGNIOL-VILLARD int ps2ser_check(void) 27416b195c8SJean-Christophe PLAGNIOL-VILLARD { 27516b195c8SJean-Christophe PLAGNIOL-VILLARD int flags; 27616b195c8SJean-Christophe PLAGNIOL-VILLARD 27716b195c8SJean-Christophe PLAGNIOL-VILLARD flags = disable_interrupts(); 27816b195c8SJean-Christophe PLAGNIOL-VILLARD ps2ser_interrupt(NULL); 27916b195c8SJean-Christophe PLAGNIOL-VILLARD if (flags) enable_interrupts(); 28016b195c8SJean-Christophe PLAGNIOL-VILLARD 28116b195c8SJean-Christophe PLAGNIOL-VILLARD return atomic_read(&ps2buf_cnt); 28216b195c8SJean-Christophe PLAGNIOL-VILLARD } 28316b195c8SJean-Christophe PLAGNIOL-VILLARD 28416b195c8SJean-Christophe PLAGNIOL-VILLARD static void ps2ser_interrupt(void *dev_id) 28516b195c8SJean-Christophe PLAGNIOL-VILLARD { 28616b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC5xxx 28716b195c8SJean-Christophe PLAGNIOL-VILLARD volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE; 2881287e0c5SWolfgang Grandegger #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \ 2891287e0c5SWolfgang Grandegger defined(CONFIG_MPC8548) || defined(CONFIG_MPC8555) 29016b195c8SJean-Christophe PLAGNIOL-VILLARD NS16550_t com_port = (NS16550_t)COM_BASE; 29116b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 29216b195c8SJean-Christophe PLAGNIOL-VILLARD int chr; 29316b195c8SJean-Christophe PLAGNIOL-VILLARD int status; 29416b195c8SJean-Christophe PLAGNIOL-VILLARD 29516b195c8SJean-Christophe PLAGNIOL-VILLARD do { 29616b195c8SJean-Christophe PLAGNIOL-VILLARD chr = ps2ser_getc_hw(); 29716b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC5xxx 29816b195c8SJean-Christophe PLAGNIOL-VILLARD status = psc->psc_status; 2991287e0c5SWolfgang Grandegger #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \ 3001287e0c5SWolfgang Grandegger defined(CONFIG_MPC8548) || defined(CONFIG_MPC8555) 30116b195c8SJean-Christophe PLAGNIOL-VILLARD status = com_port->lsr; 30216b195c8SJean-Christophe PLAGNIOL-VILLARD #else 30316b195c8SJean-Christophe PLAGNIOL-VILLARD status = ps2ser_in(UART_IIR); 30416b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 30516b195c8SJean-Christophe PLAGNIOL-VILLARD if (chr < 0) continue; 30616b195c8SJean-Christophe PLAGNIOL-VILLARD 30716b195c8SJean-Christophe PLAGNIOL-VILLARD if (atomic_read(&ps2buf_cnt) < PS2BUF_SIZE) { 30816b195c8SJean-Christophe PLAGNIOL-VILLARD ps2buf[ps2buf_in_idx++] = chr; 30916b195c8SJean-Christophe PLAGNIOL-VILLARD ps2buf_in_idx &= (PS2BUF_SIZE - 1); 31016b195c8SJean-Christophe PLAGNIOL-VILLARD atomic_inc(&ps2buf_cnt); 31116b195c8SJean-Christophe PLAGNIOL-VILLARD } else { 31216b195c8SJean-Christophe PLAGNIOL-VILLARD printf ("ps2ser.c: buffer overflow\n"); 31316b195c8SJean-Christophe PLAGNIOL-VILLARD } 31416b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC5xxx 31516b195c8SJean-Christophe PLAGNIOL-VILLARD } while (status & PSC_SR_RXRDY); 3161287e0c5SWolfgang Grandegger #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \ 3171287e0c5SWolfgang Grandegger defined(CONFIG_MPC8548) || defined(CONFIG_MPC8555) 31816b195c8SJean-Christophe PLAGNIOL-VILLARD } while (status & LSR_DR); 31916b195c8SJean-Christophe PLAGNIOL-VILLARD #else 32016b195c8SJean-Christophe PLAGNIOL-VILLARD } while (status & UART_IIR_RDI); 32116b195c8SJean-Christophe PLAGNIOL-VILLARD #endif 32216b195c8SJean-Christophe PLAGNIOL-VILLARD 32316b195c8SJean-Christophe PLAGNIOL-VILLARD if (atomic_read(&ps2buf_cnt)) { 32416b195c8SJean-Christophe PLAGNIOL-VILLARD ps2mult_callback(atomic_read(&ps2buf_cnt)); 32516b195c8SJean-Christophe PLAGNIOL-VILLARD } 32616b195c8SJean-Christophe PLAGNIOL-VILLARD } 327