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