mcf.c revision 3732b68f22857201fa09cb82b128f295096a2375
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>
2649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#include <asm/coldfire.h>
2749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#include <asm/mcfsim.h>
2849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#include <asm/mcfuart.h>
2949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#include <asm/nettel.h>
3049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
3149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/
3249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
3349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/*
3449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer *	Some boards implement the DTR/DCD lines using GPIO lines, most
3549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer *	don't. Dummy out the access macros for those that don't. Those
3649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer *	that do should define these macros somewhere in there board
3749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer *	specific inlude files.
3849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer */
3949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#if !defined(mcf_getppdcd)
4049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#define	mcf_getppdcd(p)		(1)
4149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#endif
4249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#if !defined(mcf_getppdtr)
4349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#define	mcf_getppdtr(p)		(1)
4449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#endif
4549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#if !defined(mcf_setppdtr)
4649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#define	mcf_setppdtr(p, v)	do { } while (0)
4749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#endif
4849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
4949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/
5049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
5149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/*
5249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer *	Local per-uart structure.
5349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer */
5449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstruct mcf_uart {
5549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	struct uart_port	port;
5649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	unsigned int		sigs;		/* Local copy of line sigs */
5749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	unsigned char		imr;		/* Local IMR mirror */
5849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer};
5949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
6049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/
6149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
6249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic unsigned int mcf_tx_empty(struct uart_port *port)
6349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{
6449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	return (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXEMPTY) ?
6549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		TIOCSER_TEMT : 0;
6649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer}
6749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
6849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/
6949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
7049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic unsigned int mcf_get_mctrl(struct uart_port *port)
7149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{
729f69ba86d66297189916ceae401fe0944a207714Greg Ungerer	struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
7349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	unsigned long flags;
7449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	unsigned int sigs;
7549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
7649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	spin_lock_irqsave(&port->lock, flags);
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);
8249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	spin_unlock_irqrestore(&port->lock, flags);
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	unsigned long flags;
9249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
9349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	spin_lock_irqsave(&port->lock, flags);
9449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	pp->sigs = sigs;
9549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	mcf_setppdtr(port->line, (sigs & TIOCM_DTR));
9649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	if (sigs & TIOCM_RTS)
9749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP1);
9849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	else
9949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP0);
10049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	spin_unlock_irqrestore(&port->lock, flags);
10149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer}
10249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
10349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/
10449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
10549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_start_tx(struct uart_port *port)
10649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{
1079f69ba86d66297189916ceae401fe0944a207714Greg Ungerer	struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
10849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	unsigned long flags;
10949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
11049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	spin_lock_irqsave(&port->lock, flags);
11149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	pp->imr |= MCFUART_UIR_TXREADY;
11249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	writeb(pp->imr, port->membase + MCFUART_UIMR);
11349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	spin_unlock_irqrestore(&port->lock, flags);
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	unsigned long flags;
12249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
12349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	spin_lock_irqsave(&port->lock, flags);
12449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	pp->imr &= ~MCFUART_UIR_TXREADY;
12549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	writeb(pp->imr, port->membase + MCFUART_UIMR);
12649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	spin_unlock_irqrestore(&port->lock, flags);
12749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer}
12849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
12949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/
13049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
13149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_stop_rx(struct uart_port *port)
13249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{
1339f69ba86d66297189916ceae401fe0944a207714Greg Ungerer	struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
13449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	unsigned long flags;
13549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
13649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	spin_lock_irqsave(&port->lock, flags);
13749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	pp->imr &= ~MCFUART_UIR_RXREADY;
13849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	writeb(pp->imr, port->membase + MCFUART_UIMR);
13949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	spin_unlock_irqrestore(&port->lock, flags);
14049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer}
14149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
14249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/
14349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
14449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_break_ctl(struct uart_port *port, int break_state)
14549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{
14649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	unsigned long flags;
14749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
14849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	spin_lock_irqsave(&port->lock, flags);
14949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	if (break_state == -1)
15049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		writeb(MCFUART_UCR_CMDBREAKSTART, port->membase + MCFUART_UCR);
15149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	else
15249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		writeb(MCFUART_UCR_CMDBREAKSTOP, port->membase + MCFUART_UCR);
15349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	spin_unlock_irqrestore(&port->lock, flags);
15449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer}
15549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
15649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/
15749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
15849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_enable_ms(struct uart_port *port)
15949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{
16049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer}
16149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
16249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/
16349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
16449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic int mcf_startup(struct uart_port *port)
16549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{
1669f69ba86d66297189916ceae401fe0944a207714Greg Ungerer	struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
16749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	unsigned long flags;
16849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
16949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	spin_lock_irqsave(&port->lock, flags);
17049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
17149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	/* Reset UART, get it into known state... */
17249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	writeb(MCFUART_UCR_CMDRESETRX, port->membase + MCFUART_UCR);
17349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	writeb(MCFUART_UCR_CMDRESETTX, port->membase + MCFUART_UCR);
17449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
17549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	/* Enable the UART transmitter and receiver */
17649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	writeb(MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE,
17749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		port->membase + MCFUART_UCR);
17849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
17949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	/* Enable RX interrupts now */
18049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	pp->imr = MCFUART_UIR_RXREADY;
18149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	writeb(pp->imr, port->membase + MCFUART_UIMR);
18249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
18349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	spin_unlock_irqrestore(&port->lock, flags);
18449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
18549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	return 0;
18649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer}
18749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
18849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/
18949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
19049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_shutdown(struct uart_port *port)
19149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{
1929f69ba86d66297189916ceae401fe0944a207714Greg Ungerer	struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
19349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	unsigned long flags;
19449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
19549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	spin_lock_irqsave(&port->lock, flags);
19649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
19749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	/* Disable all interrupts now */
19849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	pp->imr = 0;
19949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	writeb(pp->imr, port->membase + MCFUART_UIMR);
20049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
20149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	/* Disable UART transmitter and receiver */
20249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	writeb(MCFUART_UCR_CMDRESETRX, port->membase + MCFUART_UCR);
20349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	writeb(MCFUART_UCR_CMDRESETTX, port->membase + MCFUART_UCR);
20449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
20549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	spin_unlock_irqrestore(&port->lock, flags);
20649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer}
20749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
20849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/
20949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
21049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_set_termios(struct uart_port *port, struct ktermios *termios,
21149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	struct ktermios *old)
21249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{
21349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	unsigned long flags;
21449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	unsigned int baud, baudclk;
21526a4bc66a6f57299027e04d90b14fe56a44c6d2bJohn Adamson#if defined(CONFIG_M5272)
21626a4bc66a6f57299027e04d90b14fe56a44c6d2bJohn Adamson	unsigned int baudfr;
21726a4bc66a6f57299027e04d90b14fe56a44c6d2bJohn Adamson#endif
21849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	unsigned char mr1, mr2;
21949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
22049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	baud = uart_get_baud_rate(port, termios, old, 0, 230400);
22126a4bc66a6f57299027e04d90b14fe56a44c6d2bJohn Adamson#if defined(CONFIG_M5272)
22226a4bc66a6f57299027e04d90b14fe56a44c6d2bJohn Adamson	baudclk = (MCF_BUSCLK / baud) / 32;
22326a4bc66a6f57299027e04d90b14fe56a44c6d2bJohn Adamson	baudfr = (((MCF_BUSCLK / baud) + 1) / 2) % 16;
22426a4bc66a6f57299027e04d90b14fe56a44c6d2bJohn Adamson#else
22549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	baudclk = ((MCF_BUSCLK / baud) + 16) / 32;
22626a4bc66a6f57299027e04d90b14fe56a44c6d2bJohn Adamson#endif
22749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
22849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	mr1 = MCFUART_MR1_RXIRQRDY | MCFUART_MR1_RXERRCHAR;
22949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	mr2 = 0;
23049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
23149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	switch (termios->c_cflag & CSIZE) {
23249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	case CS5: mr1 |= MCFUART_MR1_CS5; break;
23349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	case CS6: mr1 |= MCFUART_MR1_CS6; break;
23449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	case CS7: mr1 |= MCFUART_MR1_CS7; break;
23549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	case CS8:
23649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	default:  mr1 |= MCFUART_MR1_CS8; break;
23749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	}
23849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
23949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	if (termios->c_cflag & PARENB) {
24049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		if (termios->c_cflag & CMSPAR) {
24149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer			if (termios->c_cflag & PARODD)
24249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer				mr1 |= MCFUART_MR1_PARITYMARK;
24349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer			else
24449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer				mr1 |= MCFUART_MR1_PARITYSPACE;
24549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		} else {
24649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer			if (termios->c_cflag & PARODD)
24749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer				mr1 |= MCFUART_MR1_PARITYODD;
24849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer			else
24949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer				mr1 |= MCFUART_MR1_PARITYEVEN;
25049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		}
25149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	} else {
25249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		mr1 |= MCFUART_MR1_PARITYNONE;
25349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	}
25449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
25549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	if (termios->c_cflag & CSTOPB)
25649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		mr2 |= MCFUART_MR2_STOP2;
25749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	else
25849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		mr2 |= MCFUART_MR2_STOP1;
25949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
26049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	if (termios->c_cflag & CRTSCTS) {
26149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		mr1 |= MCFUART_MR1_RXRTS;
26249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		mr2 |= MCFUART_MR2_TXCTS;
26349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	}
26449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
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
327ebd2c8f6d2ec4012c267ecb95e72a57b8355a705Alan Cox	tty_flip_buffer_push(port->state->port.tty);
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);
35949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	}
36049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer}
36149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
36249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/
36349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
36449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic irqreturn_t mcf_interrupt(int irq, void *data)
36549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{
36649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	struct uart_port *port = data;
3679f69ba86d66297189916ceae401fe0944a207714Greg Ungerer	struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
36849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	unsigned int isr;
36949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
37049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	isr = readb(port->membase + MCFUART_UISR) & pp->imr;
37149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	if (isr & MCFUART_UIR_RXREADY)
37249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		mcf_rx_chars(pp);
37349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	if (isr & MCFUART_UIR_TXREADY)
37449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		mcf_tx_chars(pp);
37549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	return IRQ_HANDLED;
37649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer}
37749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
37849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/
37949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
38049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_config_port(struct uart_port *port, int flags)
38149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{
38249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	port->type = PORT_MCF;
3833732b68f22857201fa09cb82b128f295096a2375Philippe De Muyter	port->fifosize = MCFUART_TXFIFOSIZE;
38449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
38549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	/* Clear mask, so no surprise interrupts. */
38649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	writeb(0, port->membase + MCFUART_UIMR);
38749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
38849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	if (request_irq(port->irq, mcf_interrupt, IRQF_DISABLED, "UART", port))
38949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		printk(KERN_ERR "MCF: unable to attach ColdFire UART %d "
39049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer			"interrupt vector=%d\n", port->line, port->irq);
39149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer}
39249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
39349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/
39449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
39549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic const char *mcf_type(struct uart_port *port)
39649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{
39749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	return (port->type == PORT_MCF) ? "ColdFire UART" : NULL;
39849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer}
39949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
40049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/
40149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
40249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic int mcf_request_port(struct uart_port *port)
40349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{
40449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	/* UARTs always present */
40549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	return 0;
40649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer}
40749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
40849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/
40949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
41049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_release_port(struct uart_port *port)
41149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{
41249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	/* Nothing to release... */
41349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer}
41449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
41549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/
41649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
41749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic int mcf_verify_port(struct uart_port *port, struct serial_struct *ser)
41849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{
41949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	if ((ser->type != PORT_UNKNOWN) && (ser->type != PORT_MCF))
42049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		return -EINVAL;
42149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	return 0;
42249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer}
42349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
42449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/
42549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
42649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/*
42749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer *	Define the basic serial functions we support.
42849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer */
4293732b68f22857201fa09cb82b128f295096a2375Philippe De Muyterstatic const struct uart_ops mcf_uart_ops = {
43049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	.tx_empty	= mcf_tx_empty,
43149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	.get_mctrl	= mcf_get_mctrl,
43249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	.set_mctrl	= mcf_set_mctrl,
43349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	.start_tx	= mcf_start_tx,
43449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	.stop_tx	= mcf_stop_tx,
43549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	.stop_rx	= mcf_stop_rx,
43649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	.enable_ms	= mcf_enable_ms,
43749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	.break_ctl	= mcf_break_ctl,
43849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	.startup	= mcf_startup,
43949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	.shutdown	= mcf_shutdown,
44049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	.set_termios	= mcf_set_termios,
44149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	.type		= mcf_type,
44249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	.request_port	= mcf_request_port,
44349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	.release_port	= mcf_release_port,
44449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	.config_port	= mcf_config_port,
44549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	.verify_port	= mcf_verify_port,
44649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer};
44749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
44849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic struct mcf_uart mcf_ports[3];
44949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
45016791963ff7dd6a108251f5fa4b273cf1ffe531fGreg Ungerer#define	MCF_MAXPORTS	ARRAY_SIZE(mcf_ports)
45149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
45249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/
45349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#if defined(CONFIG_SERIAL_MCF_CONSOLE)
45449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/
45549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
45649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererint __init early_mcf_setup(struct mcf_platform_uart *platp)
45749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{
45849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	struct uart_port *port;
45949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	int i;
46049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
46149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	for (i = 0; ((i < MCF_MAXPORTS) && (platp[i].mapbase)); i++) {
46249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		port = &mcf_ports[i].port;
46349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
46449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		port->line = i;
46549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		port->type = PORT_MCF;
46649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		port->mapbase = platp[i].mapbase;
46749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		port->membase = (platp[i].membase) ? platp[i].membase :
46849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer			(unsigned char __iomem *) port->mapbase;
46949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		port->iotype = SERIAL_IO_MEM;
47049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		port->irq = platp[i].irq;
47149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		port->uartclk = MCF_BUSCLK;
47249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		port->flags = ASYNC_BOOT_AUTOCONF;
47349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		port->ops = &mcf_uart_ops;
47449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	}
47549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
47649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	return 0;
47749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer}
47849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
47949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/
48049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
48149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_console_putc(struct console *co, const char c)
48249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{
48349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	struct uart_port *port = &(mcf_ports + co->index)->port;
48449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	int i;
48549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
48649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	for (i = 0; (i < 0x10000); i++) {
48749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		if (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXREADY)
48849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer			break;
48949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	}
49049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	writeb(c, port->membase + MCFUART_UTB);
49149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	for (i = 0; (i < 0x10000); i++) {
49249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		if (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXREADY)
49349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer			break;
49449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	}
49549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer}
49649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
49749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/
49849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
49949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_console_write(struct console *co, const char *s, unsigned int count)
50049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{
50149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	for (; (count); count--, s++) {
50249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		mcf_console_putc(co, *s);
50349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		if (*s == '\n')
50449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer			mcf_console_putc(co, '\r');
50549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	}
50649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer}
50749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
50849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/
50949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
51049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic int __init mcf_console_setup(struct console *co, char *options)
51149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{
51249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	struct uart_port *port;
51349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	int baud = CONFIG_SERIAL_MCF_BAUDRATE;
51449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	int bits = 8;
51549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	int parity = 'n';
51649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	int flow = 'n';
51749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
5184330e179a96bc9310d36e9b858bc8f275f329312Len Sorensen	if ((co->index < 0) || (co->index >= MCF_MAXPORTS))
51949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		co->index = 0;
52049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	port = &mcf_ports[co->index].port;
52149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	if (port->membase == 0)
52249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		return -ENODEV;
52349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
52449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	if (options)
52549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		uart_parse_options(options, &baud, &parity, &bits, &flow);
52649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
52749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	return uart_set_options(port, co, baud, parity, bits, flow);
52849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer}
52949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
53049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/
53149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
53249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic struct uart_driver mcf_driver;
53349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
53449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic struct console mcf_console = {
53549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	.name		= "ttyS",
53649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	.write		= mcf_console_write,
53749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	.device		= uart_console_device,
53849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	.setup		= mcf_console_setup,
53949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	.flags		= CON_PRINTBUFFER,
54049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	.index		= -1,
54149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	.data		= &mcf_driver,
54249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer};
54349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
54449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic int __init mcf_console_init(void)
54549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{
54649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	register_console(&mcf_console);
54749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	return 0;
54849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer}
54949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
55049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererconsole_initcall(mcf_console_init);
55149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
55249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#define	MCF_CONSOLE	&mcf_console
55349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
55449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/
55549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#else
55649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/
55749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
55849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#define	MCF_CONSOLE	NULL
55949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
56049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/
56149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#endif /* CONFIG_MCF_CONSOLE */
56249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/
56349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
56449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/*
56549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer *	Define the mcf UART driver structure.
56649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer */
56749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic struct uart_driver mcf_driver = {
56849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	.owner		= THIS_MODULE,
56949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	.driver_name	= "mcf",
57049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	.dev_name	= "ttyS",
57149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	.major		= TTY_MAJOR,
57249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	.minor		= 64,
57349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	.nr		= MCF_MAXPORTS,
57449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	.cons		= MCF_CONSOLE,
57549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer};
57649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
57749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/
57849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
57949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic int __devinit mcf_probe(struct platform_device *pdev)
58049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{
58149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	struct mcf_platform_uart *platp = pdev->dev.platform_data;
58249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	struct uart_port *port;
58349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	int i;
58449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
58549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	for (i = 0; ((i < MCF_MAXPORTS) && (platp[i].mapbase)); i++) {
58649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		port = &mcf_ports[i].port;
58749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
58849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		port->line = i;
58949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		port->type = PORT_MCF;
59049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		port->mapbase = platp[i].mapbase;
59149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		port->membase = (platp[i].membase) ? platp[i].membase :
59249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer			(unsigned char __iomem *) platp[i].mapbase;
59349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		port->iotype = SERIAL_IO_MEM;
59449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		port->irq = platp[i].irq;
59549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		port->uartclk = MCF_BUSCLK;
59649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		port->ops = &mcf_uart_ops;
59749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		port->flags = ASYNC_BOOT_AUTOCONF;
59849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
59949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		uart_add_one_port(&mcf_driver, port);
60049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	}
60149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
60249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	return 0;
60349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer}
60449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
60549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/
60649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
607d6f80e3a2a8c49f3e9c350b15f510c6eb8c1770dUwe Kleine-Königstatic int __devexit mcf_remove(struct platform_device *pdev)
60849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{
60949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	struct uart_port *port;
61049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	int i;
61149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
61249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	for (i = 0; (i < MCF_MAXPORTS); i++) {
61349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		port = &mcf_ports[i].port;
61449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		if (port)
61549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer			uart_remove_one_port(&mcf_driver, port);
61649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	}
61749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
61849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	return 0;
61949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer}
62049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
62149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/
62249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
62349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic struct platform_driver mcf_platform_driver = {
62449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	.probe		= mcf_probe,
62549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	.remove		= __devexit_p(mcf_remove),
62649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	.driver		= {
62749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		.name	= "mcfuart",
62849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		.owner	= THIS_MODULE,
62949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	},
63049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer};
63149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
63249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/
63349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
63449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic int __init mcf_init(void)
63549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{
63649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	int rc;
63749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
63849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	printk("ColdFire internal UART serial driver\n");
63949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
64049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	rc = uart_register_driver(&mcf_driver);
64149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	if (rc)
64249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		return rc;
64349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	rc = platform_driver_register(&mcf_platform_driver);
64449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	if (rc)
64549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer		return rc;
64649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	return 0;
64749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer}
64849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
64949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/
65049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
65149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void __exit mcf_exit(void)
65249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{
65349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	platform_driver_unregister(&mcf_platform_driver);
65449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer	uart_unregister_driver(&mcf_driver);
65549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer}
65649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
65749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/
65849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
65949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerermodule_init(mcf_init);
66049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerermodule_exit(mcf_exit);
66149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
66249aa49bfd40d718095669c1c70c9d167b814e29bGreg UngererMODULE_AUTHOR("Greg Ungerer <gerg@snapgear.com>");
66349aa49bfd40d718095669c1c70c9d167b814e29bGreg UngererMODULE_DESCRIPTION("Freescale ColdFire UART driver");
66449aa49bfd40d718095669c1c70c9d167b814e29bGreg UngererMODULE_LICENSE("GPL");
665e169c139642fb4c682ec12a409725508dbefa520Kay SieversMODULE_ALIAS("platform:mcfuart");
66649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer
66749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/
668