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> 27574de559c1797618fd8ed03576837eb3113c5d26Jingoo Han#include <linux/platform_device.h> 2849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#include <asm/coldfire.h> 2949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#include <asm/mcfsim.h> 3049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#include <asm/mcfuart.h> 3149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#include <asm/nettel.h> 3249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 3349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 3449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 3549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/* 3649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer * Some boards implement the DTR/DCD lines using GPIO lines, most 3749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer * don't. Dummy out the access macros for those that don't. Those 3849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer * that do should define these macros somewhere in there board 3949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer * specific inlude files. 4049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer */ 4149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#if !defined(mcf_getppdcd) 4249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#define mcf_getppdcd(p) (1) 4349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#endif 4449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#if !defined(mcf_getppdtr) 4549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#define mcf_getppdtr(p) (1) 4649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#endif 4749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#if !defined(mcf_setppdtr) 4849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#define mcf_setppdtr(p, v) do { } while (0) 4949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#endif 5049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 5149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 5249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 5349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/* 5449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer * Local per-uart structure. 5549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer */ 5649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstruct mcf_uart { 5749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer struct uart_port port; 5849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer unsigned int sigs; /* Local copy of line sigs */ 5949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer unsigned char imr; /* Local IMR mirror */ 60496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen struct serial_rs485 rs485; /* RS485 settings */ 6149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer}; 6249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 6349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 6449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 6549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic unsigned int mcf_tx_empty(struct uart_port *port) 6649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 6749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer return (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXEMPTY) ? 6849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer TIOCSER_TEMT : 0; 6949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 7049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 7149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 7249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 7349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic unsigned int mcf_get_mctrl(struct uart_port *port) 7449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 759f69ba86d66297189916ceae401fe0944a207714Greg Ungerer struct mcf_uart *pp = container_of(port, struct mcf_uart, port); 7649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer unsigned int sigs; 7749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 7849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer sigs = (readb(port->membase + MCFUART_UIPR) & MCFUART_UIPR_CTS) ? 7949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 0 : TIOCM_CTS; 8049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer sigs |= (pp->sigs & TIOCM_RTS); 8149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer sigs |= (mcf_getppdcd(port->line) ? TIOCM_CD : 0); 8249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer sigs |= (mcf_getppdtr(port->line) ? TIOCM_DTR : 0); 830ac8382e9cfdd723445692fc97aaa4643929750dYury Georgievskiy 8449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer return sigs; 8549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 8649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 8749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 8849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 8949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_set_mctrl(struct uart_port *port, unsigned int sigs) 9049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 919f69ba86d66297189916ceae401fe0944a207714Greg Ungerer struct mcf_uart *pp = container_of(port, struct mcf_uart, port); 9249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 9349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer pp->sigs = sigs; 9449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer mcf_setppdtr(port->line, (sigs & TIOCM_DTR)); 9549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (sigs & TIOCM_RTS) 9649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP1); 9749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer else 9849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP0); 9949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 10049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 10149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 10249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 10349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_start_tx(struct uart_port *port) 10449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 1059f69ba86d66297189916ceae401fe0944a207714Greg Ungerer struct mcf_uart *pp = container_of(port, struct mcf_uart, port); 10649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 107496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen if (pp->rs485.flags & SER_RS485_ENABLED) { 108496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen /* Enable Transmitter */ 109496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen writeb(MCFUART_UCR_TXENABLE, port->membase + MCFUART_UCR); 110496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen /* Manually assert RTS */ 111496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP1); 112496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen } 11349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer pp->imr |= MCFUART_UIR_TXREADY; 11449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(pp->imr, port->membase + MCFUART_UIMR); 11549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 11649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 11749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 11849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 11949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_stop_tx(struct uart_port *port) 12049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 1219f69ba86d66297189916ceae401fe0944a207714Greg Ungerer struct mcf_uart *pp = container_of(port, struct mcf_uart, port); 12249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 12349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer pp->imr &= ~MCFUART_UIR_TXREADY; 12449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(pp->imr, port->membase + MCFUART_UIMR); 12549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 12649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 12749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 12849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 12949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_stop_rx(struct uart_port *port) 13049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 1319f69ba86d66297189916ceae401fe0944a207714Greg Ungerer struct mcf_uart *pp = container_of(port, struct mcf_uart, port); 13249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 13349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer pp->imr &= ~MCFUART_UIR_RXREADY; 13449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(pp->imr, port->membase + MCFUART_UIMR); 13549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 13649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 13749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 13849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 13949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_break_ctl(struct uart_port *port, int break_state) 14049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 14149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer unsigned long flags; 14249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 14349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer spin_lock_irqsave(&port->lock, flags); 14449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (break_state == -1) 14549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(MCFUART_UCR_CMDBREAKSTART, port->membase + MCFUART_UCR); 14649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer else 14749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(MCFUART_UCR_CMDBREAKSTOP, port->membase + MCFUART_UCR); 14849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer spin_unlock_irqrestore(&port->lock, flags); 14949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 15049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 15149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 15249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 15349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic int mcf_startup(struct uart_port *port) 15449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 1559f69ba86d66297189916ceae401fe0944a207714Greg Ungerer struct mcf_uart *pp = container_of(port, struct mcf_uart, port); 15649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer unsigned long flags; 15749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 15849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer spin_lock_irqsave(&port->lock, flags); 15949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 16049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer /* Reset UART, get it into known state... */ 16149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(MCFUART_UCR_CMDRESETRX, port->membase + MCFUART_UCR); 16249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(MCFUART_UCR_CMDRESETTX, port->membase + MCFUART_UCR); 16349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 16449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer /* Enable the UART transmitter and receiver */ 16549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE, 16649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->membase + MCFUART_UCR); 16749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 16849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer /* Enable RX interrupts now */ 16949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer pp->imr = MCFUART_UIR_RXREADY; 17049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(pp->imr, port->membase + MCFUART_UIMR); 17149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 17249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer spin_unlock_irqrestore(&port->lock, flags); 17349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 17449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer return 0; 17549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 17649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 17749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 17849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 17949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_shutdown(struct uart_port *port) 18049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 1819f69ba86d66297189916ceae401fe0944a207714Greg Ungerer struct mcf_uart *pp = container_of(port, struct mcf_uart, port); 18249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer unsigned long flags; 18349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 18449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer spin_lock_irqsave(&port->lock, flags); 18549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 18649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer /* Disable all interrupts now */ 18749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer pp->imr = 0; 18849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(pp->imr, port->membase + MCFUART_UIMR); 18949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 19049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer /* Disable UART transmitter and receiver */ 19149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(MCFUART_UCR_CMDRESETRX, port->membase + MCFUART_UCR); 19249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(MCFUART_UCR_CMDRESETTX, port->membase + MCFUART_UCR); 19349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 19449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer spin_unlock_irqrestore(&port->lock, flags); 19549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 19649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 19749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 19849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 19949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_set_termios(struct uart_port *port, struct ktermios *termios, 20049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer struct ktermios *old) 20149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 202496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen struct mcf_uart *pp = container_of(port, struct mcf_uart, port); 20349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer unsigned long flags; 20449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer unsigned int baud, baudclk; 20526a4bc66a6f57299027e04d90b14fe56a44c6d2bJohn Adamson#if defined(CONFIG_M5272) 20626a4bc66a6f57299027e04d90b14fe56a44c6d2bJohn Adamson unsigned int baudfr; 20726a4bc66a6f57299027e04d90b14fe56a44c6d2bJohn Adamson#endif 20849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer unsigned char mr1, mr2; 20949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 21049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer baud = uart_get_baud_rate(port, termios, old, 0, 230400); 21126a4bc66a6f57299027e04d90b14fe56a44c6d2bJohn Adamson#if defined(CONFIG_M5272) 21226a4bc66a6f57299027e04d90b14fe56a44c6d2bJohn Adamson baudclk = (MCF_BUSCLK / baud) / 32; 21326a4bc66a6f57299027e04d90b14fe56a44c6d2bJohn Adamson baudfr = (((MCF_BUSCLK / baud) + 1) / 2) % 16; 21426a4bc66a6f57299027e04d90b14fe56a44c6d2bJohn Adamson#else 21549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer baudclk = ((MCF_BUSCLK / baud) + 16) / 32; 21626a4bc66a6f57299027e04d90b14fe56a44c6d2bJohn Adamson#endif 21749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 21849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer mr1 = MCFUART_MR1_RXIRQRDY | MCFUART_MR1_RXERRCHAR; 21949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer mr2 = 0; 22049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 22149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer switch (termios->c_cflag & CSIZE) { 22249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer case CS5: mr1 |= MCFUART_MR1_CS5; break; 22349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer case CS6: mr1 |= MCFUART_MR1_CS6; break; 22449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer case CS7: mr1 |= MCFUART_MR1_CS7; break; 22549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer case CS8: 22649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer default: mr1 |= MCFUART_MR1_CS8; break; 22749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } 22849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 22949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (termios->c_cflag & PARENB) { 23049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (termios->c_cflag & CMSPAR) { 23149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (termios->c_cflag & PARODD) 23249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer mr1 |= MCFUART_MR1_PARITYMARK; 23349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer else 23449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer mr1 |= MCFUART_MR1_PARITYSPACE; 23549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } else { 23649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (termios->c_cflag & PARODD) 23749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer mr1 |= MCFUART_MR1_PARITYODD; 23849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer else 23949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer mr1 |= MCFUART_MR1_PARITYEVEN; 24049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } 24149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } else { 24249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer mr1 |= MCFUART_MR1_PARITYNONE; 24349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } 24449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 245ef8b9ddcb45fa3b1e11acd72be2398001e807d14Peter Hurley /* 246ef8b9ddcb45fa3b1e11acd72be2398001e807d14Peter Hurley * FIXME: port->read_status_mask and port->ignore_status_mask 247ef8b9ddcb45fa3b1e11acd72be2398001e807d14Peter Hurley * need to be initialized based on termios settings for 248ef8b9ddcb45fa3b1e11acd72be2398001e807d14Peter Hurley * INPCK, IGNBRK, IGNPAR, PARMRK, BRKINT 249ef8b9ddcb45fa3b1e11acd72be2398001e807d14Peter Hurley */ 250ef8b9ddcb45fa3b1e11acd72be2398001e807d14Peter Hurley 25149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (termios->c_cflag & CSTOPB) 25249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer mr2 |= MCFUART_MR2_STOP2; 25349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer else 25449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer mr2 |= MCFUART_MR2_STOP1; 25549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 25649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (termios->c_cflag & CRTSCTS) { 25749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer mr1 |= MCFUART_MR1_RXRTS; 25849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer mr2 |= MCFUART_MR2_TXCTS; 25949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } 26049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 261496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen if (pp->rs485.flags & SER_RS485_ENABLED) { 262496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen dev_dbg(port->dev, "Setting UART to RS485\n"); 263496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen mr2 |= MCFUART_MR2_TXRTS; 264496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen } 265496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen 26649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer spin_lock_irqsave(&port->lock, flags); 2673732b68f22857201fa09cb82b128f295096a2375Philippe De Muyter uart_update_timeout(port, termios->c_cflag, baud); 26849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(MCFUART_UCR_CMDRESETRX, port->membase + MCFUART_UCR); 26949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(MCFUART_UCR_CMDRESETTX, port->membase + MCFUART_UCR); 27049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(MCFUART_UCR_CMDRESETMRPTR, port->membase + MCFUART_UCR); 27149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(mr1, port->membase + MCFUART_UMR); 27249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(mr2, port->membase + MCFUART_UMR); 27349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb((baudclk & 0xff00) >> 8, port->membase + MCFUART_UBG1); 27449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb((baudclk & 0xff), port->membase + MCFUART_UBG2); 27526a4bc66a6f57299027e04d90b14fe56a44c6d2bJohn Adamson#if defined(CONFIG_M5272) 27626a4bc66a6f57299027e04d90b14fe56a44c6d2bJohn Adamson writeb((baudfr & 0x0f), port->membase + MCFUART_UFPD); 27726a4bc66a6f57299027e04d90b14fe56a44c6d2bJohn Adamson#endif 27849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(MCFUART_UCSR_RXCLKTIMER | MCFUART_UCSR_TXCLKTIMER, 27949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->membase + MCFUART_UCSR); 28049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE, 28149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->membase + MCFUART_UCR); 28249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer spin_unlock_irqrestore(&port->lock, flags); 28349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 28449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 28549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 28649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 28749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_rx_chars(struct mcf_uart *pp) 28849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 2899f69ba86d66297189916ceae401fe0944a207714Greg Ungerer struct uart_port *port = &pp->port; 29049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer unsigned char status, ch, flag; 29149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 29249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer while ((status = readb(port->membase + MCFUART_USR)) & MCFUART_USR_RXREADY) { 29349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer ch = readb(port->membase + MCFUART_URB); 29449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer flag = TTY_NORMAL; 29549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->icount.rx++; 29649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 29749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (status & MCFUART_USR_RXERR) { 29849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(MCFUART_UCR_CMDRESETERR, 29949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->membase + MCFUART_UCR); 30049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 30149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (status & MCFUART_USR_RXBREAK) { 30249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->icount.brk++; 30349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (uart_handle_break(port)) 30449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer continue; 30549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } else if (status & MCFUART_USR_RXPARITY) { 30649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->icount.parity++; 30749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } else if (status & MCFUART_USR_RXOVERRUN) { 30849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->icount.overrun++; 30949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } else if (status & MCFUART_USR_RXFRAMING) { 31049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->icount.frame++; 31149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } 31249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 31349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer status &= port->read_status_mask; 31449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 31549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (status & MCFUART_USR_RXBREAK) 31649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer flag = TTY_BREAK; 31749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer else if (status & MCFUART_USR_RXPARITY) 31849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer flag = TTY_PARITY; 31949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer else if (status & MCFUART_USR_RXFRAMING) 32049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer flag = TTY_FRAME; 32149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } 32249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 32349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (uart_handle_sysrq_char(port, ch)) 32449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer continue; 32549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer uart_insert_char(port, status, MCFUART_USR_RXOVERRUN, ch, flag); 32649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } 32749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 3285275ad70fed320f6264d98f0b6f32c06941ccf26Viresh Kumar spin_unlock(&port->lock); 3292e124b4a390ca85325fae75764bef92f0547fa25Jiri Slaby tty_flip_buffer_push(&port->state->port); 3305275ad70fed320f6264d98f0b6f32c06941ccf26Viresh Kumar spin_lock(&port->lock); 33149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 33249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 33349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 33449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 33549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_tx_chars(struct mcf_uart *pp) 33649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 3379f69ba86d66297189916ceae401fe0944a207714Greg Ungerer struct uart_port *port = &pp->port; 338ebd2c8f6d2ec4012c267ecb95e72a57b8355a705Alan Cox struct circ_buf *xmit = &port->state->xmit; 33949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 34049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (port->x_char) { 34149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer /* Send special char - probably flow control */ 34249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(port->x_char, port->membase + MCFUART_UTB); 34349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->x_char = 0; 34449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->icount.tx++; 34549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer return; 34649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } 34749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 34849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer while (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXREADY) { 34949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (xmit->head == xmit->tail) 35049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer break; 35149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(xmit->buf[xmit->tail], port->membase + MCFUART_UTB); 35249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE -1); 35349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->icount.tx++; 35449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } 35549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 35649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) 35749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer uart_write_wakeup(port); 35849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 35949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (xmit->head == xmit->tail) { 36049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer pp->imr &= ~MCFUART_UIR_TXREADY; 36149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(pp->imr, port->membase + MCFUART_UIMR); 362496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen /* Disable TX to negate RTS automatically */ 363496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen if (pp->rs485.flags & SER_RS485_ENABLED) 364496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen writeb(MCFUART_UCR_TXDISABLE, 365496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen port->membase + MCFUART_UCR); 36649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } 36749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 36849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 36949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 37049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 37149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic irqreturn_t mcf_interrupt(int irq, void *data) 37249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 37349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer struct uart_port *port = data; 3749f69ba86d66297189916ceae401fe0944a207714Greg Ungerer struct mcf_uart *pp = container_of(port, struct mcf_uart, port); 37549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer unsigned int isr; 3760ac8382e9cfdd723445692fc97aaa4643929750dYury Georgievskiy irqreturn_t ret = IRQ_NONE; 37749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 37849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer isr = readb(port->membase + MCFUART_UISR) & pp->imr; 3790ac8382e9cfdd723445692fc97aaa4643929750dYury Georgievskiy 3800ac8382e9cfdd723445692fc97aaa4643929750dYury Georgievskiy spin_lock(&port->lock); 3810ac8382e9cfdd723445692fc97aaa4643929750dYury Georgievskiy if (isr & MCFUART_UIR_RXREADY) { 38249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer mcf_rx_chars(pp); 3830ac8382e9cfdd723445692fc97aaa4643929750dYury Georgievskiy ret = IRQ_HANDLED; 3840ac8382e9cfdd723445692fc97aaa4643929750dYury Georgievskiy } 3850ac8382e9cfdd723445692fc97aaa4643929750dYury Georgievskiy if (isr & MCFUART_UIR_TXREADY) { 38649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer mcf_tx_chars(pp); 3870ac8382e9cfdd723445692fc97aaa4643929750dYury Georgievskiy ret = IRQ_HANDLED; 3880ac8382e9cfdd723445692fc97aaa4643929750dYury Georgievskiy } 3890ac8382e9cfdd723445692fc97aaa4643929750dYury Georgievskiy spin_unlock(&port->lock); 3900ac8382e9cfdd723445692fc97aaa4643929750dYury Georgievskiy 3910ac8382e9cfdd723445692fc97aaa4643929750dYury Georgievskiy return ret; 39249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 39349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 39449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 39549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 39649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_config_port(struct uart_port *port, int flags) 39749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 39849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->type = PORT_MCF; 3993732b68f22857201fa09cb82b128f295096a2375Philippe De Muyter port->fifosize = MCFUART_TXFIFOSIZE; 40049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 40149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer /* Clear mask, so no surprise interrupts. */ 40249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(0, port->membase + MCFUART_UIMR); 40349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 4049cfb5c05fee914cc65d4706801f6bc424082b5f5Yong Zhang if (request_irq(port->irq, mcf_interrupt, 0, "UART", port)) 40549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer printk(KERN_ERR "MCF: unable to attach ColdFire UART %d " 40649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer "interrupt vector=%d\n", port->line, port->irq); 40749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 40849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 40949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 41049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 41149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic const char *mcf_type(struct uart_port *port) 41249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 41349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer return (port->type == PORT_MCF) ? "ColdFire UART" : NULL; 41449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 41549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 41649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 41749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 41849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic int mcf_request_port(struct uart_port *port) 41949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 42049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer /* UARTs always present */ 42149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer return 0; 42249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 42349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 42449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 42549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 42649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_release_port(struct uart_port *port) 42749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 42849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer /* Nothing to release... */ 42949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 43049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 43149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 43249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 43349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic int mcf_verify_port(struct uart_port *port, struct serial_struct *ser) 43449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 43549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if ((ser->type != PORT_UNKNOWN) && (ser->type != PORT_MCF)) 43649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer return -EINVAL; 43749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer return 0; 43849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 43949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 44049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 44149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 442496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen/* Enable or disable the RS485 support */ 443496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyenstatic void mcf_config_rs485(struct uart_port *port, struct serial_rs485 *rs485) 444496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen{ 445496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen struct mcf_uart *pp = container_of(port, struct mcf_uart, port); 446496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen unsigned long flags; 447496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen unsigned char mr1, mr2; 448496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen 449496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen spin_lock_irqsave(&port->lock, flags); 450496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen /* Get mode registers */ 451496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen mr1 = readb(port->membase + MCFUART_UMR); 452496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen mr2 = readb(port->membase + MCFUART_UMR); 453496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen if (rs485->flags & SER_RS485_ENABLED) { 454496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen dev_dbg(port->dev, "Setting UART to RS485\n"); 455496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen /* Automatically negate RTS after TX completes */ 456496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen mr2 |= MCFUART_MR2_TXRTS; 457496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen } else { 458496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen dev_dbg(port->dev, "Setting UART to RS232\n"); 459496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen mr2 &= ~MCFUART_MR2_TXRTS; 460496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen } 461496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen writeb(mr1, port->membase + MCFUART_UMR); 462496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen writeb(mr2, port->membase + MCFUART_UMR); 463496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen pp->rs485 = *rs485; 464496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen spin_unlock_irqrestore(&port->lock, flags); 465496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen} 466496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen 467496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyenstatic int mcf_ioctl(struct uart_port *port, unsigned int cmd, 468496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen unsigned long arg) 469496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen{ 470496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen switch (cmd) { 471496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen case TIOCSRS485: { 472496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen struct serial_rs485 rs485; 473496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen if (copy_from_user(&rs485, (struct serial_rs485 *)arg, 474496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen sizeof(struct serial_rs485))) 475496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen return -EFAULT; 476496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen mcf_config_rs485(port, &rs485); 477496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen break; 478496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen } 479496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen case TIOCGRS485: { 480496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen struct mcf_uart *pp = container_of(port, struct mcf_uart, port); 481496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen if (copy_to_user((struct serial_rs485 *)arg, &pp->rs485, 482496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen sizeof(struct serial_rs485))) 483496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen return -EFAULT; 484496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen break; 485496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen } 486496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen default: 487496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen return -ENOIOCTLCMD; 488496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen } 489496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen return 0; 490496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen} 491496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen 492496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen/****************************************************************************/ 493496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen 49449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/* 49549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer * Define the basic serial functions we support. 49649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer */ 4973732b68f22857201fa09cb82b128f295096a2375Philippe De Muyterstatic const struct uart_ops mcf_uart_ops = { 49849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .tx_empty = mcf_tx_empty, 49949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .get_mctrl = mcf_get_mctrl, 50049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .set_mctrl = mcf_set_mctrl, 50149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .start_tx = mcf_start_tx, 50249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .stop_tx = mcf_stop_tx, 50349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .stop_rx = mcf_stop_rx, 50449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .break_ctl = mcf_break_ctl, 50549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .startup = mcf_startup, 50649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .shutdown = mcf_shutdown, 50749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .set_termios = mcf_set_termios, 50849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .type = mcf_type, 50949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .request_port = mcf_request_port, 51049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .release_port = mcf_release_port, 51149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .config_port = mcf_config_port, 51249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .verify_port = mcf_verify_port, 513496c907740ff083499f5449d2907af442e79ceb0Quoc-Viet Nguyen .ioctl = mcf_ioctl, 51449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer}; 51549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 5162545cf6e94b4eb5a2c48dd55751aa9a70ff1ff9dPhilippe De Muyterstatic struct mcf_uart mcf_ports[4]; 51749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 51816791963ff7dd6a108251f5fa4b273cf1ffe531fGreg Ungerer#define MCF_MAXPORTS ARRAY_SIZE(mcf_ports) 51949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 52049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 52149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#if defined(CONFIG_SERIAL_MCF_CONSOLE) 52249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 52349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 52449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererint __init early_mcf_setup(struct mcf_platform_uart *platp) 52549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 52649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer struct uart_port *port; 52749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer int i; 52849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 52949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer for (i = 0; ((i < MCF_MAXPORTS) && (platp[i].mapbase)); i++) { 53049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port = &mcf_ports[i].port; 53149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 53249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->line = i; 53349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->type = PORT_MCF; 53449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->mapbase = platp[i].mapbase; 53549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->membase = (platp[i].membase) ? platp[i].membase : 53649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer (unsigned char __iomem *) port->mapbase; 53749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->iotype = SERIAL_IO_MEM; 53849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->irq = platp[i].irq; 53949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->uartclk = MCF_BUSCLK; 5405fda7a0e715c32c6dd9a39ebce8429eeafb64b7dPeter Hurley port->flags = UPF_BOOT_AUTOCONF; 54149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->ops = &mcf_uart_ops; 54249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } 54349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 54449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer return 0; 54549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 54649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 54749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 54849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 54949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_console_putc(struct console *co, const char c) 55049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 55149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer struct uart_port *port = &(mcf_ports + co->index)->port; 55249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer int i; 55349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 55449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer for (i = 0; (i < 0x10000); i++) { 55549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXREADY) 55649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer break; 55749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } 55849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer writeb(c, port->membase + MCFUART_UTB); 55949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer for (i = 0; (i < 0x10000); i++) { 56049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXREADY) 56149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer break; 56249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } 56349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 56449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 56549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 56649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 56749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void mcf_console_write(struct console *co, const char *s, unsigned int count) 56849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 56949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer for (; (count); count--, s++) { 57049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer mcf_console_putc(co, *s); 57149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (*s == '\n') 57249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer mcf_console_putc(co, '\r'); 57349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } 57449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 57549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 57649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 57749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 57849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic int __init mcf_console_setup(struct console *co, char *options) 57949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 58049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer struct uart_port *port; 58149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer int baud = CONFIG_SERIAL_MCF_BAUDRATE; 58249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer int bits = 8; 58349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer int parity = 'n'; 58449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer int flow = 'n'; 58549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 5864330e179a96bc9310d36e9b858bc8f275f329312Len Sorensen if ((co->index < 0) || (co->index >= MCF_MAXPORTS)) 58749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer co->index = 0; 58849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port = &mcf_ports[co->index].port; 58949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (port->membase == 0) 59049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer return -ENODEV; 59149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 59249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (options) 59349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer uart_parse_options(options, &baud, &parity, &bits, &flow); 59449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 59549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer return uart_set_options(port, co, baud, parity, bits, flow); 59649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 59749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 59849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 59949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 60049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic struct uart_driver mcf_driver; 60149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 60249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic struct console mcf_console = { 60349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .name = "ttyS", 60449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .write = mcf_console_write, 60549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .device = uart_console_device, 60649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .setup = mcf_console_setup, 60749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .flags = CON_PRINTBUFFER, 60849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .index = -1, 60949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .data = &mcf_driver, 61049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer}; 61149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 61249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic int __init mcf_console_init(void) 61349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 61449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer register_console(&mcf_console); 61549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer return 0; 61649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 61749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 61849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererconsole_initcall(mcf_console_init); 61949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 62049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#define MCF_CONSOLE &mcf_console 62149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 62249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 62349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#else 62449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 62549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 62649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#define MCF_CONSOLE NULL 62749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 62849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 62949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer#endif /* CONFIG_MCF_CONSOLE */ 63049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 63149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 63249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/* 63349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer * Define the mcf UART driver structure. 63449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer */ 63549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic struct uart_driver mcf_driver = { 63649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .owner = THIS_MODULE, 63749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .driver_name = "mcf", 63849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .dev_name = "ttyS", 63949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .major = TTY_MAJOR, 64049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .minor = 64, 64149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .nr = MCF_MAXPORTS, 64249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .cons = MCF_CONSOLE, 64349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer}; 64449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 64549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 64649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 6479671f09921d93e722a28ae9610d478e092ac5466Bill Pembertonstatic int mcf_probe(struct platform_device *pdev) 64849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 649574de559c1797618fd8ed03576837eb3113c5d26Jingoo Han struct mcf_platform_uart *platp = dev_get_platdata(&pdev->dev); 65049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer struct uart_port *port; 65149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer int i; 65249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 65349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer for (i = 0; ((i < MCF_MAXPORTS) && (platp[i].mapbase)); i++) { 65449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port = &mcf_ports[i].port; 65549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 65649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->line = i; 65749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->type = PORT_MCF; 65849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->mapbase = platp[i].mapbase; 65949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->membase = (platp[i].membase) ? platp[i].membase : 66049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer (unsigned char __iomem *) platp[i].mapbase; 66149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->iotype = SERIAL_IO_MEM; 66249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->irq = platp[i].irq; 66349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->uartclk = MCF_BUSCLK; 66449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port->ops = &mcf_uart_ops; 6655fda7a0e715c32c6dd9a39ebce8429eeafb64b7dPeter Hurley port->flags = UPF_BOOT_AUTOCONF; 66649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 66749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer uart_add_one_port(&mcf_driver, port); 66849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } 66949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 67049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer return 0; 67149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 67249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 67349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 67449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 675ae8d8a146725a966bd7c59c94f4d0016dcf7a04fBill Pembertonstatic int mcf_remove(struct platform_device *pdev) 67649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 67749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer struct uart_port *port; 67849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer int i; 67949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 68049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer for (i = 0; (i < MCF_MAXPORTS); i++) { 68149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer port = &mcf_ports[i].port; 68249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (port) 68349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer uart_remove_one_port(&mcf_driver, port); 68449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer } 68549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 68649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer return 0; 68749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 68849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 68949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 69049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 69149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic struct platform_driver mcf_platform_driver = { 69249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .probe = mcf_probe, 6932d47b7160243b1422006b91debf438484a4fde58Bill Pemberton .remove = mcf_remove, 69449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .driver = { 69549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .name = "mcfuart", 69649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer .owner = THIS_MODULE, 69749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer }, 69849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer}; 69949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 70049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 70149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 70249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic int __init mcf_init(void) 70349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 70449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer int rc; 70549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 70649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer printk("ColdFire internal UART serial driver\n"); 70749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 70849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer rc = uart_register_driver(&mcf_driver); 70949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer if (rc) 71049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer return rc; 71149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer rc = platform_driver_register(&mcf_platform_driver); 7122b359172e013c6b1b7e424e5be92a70fc7cceaafWei Yongjun if (rc) { 7132b359172e013c6b1b7e424e5be92a70fc7cceaafWei Yongjun uart_unregister_driver(&mcf_driver); 71449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer return rc; 7152b359172e013c6b1b7e424e5be92a70fc7cceaafWei Yongjun } 71649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer return 0; 71749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 71849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 71949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 72049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 72149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungererstatic void __exit mcf_exit(void) 72249aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer{ 72349aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer platform_driver_unregister(&mcf_platform_driver); 72449aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer uart_unregister_driver(&mcf_driver); 72549aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer} 72649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 72749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 72849aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 72949aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerermodule_init(mcf_init); 73049aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerermodule_exit(mcf_exit); 73149aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 73249aa49bfd40d718095669c1c70c9d167b814e29bGreg UngererMODULE_AUTHOR("Greg Ungerer <gerg@snapgear.com>"); 73349aa49bfd40d718095669c1c70c9d167b814e29bGreg UngererMODULE_DESCRIPTION("Freescale ColdFire UART driver"); 73449aa49bfd40d718095669c1c70c9d167b814e29bGreg UngererMODULE_LICENSE("GPL"); 735e169c139642fb4c682ec12a409725508dbefa520Kay SieversMODULE_ALIAS("platform:mcfuart"); 73649aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer 73749aa49bfd40d718095669c1c70c9d167b814e29bGreg Ungerer/****************************************************************************/ 738