📄 mpc52xx_uart.c
字号:
if (err && (port->flags & UPF_IOREMAP)) { iounmap(port->membase); port->membase = NULL; } return err;}static voidmpc52xx_uart_config_port(struct uart_port *port, int flags){ if ( (flags & UART_CONFIG_TYPE) && (mpc52xx_uart_request_port(port) == 0) ) port->type = PORT_MPC52xx;}static intmpc52xx_uart_verify_port(struct uart_port *port, struct serial_struct *ser){ if ( ser->type != PORT_UNKNOWN && ser->type != PORT_MPC52xx ) return -EINVAL; if ( (ser->irq != port->irq) || (ser->io_type != SERIAL_IO_MEM) || (ser->baud_base != port->uartclk) || (ser->iomem_base != (void*)port->mapbase) || (ser->hub6 != 0 ) ) return -EINVAL; return 0;}static struct uart_ops mpc52xx_uart_ops = { .tx_empty = mpc52xx_uart_tx_empty, .set_mctrl = mpc52xx_uart_set_mctrl, .get_mctrl = mpc52xx_uart_get_mctrl, .stop_tx = mpc52xx_uart_stop_tx, .start_tx = mpc52xx_uart_start_tx, .send_xchar = mpc52xx_uart_send_xchar, .stop_rx = mpc52xx_uart_stop_rx, .enable_ms = mpc52xx_uart_enable_ms, .break_ctl = mpc52xx_uart_break_ctl, .startup = mpc52xx_uart_startup, .shutdown = mpc52xx_uart_shutdown, .set_termios = mpc52xx_uart_set_termios,/* .pm = mpc52xx_uart_pm, Not supported yet *//* .set_wake = mpc52xx_uart_set_wake, Not supported yet */ .type = mpc52xx_uart_type, .release_port = mpc52xx_uart_release_port, .request_port = mpc52xx_uart_request_port, .config_port = mpc52xx_uart_config_port, .verify_port = mpc52xx_uart_verify_port};/* ======================================================================== *//* Interrupt handling *//* ======================================================================== */static inline intmpc52xx_uart_int_rx_chars(struct uart_port *port){ struct tty_struct *tty = port->info->tty; unsigned char ch, flag; unsigned short status; /* While we can read, do so ! */ while ( (status = in_be16(&PSC(port)->mpc52xx_psc_status)) & MPC52xx_PSC_SR_RXRDY) { /* Get the char */ ch = in_8(&PSC(port)->mpc52xx_psc_buffer_8); /* Handle sysreq char */#ifdef SUPPORT_SYSRQ if (uart_handle_sysrq_char(port, ch)) { port->sysrq = 0; continue; }#endif /* Store it */ flag = TTY_NORMAL; port->icount.rx++; if ( status & (MPC52xx_PSC_SR_PE | MPC52xx_PSC_SR_FE | MPC52xx_PSC_SR_RB) ) { if (status & MPC52xx_PSC_SR_RB) { flag = TTY_BREAK; uart_handle_break(port); } else if (status & MPC52xx_PSC_SR_PE) flag = TTY_PARITY; else if (status & MPC52xx_PSC_SR_FE) flag = TTY_FRAME; /* Clear error condition */ out_8(&PSC(port)->command,MPC52xx_PSC_RST_ERR_STAT); } tty_insert_flip_char(tty, ch, flag); if (status & MPC52xx_PSC_SR_OE) { /* * Overrun is special, since it's * reported immediately, and doesn't * affect the current character */ tty_insert_flip_char(tty, 0, TTY_OVERRUN); } } tty_flip_buffer_push(tty); return in_be16(&PSC(port)->mpc52xx_psc_status) & MPC52xx_PSC_SR_RXRDY;}static inline intmpc52xx_uart_int_tx_chars(struct uart_port *port){ struct circ_buf *xmit = &port->info->xmit; /* Process out of band chars */ if (port->x_char) { out_8(&PSC(port)->mpc52xx_psc_buffer_8, port->x_char); port->icount.tx++; port->x_char = 0; return 1; } /* Nothing to do ? */ if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { mpc52xx_uart_stop_tx(port); return 0; } /* Send chars */ while (in_be16(&PSC(port)->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXRDY) { out_8(&PSC(port)->mpc52xx_psc_buffer_8, xmit->buf[xmit->tail]); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); port->icount.tx++; if (uart_circ_empty(xmit)) break; } /* Wake up */ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(port); /* Maybe we're done after all */ if (uart_circ_empty(xmit)) { mpc52xx_uart_stop_tx(port); return 0; } return 1;}static irqreturn_tmpc52xx_uart_int(int irq, void *dev_id){ struct uart_port *port = dev_id; unsigned long pass = ISR_PASS_LIMIT; unsigned int keepgoing; unsigned short status; spin_lock(&port->lock); /* While we have stuff to do, we continue */ do { /* If we don't find anything to do, we stop */ keepgoing = 0; /* Read status */ status = in_be16(&PSC(port)->mpc52xx_psc_isr); status &= port->read_status_mask; /* Do we need to receive chars ? */ /* For this RX interrupts must be on and some chars waiting */ if ( status & MPC52xx_PSC_IMR_RXRDY ) keepgoing |= mpc52xx_uart_int_rx_chars(port); /* Do we need to send chars ? */ /* For this, TX must be ready and TX interrupt enabled */ if ( status & MPC52xx_PSC_IMR_TXRDY ) keepgoing |= mpc52xx_uart_int_tx_chars(port); /* Limit number of iteration */ if ( !(--pass) ) keepgoing = 0; } while (keepgoing); spin_unlock(&port->lock); return IRQ_HANDLED;}/* ======================================================================== *//* Console ( if applicable ) *//* ======================================================================== */#ifdef CONFIG_SERIAL_MPC52xx_CONSOLEstatic void __initmpc52xx_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits, int *flow){ struct mpc52xx_psc __iomem *psc = PSC(port); unsigned char mr1; pr_debug("mpc52xx_console_get_options(port=%p)\n", port); /* Read the mode registers */ out_8(&psc->command,MPC52xx_PSC_SEL_MODE_REG_1); mr1 = in_8(&psc->mode); /* CT{U,L}R are write-only ! */ *baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD;#if !defined(CONFIG_PPC_MERGE) if (__res.bi_baudrate) *baud = __res.bi_baudrate;#endif /* Parse them */ switch (mr1 & MPC52xx_PSC_MODE_BITS_MASK) { case MPC52xx_PSC_MODE_5_BITS: *bits = 5; break; case MPC52xx_PSC_MODE_6_BITS: *bits = 6; break; case MPC52xx_PSC_MODE_7_BITS: *bits = 7; break; case MPC52xx_PSC_MODE_8_BITS: default: *bits = 8; } if (mr1 & MPC52xx_PSC_MODE_PARNONE) *parity = 'n'; else *parity = mr1 & MPC52xx_PSC_MODE_PARODD ? 'o' : 'e';}static voidmpc52xx_console_write(struct console *co, const char *s, unsigned int count){ struct uart_port *port = &mpc52xx_uart_ports[co->index]; struct mpc52xx_psc __iomem *psc = PSC(port); unsigned int i, j; /* Disable interrupts */ out_be16(&psc->mpc52xx_psc_imr, 0); /* Wait the TX buffer to be empty */ j = 5000000; /* Maximum wait */ while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP) && --j) udelay(1); /* Write all the chars */ for (i = 0; i < count; i++, s++) { /* Line return handling */ if (*s == '\n') out_8(&psc->mpc52xx_psc_buffer_8, '\r'); /* Send the char */ out_8(&psc->mpc52xx_psc_buffer_8, *s); /* Wait the TX buffer to be empty */ j = 20000; /* Maximum wait */ while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP) && --j) udelay(1); } /* Restore interrupt state */ out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask);}#if !defined(CONFIG_PPC_MERGE)static int __initmpc52xx_console_setup(struct console *co, char *options){ struct uart_port *port = &mpc52xx_uart_ports[co->index]; int baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD; int bits = 8; int parity = 'n'; int flow = 'n'; if (co->index < 0 || co->index >= MPC52xx_PSC_MAXNUM) return -EINVAL; /* Basic port init. Needed since we use some uart_??? func before * real init for early access */ spin_lock_init(&port->lock); port->uartclk = __res.bi_ipbfreq / 2; /* Look at CTLR doc */ port->ops = &mpc52xx_uart_ops; port->mapbase = MPC52xx_PA(MPC52xx_PSCx_OFFSET(co->index+1)); /* We ioremap ourself */ port->membase = ioremap(port->mapbase, MPC52xx_PSC_SIZE); if (port->membase == NULL) return -EINVAL; /* Setup the port parameters accoding to options */ if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); else mpc52xx_console_get_options(port, &baud, &parity, &bits, &flow); return uart_set_options(port, co, baud, parity, bits, flow);}#elsestatic int __initmpc52xx_console_setup(struct console *co, char *options){ struct uart_port *port = &mpc52xx_uart_ports[co->index]; struct device_node *np = mpc52xx_uart_nodes[co->index]; unsigned int ipb_freq; struct resource res; int ret; int baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD; int bits = 8; int parity = 'n'; int flow = 'n'; pr_debug("mpc52xx_console_setup co=%p, co->index=%i, options=%s\n", co, co->index, options); if ((co->index < 0) || (co->index > MPC52xx_PSC_MAXNUM)) { pr_debug("PSC%x out of range\n", co->index); return -EINVAL; } if (!np) { pr_debug("PSC%x not found in device tree\n", co->index); return -EINVAL; } pr_debug("Console on ttyPSC%x is %s\n", co->index, mpc52xx_uart_nodes[co->index]->full_name); /* Fetch register locations */ if ((ret = of_address_to_resource(np, 0, &res)) != 0) { pr_debug("Could not get resources for PSC%x\n", co->index); return ret; } /* Search for bus-frequency property in this node or a parent */ if ((ipb_freq = mpc52xx_find_ipb_freq(np)) == 0) { pr_debug("Could not find IPB bus frequency!\n"); return -EINVAL; } /* Basic port init. Needed since we use some uart_??? func before * real init for early access */ spin_lock_init(&port->lock); port->uartclk = ipb_freq / 2; port->ops = &mpc52xx_uart_ops; port->mapbase = res.start; port->membase = ioremap(res.start, sizeof(struct mpc52xx_psc)); port->irq = irq_of_parse_and_map(np, 0); if (port->membase == NULL) return -EINVAL; pr_debug("mpc52xx-psc uart at %p, mapped to %p, irq=%x, freq=%i\n", (void*)port->mapbase, port->membase, port->irq, port->uartclk); /* Setup the port parameters accoding to options */ if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); else mpc52xx_console_get_options(port, &baud, &parity, &bits, &flow); pr_debug("Setting console parameters: %i %i%c1 flow=%c\n", baud, bits, parity, flow); return uart_set_options(port, co, baud, parity, bits, flow);}#endif /* defined(CONFIG_PPC_MERGE) */static struct uart_driver mpc52xx_uart_driver;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -