Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Driver for the 98626/98644/internal serial interface on hp300/hp400
0004  * (based on the National Semiconductor INS8250/NS16550AF/WD16C552 UARTs)
0005  *
0006  * Ported from 2.2 and modified to use the normal 8250 driver
0007  * by Kars de Jong <jongk@linux-m68k.org>, May 2004.
0008  */
0009 #include <linux/module.h>
0010 #include <linux/init.h>
0011 #include <linux/string.h>
0012 #include <linux/kernel.h>
0013 #include <linux/serial.h>
0014 #include <linux/serial_8250.h>
0015 #include <linux/delay.h>
0016 #include <linux/dio.h>
0017 #include <linux/console.h>
0018 #include <linux/slab.h>
0019 #include <asm/io.h>
0020 
0021 #include "8250.h"
0022 
0023 #if !defined(CONFIG_HPDCA) && !defined(CONFIG_HPAPCI) && !defined(CONFIG_COMPILE_TEST)
0024 #warning CONFIG_SERIAL_8250 defined but neither CONFIG_HPDCA nor CONFIG_HPAPCI defined, are you sure?
0025 #endif
0026 
0027 #ifdef CONFIG_HPAPCI
0028 struct hp300_port {
0029     struct hp300_port *next;    /* next port */
0030     int line;           /* line (tty) number */
0031 };
0032 
0033 static struct hp300_port *hp300_ports;
0034 #endif
0035 
0036 #ifdef CONFIG_HPDCA
0037 
0038 static int hpdca_init_one(struct dio_dev *d,
0039                     const struct dio_device_id *ent);
0040 static void hpdca_remove_one(struct dio_dev *d);
0041 
0042 static struct dio_device_id hpdca_dio_tbl[] = {
0043     { DIO_ID_DCA0 },
0044     { DIO_ID_DCA0REM },
0045     { DIO_ID_DCA1 },
0046     { DIO_ID_DCA1REM },
0047     { 0 }
0048 };
0049 
0050 static struct dio_driver hpdca_driver = {
0051     .name      = "hpdca",
0052     .id_table  = hpdca_dio_tbl,
0053     .probe     = hpdca_init_one,
0054     .remove    = hpdca_remove_one,
0055 };
0056 
0057 #endif
0058 
0059 static unsigned int num_ports;
0060 
0061 extern int hp300_uart_scode;
0062 
0063 /* Offset to UART registers from base of DCA */
0064 #define UART_OFFSET 17
0065 
0066 #define DCA_ID      0x01    /* ID (read), reset (write) */
0067 #define DCA_IC      0x03    /* Interrupt control        */
0068 
0069 /* Interrupt control */
0070 #define DCA_IC_IE   0x80    /* Master interrupt enable  */
0071 
0072 #define HPDCA_BAUD_BASE 153600
0073 
0074 /* Base address of the Frodo part */
0075 #define FRODO_BASE  (0x41c000)
0076 
0077 /*
0078  * Where we find the 8250-like APCI ports, and how far apart they are.
0079  */
0080 #define FRODO_APCIBASE      0x0
0081 #define FRODO_APCISPACE     0x20
0082 #define FRODO_APCI_OFFSET(x)    (FRODO_APCIBASE + ((x) * FRODO_APCISPACE))
0083 
0084 #define HPAPCI_BAUD_BASE 500400
0085 
0086 #ifdef CONFIG_SERIAL_8250_CONSOLE
0087 /*
0088  * Parse the bootinfo to find descriptions for headless console and
0089  * debug serial ports and register them with the 8250 driver.
0090  */
0091 int __init hp300_setup_serial_console(void)
0092 {
0093     int scode;
0094     struct uart_port port;
0095 
0096     memset(&port, 0, sizeof(port));
0097 
0098     if (hp300_uart_scode < 0 || hp300_uart_scode > DIO_SCMAX)
0099         return 0;
0100 
0101     if (DIO_SCINHOLE(hp300_uart_scode))
0102         return 0;
0103 
0104     scode = hp300_uart_scode;
0105 
0106     /* Memory mapped I/O */
0107     port.iotype = UPIO_MEM;
0108     port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF;
0109     port.type = PORT_UNKNOWN;
0110 
0111     /* Check for APCI console */
0112     if (scode == 256) {
0113 #ifdef CONFIG_HPAPCI
0114         pr_info("Serial console is HP APCI 1\n");
0115 
0116         port.uartclk = HPAPCI_BAUD_BASE * 16;
0117         port.mapbase = (FRODO_BASE + FRODO_APCI_OFFSET(1));
0118         port.membase = (char *)(port.mapbase + DIO_VIRADDRBASE);
0119         port.regshift = 2;
0120         add_preferred_console("ttyS", port.line, "9600n8");
0121 #else
0122         pr_warn("Serial console is APCI but support is disabled (CONFIG_HPAPCI)!\n");
0123         return 0;
0124 #endif
0125     } else {
0126 #ifdef CONFIG_HPDCA
0127         unsigned long pa = dio_scodetophysaddr(scode);
0128         if (!pa)
0129             return 0;
0130 
0131         pr_info("Serial console is HP DCA at select code %d\n", scode);
0132 
0133         port.uartclk = HPDCA_BAUD_BASE * 16;
0134         port.mapbase = (pa + UART_OFFSET);
0135         port.membase = (char *)(port.mapbase + DIO_VIRADDRBASE);
0136         port.regshift = 1;
0137         port.irq = DIO_IPL(pa + DIO_VIRADDRBASE);
0138 
0139         /* Enable board-interrupts */
0140         out_8(pa + DIO_VIRADDRBASE + DCA_IC, DCA_IC_IE);
0141 
0142         if (DIO_ID(pa + DIO_VIRADDRBASE) & 0x80)
0143             add_preferred_console("ttyS", port.line, "9600n8");
0144 #else
0145         pr_warn("Serial console is DCA but support is disabled (CONFIG_HPDCA)!\n");
0146         return 0;
0147 #endif
0148     }
0149 
0150     if (early_serial_setup(&port) < 0)
0151         pr_warn("%s: early_serial_setup() failed.\n", __func__);
0152     return 0;
0153 }
0154 #endif /* CONFIG_SERIAL_8250_CONSOLE */
0155 
0156 #ifdef CONFIG_HPDCA
0157 static int hpdca_init_one(struct dio_dev *d,
0158                 const struct dio_device_id *ent)
0159 {
0160     struct uart_8250_port uart;
0161     int line;
0162 
0163 #ifdef CONFIG_SERIAL_8250_CONSOLE
0164     if (hp300_uart_scode == d->scode) {
0165         /* Already got it. */
0166         return 0;
0167     }
0168 #endif
0169     memset(&uart, 0, sizeof(uart));
0170 
0171     /* Memory mapped I/O */
0172     uart.port.iotype = UPIO_MEM;
0173     uart.port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF;
0174     uart.port.irq = d->ipl;
0175     uart.port.uartclk = HPDCA_BAUD_BASE * 16;
0176     uart.port.mapbase = (d->resource.start + UART_OFFSET);
0177     uart.port.membase = (char *)(uart.port.mapbase + DIO_VIRADDRBASE);
0178     uart.port.regshift = 1;
0179     uart.port.dev = &d->dev;
0180     line = serial8250_register_8250_port(&uart);
0181 
0182     if (line < 0) {
0183         dev_notice(&d->dev,
0184               "8250_hp300: register_serial() DCA scode %d irq %d failed\n",
0185               d->scode, uart.port.irq);
0186         return -ENOMEM;
0187     }
0188 
0189     /* Enable board-interrupts */
0190     out_8(d->resource.start + DIO_VIRADDRBASE + DCA_IC, DCA_IC_IE);
0191     dio_set_drvdata(d, (void *)line);
0192 
0193     /* Reset the DCA */
0194     out_8(d->resource.start + DIO_VIRADDRBASE + DCA_ID, 0xff);
0195     udelay(100);
0196 
0197     num_ports++;
0198 
0199     return 0;
0200 }
0201 #endif
0202 
0203 static int __init hp300_8250_init(void)
0204 {
0205     static int called;
0206 #ifdef CONFIG_HPAPCI
0207     int line;
0208     unsigned long base;
0209     struct uart_8250_port uart;
0210     struct hp300_port *port;
0211     int i;
0212 #endif
0213     if (called)
0214         return -ENODEV;
0215     called = 1;
0216 
0217     if (!MACH_IS_HP300)
0218         return -ENODEV;
0219 
0220 #ifdef CONFIG_HPDCA
0221     dio_register_driver(&hpdca_driver);
0222 #endif
0223 #ifdef CONFIG_HPAPCI
0224     if (hp300_model < HP_400) {
0225         if (!num_ports)
0226             return -ENODEV;
0227         return 0;
0228     }
0229     /* These models have the Frodo chip.
0230      * Port 0 is reserved for the Apollo Domain keyboard.
0231      * Port 1 is either the console or the DCA.
0232      */
0233     for (i = 1; i < 4; i++) {
0234         /* Port 1 is the console on a 425e, on other machines it's
0235          * mapped to DCA.
0236          */
0237 #ifdef CONFIG_SERIAL_8250_CONSOLE
0238         if (i == 1)
0239             continue;
0240 #endif
0241 
0242         /* Create new serial device */
0243         port = kmalloc(sizeof(struct hp300_port), GFP_KERNEL);
0244         if (!port)
0245             return -ENOMEM;
0246 
0247         memset(&uart, 0, sizeof(uart));
0248 
0249         base = (FRODO_BASE + FRODO_APCI_OFFSET(i));
0250 
0251         /* Memory mapped I/O */
0252         uart.port.iotype = UPIO_MEM;
0253         uart.port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ
0254                 | UPF_BOOT_AUTOCONF;
0255         /* XXX - no interrupt support yet */
0256         uart.port.irq = 0;
0257         uart.port.uartclk = HPAPCI_BAUD_BASE * 16;
0258         uart.port.mapbase = base;
0259         uart.port.membase = (char *)(base + DIO_VIRADDRBASE);
0260         uart.port.regshift = 2;
0261 
0262         line = serial8250_register_8250_port(&uart);
0263 
0264         if (line < 0) {
0265             dev_notice(uart.port.dev,
0266                    "8250_hp300: register_serial() APCI %d irq %d failed\n",
0267                    i, uart.port.irq);
0268             kfree(port);
0269             continue;
0270         }
0271 
0272         port->line = line;
0273         port->next = hp300_ports;
0274         hp300_ports = port;
0275 
0276         num_ports++;
0277     }
0278 #endif
0279 
0280     /* Any boards found? */
0281     if (!num_ports)
0282         return -ENODEV;
0283 
0284     return 0;
0285 }
0286 
0287 #ifdef CONFIG_HPDCA
0288 static void hpdca_remove_one(struct dio_dev *d)
0289 {
0290     int line;
0291 
0292     line = (int) dio_get_drvdata(d);
0293     if (d->resource.start) {
0294         /* Disable board-interrupts */
0295         out_8(d->resource.start + DIO_VIRADDRBASE + DCA_IC, 0);
0296     }
0297     serial8250_unregister_port(line);
0298 }
0299 #endif
0300 
0301 static void __exit hp300_8250_exit(void)
0302 {
0303 #ifdef CONFIG_HPAPCI
0304     struct hp300_port *port, *to_free;
0305 
0306     for (port = hp300_ports; port; ) {
0307         serial8250_unregister_port(port->line);
0308         to_free = port;
0309         port = port->next;
0310         kfree(to_free);
0311     }
0312 
0313     hp300_ports = NULL;
0314 #endif
0315 #ifdef CONFIG_HPDCA
0316     dio_unregister_driver(&hpdca_driver);
0317 #endif
0318 }
0319 
0320 module_init(hp300_8250_init);
0321 module_exit(hp300_8250_exit);
0322 MODULE_DESCRIPTION("HP DCA/APCI serial driver");
0323 MODULE_AUTHOR("Kars de Jong <jongk@linux-m68k.org>");
0324 MODULE_LICENSE("GPL");