mcf.c revision 496c907740ff083499f5449d2907af442e79ceb0
149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/* 449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer * mcf.c -- Freescale ColdFire UART driver 549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer * 649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer * (C) Copyright 2003-2007, Greg Ungerer <gerg@snapgear.com> 749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer * 849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer * This program is free software; you can redistribute it and/or modify 949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer * it under the terms of the GNU General Public License as published by 1049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer * the Free Software Foundation; either version 2 of the License, or 1149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer * (at your option) any later version. 1249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer */ 1349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 1449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 1549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 1649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#include <linux/kernel.h> 1749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#include <linux/init.h> 1849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#include <linux/interrupt.h> 1949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#include <linux/module.h> 2049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#include <linux/console.h> 2149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#include <linux/tty.h> 2249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#include <linux/tty_flip.h> 2349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#include <linux/serial.h> 2449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#include <linux/serial_core.h> 2549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#include <linux/io.h> 26496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen#include <linux/uaccess.h> 2749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#include <asm/coldfire.h> 2849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#include <asm/mcfsim.h> 2949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#include <asm/mcfuart.h> 3049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#include <asm/nettel.h> 3149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 3249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 3349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 3449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/* 3549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer * Some boards implement the DTR/DCD lines using GPIO lines, most 3649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer * don't. Dummy out the access macros for those that don't. Those 3749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer * that do should define these macros somewhere in there board 3849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer * specific inlude files. 3949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer */ 4049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#if !defined(mcf_getppdcd) 4149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#define mcf_getppdcd(p) (1) 4249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#endif 4349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#if !defined(mcf_getppdtr) 4449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#define mcf_getppdtr(p) (1) 4549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#endif 4649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#if !defined(mcf_setppdtr) 4749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#define mcf_setppdtr(p, v) do { } while (0) 4849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#endif 4949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 5049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 5149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 5249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/* 5349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer * Local per-uart structure. 5449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer */ 5549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstruct mcf_uart { 5649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer struct uart_port port; 5749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer unsigned int sigs; /* Local copy of line sigs */ 5849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer unsigned char imr; /* Local IMR mirror */ 59496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen struct serial_rs485 rs485; /* RS485 settings */ 6049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer}; 6149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 6249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 6349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 6449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic unsigned int mcf_tx_empty(struct uart_port *port) 6549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 6649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer return (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXEMPTY) ? 6749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer TIOCSER_TEMT : 0; 6849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 6949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 7049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 7149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 7249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic unsigned int mcf_get_mctrl(struct uart_port *port) 7349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 749f69ba86d66297189916ceae401fe0944a207714Greg Ungerer struct mcf_uart *pp = container_of(port, struct mcf_uart, port); 7549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer unsigned int sigs; 7649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 7749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer sigs = (readb(port->membase + MCFUART_UIPR) & MCFUART_UIPR_CTS) ? 7849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 0 : TIOCM_CTS; 7949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer sigs |= (pp->sigs & TIOCM_RTS); 8049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer sigs |= (mcf_getppdcd(port->line) ? TIOCM_CD : 0); 8149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer sigs |= (mcf_getppdtr(port->line) ? TIOCM_DTR : 0); 820ac8382e9cfdd723445692fc97aaa4643929750dYury Georgievskiy 8349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer return sigs; 8449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 8549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 8649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 8749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 8849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_set_mctrl(struct uart_port *port, unsigned int sigs) 8949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 909f69ba86d66297189916ceae401fe0944a207714Greg Ungerer struct mcf_uart *pp = container_of(port, struct mcf_uart, port); 9149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 9249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer pp->sigs = sigs; 9349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer mcf_setppdtr(port->line, (sigs & TIOCM_DTR)); 9449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (sigs & TIOCM_RTS) 9549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP1); 9649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer else 9749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP0); 9849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 9949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 10049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 10149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 10249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_start_tx(struct uart_port *port) 10349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 1049f69ba86d66297189916ceae401fe0944a207714Greg Ungerer struct mcf_uart *pp = container_of(port, struct mcf_uart, port); 10549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 106496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen if (pp->rs485.flags & SER_RS485_ENABLED) { 107496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen /* Enable Transmitter */ 108496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen writeb(MCFUART_UCR_TXENABLE, port->membase + MCFUART_UCR); 109496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen /* Manually assert RTS */ 110496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP1); 111496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen } 11249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer pp->imr |= MCFUART_UIR_TXREADY; 11349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(pp->imr, port->membase + MCFUART_UIMR); 11449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 11549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 11649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 11749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 11849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_stop_tx(struct uart_port *port) 11949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 1209f69ba86d66297189916ceae401fe0944a207714Greg Ungerer struct mcf_uart *pp = container_of(port, struct mcf_uart, port); 12149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 12249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer pp->imr &= ~MCFUART_UIR_TXREADY; 12349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(pp->imr, port->membase + MCFUART_UIMR); 12449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 12549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 12649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 12749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 12849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_stop_rx(struct uart_port *port) 12949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 1309f69ba86d66297189916ceae401fe0944a207714Greg Ungerer struct mcf_uart *pp = container_of(port, struct mcf_uart, port); 13149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 13249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer pp->imr &= ~MCFUART_UIR_RXREADY; 13349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(pp->imr, port->membase + MCFUART_UIMR); 13449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 13549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 13649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 13749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 13849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_break_ctl(struct uart_port *port, int break_state) 13949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 14049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer unsigned long flags; 14149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 14249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer spin_lock_irqsave(&port->lock, flags); 14349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (break_state == -1) 14449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(MCFUART_UCR_CMDBREAKSTART, port->membase + MCFUART_UCR); 14549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer else 14649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(MCFUART_UCR_CMDBREAKSTOP, port->membase + MCFUART_UCR); 14749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer spin_unlock_irqrestore(&port->lock, flags); 14849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 14949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 15049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 15149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 15249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_enable_ms(struct uart_port *port) 15349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 15449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 15549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 15649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 15749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 15849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic int mcf_startup(struct uart_port *port) 15949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 1609f69ba86d66297189916ceae401fe0944a207714Greg Ungerer struct mcf_uart *pp = container_of(port, struct mcf_uart, port); 16149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer unsigned long flags; 16249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 16349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer spin_lock_irqsave(&port->lock, flags); 16449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 16549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer /* Reset UART, get it into known state... */ 16649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(MCFUART_UCR_CMDRESETRX, port->membase + MCFUART_UCR); 16749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(MCFUART_UCR_CMDRESETTX, port->membase + MCFUART_UCR); 16849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 16949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer /* Enable the UART transmitter and receiver */ 17049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE, 17149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->membase + MCFUART_UCR); 17249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 17349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer /* Enable RX interrupts now */ 17449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer pp->imr = MCFUART_UIR_RXREADY; 17549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(pp->imr, port->membase + MCFUART_UIMR); 17649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 17749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer spin_unlock_irqrestore(&port->lock, flags); 17849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 17949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer return 0; 18049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 18149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 18249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 18349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 18449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_shutdown(struct uart_port *port) 18549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 1869f69ba86d66297189916ceae401fe0944a207714Greg Ungerer struct mcf_uart *pp = container_of(port, struct mcf_uart, port); 18749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer unsigned long flags; 18849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 18949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer spin_lock_irqsave(&port->lock, flags); 19049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 19149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer /* Disable all interrupts now */ 19249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer pp->imr = 0; 19349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(pp->imr, port->membase + MCFUART_UIMR); 19449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 19549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer /* Disable UART transmitter and receiver */ 19649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(MCFUART_UCR_CMDRESETRX, port->membase + MCFUART_UCR); 19749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(MCFUART_UCR_CMDRESETTX, port->membase + MCFUART_UCR); 19849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 19949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer spin_unlock_irqrestore(&port->lock, flags); 20049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 20149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 20249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 20349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 20449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_set_termios(struct uart_port *port, struct ktermios *termios, 20549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer struct ktermios *old) 20649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 207496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen struct mcf_uart *pp = container_of(port, struct mcf_uart, port); 20849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer unsigned long flags; 20949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer unsigned int baud, baudclk; 21026a4bc66a6f57299027e04d90b14fe56a44c6d2bJohn Adamson#if defined(CONFIG_M5272) 21126a4bc66a6f57299027e04d90b14fe56a44c6d2bJohn Adamson unsigned int baudfr; 21226a4bc66a6f57299027e04d90b14fe56a44c6d2bJohn Adamson#endif 21349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer unsigned char mr1, mr2; 21449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 21549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer baud = uart_get_baud_rate(port, termios, old, 0, 230400); 21626a4bc66a6f57299027e04d90b14fe56a44c6d2bJohn Adamson#if defined(CONFIG_M5272) 21726a4bc66a6f57299027e04d90b14fe56a44c6d2bJohn Adamson baudclk = (MCF_BUSCLK / baud) / 32; 21826a4bc66a6f57299027e04d90b14fe56a44c6d2bJohn Adamson baudfr = (((MCF_BUSCLK / baud) + 1) / 2) % 16; 21926a4bc66a6f57299027e04d90b14fe56a44c6d2bJohn Adamson#else 22049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer baudclk = ((MCF_BUSCLK / baud) + 16) / 32; 22126a4bc66a6f57299027e04d90b14fe56a44c6d2bJohn Adamson#endif 22249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 22349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer mr1 = MCFUART_MR1_RXIRQRDY | MCFUART_MR1_RXERRCHAR; 22449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer mr2 = 0; 22549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 22649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer switch (termios->c_cflag & CSIZE) { 22749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer case CS5: mr1 |= MCFUART_MR1_CS5; break; 22849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer case CS6: mr1 |= MCFUART_MR1_CS6; break; 22949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer case CS7: mr1 |= MCFUART_MR1_CS7; break; 23049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer case CS8: 23149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer default: mr1 |= MCFUART_MR1_CS8; break; 23249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } 23349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 23449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (termios->c_cflag & PARENB) { 23549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (termios->c_cflag & CMSPAR) { 23649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (termios->c_cflag & PARODD) 23749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer mr1 |= MCFUART_MR1_PARITYMARK; 23849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer else 23949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer mr1 |= MCFUART_MR1_PARITYSPACE; 24049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } else { 24149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (termios->c_cflag & PARODD) 24249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer mr1 |= MCFUART_MR1_PARITYODD; 24349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer else 24449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer mr1 |= MCFUART_MR1_PARITYEVEN; 24549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } 24649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } else { 24749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer mr1 |= MCFUART_MR1_PARITYNONE; 24849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } 24949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 25049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (termios->c_cflag & CSTOPB) 25149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer mr2 |= MCFUART_MR2_STOP2; 25249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer else 25349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer mr2 |= MCFUART_MR2_STOP1; 25449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 25549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (termios->c_cflag & CRTSCTS) { 25649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer mr1 |= MCFUART_MR1_RXRTS; 25749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer mr2 |= MCFUART_MR2_TXCTS; 25849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } 25949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 260496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen if (pp->rs485.flags & SER_RS485_ENABLED) { 261496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen dev_dbg(port->dev, "Setting UART to RS485\n"); 262496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen mr2 |= MCFUART_MR2_TXRTS; 263496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen } 264496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen 26549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer spin_lock_irqsave(&port->lock, flags); 2663732b68f22857201fa09cb82b128f295096a2375Philippe De Muyter uart_update_timeout(port, termios->c_cflag, baud); 26749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(MCFUART_UCR_CMDRESETRX, port->membase + MCFUART_UCR); 26849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(MCFUART_UCR_CMDRESETTX, port->membase + MCFUART_UCR); 26949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(MCFUART_UCR_CMDRESETMRPTR, port->membase + MCFUART_UCR); 27049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(mr1, port->membase + MCFUART_UMR); 27149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(mr2, port->membase + MCFUART_UMR); 27249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb((baudclk & 0xff00) >> 8, port->membase + MCFUART_UBG1); 27349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb((baudclk & 0xff), port->membase + MCFUART_UBG2); 27426a4bc66a6f57299027e04d90b14fe56a44c6d2bJohn Adamson#if defined(CONFIG_M5272) 27526a4bc66a6f57299027e04d90b14fe56a44c6d2bJohn Adamson writeb((baudfr & 0x0f), port->membase + MCFUART_UFPD); 27626a4bc66a6f57299027e04d90b14fe56a44c6d2bJohn Adamson#endif 27749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(MCFUART_UCSR_RXCLKTIMER | MCFUART_UCSR_TXCLKTIMER, 27849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->membase + MCFUART_UCSR); 27949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE, 28049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->membase + MCFUART_UCR); 28149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer spin_unlock_irqrestore(&port->lock, flags); 28249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 28349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 28449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 28549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 28649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_rx_chars(struct mcf_uart *pp) 28749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 2889f69ba86d66297189916ceae401fe0944a207714Greg Ungerer struct uart_port *port = &pp->port; 28949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer unsigned char status, ch, flag; 29049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 29149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer while ((status = readb(port->membase + MCFUART_USR)) & MCFUART_USR_RXREADY) { 29249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer ch = readb(port->membase + MCFUART_URB); 29349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer flag = TTY_NORMAL; 29449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->icount.rx++; 29549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 29649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (status & MCFUART_USR_RXERR) { 29749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(MCFUART_UCR_CMDRESETERR, 29849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->membase + MCFUART_UCR); 29949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 30049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (status & MCFUART_USR_RXBREAK) { 30149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->icount.brk++; 30249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (uart_handle_break(port)) 30349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer continue; 30449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } else if (status & MCFUART_USR_RXPARITY) { 30549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->icount.parity++; 30649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } else if (status & MCFUART_USR_RXOVERRUN) { 30749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->icount.overrun++; 30849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } else if (status & MCFUART_USR_RXFRAMING) { 30949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->icount.frame++; 31049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } 31149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 31249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer status &= port->read_status_mask; 31349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 31449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (status & MCFUART_USR_RXBREAK) 31549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer flag = TTY_BREAK; 31649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer else if (status & MCFUART_USR_RXPARITY) 31749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer flag = TTY_PARITY; 31849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer else if (status & MCFUART_USR_RXFRAMING) 31949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer flag = TTY_FRAME; 32049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } 32149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 32249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (uart_handle_sysrq_char(port, ch)) 32349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer continue; 32449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer uart_insert_char(port, status, MCFUART_USR_RXOVERRUN, ch, flag); 32549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } 32649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 3272e124b4a390ca85325fae75764bef92f0547fa25Jiri Slaby tty_flip_buffer_push(&port->state->port); 32849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 32949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 33049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 33149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 33249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_tx_chars(struct mcf_uart *pp) 33349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 3349f69ba86d66297189916ceae401fe0944a207714Greg Ungerer struct uart_port *port = &pp->port; 335ebd2c8f6d2ec4012c267ecb95e72a57b8355a705Alan Cox struct circ_buf *xmit = &port->state->xmit; 33649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 33749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (port->x_char) { 33849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer /* Send special char - probably flow control */ 33949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(port->x_char, port->membase + MCFUART_UTB); 34049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->x_char = 0; 34149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->icount.tx++; 34249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer return; 34349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } 34449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 34549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer while (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXREADY) { 34649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (xmit->head == xmit->tail) 34749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer break; 34849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(xmit->buf[xmit->tail], port->membase + MCFUART_UTB); 34949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE -1); 35049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->icount.tx++; 35149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } 35249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 35349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) 35449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer uart_write_wakeup(port); 35549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 35649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (xmit->head == xmit->tail) { 35749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer pp->imr &= ~MCFUART_UIR_TXREADY; 35849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(pp->imr, port->membase + MCFUART_UIMR); 359496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen /* Disable TX to negate RTS automatically */ 360496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen if (pp->rs485.flags & SER_RS485_ENABLED) 361496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen writeb(MCFUART_UCR_TXDISABLE, 362496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen port->membase + MCFUART_UCR); 36349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } 36449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 36549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 36649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 36749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 36849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic irqreturn_t mcf_interrupt(int irq, void *data) 36949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 37049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer struct uart_port *port = data; 3719f69ba86d66297189916ceae401fe0944a207714Greg Ungerer struct mcf_uart *pp = container_of(port, struct mcf_uart, port); 37249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer unsigned int isr; 3730ac8382e9cfdd723445692fc97aaa4643929750dYury Georgievskiy irqreturn_t ret = IRQ_NONE; 37449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 37549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer isr = readb(port->membase + MCFUART_UISR) & pp->imr; 3760ac8382e9cfdd723445692fc97aaa4643929750dYury Georgievskiy 3770ac8382e9cfdd723445692fc97aaa4643929750dYury Georgievskiy spin_lock(&port->lock); 3780ac8382e9cfdd723445692fc97aaa4643929750dYury Georgievskiy if (isr & MCFUART_UIR_RXREADY) { 37949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer mcf_rx_chars(pp); 3800ac8382e9cfdd723445692fc97aaa4643929750dYury Georgievskiy ret = IRQ_HANDLED; 3810ac8382e9cfdd723445692fc97aaa4643929750dYury Georgievskiy } 3820ac8382e9cfdd723445692fc97aaa4643929750dYury Georgievskiy if (isr & MCFUART_UIR_TXREADY) { 38349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer mcf_tx_chars(pp); 3840ac8382e9cfdd723445692fc97aaa4643929750dYury Georgievskiy ret = IRQ_HANDLED; 3850ac8382e9cfdd723445692fc97aaa4643929750dYury Georgievskiy } 3860ac8382e9cfdd723445692fc97aaa4643929750dYury Georgievskiy spin_unlock(&port->lock); 3870ac8382e9cfdd723445692fc97aaa4643929750dYury Georgievskiy 3880ac8382e9cfdd723445692fc97aaa4643929750dYury Georgievskiy return ret; 38949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 39049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 39149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 39249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 39349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_config_port(struct uart_port *port, int flags) 39449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 39549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->type = PORT_MCF; 3963732b68f22857201fa09cb82b128f295096a2375Philippe De Muyter port->fifosize = MCFUART_TXFIFOSIZE; 39749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 39849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer /* Clear mask, so no surprise interrupts. */ 39949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(0, port->membase + MCFUART_UIMR); 40049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 4019cfb5c05fee914cc65d4706801f6bc424082b5f5Yong Zhang if (request_irq(port->irq, mcf_interrupt, 0, "UART", port)) 40249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer printk(KERN_ERR "MCF: unable to attach ColdFire UART %d " 40349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer "interrupt vector=%d\n", port->line, port->irq); 40449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 40549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 40649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 40749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 40849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic const char *mcf_type(struct uart_port *port) 40949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 41049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer return (port->type == PORT_MCF) ? "ColdFire UART" : NULL; 41149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 41249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 41349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 41449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 41549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic int mcf_request_port(struct uart_port *port) 41649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 41749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer /* UARTs always present */ 41849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer return 0; 41949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 42049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 42149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 42249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 42349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_release_port(struct uart_port *port) 42449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 42549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer /* Nothing to release... */ 42649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 42749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 42849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 42949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 43049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic int mcf_verify_port(struct uart_port *port, struct serial_struct *ser) 43149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 43249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if ((ser->type != PORT_UNKNOWN) && (ser->type != PORT_MCF)) 43349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer return -EINVAL; 43449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer return 0; 43549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 43649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 43749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 43849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 439496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen/* Enable or disable the RS485 support */ 440496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyenstatic void mcf_config_rs485(struct uart_port *port, struct serial_rs485 *rs485) 441496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen{ 442496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen struct mcf_uart *pp = container_of(port, struct mcf_uart, port); 443496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen unsigned long flags; 444496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen unsigned char mr1, mr2; 445496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen 446496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen spin_lock_irqsave(&port->lock, flags); 447496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen /* Get mode registers */ 448496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen mr1 = readb(port->membase + MCFUART_UMR); 449496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen mr2 = readb(port->membase + MCFUART_UMR); 450496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen if (rs485->flags & SER_RS485_ENABLED) { 451496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen dev_dbg(port->dev, "Setting UART to RS485\n"); 452496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen /* Automatically negate RTS after TX completes */ 453496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen mr2 |= MCFUART_MR2_TXRTS; 454496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen } else { 455496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen dev_dbg(port->dev, "Setting UART to RS232\n"); 456496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen mr2 &= ~MCFUART_MR2_TXRTS; 457496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen } 458496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen writeb(mr1, port->membase + MCFUART_UMR); 459496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen writeb(mr2, port->membase + MCFUART_UMR); 460496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen pp->rs485 = *rs485; 461496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen spin_unlock_irqrestore(&port->lock, flags); 462496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen} 463496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen 464496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyenstatic int mcf_ioctl(struct uart_port *port, unsigned int cmd, 465496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen unsigned long arg) 466496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen{ 467496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen switch (cmd) { 468496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen case TIOCSRS485: { 469496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen struct serial_rs485 rs485; 470496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen if (copy_from_user(&rs485, (struct serial_rs485 *)arg, 471496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen sizeof(struct serial_rs485))) 472496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen return -EFAULT; 473496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen mcf_config_rs485(port, &rs485); 474496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen break; 475496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen } 476496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen case TIOCGRS485: { 477496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen struct mcf_uart *pp = container_of(port, struct mcf_uart, port); 478496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen if (copy_to_user((struct serial_rs485 *)arg, &pp->rs485, 479496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen sizeof(struct serial_rs485))) 480496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen return -EFAULT; 481496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen break; 482496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen } 483496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen default: 484496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen return -ENOIOCTLCMD; 485496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen } 486496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen return 0; 487496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen} 488496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen 489496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen/****************************************************************************/ 490496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen 49149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/* 49249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer * Define the basic serial functions we support. 49349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer */ 4943732b68f22857201fa09cb82b128f295096a2375Philippe De Muyterstatic const struct uart_ops mcf_uart_ops = { 49549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .tx_empty = mcf_tx_empty, 49649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .get_mctrl = mcf_get_mctrl, 49749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .set_mctrl = mcf_set_mctrl, 49849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .start_tx = mcf_start_tx, 49949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .stop_tx = mcf_stop_tx, 50049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .stop_rx = mcf_stop_rx, 50149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .enable_ms = mcf_enable_ms, 50249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .break_ctl = mcf_break_ctl, 50349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .startup = mcf_startup, 50449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .shutdown = mcf_shutdown, 50549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .set_termios = mcf_set_termios, 50649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .type = mcf_type, 50749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .request_port = mcf_request_port, 50849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .release_port = mcf_release_port, 50949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .config_port = mcf_config_port, 51049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .verify_port = mcf_verify_port, 511496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen .ioctl = mcf_ioctl, 51249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer}; 51349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 5142545cf6e94b4eb5a2c48dd55751aa9a70ff1ff9dPhilippe De Muyterstatic struct mcf_uart mcf_ports[4]; 51549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 51616791963ff7dd6a108251f5fa4b273cf1ffe531fGreg Ungerer#define MCF_MAXPORTS ARRAY_SIZE(mcf_ports) 51749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 51849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 51949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#if defined(CONFIG_SERIAL_MCF_CONSOLE) 52049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 52149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 52249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererint __init early_mcf_setup(struct mcf_platform_uart *platp) 52349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 52449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer struct uart_port *port; 52549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer int i; 52649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 52749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer for (i = 0; ((i < MCF_MAXPORTS) && (platp[i].mapbase)); i++) { 52849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port = &mcf_ports[i].port; 52949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 53049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->line = i; 53149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->type = PORT_MCF; 53249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->mapbase = platp[i].mapbase; 53349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->membase = (platp[i].membase) ? platp[i].membase : 53449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer (unsigned char __iomem *) port->mapbase; 53549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->iotype = SERIAL_IO_MEM; 53649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->irq = platp[i].irq; 53749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->uartclk = MCF_BUSCLK; 53849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->flags = ASYNC_BOOT_AUTOCONF; 53949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->ops = &mcf_uart_ops; 54049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } 54149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 54249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer return 0; 54349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 54449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 54549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 54649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 54749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_console_putc(struct console *co, const char c) 54849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 54949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer struct uart_port *port = &(mcf_ports + co->index)->port; 55049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer int i; 55149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 55249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer for (i = 0; (i < 0x10000); i++) { 55349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXREADY) 55449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer break; 55549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } 55649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(c, port->membase + MCFUART_UTB); 55749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer for (i = 0; (i < 0x10000); i++) { 55849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXREADY) 55949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer break; 56049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } 56149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 56249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 56349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 56449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 56549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_console_write(struct console *co, const char *s, unsigned int count) 56649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 56749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer for (; (count); count--, s++) { 56849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer mcf_console_putc(co, *s); 56949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (*s == '\n') 57049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer mcf_console_putc(co, '\r'); 57149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } 57249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 57349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 57449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 57549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 57649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic int __init mcf_console_setup(struct console *co, char *options) 57749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 57849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer struct uart_port *port; 57949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer int baud = CONFIG_SERIAL_MCF_BAUDRATE; 58049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer int bits = 8; 58149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer int parity = 'n'; 58249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer int flow = 'n'; 58349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 5844330e179a96bc9310d36e9b858bc8f275f329312Len Sorensen if ((co->index < 0) || (co->index >= MCF_MAXPORTS)) 58549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer co->index = 0; 58649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port = &mcf_ports[co->index].port; 58749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (port->membase == 0) 58849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer return -ENODEV; 58949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 59049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (options) 59149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer uart_parse_options(options, &baud, &parity, &bits, &flow); 59249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 59349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer return uart_set_options(port, co, baud, parity, bits, flow); 59449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 59549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 59649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 59749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 59849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic struct uart_driver mcf_driver; 59949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 60049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic struct console mcf_console = { 60149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .name = "ttyS", 60249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .write = mcf_console_write, 60349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .device = uart_console_device, 60449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .setup = mcf_console_setup, 60549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .flags = CON_PRINTBUFFER, 60649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .index = -1, 60749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .data = &mcf_driver, 60849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer}; 60949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 61049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic int __init mcf_console_init(void) 61149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 61249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer register_console(&mcf_console); 61349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer return 0; 61449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 61549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 61649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererconsole_initcall(mcf_console_init); 61749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 61849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#define MCF_CONSOLE &mcf_console 61949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 62049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 62149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#else 62249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 62349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 62449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#define MCF_CONSOLE NULL 62549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 62649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 62749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#endif /* CONFIG_MCF_CONSOLE */ 62849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 62949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 63049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/* 63149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer * Define the mcf UART driver structure. 63249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer */ 63349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic struct uart_driver mcf_driver = { 63449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .owner = THIS_MODULE, 63549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .driver_name = "mcf", 63649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .dev_name = "ttyS", 63749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .major = TTY_MAJOR, 63849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .minor = 64, 63949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .nr = MCF_MAXPORTS, 64049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .cons = MCF_CONSOLE, 64149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer}; 64249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 64349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 64449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 6459671f09921d93e722a28ae9610d478e092ac5466Bill Pembertonstatic int mcf_probe(struct platform_device *pdev) 64649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 64749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer struct mcf_platform_uart *platp = pdev->dev.platform_data; 64849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer struct uart_port *port; 64949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer int i; 65049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 65149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer for (i = 0; ((i < MCF_MAXPORTS) && (platp[i].mapbase)); i++) { 65249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port = &mcf_ports[i].port; 65349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 65449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->line = i; 65549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->type = PORT_MCF; 65649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->mapbase = platp[i].mapbase; 65749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->membase = (platp[i].membase) ? platp[i].membase : 65849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer (unsigned char __iomem *) platp[i].mapbase; 65949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->iotype = SERIAL_IO_MEM; 66049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->irq = platp[i].irq; 66149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->uartclk = MCF_BUSCLK; 66249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->ops = &mcf_uart_ops; 66349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->flags = ASYNC_BOOT_AUTOCONF; 66449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 66549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer uart_add_one_port(&mcf_driver, port); 66649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } 66749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 66849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer return 0; 66949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 67049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 67149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 67249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 673ae8d8a146725a966bd7c59c94f4d0016dcf7a04fBill Pembertonstatic int mcf_remove(struct platform_device *pdev) 67449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 67549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer struct uart_port *port; 67649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer int i; 67749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 67849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer for (i = 0; (i < MCF_MAXPORTS); i++) { 67949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port = &mcf_ports[i].port; 68049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (port) 68149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer uart_remove_one_port(&mcf_driver, port); 68249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } 68349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 68449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer return 0; 68549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 68649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 68749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 68849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 68949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic struct platform_driver mcf_platform_driver = { 69049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .probe = mcf_probe, 6912d47b7160243b1422006b91debf438484a4fde58Bill Pemberton .remove = mcf_remove, 69249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .driver = { 69349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .name = "mcfuart", 69449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .owner = THIS_MODULE, 69549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer }, 69649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer}; 69749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 69849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 69949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 70049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic int __init mcf_init(void) 70149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 70249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer int rc; 70349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 70449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer printk("ColdFire internal UART serial driver\n"); 70549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 70649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer rc = uart_register_driver(&mcf_driver); 70749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (rc) 70849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer return rc; 70949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer rc = platform_driver_register(&mcf_platform_driver); 71049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (rc) 71149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer return rc; 71249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer return 0; 71349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 71449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 71549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 71649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 71749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void __exit mcf_exit(void) 71849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 71949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer platform_driver_unregister(&mcf_platform_driver); 72049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer uart_unregister_driver(&mcf_driver); 72149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 72249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 72349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 72449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 72549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerermodule_init(mcf_init); 72649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerermodule_exit(mcf_exit); 72749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 72849aa49bfd40d718095669c1c70c9d167b814e29bGreg UngererMODULE_AUTHOR("Greg Ungerer <gerg@snapgear.com>"); 72949aa49bfd40d718095669c1c70c9d167b814e29bGreg UngererMODULE_DESCRIPTION("Freescale ColdFire UART driver"); 73049aa49bfd40d718095669c1c70c9d167b814e29bGreg UngererMODULE_LICENSE("GPL"); 731e169c139642fb4c682ec12a409725508dbefa520Kay SieversMODULE_ALIAS("platform:mcfuart"); 73249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 73349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 734