11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Derived from many drivers using generic_serial interface,
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * especially serial_tx3912.c by Steven J. Hill and r39xx_serial.c
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (was in Linux/VR tree) by Jim Pick.
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Copyright (C) 1999 Harald Koerfgen
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Copyright (C) 2000 Jim Pick <jim@jimpick.com>
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Copyright (C) 2001 Steven J. Hill (sjhill@realitydiluted.com)
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Copyright (C) 2000-2002 Toshiba Corporation
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License version 2 as
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * published by the Free Software Foundation.
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Serial driver for TX3927/TX4927/TX4925/TX4938 internal SIO controller
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if defined(CONFIG_SERIAL_TXX9_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SUPPORT_SYSRQ
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h>
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/console.h>
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h>
270970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto#include <linux/platform_device.h>
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h>
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/serial_core.h>
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/serial.h>
31ee160a38eee357ed2572cf41437d5814ce53c839Jiri Slaby#include <linux/tty.h>
32ee160a38eee357ed2572cf41437d5814ce53c839Jiri Slaby#include <linux/tty_flip.h>
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h>
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3637a6c7d0096bb54daa2cf3cc66a66bdbb57cb204Atsushi Nemotostatic char *serial_version = "1.11";
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char *serial_name = "TX39/49 Serial driver";
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PASS_LIMIT	256
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if !defined(CONFIG_SERIAL_TXX9_STDSERIAL)
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* "ttyS" is used for standard serial driver */
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_TTY_NAME "ttyTX"
4407bafde351470e19168dfc6385ff417e832850c1Atsushi Nemoto#define TXX9_TTY_MINOR_START	196
4507bafde351470e19168dfc6385ff417e832850c1Atsushi Nemoto#define TXX9_TTY_MAJOR	204
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* acts like standard serial driver */
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_TTY_NAME "ttyS"
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_TTY_MINOR_START	64
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_TTY_MAJOR	TTY_MAJOR
5107bafde351470e19168dfc6385ff417e832850c1Atsushi Nemoto#endif
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* flag aliases */
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UPF_TXX9_HAVE_CTS_LINE	UPF_BUGGY_UART
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UPF_TXX9_USE_SCLK	UPF_MAGIC_MULTIPLIER
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PCI
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* support for Toshiba TC86C001 SIO */
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ENABLE_SERIAL_TXX9_PCI
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Number of serial ports
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
65138c5d258cf06c278f5d7fe0a806e50fe413a08fAtsushi Nemoto#define UART_NR  CONFIG_SERIAL_TXX9_NR_UARTS
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct uart_txx9_port {
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct uart_port	port;
690970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	/* No additional info for now */
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_REGION_SIZE	0x24
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* TXX9 Serial Registers */
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SILCR	0x00
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIDICR	0x04
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIDISR	0x08
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SICISR	0x0c
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIFCR	0x10
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIFLCR	0x14
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIBGR	0x18
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SITFIFO	0x1c
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIRFIFO	0x20
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* SILCR : Line Control */
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SILCR_SCS_MASK	0x00000060
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SILCR_SCS_IMCLK	0x00000000
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SILCR_SCS_IMCLK_BG	0x00000020
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SILCR_SCS_SCLK	0x00000040
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SILCR_SCS_SCLK_BG	0x00000060
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SILCR_UEPS	0x00000010
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SILCR_UPEN	0x00000008
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SILCR_USBL_MASK	0x00000004
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SILCR_USBL_1BIT	0x00000000
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SILCR_USBL_2BIT	0x00000004
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SILCR_UMODE_MASK	0x00000003
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SILCR_UMODE_8BIT	0x00000000
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SILCR_UMODE_7BIT	0x00000001
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* SIDICR : DMA/Int. Control */
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIDICR_TDE	0x00008000
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIDICR_RDE	0x00004000
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIDICR_TIE	0x00002000
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIDICR_RIE	0x00001000
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIDICR_SPIE	0x00000800
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIDICR_CTSAC	0x00000600
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIDICR_STIE_MASK	0x0000003f
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIDICR_STIE_OERS		0x00000020
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIDICR_STIE_CTSS		0x00000010
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIDICR_STIE_RBRKD	0x00000008
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIDICR_STIE_TRDY		0x00000004
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIDICR_STIE_TXALS	0x00000002
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIDICR_STIE_UBRKD	0x00000001
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* SIDISR : DMA/Int. Status */
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIDISR_UBRK	0x00008000
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIDISR_UVALID	0x00004000
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIDISR_UFER	0x00002000
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIDISR_UPER	0x00001000
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIDISR_UOER	0x00000800
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIDISR_ERI	0x00000400
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIDISR_TOUT	0x00000200
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIDISR_TDIS	0x00000100
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIDISR_RDIS	0x00000080
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIDISR_STIS	0x00000040
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIDISR_RFDN_MASK	0x0000001f
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* SICISR : Change Int. Status */
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SICISR_OERS	0x00000020
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SICISR_CTSS	0x00000010
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SICISR_RBRKD	0x00000008
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SICISR_TRDY	0x00000004
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SICISR_TXALS	0x00000002
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SICISR_UBRKD	0x00000001
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* SIFCR : FIFO Control */
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIFCR_SWRST	0x00008000
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIFCR_RDIL_MASK	0x00000180
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIFCR_RDIL_1	0x00000000
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIFCR_RDIL_4	0x00000080
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIFCR_RDIL_8	0x00000100
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIFCR_RDIL_12	0x00000180
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIFCR_RDIL_MAX	0x00000180
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIFCR_TDIL_MASK	0x00000018
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIFCR_TDIL_MASK	0x00000018
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIFCR_TDIL_1	0x00000000
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIFCR_TDIL_4	0x00000001
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIFCR_TDIL_8	0x00000010
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIFCR_TDIL_MAX	0x00000010
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIFCR_TFRST	0x00000004
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIFCR_RFRST	0x00000002
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIFCR_FRSTE	0x00000001
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIO_TX_FIFO	8
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIO_RX_FIFO	16
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* SIFLCR : Flow Control */
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIFLCR_RCS	0x00001000
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIFLCR_TES	0x00000800
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIFLCR_RTSSC	0x00000200
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIFLCR_RSDE	0x00000100
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIFLCR_TSDE	0x00000080
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIFLCR_RTSTL_MASK	0x0000001e
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIFLCR_RTSTL_MAX	0x0000001e
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIFLCR_TBRK	0x00000001
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* SIBGR : Baudrate Control */
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIBGR_BCLK_MASK	0x00000300
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIBGR_BCLK_T0	0x00000000
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIBGR_BCLK_T2	0x00000100
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIBGR_BCLK_T4	0x00000200
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIBGR_BCLK_T6	0x00000300
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXX9_SIBGR_BRD_MASK	0x000000ff
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline unsigned int sio_in(struct uart_txx9_port *up, int offset)
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (up->port.iotype) {
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
17883485f826bea154a0ab41e9b8689105531dd7cb2Atsushi Nemoto		return __raw_readl(up->port.membase + offset);
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case UPIO_PORT:
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return inl(up->port.iobase + offset);
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssio_out(struct uart_txx9_port *up, int offset, int value)
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (up->port.iotype) {
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
18983485f826bea154a0ab41e9b8689105531dd7cb2Atsushi Nemoto		__raw_writel(value, up->port.membase + offset);
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case UPIO_PORT:
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outl(value, up->port.iobase + offset);
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssio_mask(struct uart_txx9_port *up, int offset, unsigned int value)
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sio_out(up, offset, sio_in(up, offset) & ~value);
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssio_set(struct uart_txx9_port *up, int offset, unsigned int value)
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sio_out(up, offset, sio_in(up, offset) | value);
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssio_quot_set(struct uart_txx9_port *up, int quot)
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	quot >>= 1;
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (quot < 256)
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sio_out(up, TXX9_SIBGR, quot | TXX9_SIBGR_BCLK_T0);
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else if (quot < (256 << 2))
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sio_out(up, TXX9_SIBGR, (quot >> 2) | TXX9_SIBGR_BCLK_T2);
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else if (quot < (256 << 4))
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sio_out(up, TXX9_SIBGR, (quot >> 4) | TXX9_SIBGR_BCLK_T4);
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else if (quot < (256 << 6))
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sio_out(up, TXX9_SIBGR, (quot >> 6) | TXX9_SIBGR_BCLK_T6);
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sio_out(up, TXX9_SIBGR, 0xff | TXX9_SIBGR_BCLK_T6);
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
224aa76224a38530f9c69d1670c47fdeea30a420a73Atsushi Nemotostatic struct uart_txx9_port *to_uart_txx9_port(struct uart_port *port)
225aa76224a38530f9c69d1670c47fdeea30a420a73Atsushi Nemoto{
226aa76224a38530f9c69d1670c47fdeea30a420a73Atsushi Nemoto	return container_of(port, struct uart_txx9_port, port);
227aa76224a38530f9c69d1670c47fdeea30a420a73Atsushi Nemoto}
228aa76224a38530f9c69d1670c47fdeea30a420a73Atsushi Nemoto
229b129a8ccd53f74c43e4c83c8e0031a4990040830Russell Kingstatic void serial_txx9_stop_tx(struct uart_port *port)
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
231aa76224a38530f9c69d1670c47fdeea30a420a73Atsushi Nemoto	struct uart_txx9_port *up = to_uart_txx9_port(port);
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sio_mask(up, TXX9_SIDICR, TXX9_SIDICR_TIE);
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
235b129a8ccd53f74c43e4c83c8e0031a4990040830Russell Kingstatic void serial_txx9_start_tx(struct uart_port *port)
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
237aa76224a38530f9c69d1670c47fdeea30a420a73Atsushi Nemoto	struct uart_txx9_port *up = to_uart_txx9_port(port);
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sio_set(up, TXX9_SIDICR, TXX9_SIDICR_TIE);
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void serial_txx9_stop_rx(struct uart_port *port)
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
243aa76224a38530f9c69d1670c47fdeea30a420a73Atsushi Nemoto	struct uart_txx9_port *up = to_uart_txx9_port(port);
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	up->port.read_status_mask &= ~TXX9_SIDISR_RDIS;
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void serial_txx9_enable_ms(struct uart_port *port)
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* TXX9-SIO can not control DTR... */
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2520970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemotostatic void serial_txx9_initialize(struct uart_port *port)
2530970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto{
254aa76224a38530f9c69d1670c47fdeea30a420a73Atsushi Nemoto	struct uart_txx9_port *up = to_uart_txx9_port(port);
2550970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	unsigned int tmout = 10000;
2560970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto
2570970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	sio_out(up, TXX9_SIFCR, TXX9_SIFCR_SWRST);
2580970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	/* TX4925 BUG WORKAROUND.  Accessing SIOC register
2590970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	 * immediately after soft reset causes bus error. */
2600970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	mmiowb();
2610970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	udelay(1);
2620970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	while ((sio_in(up, TXX9_SIFCR) & TXX9_SIFCR_SWRST) && --tmout)
2630970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		udelay(1);
2640970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	/* TX Int by FIFO Empty, RX Int by Receiving 1 char. */
2650970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	sio_set(up, TXX9_SIFCR,
2660970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		TXX9_SIFCR_TDIL_MAX | TXX9_SIFCR_RDIL_1);
2670970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	/* initial settings */
2680970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	sio_out(up, TXX9_SILCR,
2690970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		TXX9_SILCR_UMODE_8BIT | TXX9_SILCR_USBL_1BIT |
2700970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		((up->port.flags & UPF_TXX9_USE_SCLK) ?
2710970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		 TXX9_SILCR_SCS_SCLK_BG : TXX9_SILCR_SCS_IMCLK_BG));
2720970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	sio_quot_set(up, uart_get_divisor(port, 9600));
2730970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	sio_out(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSTL_MAX /* 15 */);
2740970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	sio_out(up, TXX9_SIDICR, 0);
2750970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto}
2760970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void
2787d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsreceive_chars(struct uart_txx9_port *up, unsigned int *status)
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
280ebd2c8f6d2ec4012c267ecb95e72a57b8355a705Alan Cox	struct tty_struct *tty = up->port.state->port.tty;
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char ch;
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int disr = *status;
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int max_count = 256;
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char flag;
28583485f826bea154a0ab41e9b8689105531dd7cb2Atsushi Nemoto	unsigned int next_ignore_status_mask;
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do {
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ch = sio_in(up, TXX9_SIRFIFO);
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		flag = TTY_NORMAL;
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		up->port.icount.rx++;
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29283485f826bea154a0ab41e9b8689105531dd7cb2Atsushi Nemoto		/* mask out RFDN_MASK bit added by previous overrun */
29383485f826bea154a0ab41e9b8689105531dd7cb2Atsushi Nemoto		next_ignore_status_mask =
29483485f826bea154a0ab41e9b8689105531dd7cb2Atsushi Nemoto			up->port.ignore_status_mask & ~TXX9_SIDISR_RFDN_MASK;
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (unlikely(disr & (TXX9_SIDISR_UBRK | TXX9_SIDISR_UPER |
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     TXX9_SIDISR_UFER | TXX9_SIDISR_UOER))) {
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * For statistics only
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (disr & TXX9_SIDISR_UBRK) {
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				disr &= ~(TXX9_SIDISR_UFER | TXX9_SIDISR_UPER);
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				up->port.icount.brk++;
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/*
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * We do the SysRQ and SAK checking
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * here because otherwise the break
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * may get masked by ignore_status_mask
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * or read_status_mask.
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 */
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (uart_handle_break(&up->port))
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					goto ignore_char;
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else if (disr & TXX9_SIDISR_UPER)
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				up->port.icount.parity++;
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else if (disr & TXX9_SIDISR_UFER)
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				up->port.icount.frame++;
31583485f826bea154a0ab41e9b8689105531dd7cb2Atsushi Nemoto			if (disr & TXX9_SIDISR_UOER) {
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				up->port.icount.overrun++;
31783485f826bea154a0ab41e9b8689105531dd7cb2Atsushi Nemoto				/*
31883485f826bea154a0ab41e9b8689105531dd7cb2Atsushi Nemoto				 * The receiver read buffer still hold
31983485f826bea154a0ab41e9b8689105531dd7cb2Atsushi Nemoto				 * a char which caused overrun.
32083485f826bea154a0ab41e9b8689105531dd7cb2Atsushi Nemoto				 * Ignore next char by adding RFDN_MASK
32183485f826bea154a0ab41e9b8689105531dd7cb2Atsushi Nemoto				 * to ignore_status_mask temporarily.
32283485f826bea154a0ab41e9b8689105531dd7cb2Atsushi Nemoto				 */
32383485f826bea154a0ab41e9b8689105531dd7cb2Atsushi Nemoto				next_ignore_status_mask |=
32483485f826bea154a0ab41e9b8689105531dd7cb2Atsushi Nemoto					TXX9_SIDISR_RFDN_MASK;
32583485f826bea154a0ab41e9b8689105531dd7cb2Atsushi Nemoto			}
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * Mask off conditions which should be ingored.
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			disr &= up->port.read_status_mask;
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (disr & TXX9_SIDISR_UBRK) {
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				flag = TTY_BREAK;
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else if (disr & TXX9_SIDISR_UPER)
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				flag = TTY_PARITY;
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else if (disr & TXX9_SIDISR_UFER)
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				flag = TTY_FRAME;
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3397d12e780e003f93433d49ce78cfedf4b4c52adc5David Howells		if (uart_handle_sysrq_char(&up->port, ch))
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto ignore_char;
34105ab3014636ff60a319d37cdf37dca594b015eecRussell King
34205ab3014636ff60a319d37cdf37dca594b015eecRussell King		uart_insert_char(&up->port, disr, TXX9_SIDISR_UOER, ch, flag);
34305ab3014636ff60a319d37cdf37dca594b015eecRussell King
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ignore_char:
34583485f826bea154a0ab41e9b8689105531dd7cb2Atsushi Nemoto		up->port.ignore_status_mask = next_ignore_status_mask;
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		disr = sio_in(up, TXX9_SIDISR);
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} while (!(disr & TXX9_SIDISR_UVALID) && (max_count-- > 0));
348f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle	spin_unlock(&up->port.lock);
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tty_flip_buffer_push(tty);
350f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle	spin_lock(&up->port.lock);
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*status = disr;
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void transmit_chars(struct uart_txx9_port *up)
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
356ebd2c8f6d2ec4012c267ecb95e72a57b8355a705Alan Cox	struct circ_buf *xmit = &up->port.state->xmit;
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int count;
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (up->port.x_char) {
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sio_out(up, TXX9_SITFIFO, up->port.x_char);
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		up->port.icount.tx++;
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		up->port.x_char = 0;
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
366b129a8ccd53f74c43e4c83c8e0031a4990040830Russell King		serial_txx9_stop_tx(&up->port);
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	count = TXX9_SIO_TX_FIFO;
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do {
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sio_out(up, TXX9_SITFIFO, xmit->buf[xmit->tail]);
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		up->port.icount.tx++;
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (uart_circ_empty(xmit))
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} while (--count > 0);
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		uart_write_wakeup(&up->port);
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (uart_circ_empty(xmit))
383b129a8ccd53f74c43e4c83c8e0031a4990040830Russell King		serial_txx9_stop_tx(&up->port);
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3867d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t serial_txx9_interrupt(int irq, void *dev_id)
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int pass_counter = 0;
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct uart_txx9_port *up = dev_id;
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int status;
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (1) {
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_lock(&up->port.lock);
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		status = sio_in(up, TXX9_SIDISR);
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!(sio_in(up, TXX9_SIDICR) & TXX9_SIDICR_TIE))
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			status &= ~TXX9_SIDISR_TDIS;
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!(status & (TXX9_SIDISR_TDIS | TXX9_SIDISR_RDIS |
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				TXX9_SIDISR_TOUT))) {
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			spin_unlock(&up->port.lock);
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (status & TXX9_SIDISR_RDIS)
4047d12e780e003f93433d49ce78cfedf4b4c52adc5David Howells			receive_chars(up, &status);
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (status & TXX9_SIDISR_TDIS)
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			transmit_chars(up);
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Clear TX/RX Int. Status */
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sio_mask(up, TXX9_SIDISR,
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 TXX9_SIDISR_TDIS | TXX9_SIDISR_RDIS |
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 TXX9_SIDISR_TOUT);
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_unlock(&up->port.lock);
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (pass_counter++ > PASS_LIMIT)
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return pass_counter ? IRQ_HANDLED : IRQ_NONE;
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int serial_txx9_tx_empty(struct uart_port *port)
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
422aa76224a38530f9c69d1670c47fdeea30a420a73Atsushi Nemoto	struct uart_txx9_port *up = to_uart_txx9_port(port);
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int ret;
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&up->port.lock, flags);
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ret = (sio_in(up, TXX9_SICISR) & TXX9_SICISR_TXALS) ? TIOCSER_TEMT : 0;
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&up->port.lock, flags);
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int serial_txx9_get_mctrl(struct uart_port *port)
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
435aa76224a38530f9c69d1670c47fdeea30a420a73Atsushi Nemoto	struct uart_txx9_port *up = to_uart_txx9_port(port);
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int ret;
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
438999999616e45c603da45ee2667741fb7348629a5Atsushi Nemoto	/* no modem control lines */
439999999616e45c603da45ee2667741fb7348629a5Atsushi Nemoto	ret = TIOCM_CAR | TIOCM_DSR;
440999999616e45c603da45ee2667741fb7348629a5Atsushi Nemoto	ret |= (sio_in(up, TXX9_SIFLCR) & TXX9_SIFLCR_RTSSC) ? 0 : TIOCM_RTS;
441999999616e45c603da45ee2667741fb7348629a5Atsushi Nemoto	ret |= (sio_in(up, TXX9_SICISR) & TXX9_SICISR_CTSS) ? 0 : TIOCM_CTS;
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void serial_txx9_set_mctrl(struct uart_port *port, unsigned int mctrl)
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
448aa76224a38530f9c69d1670c47fdeea30a420a73Atsushi Nemoto	struct uart_txx9_port *up = to_uart_txx9_port(port);
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mctrl & TIOCM_RTS)
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sio_mask(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSSC);
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sio_set(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSSC);
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void serial_txx9_break_ctl(struct uart_port *port, int break_state)
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
458aa76224a38530f9c69d1670c47fdeea30a420a73Atsushi Nemoto	struct uart_txx9_port *up = to_uart_txx9_port(port);
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&up->port.lock, flags);
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (break_state == -1)
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sio_set(up, TXX9_SIFLCR, TXX9_SIFLCR_TBRK);
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sio_mask(up, TXX9_SIFLCR, TXX9_SIFLCR_TBRK);
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&up->port.lock, flags);
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
469a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto#if defined(CONFIG_SERIAL_TXX9_CONSOLE) || (CONFIG_CONSOLE_POLL)
470a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto/*
471a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto *	Wait for transmitter & holding register to empty
472a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto */
473a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemotostatic void wait_for_xmitr(struct uart_txx9_port *up)
474a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto{
475a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	unsigned int tmout = 10000;
476a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto
477a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	/* Wait up to 10ms for the character(s) to be sent. */
478a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	while (--tmout &&
479a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	       !(sio_in(up, TXX9_SICISR) & TXX9_SICISR_TXALS))
480a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto		udelay(1);
481a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto
482a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	/* Wait up to 1s for flow control if necessary */
483a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	if (up->port.flags & UPF_CONS_FLOW) {
484a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto		tmout = 1000000;
485a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto		while (--tmout &&
486a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto		       (sio_in(up, TXX9_SICISR) & TXX9_SICISR_CTSS))
487a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto			udelay(1);
488a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	}
489a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto}
490a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto#endif
491a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto
492a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto#ifdef CONFIG_CONSOLE_POLL
493a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto/*
494a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto * Console polling routines for writing and reading from the uart while
495a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto * in an interrupt or debug context.
496a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto */
497a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto
498a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemotostatic int serial_txx9_get_poll_char(struct uart_port *port)
499a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto{
500a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	unsigned int ier;
501a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	unsigned char c;
502aa76224a38530f9c69d1670c47fdeea30a420a73Atsushi Nemoto	struct uart_txx9_port *up = to_uart_txx9_port(port);
503a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto
504a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	/*
505a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	 *	First save the IER then disable the interrupts
506a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	 */
507a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	ier = sio_in(up, TXX9_SIDICR);
508a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	sio_out(up, TXX9_SIDICR, 0);
509a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto
510a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	while (sio_in(up, TXX9_SIDISR) & TXX9_SIDISR_UVALID)
511a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto		;
512a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto
513a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	c = sio_in(up, TXX9_SIRFIFO);
514a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto
515a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	/*
516a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	 *	Finally, clear RX interrupt status
517a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	 *	and restore the IER
518a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	 */
519a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	sio_mask(up, TXX9_SIDISR, TXX9_SIDISR_RDIS);
520a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	sio_out(up, TXX9_SIDICR, ier);
521a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	return c;
522a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto}
523a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto
524a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto
525a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemotostatic void serial_txx9_put_poll_char(struct uart_port *port, unsigned char c)
526a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto{
527a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	unsigned int ier;
528aa76224a38530f9c69d1670c47fdeea30a420a73Atsushi Nemoto	struct uart_txx9_port *up = to_uart_txx9_port(port);
529a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto
530a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	/*
531a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	 *	First save the IER then disable the interrupts
532a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	 */
533a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	ier = sio_in(up, TXX9_SIDICR);
534a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	sio_out(up, TXX9_SIDICR, 0);
535a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto
536a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	wait_for_xmitr(up);
537a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	/*
538a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	 *	Send the character out.
539a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	 *	If a LF, also do CR...
540a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	 */
541a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	sio_out(up, TXX9_SITFIFO, c);
542a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	if (c == 10) {
543a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto		wait_for_xmitr(up);
544a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto		sio_out(up, TXX9_SITFIFO, 13);
545a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	}
546a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto
547a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	/*
548a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	 *	Finally, wait for transmitter to become empty
549a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	 *	and restore the IER
550a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	 */
551a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	wait_for_xmitr(up);
552a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	sio_out(up, TXX9_SIDICR, ier);
553a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto}
554a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto
555a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto#endif /* CONFIG_CONSOLE_POLL */
556a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int serial_txx9_startup(struct uart_port *port)
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
559aa76224a38530f9c69d1670c47fdeea30a420a73Atsushi Nemoto	struct uart_txx9_port *up = to_uart_txx9_port(port);
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int retval;
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Clear the FIFO buffers and disable them.
5657f927fcc2fd1575d01efb4b76665975007945690Alexey Dobriyan	 * (they will be reenabled in set_termios())
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sio_set(up, TXX9_SIFCR,
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		TXX9_SIFCR_TFRST | TXX9_SIFCR_RFRST | TXX9_SIFCR_FRSTE);
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* clear reset */
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sio_mask(up, TXX9_SIFCR,
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 TXX9_SIFCR_TFRST | TXX9_SIFCR_RFRST | TXX9_SIFCR_FRSTE);
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sio_out(up, TXX9_SIDICR, 0);
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Clear the interrupt registers.
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sio_out(up, TXX9_SIDISR, 0);
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	retval = request_irq(up->port.irq, serial_txx9_interrupt,
58040663cc7f1c1ccf515d8af9470925a0cb2f59b5dThomas Gleixner			     IRQF_SHARED, "serial_txx9", up);
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (retval)
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return retval;
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Now, initialize the UART
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&up->port.lock, flags);
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	serial_txx9_set_mctrl(&up->port, up->port.mctrl);
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&up->port.lock, flags);
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Enable RX/TX */
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sio_mask(up, TXX9_SIFLCR, TXX9_SIFLCR_RSDE | TXX9_SIFLCR_TSDE);
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Finally, enable interrupts.
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sio_set(up, TXX9_SIDICR, TXX9_SIDICR_RIE);
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void serial_txx9_shutdown(struct uart_port *port)
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
604aa76224a38530f9c69d1670c47fdeea30a420a73Atsushi Nemoto	struct uart_txx9_port *up = to_uart_txx9_port(port);
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Disable interrupts from this port
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sio_out(up, TXX9_SIDICR, 0);	/* disable all intrs */
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&up->port.lock, flags);
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	serial_txx9_set_mctrl(&up->port, up->port.mctrl);
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&up->port.lock, flags);
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Disable break condition
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sio_mask(up, TXX9_SIFLCR, TXX9_SIFLCR_TBRK);
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SERIAL_TXX9_CONSOLE
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (up->port.cons && up->port.line == up->port.cons->index) {
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		free_irq(up->port.irq, up);
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* reset FIFOs */
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sio_set(up, TXX9_SIFCR,
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		TXX9_SIFCR_TFRST | TXX9_SIFCR_RFRST | TXX9_SIFCR_FRSTE);
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* clear reset */
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sio_mask(up, TXX9_SIFCR,
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 TXX9_SIFCR_TFRST | TXX9_SIFCR_RFRST | TXX9_SIFCR_FRSTE);
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Disable RX/TX */
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sio_set(up, TXX9_SIFLCR, TXX9_SIFLCR_RSDE | TXX9_SIFLCR_TSDE);
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	free_irq(up->port.irq, up);
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
641606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Coxserial_txx9_set_termios(struct uart_port *port, struct ktermios *termios,
642606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Cox		       struct ktermios *old)
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
644aa76224a38530f9c69d1670c47fdeea30a420a73Atsushi Nemoto	struct uart_txx9_port *up = to_uart_txx9_port(port);
6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int cval, fcr = 0;
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int baud, quot;
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
649999999616e45c603da45ee2667741fb7348629a5Atsushi Nemoto	/*
650999999616e45c603da45ee2667741fb7348629a5Atsushi Nemoto	 * We don't support modem control lines.
651999999616e45c603da45ee2667741fb7348629a5Atsushi Nemoto	 */
652999999616e45c603da45ee2667741fb7348629a5Atsushi Nemoto	termios->c_cflag &= ~(HUPCL | CMSPAR);
653999999616e45c603da45ee2667741fb7348629a5Atsushi Nemoto	termios->c_cflag |= CLOCAL;
654999999616e45c603da45ee2667741fb7348629a5Atsushi Nemoto
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cval = sio_in(up, TXX9_SILCR);
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* byte size and parity */
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cval &= ~TXX9_SILCR_UMODE_MASK;
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (termios->c_cflag & CSIZE) {
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case CS7:
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cval |= TXX9_SILCR_UMODE_7BIT;
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case CS5:	/* not supported */
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case CS6:	/* not supported */
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case CS8:
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cval |= TXX9_SILCR_UMODE_8BIT;
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cval &= ~TXX9_SILCR_USBL_MASK;
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (termios->c_cflag & CSTOPB)
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cval |= TXX9_SILCR_USBL_2BIT;
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cval |= TXX9_SILCR_USBL_1BIT;
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cval &= ~(TXX9_SILCR_UPEN | TXX9_SILCR_UEPS);
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (termios->c_cflag & PARENB)
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cval |= TXX9_SILCR_UPEN;
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(termios->c_cflag & PARODD))
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cval |= TXX9_SILCR_UEPS;
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Ask the core to calculate the divisor for us.
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16/2);
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	quot = uart_get_divisor(port, baud);
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Set up FIFOs */
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* TX Int by FIFO Empty, RX Int by Receiving 1 char. */
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	fcr = TXX9_SIFCR_TDIL_MAX | TXX9_SIFCR_RDIL_1;
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Ok, we're now changing the port state.  Do it with
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * interrupts disabled.
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&up->port.lock, flags);
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Update the per-port timeout.
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uart_update_timeout(port, termios->c_cflag, baud);
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	up->port.read_status_mask = TXX9_SIDISR_UOER |
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		TXX9_SIDISR_TDIS | TXX9_SIDISR_RDIS;
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (termios->c_iflag & INPCK)
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		up->port.read_status_mask |= TXX9_SIDISR_UFER | TXX9_SIDISR_UPER;
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (termios->c_iflag & (BRKINT | PARMRK))
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		up->port.read_status_mask |= TXX9_SIDISR_UBRK;
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Characteres to ignore
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	up->port.ignore_status_mask = 0;
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (termios->c_iflag & IGNPAR)
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		up->port.ignore_status_mask |= TXX9_SIDISR_UPER | TXX9_SIDISR_UFER;
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (termios->c_iflag & IGNBRK) {
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		up->port.ignore_status_mask |= TXX9_SIDISR_UBRK;
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * If we're ignoring parity and break indicators,
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * ignore overruns too (for real raw support).
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (termios->c_iflag & IGNPAR)
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			up->port.ignore_status_mask |= TXX9_SIDISR_UOER;
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * ignore all characters if CREAD is not set
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((termios->c_cflag & CREAD) == 0)
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		up->port.ignore_status_mask |= TXX9_SIDISR_RDIS;
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* CTS flow control flag */
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((termios->c_cflag & CRTSCTS) &&
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (up->port.flags & UPF_TXX9_HAVE_CTS_LINE)) {
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sio_set(up, TXX9_SIFLCR,
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			TXX9_SIFLCR_RCS | TXX9_SIFLCR_TES);
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sio_mask(up, TXX9_SIFLCR,
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 TXX9_SIFLCR_RCS | TXX9_SIFLCR_TES);
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sio_out(up, TXX9_SILCR, cval);
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sio_quot_set(up, quot);
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sio_out(up, TXX9_SIFCR, fcr);
7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	serial_txx9_set_mctrl(&up->port, up->port.mctrl);
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&up->port.lock, flags);
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsserial_txx9_pm(struct uart_port *port, unsigned int state,
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	      unsigned int oldstate)
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
75323f42b7b2e538a27bc457a9ba12a6656343dc5eaAtsushi Nemoto	/*
75423f42b7b2e538a27bc457a9ba12a6656343dc5eaAtsushi Nemoto	 * If oldstate was -1 this is called from
75523f42b7b2e538a27bc457a9ba12a6656343dc5eaAtsushi Nemoto	 * uart_configure_port().  In this case do not initialize the
75623f42b7b2e538a27bc457a9ba12a6656343dc5eaAtsushi Nemoto	 * port now, because the port was already initialized (for
75723f42b7b2e538a27bc457a9ba12a6656343dc5eaAtsushi Nemoto	 * non-console port) or should not be initialized here (for
75823f42b7b2e538a27bc457a9ba12a6656343dc5eaAtsushi Nemoto	 * console port).  If we initialized the port here we lose
75923f42b7b2e538a27bc457a9ba12a6656343dc5eaAtsushi Nemoto	 * serial console settings.
76023f42b7b2e538a27bc457a9ba12a6656343dc5eaAtsushi Nemoto	 */
76123f42b7b2e538a27bc457a9ba12a6656343dc5eaAtsushi Nemoto	if (state == 0 && oldstate != -1)
7620970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		serial_txx9_initialize(port);
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int serial_txx9_request_resource(struct uart_txx9_port *up)
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int size = TXX9_REGION_SIZE;
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret = 0;
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (up->port.iotype) {
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!up->port.mapbase)
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!request_mem_region(up->port.mapbase, size, "serial_txx9")) {
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ret = -EBUSY;
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (up->port.flags & UPF_IOREMAP) {
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			up->port.membase = ioremap(up->port.mapbase, size);
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!up->port.membase) {
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				release_mem_region(up->port.mapbase, size);
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ret = -ENOMEM;
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case UPIO_PORT:
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!request_region(up->port.iobase, size, "serial_txx9"))
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ret = -EBUSY;
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void serial_txx9_release_resource(struct uart_txx9_port *up)
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int size = TXX9_REGION_SIZE;
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (up->port.iotype) {
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!up->port.mapbase)
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (up->port.flags & UPF_IOREMAP) {
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			iounmap(up->port.membase);
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			up->port.membase = NULL;
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		release_mem_region(up->port.mapbase, size);
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case UPIO_PORT:
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		release_region(up->port.iobase, size);
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void serial_txx9_release_port(struct uart_port *port)
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
822aa76224a38530f9c69d1670c47fdeea30a420a73Atsushi Nemoto	struct uart_txx9_port *up = to_uart_txx9_port(port);
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	serial_txx9_release_resource(up);
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int serial_txx9_request_port(struct uart_port *port)
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
828aa76224a38530f9c69d1670c47fdeea30a420a73Atsushi Nemoto	struct uart_txx9_port *up = to_uart_txx9_port(port);
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return serial_txx9_request_resource(up);
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void serial_txx9_config_port(struct uart_port *port, int uflags)
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
834aa76224a38530f9c69d1670c47fdeea30a420a73Atsushi Nemoto	struct uart_txx9_port *up = to_uart_txx9_port(port);
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret;
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Find the region that we can probe for.  This in turn
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * tells us whether we can probe for the type of port.
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ret = serial_txx9_request_resource(up);
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ret < 0)
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	port->type = PORT_TXX9;
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	up->port.fifosize = TXX9_SIO_TX_FIFO;
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SERIAL_TXX9_CONSOLE
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (up->port.line == up->port.cons->index)
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
8510970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	serial_txx9_initialize(port);
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char *
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsserial_txx9_type(struct uart_port *port)
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return "txx9";
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct uart_ops serial_txx9_pops = {
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.tx_empty	= serial_txx9_tx_empty,
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.set_mctrl	= serial_txx9_set_mctrl,
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.get_mctrl	= serial_txx9_get_mctrl,
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.stop_tx	= serial_txx9_stop_tx,
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.start_tx	= serial_txx9_start_tx,
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.stop_rx	= serial_txx9_stop_rx,
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.enable_ms	= serial_txx9_enable_ms,
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.break_ctl	= serial_txx9_break_ctl,
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.startup	= serial_txx9_startup,
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.shutdown	= serial_txx9_shutdown,
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.set_termios	= serial_txx9_set_termios,
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.pm		= serial_txx9_pm,
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.type		= serial_txx9_type,
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.release_port	= serial_txx9_release_port,
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.request_port	= serial_txx9_request_port,
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.config_port	= serial_txx9_config_port,
877a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto#ifdef CONFIG_CONSOLE_POLL
878a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	.poll_get_char	= serial_txx9_get_poll_char,
879a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto	.poll_put_char	= serial_txx9_put_poll_char,
880a10b32db34898d0db58a58ef76a70c374931bbffAtsushi Nemoto#endif
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct uart_txx9_port serial_txx9_ports[UART_NR];
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8850970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemotostatic void __init serial_txx9_register_ports(struct uart_driver *drv,
8860970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto					      struct device *dev)
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < UART_NR; i++) {
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct uart_txx9_port *up = &serial_txx9_ports[i];
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		up->port.line = i;
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		up->port.ops = &serial_txx9_pops;
8950970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		up->port.dev = dev;
89683485f826bea154a0ab41e9b8689105531dd7cb2Atsushi Nemoto		if (up->port.iobase || up->port.mapbase)
89783485f826bea154a0ab41e9b8689105531dd7cb2Atsushi Nemoto			uart_add_one_port(drv, &up->port);
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SERIAL_TXX9_CONSOLE
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
903d358788f3f30113e49882187d794832905e42592Russell Kingstatic void serial_txx9_console_putchar(struct uart_port *port, int ch)
904d358788f3f30113e49882187d794832905e42592Russell King{
905aa76224a38530f9c69d1670c47fdeea30a420a73Atsushi Nemoto	struct uart_txx9_port *up = to_uart_txx9_port(port);
906d358788f3f30113e49882187d794832905e42592Russell King
907d358788f3f30113e49882187d794832905e42592Russell King	wait_for_xmitr(up);
908d358788f3f30113e49882187d794832905e42592Russell King	sio_out(up, TXX9_SITFIFO, ch);
909d358788f3f30113e49882187d794832905e42592Russell King}
910d358788f3f30113e49882187d794832905e42592Russell King
9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Print a string to the serial port trying not to disturb
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	any possible real use of the port...
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	The console_lock must be held when we get here.
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsserial_txx9_console_write(struct console *co, const char *s, unsigned int count)
9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct uart_txx9_port *up = &serial_txx9_ports[co->index];
9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int ier, flcr;
9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *	First save the UER then disable the interrupts
9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ier = sio_in(up, TXX9_SIDICR);
9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sio_out(up, TXX9_SIDICR, 0);
9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *	Disable flow-control if enabled (and unnecessary)
9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	flcr = sio_in(up, TXX9_SIFLCR);
9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(up->port.flags & UPF_CONS_FLOW) && (flcr & TXX9_SIFLCR_TES))
9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sio_out(up, TXX9_SIFLCR, flcr & ~TXX9_SIFLCR_TES);
9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
935d358788f3f30113e49882187d794832905e42592Russell King	uart_console_write(&up->port, s, count, serial_txx9_console_putchar);
9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *	Finally, wait for transmitter to become empty
9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *	and restore the IER
9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wait_for_xmitr(up);
9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sio_out(up, TXX9_SIFLCR, flcr);
9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sio_out(up, TXX9_SIDICR, ier);
9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9460970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemotostatic int __init serial_txx9_console_setup(struct console *co, char *options)
9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct uart_port *port;
9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct uart_txx9_port *up;
9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int baud = 9600;
9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int bits = 8;
9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int parity = 'n';
9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int flow = 'n';
9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Check whether an invalid uart number has been specified, and
9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * if so, search for the first available port that does have
9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * console support.
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (co->index >= UART_NR)
9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		co->index = 0;
9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	up = &serial_txx9_ports[co->index];
9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	port = &up->port;
9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!port->ops)
9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENODEV;
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9670970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	serial_txx9_initialize(&up->port);
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (options)
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		uart_parse_options(options, &baud, &parity, &bits, &flow);
9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return uart_set_options(port, co, baud, parity, bits, flow);
9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct uart_driver serial_txx9_reg;
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct console serial_txx9_console = {
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name		= TXX9_TTY_NAME,
9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.write		= serial_txx9_console_write,
9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.device		= uart_console_device,
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.setup		= serial_txx9_console_setup,
9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.flags		= CON_PRINTBUFFER,
9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.index		= -1,
9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.data		= &serial_txx9_reg,
9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init serial_txx9_console_init(void)
9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	register_console(&serial_txx9_console);
9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsconsole_initcall(serial_txx9_console_init);
9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SERIAL_TXX9_CONSOLE	&serial_txx9_console
9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SERIAL_TXX9_CONSOLE	NULL
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct uart_driver serial_txx9_reg = {
9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.owner			= THIS_MODULE,
10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.driver_name		= "serial_txx9",
10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.dev_name		= TXX9_TTY_NAME,
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.major			= TXX9_TTY_MAJOR,
10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.minor			= TXX9_TTY_MINOR_START,
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.nr			= UART_NR,
10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.cons			= SERIAL_TXX9_CONSOLE,
10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint __init early_serial_txx9_setup(struct uart_port *port)
10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (port->line >= ARRAY_SIZE(serial_txx9_ports))
10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENODEV;
10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	serial_txx9_ports[port->line].port = *port;
10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	serial_txx9_ports[port->line].port.ops = &serial_txx9_pops;
101537a6c7d0096bb54daa2cf3cc66a66bdbb57cb204Atsushi Nemoto	serial_txx9_ports[port->line].port.flags |=
101637a6c7d0096bb54daa2cf3cc66a66bdbb57cb204Atsushi Nemoto		UPF_BOOT_AUTOCONF | UPF_FIXED_PORT;
10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1020f392ecfa12de9a2baf72789b00557bac040d6171Arjan van de Venstatic DEFINE_MUTEX(serial_txx9_mutex);
1021f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle
1022f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle/**
1023f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle *	serial_txx9_register_port - register a serial port
1024f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle *	@port: serial port template
1025f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle *
1026f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle *	Configure the serial port specified by the request.
1027f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle *
1028f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle *	The port is then probed and if necessary the IRQ is autodetected
1029f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle *	If this fails an error is returned.
1030f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle *
1031f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle *	On success the port is ready to use and the line number is returned.
1032f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle */
1033f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechlestatic int __devinit serial_txx9_register_port(struct uart_port *port)
1034f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle{
1035f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle	int i;
1036f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle	struct uart_txx9_port *uart;
1037f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle	int ret = -ENOSPC;
1038f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle
1039f392ecfa12de9a2baf72789b00557bac040d6171Arjan van de Ven	mutex_lock(&serial_txx9_mutex);
1040f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle	for (i = 0; i < UART_NR; i++) {
1041f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle		uart = &serial_txx9_ports[i];
10420970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		if (uart_match_port(&uart->port, port)) {
10430970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto			uart_remove_one_port(&serial_txx9_reg, &uart->port);
1044f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle			break;
10450970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		}
10460970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	}
10470970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	if (i == UART_NR) {
10480970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		/* Find unused port */
10490970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		for (i = 0; i < UART_NR; i++) {
10500970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto			uart = &serial_txx9_ports[i];
10510970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto			if (!(uart->port.iobase || uart->port.mapbase))
10520970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto				break;
10530970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		}
1054f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle	}
1055f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle	if (i < UART_NR) {
1056f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle		uart->port.iobase = port->iobase;
1057f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle		uart->port.membase = port->membase;
1058f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle		uart->port.irq      = port->irq;
1059f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle		uart->port.uartclk  = port->uartclk;
1060f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle		uart->port.iotype   = port->iotype;
106137a6c7d0096bb54daa2cf3cc66a66bdbb57cb204Atsushi Nemoto		uart->port.flags    = port->flags
106237a6c7d0096bb54daa2cf3cc66a66bdbb57cb204Atsushi Nemoto			| UPF_BOOT_AUTOCONF | UPF_FIXED_PORT;
1063f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle		uart->port.mapbase  = port->mapbase;
1064f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle		if (port->dev)
1065f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle			uart->port.dev = port->dev;
1066f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle		ret = uart_add_one_port(&serial_txx9_reg, &uart->port);
1067f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle		if (ret == 0)
1068f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle			ret = uart->port.line;
1069f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle	}
1070f392ecfa12de9a2baf72789b00557bac040d6171Arjan van de Ven	mutex_unlock(&serial_txx9_mutex);
1071f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle	return ret;
1072f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle}
1073f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle
1074f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle/**
1075f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle *	serial_txx9_unregister_port - remove a txx9 serial port at runtime
1076f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle *	@line: serial line number
1077f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle *
1078f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle *	Remove one serial port.  This may not be called from interrupt
1079f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle *	context.  We hand the port back to the our control.
1080f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle */
1081f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechlestatic void __devexit serial_txx9_unregister_port(int line)
1082f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle{
1083f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle	struct uart_txx9_port *uart = &serial_txx9_ports[line];
1084f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle
1085f392ecfa12de9a2baf72789b00557bac040d6171Arjan van de Ven	mutex_lock(&serial_txx9_mutex);
1086f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle	uart_remove_one_port(&serial_txx9_reg, &uart->port);
1087f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle	uart->port.flags = 0;
1088f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle	uart->port.type = PORT_UNKNOWN;
1089f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle	uart->port.iobase = 0;
1090f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle	uart->port.mapbase = 0;
109183485f826bea154a0ab41e9b8689105531dd7cb2Atsushi Nemoto	uart->port.membase = NULL;
1092f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle	uart->port.dev = NULL;
1093f392ecfa12de9a2baf72789b00557bac040d6171Arjan van de Ven	mutex_unlock(&serial_txx9_mutex);
1094f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle}
1095f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle
10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
10970970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto * Register a set of serial devices attached to a platform device.
10980970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto */
10990970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemotostatic int __devinit serial_txx9_probe(struct platform_device *dev)
11000970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto{
11010970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	struct uart_port *p = dev->dev.platform_data;
11020970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	struct uart_port port;
11030970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	int ret, i;
11040970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto
11050970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	memset(&port, 0, sizeof(struct uart_port));
11060970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	for (i = 0; p && p->uartclk != 0; p++, i++) {
11070970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		port.iobase	= p->iobase;
11080970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		port.membase	= p->membase;
11090970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		port.irq	= p->irq;
11100970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		port.uartclk	= p->uartclk;
11110970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		port.iotype	= p->iotype;
11120970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		port.flags	= p->flags;
11130970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		port.mapbase	= p->mapbase;
11140970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		port.dev	= &dev->dev;
11150970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		ret = serial_txx9_register_port(&port);
11160970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		if (ret < 0) {
11170970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto			dev_err(&dev->dev, "unable to register port at index %d "
11188433ac61acf733dc4b427de5f0891518c21538f9Atsushi Nemoto				"(IO%lx MEM%llx IRQ%d): %d\n", i,
1119ddb437b7f74de775ff50ef51a8b2970564d56f86Atsushi Nemoto				p->iobase, (unsigned long long)p->mapbase,
1120ddb437b7f74de775ff50ef51a8b2970564d56f86Atsushi Nemoto				p->irq, ret);
11210970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		}
11220970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	}
11230970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	return 0;
11240970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto}
11250970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto
11260970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto/*
11270970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto * Remove serial ports registered against a platform device.
11280970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto */
11290970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemotostatic int __devexit serial_txx9_remove(struct platform_device *dev)
11300970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto{
11310970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	int i;
11320970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto
11330970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	for (i = 0; i < UART_NR; i++) {
11340970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		struct uart_txx9_port *up = &serial_txx9_ports[i];
11350970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto
11360970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		if (up->port.dev == &dev->dev)
11370970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto			serial_txx9_unregister_port(i);
11380970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	}
11390970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	return 0;
11400970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto}
11410970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto
11420970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto#ifdef CONFIG_PM
11430970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemotostatic int serial_txx9_suspend(struct platform_device *dev, pm_message_t state)
11440970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto{
11450970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	int i;
11460970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto
11470970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	for (i = 0; i < UART_NR; i++) {
11480970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		struct uart_txx9_port *up = &serial_txx9_ports[i];
11490970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto
11500970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
11510970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto			uart_suspend_port(&serial_txx9_reg, &up->port);
11520970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	}
11530970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto
11540970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	return 0;
11550970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto}
11560970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto
11570970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemotostatic int serial_txx9_resume(struct platform_device *dev)
11580970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto{
11590970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	int i;
11600970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto
11610970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	for (i = 0; i < UART_NR; i++) {
11620970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		struct uart_txx9_port *up = &serial_txx9_ports[i];
11630970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto
11640970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
11650970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto			uart_resume_port(&serial_txx9_reg, &up->port);
11660970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	}
11670970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto
11680970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	return 0;
11690970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto}
11700970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto#endif
11710970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto
11720970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemotostatic struct platform_driver serial_txx9_plat_driver = {
11730970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	.probe		= serial_txx9_probe,
11740970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	.remove		= __devexit_p(serial_txx9_remove),
11750970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto#ifdef CONFIG_PM
11760970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	.suspend	= serial_txx9_suspend,
11770970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	.resume		= serial_txx9_resume,
11780970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto#endif
11790970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	.driver		= {
11800970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		.name	= "serial_txx9",
11810970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		.owner	= THIS_MODULE,
11820970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	},
11830970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto};
11840970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto
11850970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto#ifdef ENABLE_SERIAL_TXX9_PCI
11860970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto/*
11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Probe one serial board.  Unfortunately, there is no rhyme nor reason
11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to the arrangement of serial ports on a PCI card.
11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __devinit
11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspciserial_txx9_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct uart_port port;
11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int line;
11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int rc;
11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rc = pci_enable_device(dev);
11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rc)
11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return rc;
12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(&port, 0, sizeof(port));
12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	port.ops = &serial_txx9_pops;
12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	port.flags |= UPF_TXX9_HAVE_CTS_LINE;
12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	port.uartclk = 66670000;
12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	port.irq = dev->irq;
12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	port.iotype = UPIO_PORT;
12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	port.iobase = pci_resource_start(dev, 1);
1208f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle	port.dev = &dev->dev;
1209f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle	line = serial_txx9_register_port(&port);
12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (line < 0) {
12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), line);
12120970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		pci_disable_device(dev);
12130970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		return line;
12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12150970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	pci_set_drvdata(dev, &serial_txx9_ports[line]);
12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __devexit pciserial_txx9_remove_one(struct pci_dev *dev)
12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12220970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	struct uart_txx9_port *up = pci_get_drvdata(dev);
12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_set_drvdata(dev, NULL);
12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12260970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	if (up) {
12270970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		serial_txx9_unregister_port(up->port.line);
12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_disable_device(dev);
12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1232138c5d258cf06c278f5d7fe0a806e50fe413a08fAtsushi Nemoto#ifdef CONFIG_PM
12330370affeec3e751412e917aab931d8ba52680578Pavel Machekstatic int pciserial_txx9_suspend_one(struct pci_dev *dev, pm_message_t state)
12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12350970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	struct uart_txx9_port *up = pci_get_drvdata(dev);
12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12370970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	if (up)
12380970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		uart_suspend_port(&serial_txx9_reg, &up->port);
1239f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle	pci_save_state(dev);
1240f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle	pci_set_power_state(dev, pci_choose_state(dev, state));
12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pciserial_txx9_resume_one(struct pci_dev *dev)
12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12460970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	struct uart_txx9_port *up = pci_get_drvdata(dev);
12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1248f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle	pci_set_power_state(dev, PCI_D0);
1249f5ee56cc184e0944ebc9ff1691985219959596f6Ralf Baechle	pci_restore_state(dev);
12500970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	if (up)
12510970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		uart_resume_port(&serial_txx9_reg, &up->port);
12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1254138c5d258cf06c278f5d7fe0a806e50fe413a08fAtsushi Nemoto#endif
12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1256138c5d258cf06c278f5d7fe0a806e50fe413a08fAtsushi Nemotostatic const struct pci_device_id serial_txx9_pci_tbl[] = {
1257138c5d258cf06c278f5d7fe0a806e50fe413a08fAtsushi Nemoto	{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC86C001_MISC) },
12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 0, }
12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_driver serial_txx9_pci_driver = {
12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name		= "serial_txx9",
12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.probe		= pciserial_txx9_init_one,
12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.remove		= __devexit_p(pciserial_txx9_remove_one),
1265138c5d258cf06c278f5d7fe0a806e50fe413a08fAtsushi Nemoto#ifdef CONFIG_PM
12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.suspend	= pciserial_txx9_suspend_one,
12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.resume		= pciserial_txx9_resume_one,
1268138c5d258cf06c278f5d7fe0a806e50fe413a08fAtsushi Nemoto#endif
12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.id_table	= serial_txx9_pci_tbl,
12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DEVICE_TABLE(pci, serial_txx9_pci_tbl);
12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* ENABLE_SERIAL_TXX9_PCI */
12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12750970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemotostatic struct platform_device *serial_txx9_plat_devs;
12760970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto
12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init serial_txx9_init(void)
12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret;
12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 	printk(KERN_INFO "%s version %s\n", serial_name, serial_version);
12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ret = uart_register_driver(&serial_txx9_reg);
12840970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	if (ret)
12850970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		goto out;
12860970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto
12870970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	serial_txx9_plat_devs = platform_device_alloc("serial_txx9", -1);
12880970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	if (!serial_txx9_plat_devs) {
12890970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		ret = -ENOMEM;
12900970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		goto unreg_uart_drv;
12910970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	}
12920970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto
12930970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	ret = platform_device_add(serial_txx9_plat_devs);
12940970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	if (ret)
12950970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		goto put_dev;
12960970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto
12970970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	serial_txx9_register_ports(&serial_txx9_reg,
12980970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto				   &serial_txx9_plat_devs->dev);
12990970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto
13000970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	ret = platform_driver_register(&serial_txx9_plat_driver);
13010970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	if (ret)
13020970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		goto del_dev;
13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef ENABLE_SERIAL_TXX9_PCI
13050970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	ret = pci_register_driver(&serial_txx9_pci_driver);
13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
13070970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	if (ret == 0)
13080970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto		goto out;
13090970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto
13100970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto del_dev:
13110970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	platform_device_del(serial_txx9_plat_devs);
13120970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto put_dev:
13130970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	platform_device_put(serial_txx9_plat_devs);
13140970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto unreg_uart_drv:
13150970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	uart_unregister_driver(&serial_txx9_reg);
13160970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto out:
13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit serial_txx9_exit(void)
13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef ENABLE_SERIAL_TXX9_PCI
13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_unregister_driver(&serial_txx9_pci_driver);
13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
13270970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	platform_driver_unregister(&serial_txx9_plat_driver);
13280970769aceb9bccf038f5dba72379f68431f94dbAtsushi Nemoto	platform_device_unregister(serial_txx9_plat_devs);
132983485f826bea154a0ab41e9b8689105531dd7cb2Atsushi Nemoto	for (i = 0; i < UART_NR; i++) {
133083485f826bea154a0ab41e9b8689105531dd7cb2Atsushi Nemoto		struct uart_txx9_port *up = &serial_txx9_ports[i];
133183485f826bea154a0ab41e9b8689105531dd7cb2Atsushi Nemoto		if (up->port.iobase || up->port.mapbase)
133283485f826bea154a0ab41e9b8689105531dd7cb2Atsushi Nemoto			uart_remove_one_port(&serial_txx9_reg, &up->port);
133383485f826bea154a0ab41e9b8689105531dd7cb2Atsushi Nemoto	}
13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uart_unregister_driver(&serial_txx9_reg);
13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(serial_txx9_init);
13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(serial_txx9_exit);
13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("TX39/49 serial driver");
13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_ALIAS_CHARDEV_MAJOR(TXX9_TTY_MAJOR);
1345