11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Serial Device Initialisation for Lasi/Asp/Wax/Dino 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (c) Copyright Matthew Wilcox <willy@debian.org> 2001-2002 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License as published by 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation; either version 2 of the License, or 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (at your option) any later version. 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/serial_core.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/signal.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/hardware.h> 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/parisc-device.h> 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h> 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "8250.h" 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 278b4a483be544569cd61156be86c0becf21a02e8bAlan Coxstatic int __init serial_init_chip(struct parisc_device *dev) 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct uart_port port; 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long address; 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev->irq) { 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We find some unattached serial ports by walking native 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * busses. These should be silently ignored. Otherwise, 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * what we have here is a missing parent device, so tell 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the user what they're missing. 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 398b4a483be544569cd61156be86c0becf21a02e8bAlan Cox if (parisc_parent(dev)->id.hw_type != HPHW_IOA) 408b4a483be544569cd61156be86c0becf21a02e8bAlan Cox printk(KERN_INFO 418e8e8267f0a08c2415d5f51bc9a9fde6d5400619Alexander Beregalov "Serial: device 0x%llx not configured.\n" 4253f01bba49938f115237fe43a261c31ac13ae5c6Matthew Wilcox "Enable support for Wax, Lasi, Asp or Dino.\n", 438e8e8267f0a08c2415d5f51bc9a9fde6d5400619Alexander Beregalov (unsigned long long)dev->hpa.start); 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4753f01bba49938f115237fe43a261c31ac13ae5c6Matthew Wilcox address = dev->hpa.start; 488b4a483be544569cd61156be86c0becf21a02e8bAlan Cox if (dev->id.sversion != 0x8d) 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds address += 0x800; 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 515076c15862644edb91d2e3436b2fa3e07b28385dHelge Deller memset(&port, 0, sizeof(port)); 525076c15862644edb91d2e3436b2fa3e07b28385dHelge Deller port.iotype = UPIO_MEM; 53136ce40e9f1f24ca1dbf7714c669a7bca56440eaMatthew Wilcox /* 7.272727MHz on Lasi. Assumed the same for Dino, Wax and Timi. */ 54136ce40e9f1f24ca1dbf7714c669a7bca56440eaMatthew Wilcox port.uartclk = 7272727; 555076c15862644edb91d2e3436b2fa3e07b28385dHelge Deller port.mapbase = address; 565076c15862644edb91d2e3436b2fa3e07b28385dHelge Deller port.membase = ioremap_nocache(address, 16); 575076c15862644edb91d2e3436b2fa3e07b28385dHelge Deller port.irq = dev->irq; 585076c15862644edb91d2e3436b2fa3e07b28385dHelge Deller port.flags = UPF_BOOT_AUTOCONF; 595076c15862644edb91d2e3436b2fa3e07b28385dHelge Deller port.dev = &dev->dev; 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = serial8250_register_port(&port); 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err < 0) { 638b4a483be544569cd61156be86c0becf21a02e8bAlan Cox printk(KERN_WARNING 648b4a483be544569cd61156be86c0becf21a02e8bAlan Cox "serial8250_register_port returned error %d\n", err); 65d9964d5c9067fe58fecb7ba10b2de4771d2005d9Amol Lad iounmap(port.membase); 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 688b4a483be544569cd61156be86c0becf21a02e8bAlan Cox 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct parisc_device_id serial_tbl[] = { 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00075 }, 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008c }, 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008d }, 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0 } 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Hack. Some machines have SERIAL_0 attached to Lasi and SERIAL_1 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * attached to Dino. Unfortunately, Dino appears before Lasi in the device 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * tree. To ensure that ttyS0 == SERIAL_0, we register two drivers; one 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * which only knows about Lasi and then a second which will find all the 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * other serial ports. HPUX ignores this problem. 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct parisc_device_id lasi_tbl[] = { 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03B, 0x0008C }, /* C1xx/C1xxL */ 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03C, 0x0008C }, /* B132L */ 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03D, 0x0008C }, /* B160L */ 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03E, 0x0008C }, /* B132L+ */ 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03F, 0x0008C }, /* B180L+ */ 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { HPHW_FIO, HVERSION_REV_ANY_ID, 0x046, 0x0008C }, /* Rocky2 120 */ 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { HPHW_FIO, HVERSION_REV_ANY_ID, 0x047, 0x0008C }, /* Rocky2 150 */ 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { HPHW_FIO, HVERSION_REV_ANY_ID, 0x04E, 0x0008C }, /* Kiji L2 132 */ 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { HPHW_FIO, HVERSION_REV_ANY_ID, 0x056, 0x0008C }, /* Raven+ */ 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0 } 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DEVICE_TABLE(parisc, serial_tbl); 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct parisc_driver lasi_driver = { 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "serial_1", 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id_table = lasi_tbl, 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = serial_init_chip, 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct parisc_driver serial_driver = { 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "serial", 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id_table = serial_tbl, 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = serial_init_chip, 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1139f561dfceaafaae73ecfc81b1156dde3056e1ec9Adrian Bunkstatic int __init probe_serial_gsc(void) 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds register_parisc_driver(&lasi_driver); 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds register_parisc_driver(&serial_driver); 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(probe_serial_gsc); 121920519c1c31ca46ef6caab1a4be102ed0dfb5fbcAdrian Bunk 122920519c1c31ca46ef6caab1a4be102ed0dfb5fbcAdrian BunkMODULE_LICENSE("GPL"); 123