root/arch/mips/pmcs-msp71xx/msp_serial.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. msp_serial_out
  2. msp_serial_in
  3. msp_serial_handle_irq
  4. msp_serial_setup

   1 /*
   2  * The setup file for serial related hardware on PMC-Sierra MSP processors.
   3  *
   4  * Copyright 2005 PMC-Sierra, Inc.
   5  *
   6  *  This program is free software; you can redistribute  it and/or modify it
   7  *  under  the terms of  the GNU General  Public License as published by the
   8  *  Free Software Foundation;  either version 2 of the  License, or (at your
   9  *  option) any later version.
  10  *
  11  *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
  12  *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
  13  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
  14  *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
  15  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  16  *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
  17  *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  18  *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
  19  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  20  *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  21  *
  22  *  You should have received a copy of the  GNU General Public License along
  23  *  with this program; if not, write  to the Free Software Foundation, Inc.,
  24  *  675 Mass Ave, Cambridge, MA 02139, USA.
  25  */
  26 
  27 #include <linux/serial.h>
  28 #include <linux/serial_core.h>
  29 #include <linux/serial_reg.h>
  30 #include <linux/slab.h>
  31 
  32 #include <asm/bootinfo.h>
  33 #include <asm/io.h>
  34 #include <asm/processor.h>
  35 #include <asm/serial.h>
  36 #include <linux/serial_8250.h>
  37 
  38 #include <msp_prom.h>
  39 #include <msp_int.h>
  40 #include <msp_regs.h>
  41 
  42 struct msp_uart_data {
  43         int     last_lcr;
  44 };
  45 
  46 static void msp_serial_out(struct uart_port *p, int offset, int value)
  47 {
  48         struct msp_uart_data *d = p->private_data;
  49 
  50         if (offset == UART_LCR)
  51                 d->last_lcr = value;
  52 
  53         offset <<= p->regshift;
  54         writeb(value, p->membase + offset);
  55 }
  56 
  57 static unsigned int msp_serial_in(struct uart_port *p, int offset)
  58 {
  59         offset <<= p->regshift;
  60 
  61         return readb(p->membase + offset);
  62 }
  63 
  64 static int msp_serial_handle_irq(struct uart_port *p)
  65 {
  66         struct msp_uart_data *d = p->private_data;
  67         unsigned int iir = readb(p->membase + (UART_IIR << p->regshift));
  68 
  69         if (serial8250_handle_irq(p, iir)) {
  70                 return 1;
  71         } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
  72                 /*
  73                  * The DesignWare APB UART has an Busy Detect (0x07) interrupt
  74                  * meaning an LCR write attempt occurred while the UART was
  75                  * busy. The interrupt must be cleared by reading the UART
  76                  * status register (USR) and the LCR re-written.
  77                  *
  78                  * Note: MSP reserves 0x20 bytes of address space for the UART
  79                  * and the USR is mapped in a separate block at an offset of
  80                  * 0xc0 from the start of the UART.
  81                  */
  82                 (void)readb(p->membase + 0xc0);
  83                 writeb(d->last_lcr, p->membase + (UART_LCR << p->regshift));
  84 
  85                 return 1;
  86         }
  87 
  88         return 0;
  89 }
  90 
  91 void __init msp_serial_setup(void)
  92 {
  93         char    *s;
  94         char    *endp;
  95         struct uart_port up;
  96         unsigned int uartclk;
  97 
  98         memset(&up, 0, sizeof(up));
  99 
 100         /* Check if clock was specified in environment */
 101         s = prom_getenv("uartfreqhz");
 102         if(!(s && *s && (uartclk = simple_strtoul(s, &endp, 10)) && *endp == 0))
 103                 uartclk = MSP_BASE_BAUD;
 104         ppfinit("UART clock set to %d\n", uartclk);
 105 
 106         /* Initialize first serial port */
 107         up.mapbase      = MSP_UART0_BASE;
 108         up.membase      = ioremap_nocache(up.mapbase, MSP_UART_REG_LEN);
 109         up.irq          = MSP_INT_UART0;
 110         up.uartclk      = uartclk;
 111         up.regshift     = 2;
 112         up.iotype       = UPIO_MEM;
 113         up.flags        = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
 114         up.type         = PORT_16550A;
 115         up.line         = 0;
 116         up.serial_out   = msp_serial_out;
 117         up.serial_in    = msp_serial_in;
 118         up.handle_irq   = msp_serial_handle_irq;
 119         up.private_data = kzalloc(sizeof(struct msp_uart_data), GFP_KERNEL);
 120         if (!up.private_data) {
 121                 pr_err("failed to allocate uart private data\n");
 122                 return;
 123         }
 124         if (early_serial_setup(&up)) {
 125                 kfree(up.private_data);
 126                 pr_err("Early serial init of port 0 failed\n");
 127         }
 128 
 129         /* Initialize the second serial port, if one exists */
 130         switch (mips_machtype) {
 131                 case MACH_MSP4200_EVAL:
 132                 case MACH_MSP4200_GW:
 133                 case MACH_MSP4200_FPGA:
 134                 case MACH_MSP7120_EVAL:
 135                 case MACH_MSP7120_GW:
 136                 case MACH_MSP7120_FPGA:
 137                         /* Enable UART1 on MSP4200 and MSP7120 */
 138                         *GPIO_CFG2_REG = 0x00002299;
 139                         break;
 140 
 141                 default:
 142                         return; /* No second serial port, good-bye. */
 143         }
 144 
 145         up.mapbase      = MSP_UART1_BASE;
 146         up.membase      = ioremap_nocache(up.mapbase, MSP_UART_REG_LEN);
 147         up.irq          = MSP_INT_UART1;
 148         up.line         = 1;
 149         up.private_data         = (void*)UART1_STATUS_REG;
 150         if (early_serial_setup(&up)) {
 151                 kfree(up.private_data);
 152                 pr_err("Early serial init of port 1 failed\n");
 153         }
 154 }

/* [<][>][^][v][top][bottom][index][help] */