/*
* Driver for the PSC of the Freescale MPC52xx PSCs configured as UARTs.
*
* FIXME According to the usermanual the status bits in the status register
* are only updated when the peripherals access the FIFO and not when the
* CPU access them. So since we use this bits to know when we stop writing
* and reading, they may not be updated in-time and a race condition may
* exists. But I haven't be able to prove this and I don't care. But if
* any problem arises, it might worth checking. The TX/RX FIFO Stats
* registers should be used in addition.
* Update: Actually, they seem updated ... At least the bits we use.
*
*
* Maintainer : Sylvain Munaut <tnt@246tNt.com>
*
* Some of the code has been inspired/copied from the 2.4 code written
* by Dale Farnsworth <dfarnsworth@mvista.com>.
*
* Copyright (C) 2008 Freescale Semiconductor Inc.
* John Rigby <jrigby@gmail.com>
* Added support for MPC5121
* Copyright (C) 2006 Secret Lab Technologies Ltd.
* Grant Likely <grant.likely@secretlab.ca>
* Copyright (C) 2004-2006 Sylvain Munaut <tnt@246tNt.com>
* Copyright (C) 2003 MontaVista, Software, Inc.
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*/
/* Platform device Usage :
*
* Since PSCs can have multiple function, the correct driver for each one
* is selected by calling mpc52xx_match_psc_function(...). The function
* handled by this driver is "uart".
*
* The driver init all necessary registers to place the PSC in uart mode without
* DCD. However, the pin multiplexing aren't changed and should be set either
* by the bootloader or in the platform init code.
*
* The idx field must be equal to the PSC index (e.g. 0 for PSC1, 1 for PSC2,
* and so on). So the PSC1 is mapped to /dev/ttyPSC0, PSC2 to /dev/ttyPSC1 and
* so on. But be warned, it's an ABSOLUTE REQUIREMENT ! This is needed mainly
* fpr the console code : without this 1:1 mapping, at early boot time, when we
* are parsing the kernel args console=ttyPSC?, we wouldn't know which PSC it
* will be mapped to.
*/
/* OF Platform device Usage :
*
* This driver is only used for PSCs configured in uart mode. The device
* tree will have a node for each PSC in uart mode w/ device_type = "serial"
* and "mpc52xx-psc-uart" in the compatible string
*
* By default, PSC devices are enumerated in the order they are found. However
* a particular PSC number can be forces by adding 'device_no = <port#>'
* to the device node.
*
* The driver init all necessary registers to place the PSC in uart mode without
* DCD. However, the pin multiplexing aren't changed and should be set either
* by the bootloader or in the platform init code.
*/
#undef DEBUG
#include <linux/device.h>
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/serial.h>
#include <linux/sysrq.h>
#include <linux/console.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <asm/mpc52xx.h>
#include <asm/mpc512x.h>
#include <asm/mpc52xx_psc.h>
#if defined(CONFIG_SERIAL_MPC52xx_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
#endif
#include <linux/serial_core.h>
/* We've been assigned a range on the "Low-density serial ports" major */
#define SERIAL_PSC_MAJOR 204
#define SERIAL_PSC_MINOR 148
#define ISR_PASS_LIMIT 256 /* Max number of iteration in the interrupt */
static struct uart_port mpc52xx_uart_ports[MPC52xx_PSC_MAXNUM];
/* Rem: - We use the read_status_mask as a shadow of
* psc->mpc52xx_psc_imr
* - It's important that is array is all zero on start as we
* use it to know if it's initialized or not ! If it's not sure
* it's cleared, then a memset(...,0,...) should be added to
* the console_init
*/
/* lookup table for matching device nodes to index numbers */
static struct device_node *mpc52xx_uart_nodes[MPC52xx_PSC_MAXNUM];
static void mpc52xx_uart_of_enumerate(void);
#define PSC(port) ((struct mpc52xx_psc __iomem *)((port)->membase))
/* Forward declaration of the interruption handling routine */
static irqreturn_t mpc52xx_uart_int(int irq, void *dev_id);
/* Simple macro to test if a port is console or not. This one is taken
* for serial_core.c and maybe should be moved to serial_core.h ? */
#ifdef CONFIG_SERIAL_CORE_CONSOLE
#define uart_console(port) \
((port)->cons && (port)->cons->index == (port)->line)
#else
#define uart_console(port) (0)
#endif
/* ======================================================================== */
/* PSC fifo operations for isolating differences between 52xx and 512x */
/* ======================================================================== */
struct psc_ops {
void (*fifo_init)(struct uart_port *port);
int (*raw_rx_rdy)(struct uart_port *port);
int (*raw_tx_rdy)(struct uart_port *port);
int (*rx_rdy)(struct