mirror of https://gitee.com/openkylin/linux.git
Merge branch 'tty-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty into for-next
Conflicts: arch/arm64/kernel/early_printk.c
This commit is contained in:
commit
6e87b7030e
|
@ -0,0 +1,33 @@
|
|||
* NXP SC16IS7xx advanced Universal Asynchronous Receiver-Transmitter (UART)
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be one of the following:
|
||||
- "nxp,sc16is740" for NXP SC16IS740,
|
||||
- "nxp,sc16is741" for NXP SC16IS741,
|
||||
- "nxp,sc16is750" for NXP SC16IS750,
|
||||
- "nxp,sc16is752" for NXP SC16IS752,
|
||||
- "nxp,sc16is760" for NXP SC16IS760,
|
||||
- "nxp,sc16is762" for NXP SC16IS762.
|
||||
- reg: I2C address of the SC16IS7xx device.
|
||||
- interrupt-parent: The phandle for the interrupt controller that
|
||||
services interrupts for this IC.
|
||||
- interrupts: Should contain the UART interrupt
|
||||
- clocks: Reference to the IC source clock.
|
||||
|
||||
Optional properties:
|
||||
- gpio-controller: Marks the device node as a GPIO controller.
|
||||
- #gpio-cells: Should be two. The first cell is the GPIO number and
|
||||
the second cell is used to specify the GPIO polarity:
|
||||
0 = active high,
|
||||
1 = active low.
|
||||
|
||||
Example:
|
||||
sc16is750: sc16is750@51 {
|
||||
compatible = "nxp,sc16is750";
|
||||
reg = <0x51>;
|
||||
clocks = <&clk20m>;
|
||||
interrupt-parent = <&gpio3>;
|
||||
interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
|
@ -883,6 +883,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
|||
which are not unmapped.
|
||||
|
||||
earlycon= [KNL] Output early console device and options.
|
||||
|
||||
uart[8250],io,<addr>[,options]
|
||||
uart[8250],mmio,<addr>[,options]
|
||||
uart[8250],mmio32,<addr>[,options]
|
||||
|
@ -892,6 +893,14 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
|||
(mmio) or 32-bit (mmio32).
|
||||
The options are the same as for ttyS, above.
|
||||
|
||||
pl011,<addr>
|
||||
Start an early, polled-mode console on a pl011 serial
|
||||
port at the specified address. The pl011 serial port
|
||||
must already be setup and configured. Options are not
|
||||
yet supported.
|
||||
|
||||
smh Use ARM semihosting calls for early console.
|
||||
|
||||
earlyprintk= [X86,SH,BLACKFIN,ARM]
|
||||
earlyprintk=vga
|
||||
earlyprintk=efi
|
||||
|
|
|
@ -112,6 +112,9 @@ config IOMMU_HELPER
|
|||
config KERNEL_MODE_NEON
|
||||
def_bool y
|
||||
|
||||
config FIX_EARLYCON_MEM
|
||||
def_bool y
|
||||
|
||||
source "init/Kconfig"
|
||||
|
||||
source "kernel/Kconfig.freezer"
|
||||
|
|
|
@ -20,15 +20,6 @@ config STRICT_DEVMEM
|
|||
|
||||
If in doubt, say Y.
|
||||
|
||||
config EARLY_PRINTK
|
||||
bool "Early printk support"
|
||||
default y
|
||||
help
|
||||
Say Y here if you want to have an early console using the
|
||||
earlyprintk=<name>[,<addr>][,<options>] kernel parameter. It
|
||||
is assumed that the early console device has been initialised
|
||||
by the boot loader prior to starting the Linux kernel.
|
||||
|
||||
config PID_IN_CONTEXTIDR
|
||||
bool "Write the current PID to the CONTEXTIDR register"
|
||||
help
|
||||
|
|
|
@ -18,7 +18,6 @@ arm64-obj-$(CONFIG_SMP) += smp.o smp_spin_table.o topology.o
|
|||
arm64-obj-$(CONFIG_PERF_EVENTS) += perf_regs.o
|
||||
arm64-obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o
|
||||
arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
|
||||
arm64-obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
||||
arm64-obj-$(CONFIG_ARM64_CPU_SUSPEND) += sleep.o suspend.o
|
||||
arm64-obj-$(CONFIG_JUMP_LABEL) += jump_label.o
|
||||
arm64-obj-$(CONFIG_KGDB) += kgdb.o
|
||||
|
|
|
@ -1,156 +0,0 @@
|
|||
/*
|
||||
* Earlyprintk support.
|
||||
*
|
||||
* Copyright (C) 2012 ARM Ltd.
|
||||
* Author: Catalin Marinas <catalin.marinas@arm.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <linux/amba/serial.h>
|
||||
#include <linux/serial_reg.h>
|
||||
|
||||
#include <asm/fixmap.h>
|
||||
|
||||
static void __iomem *early_base;
|
||||
static void (*printch)(char ch);
|
||||
|
||||
/*
|
||||
* PL011 single character TX.
|
||||
*/
|
||||
static void pl011_printch(char ch)
|
||||
{
|
||||
while (readl_relaxed(early_base + UART01x_FR) & UART01x_FR_TXFF)
|
||||
;
|
||||
writeb_relaxed(ch, early_base + UART01x_DR);
|
||||
while (readl_relaxed(early_base + UART01x_FR) & UART01x_FR_BUSY)
|
||||
;
|
||||
}
|
||||
|
||||
/*
|
||||
* Semihosting-based debug console
|
||||
*/
|
||||
static void smh_printch(char ch)
|
||||
{
|
||||
asm volatile("mov x1, %0\n"
|
||||
"mov x0, #3\n"
|
||||
"hlt 0xf000\n"
|
||||
: : "r" (&ch) : "x0", "x1", "memory");
|
||||
}
|
||||
|
||||
/*
|
||||
* 8250/16550 (8-bit aligned registers) single character TX.
|
||||
*/
|
||||
static void uart8250_8bit_printch(char ch)
|
||||
{
|
||||
while (!(readb_relaxed(early_base + UART_LSR) & UART_LSR_THRE))
|
||||
;
|
||||
writeb_relaxed(ch, early_base + UART_TX);
|
||||
}
|
||||
|
||||
/*
|
||||
* 8250/16550 (32-bit aligned registers) single character TX.
|
||||
*/
|
||||
static void uart8250_32bit_printch(char ch)
|
||||
{
|
||||
while (!(readl_relaxed(early_base + (UART_LSR << 2)) & UART_LSR_THRE))
|
||||
;
|
||||
writel_relaxed(ch, early_base + (UART_TX << 2));
|
||||
}
|
||||
|
||||
struct earlycon_match {
|
||||
const char *name;
|
||||
void (*printch)(char ch);
|
||||
};
|
||||
|
||||
static const struct earlycon_match earlycon_match[] __initconst = {
|
||||
{ .name = "pl011", .printch = pl011_printch, },
|
||||
{ .name = "smh", .printch = smh_printch, },
|
||||
{ .name = "uart8250-8bit", .printch = uart8250_8bit_printch, },
|
||||
{ .name = "uart8250-32bit", .printch = uart8250_32bit_printch, },
|
||||
{}
|
||||
};
|
||||
|
||||
static void early_write(struct console *con, const char *s, unsigned n)
|
||||
{
|
||||
while (n-- > 0) {
|
||||
if (*s == '\n')
|
||||
printch('\r');
|
||||
printch(*s);
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
static struct console early_console_dev = {
|
||||
.name = "earlycon",
|
||||
.write = early_write,
|
||||
.flags = CON_PRINTBUFFER | CON_BOOT,
|
||||
.index = -1,
|
||||
};
|
||||
|
||||
/*
|
||||
* Parse earlyprintk=... parameter in the format:
|
||||
*
|
||||
* <name>[,<addr>][,<options>]
|
||||
*
|
||||
* and register the early console. It is assumed that the UART has been
|
||||
* initialised by the bootloader already.
|
||||
*/
|
||||
static int __init setup_early_printk(char *buf)
|
||||
{
|
||||
const struct earlycon_match *match = earlycon_match;
|
||||
phys_addr_t paddr = 0;
|
||||
|
||||
if (!buf) {
|
||||
pr_warning("No earlyprintk arguments passed.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (match->name) {
|
||||
size_t len = strlen(match->name);
|
||||
if (!strncmp(buf, match->name, len)) {
|
||||
buf += len;
|
||||
break;
|
||||
}
|
||||
match++;
|
||||
}
|
||||
if (!match->name) {
|
||||
pr_warning("Unknown earlyprintk arguments: %s\n", buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* I/O address */
|
||||
if (!strncmp(buf, ",0x", 3)) {
|
||||
char *e;
|
||||
paddr = simple_strtoul(buf + 1, &e, 16);
|
||||
buf = e;
|
||||
}
|
||||
/* no options parsing yet */
|
||||
|
||||
if (paddr)
|
||||
early_base = (void __iomem *)set_fixmap_offset_io(FIX_EARLYCON_MEM_BASE, paddr);
|
||||
|
||||
printch = match->printch;
|
||||
early_console = &early_console_dev;
|
||||
register_console(&early_console_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
early_param("earlyprintk", setup_early_printk);
|
|
@ -261,6 +261,9 @@ config ARCH_HWEIGHT_CFLAGS
|
|||
config ARCH_SUPPORTS_UPROBES
|
||||
def_bool y
|
||||
|
||||
config FIX_EARLYCON_MEM
|
||||
def_bool y
|
||||
|
||||
source "init/Kconfig"
|
||||
source "kernel/Kconfig.freezer"
|
||||
|
||||
|
|
|
@ -118,10 +118,6 @@ static inline struct sk_buff *hci_uart_dequeue(struct hci_uart *hu)
|
|||
|
||||
int hci_uart_tx_wakeup(struct hci_uart *hu)
|
||||
{
|
||||
struct tty_struct *tty = hu->tty;
|
||||
struct hci_dev *hdev = hu->hdev;
|
||||
struct sk_buff *skb;
|
||||
|
||||
if (test_and_set_bit(HCI_UART_SENDING, &hu->tx_state)) {
|
||||
set_bit(HCI_UART_TX_WAKEUP, &hu->tx_state);
|
||||
return 0;
|
||||
|
@ -129,6 +125,22 @@ int hci_uart_tx_wakeup(struct hci_uart *hu)
|
|||
|
||||
BT_DBG("");
|
||||
|
||||
schedule_work(&hu->write_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hci_uart_write_work(struct work_struct *work)
|
||||
{
|
||||
struct hci_uart *hu = container_of(work, struct hci_uart, write_work);
|
||||
struct tty_struct *tty = hu->tty;
|
||||
struct hci_dev *hdev = hu->hdev;
|
||||
struct sk_buff *skb;
|
||||
|
||||
/* REVISIT: should we cope with bad skbs or ->write() returning
|
||||
* and error value ?
|
||||
*/
|
||||
|
||||
restart:
|
||||
clear_bit(HCI_UART_TX_WAKEUP, &hu->tx_state);
|
||||
|
||||
|
@ -153,7 +165,6 @@ int hci_uart_tx_wakeup(struct hci_uart *hu)
|
|||
goto restart;
|
||||
|
||||
clear_bit(HCI_UART_SENDING, &hu->tx_state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hci_uart_init_work(struct work_struct *work)
|
||||
|
@ -282,6 +293,7 @@ static int hci_uart_tty_open(struct tty_struct *tty)
|
|||
tty->receive_room = 65536;
|
||||
|
||||
INIT_WORK(&hu->init_ready, hci_uart_init_work);
|
||||
INIT_WORK(&hu->write_work, hci_uart_write_work);
|
||||
|
||||
spin_lock_init(&hu->rx_lock);
|
||||
|
||||
|
@ -319,6 +331,8 @@ static void hci_uart_tty_close(struct tty_struct *tty)
|
|||
if (hdev)
|
||||
hci_uart_close(hdev);
|
||||
|
||||
cancel_work_sync(&hu->write_work);
|
||||
|
||||
if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) {
|
||||
if (hdev) {
|
||||
if (test_bit(HCI_UART_REGISTERED, &hu->flags))
|
||||
|
|
|
@ -68,6 +68,7 @@ struct hci_uart {
|
|||
unsigned long hdev_flags;
|
||||
|
||||
struct work_struct init_ready;
|
||||
struct work_struct write_work;
|
||||
|
||||
struct hci_uart_proto *proto;
|
||||
void *priv;
|
||||
|
|
|
@ -1926,13 +1926,8 @@ static void serial8250_put_poll_char(struct uart_port *port,
|
|||
wait_for_xmitr(up, BOTH_EMPTY);
|
||||
/*
|
||||
* Send the character out.
|
||||
* If a LF, also do CR...
|
||||
*/
|
||||
serial_port_out(port, UART_TX, c);
|
||||
if (c == 10) {
|
||||
wait_for_xmitr(up, BOTH_EMPTY);
|
||||
serial_port_out(port, UART_TX, 13);
|
||||
}
|
||||
|
||||
/*
|
||||
* Finally, wait for transmitter to become empty
|
||||
|
|
|
@ -62,6 +62,70 @@ struct dw8250_data {
|
|||
struct uart_8250_dma dma;
|
||||
};
|
||||
|
||||
struct dw8250_acpi_desc {
|
||||
void (*set_termios)(struct uart_port *p, struct ktermios *termios,
|
||||
struct ktermios *old);
|
||||
};
|
||||
|
||||
#define BYT_PRV_CLK 0x800
|
||||
#define BYT_PRV_CLK_EN (1 << 0)
|
||||
#define BYT_PRV_CLK_M_VAL_SHIFT 1
|
||||
#define BYT_PRV_CLK_N_VAL_SHIFT 16
|
||||
#define BYT_PRV_CLK_UPDATE (1 << 31)
|
||||
|
||||
static void byt_set_termios(struct uart_port *p, struct ktermios *termios,
|
||||
struct ktermios *old)
|
||||
{
|
||||
unsigned int baud = tty_termios_baud_rate(termios);
|
||||
unsigned int m, n;
|
||||
u32 reg;
|
||||
|
||||
/*
|
||||
* For baud rates 0.5M, 1M, 1.5M, 2M, 2.5M, 3M, 3.5M and 4M the
|
||||
* dividers must be adjusted.
|
||||
*
|
||||
* uartclk = (m / n) * 100 MHz, where m <= n
|
||||
*/
|
||||
switch (baud) {
|
||||
case 500000:
|
||||
case 1000000:
|
||||
case 2000000:
|
||||
case 4000000:
|
||||
m = 64;
|
||||
n = 100;
|
||||
p->uartclk = 64000000;
|
||||
break;
|
||||
case 3500000:
|
||||
m = 56;
|
||||
n = 100;
|
||||
p->uartclk = 56000000;
|
||||
break;
|
||||
case 1500000:
|
||||
case 3000000:
|
||||
m = 48;
|
||||
n = 100;
|
||||
p->uartclk = 48000000;
|
||||
break;
|
||||
case 2500000:
|
||||
m = 40;
|
||||
n = 100;
|
||||
p->uartclk = 40000000;
|
||||
break;
|
||||
default:
|
||||
m = 2304;
|
||||
n = 3125;
|
||||
p->uartclk = 73728000;
|
||||
}
|
||||
|
||||
/* Reset the clock */
|
||||
reg = (m << BYT_PRV_CLK_M_VAL_SHIFT) | (n << BYT_PRV_CLK_N_VAL_SHIFT);
|
||||
writel(reg, p->membase + BYT_PRV_CLK);
|
||||
reg |= BYT_PRV_CLK_EN | BYT_PRV_CLK_UPDATE;
|
||||
writel(reg, p->membase + BYT_PRV_CLK);
|
||||
|
||||
serial8250_do_set_termios(p, termios, old);
|
||||
}
|
||||
|
||||
static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value)
|
||||
{
|
||||
struct dw8250_data *d = p->private_data;
|
||||
|
@ -278,6 +342,7 @@ static int dw8250_probe_acpi(struct uart_8250_port *up,
|
|||
{
|
||||
const struct acpi_device_id *id;
|
||||
struct uart_port *p = &up->port;
|
||||
struct dw8250_acpi_desc *acpi_desc;
|
||||
|
||||
dw8250_setup_port(up);
|
||||
|
||||
|
@ -290,14 +355,18 @@ static int dw8250_probe_acpi(struct uart_8250_port *up,
|
|||
p->serial_out = dw8250_serial_out32;
|
||||
p->regshift = 2;
|
||||
|
||||
if (!p->uartclk)
|
||||
p->uartclk = (unsigned int)id->driver_data;
|
||||
|
||||
up->dma = &data->dma;
|
||||
|
||||
up->dma->rxconf.src_maxburst = p->fifosize / 4;
|
||||
up->dma->txconf.dst_maxburst = p->fifosize / 4;
|
||||
|
||||
acpi_desc = (struct dw8250_acpi_desc *)id->driver_data;
|
||||
if (!acpi_desc)
|
||||
return 0;
|
||||
|
||||
if (acpi_desc->set_termios)
|
||||
p->set_termios = acpi_desc->set_termios;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -445,12 +514,16 @@ static const struct of_device_id dw8250_of_match[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(of, dw8250_of_match);
|
||||
|
||||
static struct dw8250_acpi_desc byt_8250_desc = {
|
||||
.set_termios = byt_set_termios,
|
||||
};
|
||||
|
||||
static const struct acpi_device_id dw8250_acpi_match[] = {
|
||||
{ "INT33C4", 0 },
|
||||
{ "INT33C5", 0 },
|
||||
{ "INT3434", 0 },
|
||||
{ "INT3435", 0 },
|
||||
{ "80860F0A", 0 },
|
||||
{ "80860F0A", (kernel_ulong_t)&byt_8250_desc},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match);
|
||||
|
|
|
@ -35,18 +35,8 @@
|
|||
#include <linux/serial_8250.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/serial.h>
|
||||
#ifdef CONFIG_FIX_EARLYCON_MEM
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/fixmap.h>
|
||||
#endif
|
||||
|
||||
struct early_serial8250_device {
|
||||
struct uart_port port;
|
||||
char options[16]; /* e.g., 115200n8 */
|
||||
unsigned int baud;
|
||||
};
|
||||
|
||||
static struct early_serial8250_device early_device;
|
||||
static struct earlycon_device *early_device;
|
||||
|
||||
unsigned int __weak __init serial8250_early_in(struct uart_port *port, int offset)
|
||||
{
|
||||
|
@ -100,7 +90,7 @@ static void __init serial_putc(struct uart_port *port, int c)
|
|||
static void __init early_serial8250_write(struct console *console,
|
||||
const char *s, unsigned int count)
|
||||
{
|
||||
struct uart_port *port = &early_device.port;
|
||||
struct uart_port *port = &early_device->port;
|
||||
unsigned int ier;
|
||||
|
||||
/* Save the IER and disable interrupts */
|
||||
|
@ -129,7 +119,7 @@ static unsigned int __init probe_baud(struct uart_port *port)
|
|||
return (port->uartclk / 16) / quot;
|
||||
}
|
||||
|
||||
static void __init init_port(struct early_serial8250_device *device)
|
||||
static void __init init_port(struct earlycon_device *device)
|
||||
{
|
||||
struct uart_port *port = &device->port;
|
||||
unsigned int divisor;
|
||||
|
@ -148,128 +138,42 @@ static void __init init_port(struct early_serial8250_device *device)
|
|||
serial8250_early_out(port, UART_LCR, c & ~UART_LCR_DLAB);
|
||||
}
|
||||
|
||||
static int __init parse_options(struct early_serial8250_device *device,
|
||||
char *options)
|
||||
static int __init early_serial8250_setup(struct earlycon_device *device,
|
||||
const char *options)
|
||||
{
|
||||
struct uart_port *port = &device->port;
|
||||
int mmio, mmio32, length;
|
||||
|
||||
if (!options)
|
||||
return -ENODEV;
|
||||
|
||||
port->uartclk = BASE_BAUD * 16;
|
||||
|
||||
mmio = !strncmp(options, "mmio,", 5);
|
||||
mmio32 = !strncmp(options, "mmio32,", 7);
|
||||
if (mmio || mmio32) {
|
||||
port->iotype = (mmio ? UPIO_MEM : UPIO_MEM32);
|
||||
port->mapbase = simple_strtoul(options + (mmio ? 5 : 7),
|
||||
&options, 0);
|
||||
if (mmio32)
|
||||
port->regshift = 2;
|
||||
#ifdef CONFIG_FIX_EARLYCON_MEM
|
||||
set_fixmap_nocache(FIX_EARLYCON_MEM_BASE,
|
||||
port->mapbase & PAGE_MASK);
|
||||
port->membase =
|
||||
(void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE);
|
||||
port->membase += port->mapbase & ~PAGE_MASK;
|
||||
#else
|
||||
port->membase = ioremap_nocache(port->mapbase, 64);
|
||||
if (!port->membase) {
|
||||
printk(KERN_ERR "%s: Couldn't ioremap 0x%llx\n",
|
||||
__func__,
|
||||
(unsigned long long) port->mapbase);
|
||||
return -ENOMEM;
|
||||
}
|
||||
#endif
|
||||
} else if (!strncmp(options, "io,", 3)) {
|
||||
port->iotype = UPIO_PORT;
|
||||
port->iobase = simple_strtoul(options + 3, &options, 0);
|
||||
mmio = 0;
|
||||
} else
|
||||
return -EINVAL;
|
||||
|
||||
options = strchr(options, ',');
|
||||
if (options) {
|
||||
options++;
|
||||
device->baud = simple_strtoul(options, NULL, 0);
|
||||
length = min(strcspn(options, " ") + 1,
|
||||
(size_t)(sizeof(device->options)));
|
||||
strlcpy(device->options, options, length);
|
||||
} else {
|
||||
device->baud = probe_baud(port);
|
||||
snprintf(device->options, sizeof(device->options), "%u",
|
||||
device->baud);
|
||||
}
|
||||
|
||||
if (mmio || mmio32)
|
||||
printk(KERN_INFO
|
||||
"Early serial console at MMIO%s 0x%llx (options '%s')\n",
|
||||
mmio32 ? "32" : "",
|
||||
(unsigned long long)port->mapbase,
|
||||
device->options);
|
||||
else
|
||||
printk(KERN_INFO
|
||||
"Early serial console at I/O port 0x%lx (options '%s')\n",
|
||||
port->iobase,
|
||||
device->options);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct console early_serial8250_console __initdata = {
|
||||
.name = "uart",
|
||||
.write = early_serial8250_write,
|
||||
.flags = CON_PRINTBUFFER | CON_BOOT,
|
||||
.index = -1,
|
||||
};
|
||||
|
||||
static int __init early_serial8250_setup(char *options)
|
||||
{
|
||||
struct early_serial8250_device *device = &early_device;
|
||||
int err;
|
||||
|
||||
if (device->port.membase || device->port.iobase)
|
||||
if (!(device->port.membase || device->port.iobase))
|
||||
return 0;
|
||||
|
||||
err = parse_options(device, options);
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (!device->baud)
|
||||
device->baud = probe_baud(&device->port);
|
||||
|
||||
init_port(device);
|
||||
|
||||
early_device = device;
|
||||
device->con->write = early_serial8250_write;
|
||||
return 0;
|
||||
}
|
||||
EARLYCON_DECLARE(uart8250, early_serial8250_setup);
|
||||
EARLYCON_DECLARE(uart, early_serial8250_setup);
|
||||
|
||||
int __init setup_early_serial8250_console(char *cmdline)
|
||||
{
|
||||
char *options;
|
||||
int err;
|
||||
char match[] = "uart8250";
|
||||
|
||||
options = strstr(cmdline, "uart8250,");
|
||||
if (!options) {
|
||||
options = strstr(cmdline, "uart,");
|
||||
if (!options)
|
||||
return 0;
|
||||
}
|
||||
if (cmdline && cmdline[4] == ',')
|
||||
match[4] = '\0';
|
||||
|
||||
options = strchr(cmdline, ',') + 1;
|
||||
err = early_serial8250_setup(options);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
register_console(&early_serial8250_console);
|
||||
|
||||
return 0;
|
||||
return setup_earlycon(cmdline, match, early_serial8250_setup);
|
||||
}
|
||||
|
||||
int serial8250_find_port_for_earlycon(void)
|
||||
{
|
||||
struct early_serial8250_device *device = &early_device;
|
||||
struct uart_port *port = &device->port;
|
||||
struct earlycon_device *device = early_device;
|
||||
struct uart_port *port = device ? &device->port : NULL;
|
||||
int line;
|
||||
int ret;
|
||||
|
||||
if (!device->port.membase && !device->port.iobase)
|
||||
if (!port || (!port->membase && !port->iobase))
|
||||
return -ENODEV;
|
||||
|
||||
line = serial8250_find_port(port);
|
||||
|
@ -284,5 +188,3 @@ int serial8250_find_port_for_earlycon(void)
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
early_param("earlycon", setup_early_serial8250_console);
|
||||
|
|
|
@ -61,6 +61,7 @@ config SERIAL_8250_CONSOLE
|
|||
bool "Console on 8250/16550 and compatible serial port"
|
||||
depends on SERIAL_8250=y
|
||||
select SERIAL_CORE_CONSOLE
|
||||
select SERIAL_EARLYCON
|
||||
---help---
|
||||
If you say Y here, it will be possible to use a serial port as the
|
||||
system console (the system console is the device which receives all
|
||||
|
@ -90,11 +91,6 @@ config SERIAL_8250_CONSOLE
|
|||
|
||||
If unsure, say N.
|
||||
|
||||
config FIX_EARLYCON_MEM
|
||||
bool
|
||||
depends on X86
|
||||
default y
|
||||
|
||||
config SERIAL_8250_GSC
|
||||
tristate
|
||||
depends on SERIAL_8250 && GSC
|
||||
|
|
|
@ -7,6 +7,13 @@ if TTY
|
|||
menu "Serial drivers"
|
||||
depends on HAS_IOMEM
|
||||
|
||||
config SERIAL_EARLYCON
|
||||
bool
|
||||
help
|
||||
Support for early consoles with the earlycon parameter. This enables
|
||||
the console before standard serial driver is probed. The console is
|
||||
enabled when early_param is processed.
|
||||
|
||||
source "drivers/tty/serial/8250/Kconfig"
|
||||
|
||||
comment "Non-8250 serial port support"
|
||||
|
@ -53,6 +60,7 @@ config SERIAL_AMBA_PL011_CONSOLE
|
|||
bool "Support for console on AMBA serial port"
|
||||
depends on SERIAL_AMBA_PL011=y
|
||||
select SERIAL_CORE_CONSOLE
|
||||
select SERIAL_EARLYCON
|
||||
---help---
|
||||
Say Y here if you wish to use an AMBA PrimeCell UART as the system
|
||||
console (the system console is the device which receives all kernel
|
||||
|
@ -65,6 +73,16 @@ config SERIAL_AMBA_PL011_CONSOLE
|
|||
your boot loader (lilo or loadlin) about how to pass options to the
|
||||
kernel at boot time.)
|
||||
|
||||
config SERIAL_EARLYCON_ARM_SEMIHOST
|
||||
bool "Early console using ARM semihosting"
|
||||
depends on ARM64 || ARM
|
||||
select SERIAL_EARLYCON
|
||||
help
|
||||
Support for early debug console using ARM semihosting. This enables
|
||||
the console before standard serial driver is probed. This is enabled
|
||||
with "earlycon=smh" on the kernel command line. The console is
|
||||
enabled when early_param is processed.
|
||||
|
||||
config SERIAL_SB1250_DUART
|
||||
tristate "BCM1xxx on-chip DUART serial support"
|
||||
depends on SIBYTE_SB1xxx_SOC=y
|
||||
|
@ -1160,6 +1178,16 @@ config SERIAL_SCCNXP_CONSOLE
|
|||
help
|
||||
Support for console on SCCNXP serial ports.
|
||||
|
||||
config SERIAL_SC16IS7XX
|
||||
tristate "SC16IS7xx serial support"
|
||||
depends on I2C
|
||||
select SERIAL_CORE
|
||||
select REGMAP_I2C if I2C
|
||||
help
|
||||
This selects support for SC16IS7xx serial ports.
|
||||
Supported ICs are SC16IS740, SC16IS741, SC16IS750, SC16IS752,
|
||||
SC16IS760 and SC16IS762.
|
||||
|
||||
config SERIAL_BFIN_SPORT
|
||||
tristate "Blackfin SPORT emulate UART"
|
||||
depends on BLACKFIN
|
||||
|
@ -1369,18 +1397,19 @@ config SERIAL_MXS_AUART_CONSOLE
|
|||
Enable a MXS AUART port to be the system console.
|
||||
|
||||
config SERIAL_XILINX_PS_UART
|
||||
tristate "Xilinx PS UART support"
|
||||
tristate "Cadence (Xilinx Zynq) UART support"
|
||||
depends on OF
|
||||
select SERIAL_CORE
|
||||
help
|
||||
This driver supports the Xilinx PS UART port.
|
||||
This driver supports the Cadence UART. It is found e.g. in Xilinx
|
||||
Zynq.
|
||||
|
||||
config SERIAL_XILINX_PS_UART_CONSOLE
|
||||
bool "Xilinx PS UART console support"
|
||||
bool "Cadence UART console support"
|
||||
depends on SERIAL_XILINX_PS_UART=y
|
||||
select SERIAL_CORE_CONSOLE
|
||||
help
|
||||
Enable a Xilinx PS UART port to be the system console.
|
||||
Enable a Cadence UART port to be the system console.
|
||||
|
||||
config SERIAL_AR933X
|
||||
tristate "AR933X serial port support"
|
||||
|
@ -1508,6 +1537,16 @@ config SERIAL_ST_ASC_CONSOLE
|
|||
depends on SERIAL_ST_ASC=y
|
||||
select SERIAL_CORE_CONSOLE
|
||||
|
||||
config SERIAL_MEN_Z135
|
||||
tristate "MEN 16z135 Support"
|
||||
depends on MCB
|
||||
help
|
||||
Say yes here to enable support for the MEN 16z135 High Speed UART IP-Core
|
||||
on a MCB carrier.
|
||||
|
||||
This driver can also be build as a module. If so, the module will be called
|
||||
men_z135_uart.ko
|
||||
|
||||
endmenu
|
||||
|
||||
endif # TTY
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
obj-$(CONFIG_SERIAL_CORE) += serial_core.o
|
||||
obj-$(CONFIG_SERIAL_21285) += 21285.o
|
||||
|
||||
obj-$(CONFIG_SERIAL_EARLYCON) += earlycon.o
|
||||
obj-$(CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST) += earlycon-arm-semihost.o
|
||||
|
||||
# These Sparc drivers have to appear before others such as 8250
|
||||
# which share ttySx minor node space. Otherwise console device
|
||||
# names change and other unplesantries.
|
||||
|
@ -48,6 +51,7 @@ obj-$(CONFIG_SERIAL_MPSC) += mpsc.o
|
|||
obj-$(CONFIG_SERIAL_SB1250_DUART) += sb1250-duart.o
|
||||
obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o
|
||||
obj-$(CONFIG_SERIAL_SCCNXP) += sccnxp.o
|
||||
obj-$(CONFIG_SERIAL_SC16IS7XX) += sc16is7xx.o
|
||||
obj-$(CONFIG_SERIAL_JSM) += jsm/
|
||||
obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o
|
||||
obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o
|
||||
|
@ -87,3 +91,4 @@ obj-$(CONFIG_SERIAL_EFM32_UART) += efm32-uart.o
|
|||
obj-$(CONFIG_SERIAL_ARC) += arc_uart.o
|
||||
obj-$(CONFIG_SERIAL_RP2) += rp2.o
|
||||
obj-$(CONFIG_SERIAL_FSL_LPUART) += fsl_lpuart.o
|
||||
obj-$(CONFIG_SERIAL_MEN_Z135) += men_z135_uart.o
|
||||
|
|
|
@ -303,7 +303,7 @@ static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port *
|
|||
|
||||
/* Optionally make use of an RX channel as well */
|
||||
chan = dma_request_slave_channel(dev, "rx");
|
||||
|
||||
|
||||
if (!chan && plat->dma_rx_param) {
|
||||
chan = dma_request_channel(mask, plat->dma_filter, plat->dma_rx_param);
|
||||
|
||||
|
@ -2045,6 +2045,34 @@ static struct console amba_console = {
|
|||
};
|
||||
|
||||
#define AMBA_CONSOLE (&amba_console)
|
||||
|
||||
static void pl011_putc(struct uart_port *port, int c)
|
||||
{
|
||||
while (readl(port->membase + UART01x_FR) & UART01x_FR_TXFF)
|
||||
;
|
||||
writeb(c, port->membase + UART01x_DR);
|
||||
while (readl(port->membase + UART01x_FR) & UART01x_FR_BUSY)
|
||||
;
|
||||
}
|
||||
|
||||
static void pl011_early_write(struct console *con, const char *s, unsigned n)
|
||||
{
|
||||
struct earlycon_device *dev = con->data;
|
||||
|
||||
uart_console_write(&dev->port, s, n, pl011_putc);
|
||||
}
|
||||
|
||||
static int __init pl011_early_console_setup(struct earlycon_device *device,
|
||||
const char *opt)
|
||||
{
|
||||
if (!device->port.membase)
|
||||
return -ENODEV;
|
||||
|
||||
device->con->write = pl011_early_write;
|
||||
return 0;
|
||||
}
|
||||
EARLYCON_DECLARE(pl011, pl011_early_console_setup);
|
||||
|
||||
#else
|
||||
#define AMBA_CONSOLE NULL
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (C) 2012 ARM Ltd.
|
||||
* Author: Marc Zyngier <marc.zyngier@arm.com>
|
||||
*
|
||||
* Adapted for ARM and earlycon:
|
||||
* Copyright (C) 2014 Linaro Ltd.
|
||||
* Author: Rob Herring <robh@kernel.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/serial_core.h>
|
||||
|
||||
#ifdef CONFIG_THUMB2_KERNEL
|
||||
#define SEMIHOST_SWI "0xab"
|
||||
#else
|
||||
#define SEMIHOST_SWI "0x123456"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Semihosting-based debug console
|
||||
*/
|
||||
static void smh_putc(struct uart_port *port, int c)
|
||||
{
|
||||
#ifdef CONFIG_ARM64
|
||||
asm volatile("mov x1, %0\n"
|
||||
"mov x0, #3\n"
|
||||
"hlt 0xf000\n"
|
||||
: : "r" (&c) : "x0", "x1", "memory");
|
||||
#else
|
||||
asm volatile("mov r1, %0\n"
|
||||
"mov r0, #3\n"
|
||||
"svc " SEMIHOST_SWI "\n"
|
||||
: : "r" (&c) : "r0", "r1", "memory");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void smh_write(struct console *con, const char *s, unsigned n)
|
||||
{
|
||||
struct earlycon_device *dev = con->data;
|
||||
uart_console_write(&dev->port, s, n, smh_putc);
|
||||
}
|
||||
|
||||
int __init early_smh_setup(struct earlycon_device *device, const char *opt)
|
||||
{
|
||||
device->con->write = smh_write;
|
||||
return 0;
|
||||
}
|
||||
EARLYCON_DECLARE(smh, early_smh_setup);
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Linaro Ltd.
|
||||
* Author: Rob Herring <robh@kernel.org>
|
||||
*
|
||||
* Based on 8250 earlycon:
|
||||
* (c) Copyright 2004 Hewlett-Packard Development Company, L.P.
|
||||
* Bjorn Helgaas <bjorn.helgaas@hp.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/console.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/serial_core.h>
|
||||
|
||||
#ifdef CONFIG_FIX_EARLYCON_MEM
|
||||
#include <asm/fixmap.h>
|
||||
#endif
|
||||
|
||||
#include <asm/serial.h>
|
||||
|
||||
static struct console early_con = {
|
||||
.name = "earlycon",
|
||||
.flags = CON_PRINTBUFFER | CON_BOOT,
|
||||
.index = -1,
|
||||
};
|
||||
|
||||
static struct earlycon_device early_console_dev = {
|
||||
.con = &early_con,
|
||||
};
|
||||
|
||||
static void __iomem * __init earlycon_map(unsigned long paddr, size_t size)
|
||||
{
|
||||
void __iomem *base;
|
||||
#ifdef CONFIG_FIX_EARLYCON_MEM
|
||||
set_fixmap_io(FIX_EARLYCON_MEM_BASE, paddr & PAGE_MASK);
|
||||
base = (void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE);
|
||||
base += paddr & ~PAGE_MASK;
|
||||
#else
|
||||
base = ioremap(paddr, size);
|
||||
#endif
|
||||
if (!base)
|
||||
pr_err("%s: Couldn't map 0x%llx\n", __func__,
|
||||
(unsigned long long)paddr);
|
||||
|
||||
return base;
|
||||
}
|
||||
|
||||
static int __init parse_options(struct earlycon_device *device,
|
||||
char *options)
|
||||
{
|
||||
struct uart_port *port = &device->port;
|
||||
int mmio, mmio32, length;
|
||||
unsigned long addr;
|
||||
|
||||
if (!options)
|
||||
return -ENODEV;
|
||||
|
||||
mmio = !strncmp(options, "mmio,", 5);
|
||||
mmio32 = !strncmp(options, "mmio32,", 7);
|
||||
if (mmio || mmio32) {
|
||||
port->iotype = (mmio ? UPIO_MEM : UPIO_MEM32);
|
||||
options += mmio ? 5 : 7;
|
||||
addr = simple_strtoul(options, NULL, 0);
|
||||
port->mapbase = addr;
|
||||
if (mmio32)
|
||||
port->regshift = 2;
|
||||
} else if (!strncmp(options, "io,", 3)) {
|
||||
port->iotype = UPIO_PORT;
|
||||
options += 3;
|
||||
addr = simple_strtoul(options, NULL, 0);
|
||||
port->iobase = addr;
|
||||
mmio = 0;
|
||||
} else if (!strncmp(options, "0x", 2)) {
|
||||
port->iotype = UPIO_MEM;
|
||||
addr = simple_strtoul(options, NULL, 0);
|
||||
port->mapbase = addr;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
port->uartclk = BASE_BAUD * 16;
|
||||
|
||||
options = strchr(options, ',');
|
||||
if (options) {
|
||||
options++;
|
||||
device->baud = simple_strtoul(options, NULL, 0);
|
||||
length = min(strcspn(options, " ") + 1,
|
||||
(size_t)(sizeof(device->options)));
|
||||
strlcpy(device->options, options, length);
|
||||
}
|
||||
|
||||
if (mmio || mmio32)
|
||||
pr_info("Early serial console at MMIO%s 0x%llx (options '%s')\n",
|
||||
mmio32 ? "32" : "",
|
||||
(unsigned long long)port->mapbase,
|
||||
device->options);
|
||||
else
|
||||
pr_info("Early serial console at I/O port 0x%lx (options '%s')\n",
|
||||
port->iobase,
|
||||
device->options);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init setup_earlycon(char *buf, const char *match,
|
||||
int (*setup)(struct earlycon_device *, const char *))
|
||||
{
|
||||
int err;
|
||||
size_t len;
|
||||
struct uart_port *port = &early_console_dev.port;
|
||||
|
||||
if (!buf || !match || !setup)
|
||||
return 0;
|
||||
|
||||
len = strlen(match);
|
||||
if (strncmp(buf, match, len))
|
||||
return 0;
|
||||
if (buf[len] && (buf[len] != ','))
|
||||
return 0;
|
||||
|
||||
buf += len + 1;
|
||||
|
||||
err = parse_options(&early_console_dev, buf);
|
||||
/* On parsing error, pass the options buf to the setup function */
|
||||
if (!err)
|
||||
buf = NULL;
|
||||
|
||||
if (port->mapbase)
|
||||
port->membase = earlycon_map(port->mapbase, 64);
|
||||
|
||||
early_console_dev.con->data = &early_console_dev;
|
||||
err = setup(&early_console_dev, buf);
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (!early_console_dev.con->write)
|
||||
return -ENODEV;
|
||||
|
||||
register_console(early_console_dev.con);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,866 @@
|
|||
/*
|
||||
* MEN 16z135 High Speed UART
|
||||
*
|
||||
* Copyright (C) 2014 MEN Mikroelektronik GmbH (www.men.de)
|
||||
* Author: Johannes Thumshirn <johannes.thumshirn@men.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; version 2 of the License.
|
||||
*/
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ":" fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/mcb.h>
|
||||
|
||||
#define MEN_Z135_MAX_PORTS 12
|
||||
#define MEN_Z135_BASECLK 29491200
|
||||
#define MEN_Z135_FIFO_SIZE 1024
|
||||
#define MEN_Z135_NUM_MSI_VECTORS 2
|
||||
#define MEN_Z135_FIFO_WATERMARK 1020
|
||||
|
||||
#define MEN_Z135_STAT_REG 0x0
|
||||
#define MEN_Z135_RX_RAM 0x4
|
||||
#define MEN_Z135_TX_RAM 0x400
|
||||
#define MEN_Z135_RX_CTRL 0x800
|
||||
#define MEN_Z135_TX_CTRL 0x804
|
||||
#define MEN_Z135_CONF_REG 0x808
|
||||
#define MEN_Z135_UART_FREQ 0x80c
|
||||
#define MEN_Z135_BAUD_REG 0x810
|
||||
#define MENZ135_TIMEOUT 0x814
|
||||
|
||||
#define MEN_Z135_MEM_SIZE 0x818
|
||||
|
||||
#define IS_IRQ(x) ((x) & 1)
|
||||
#define IRQ_ID(x) (((x) >> 1) & 7)
|
||||
|
||||
#define MEN_Z135_IER_RXCIEN BIT(0) /* TX Space IRQ */
|
||||
#define MEN_Z135_IER_TXCIEN BIT(1) /* RX Space IRQ */
|
||||
#define MEN_Z135_IER_RLSIEN BIT(2) /* Receiver Line Status IRQ */
|
||||
#define MEN_Z135_IER_MSIEN BIT(3) /* Modem Status IRQ */
|
||||
#define MEN_Z135_ALL_IRQS (MEN_Z135_IER_RXCIEN \
|
||||
| MEN_Z135_IER_RLSIEN \
|
||||
| MEN_Z135_IER_MSIEN \
|
||||
| MEN_Z135_IER_TXCIEN)
|
||||
|
||||
#define MEN_Z135_MCR_DTR BIT(24)
|
||||
#define MEN_Z135_MCR_RTS BIT(25)
|
||||
#define MEN_Z135_MCR_OUT1 BIT(26)
|
||||
#define MEN_Z135_MCR_OUT2 BIT(27)
|
||||
#define MEN_Z135_MCR_LOOP BIT(28)
|
||||
#define MEN_Z135_MCR_RCFC BIT(29)
|
||||
|
||||
#define MEN_Z135_MSR_DCTS BIT(0)
|
||||
#define MEN_Z135_MSR_DDSR BIT(1)
|
||||
#define MEN_Z135_MSR_DRI BIT(2)
|
||||
#define MEN_Z135_MSR_DDCD BIT(3)
|
||||
#define MEN_Z135_MSR_CTS BIT(4)
|
||||
#define MEN_Z135_MSR_DSR BIT(5)
|
||||
#define MEN_Z135_MSR_RI BIT(6)
|
||||
#define MEN_Z135_MSR_DCD BIT(7)
|
||||
|
||||
#define MEN_Z135_LCR_SHIFT 8 /* LCR shift mask */
|
||||
|
||||
#define MEN_Z135_WL5 0 /* CS5 */
|
||||
#define MEN_Z135_WL6 1 /* CS6 */
|
||||
#define MEN_Z135_WL7 2 /* CS7 */
|
||||
#define MEN_Z135_WL8 3 /* CS8 */
|
||||
|
||||
#define MEN_Z135_STB_SHIFT 2 /* Stopbits */
|
||||
#define MEN_Z135_NSTB1 0
|
||||
#define MEN_Z135_NSTB2 1
|
||||
|
||||
#define MEN_Z135_PEN_SHIFT 3 /* Parity enable */
|
||||
#define MEN_Z135_PAR_DIS 0
|
||||
#define MEN_Z135_PAR_ENA 1
|
||||
|
||||
#define MEN_Z135_PTY_SHIFT 4 /* Parity type */
|
||||
#define MEN_Z135_PTY_ODD 0
|
||||
#define MEN_Z135_PTY_EVN 1
|
||||
|
||||
#define MEN_Z135_LSR_DR BIT(0)
|
||||
#define MEN_Z135_LSR_OE BIT(1)
|
||||
#define MEN_Z135_LSR_PE BIT(2)
|
||||
#define MEN_Z135_LSR_FE BIT(3)
|
||||
#define MEN_Z135_LSR_BI BIT(4)
|
||||
#define MEN_Z135_LSR_THEP BIT(5)
|
||||
#define MEN_Z135_LSR_TEXP BIT(6)
|
||||
#define MEN_Z135_LSR_RXFIFOERR BIT(7)
|
||||
|
||||
#define MEN_Z135_IRQ_ID_MST 0
|
||||
#define MEN_Z135_IRQ_ID_TSA 1
|
||||
#define MEN_Z135_IRQ_ID_RDA 2
|
||||
#define MEN_Z135_IRQ_ID_RLS 3
|
||||
#define MEN_Z135_IRQ_ID_CTI 6
|
||||
|
||||
#define LCR(x) (((x) >> MEN_Z135_LCR_SHIFT) & 0xff)
|
||||
|
||||
#define BYTES_TO_ALIGN(x) ((x) & 0x3)
|
||||
|
||||
static int line;
|
||||
|
||||
static int txlvl = 5;
|
||||
module_param(txlvl, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(txlvl, "TX IRQ trigger level 0-7, default 5 (128 byte)");
|
||||
|
||||
static int rxlvl = 6;
|
||||
module_param(rxlvl, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(rxlvl, "RX IRQ trigger level 0-7, default 6 (256 byte)");
|
||||
|
||||
static int align;
|
||||
module_param(align, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(align, "Keep hardware FIFO write pointer aligned, default 0");
|
||||
|
||||
struct men_z135_port {
|
||||
struct uart_port port;
|
||||
struct mcb_device *mdev;
|
||||
unsigned char *rxbuf;
|
||||
u32 stat_reg;
|
||||
spinlock_t lock;
|
||||
};
|
||||
#define to_men_z135(port) container_of((port), struct men_z135_port, port)
|
||||
|
||||
/**
|
||||
* men_z135_reg_set() - Set value in register
|
||||
* @uart: The UART port
|
||||
* @addr: Register address
|
||||
* @val: value to set
|
||||
*/
|
||||
static inline void men_z135_reg_set(struct men_z135_port *uart,
|
||||
u32 addr, u32 val)
|
||||
{
|
||||
struct uart_port *port = &uart->port;
|
||||
unsigned long flags;
|
||||
u32 reg;
|
||||
|
||||
spin_lock_irqsave(&uart->lock, flags);
|
||||
|
||||
reg = ioread32(port->membase + addr);
|
||||
reg |= val;
|
||||
iowrite32(reg, port->membase + addr);
|
||||
|
||||
spin_unlock_irqrestore(&uart->lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* men_z135_reg_clr() - Unset value in register
|
||||
* @uart: The UART port
|
||||
* @addr: Register address
|
||||
* @val: value to clear
|
||||
*/
|
||||
static inline void men_z135_reg_clr(struct men_z135_port *uart,
|
||||
u32 addr, u32 val)
|
||||
{
|
||||
struct uart_port *port = &uart->port;
|
||||
unsigned long flags;
|
||||
u32 reg;
|
||||
|
||||
spin_lock_irqsave(&uart->lock, flags);
|
||||
|
||||
reg = ioread32(port->membase + addr);
|
||||
reg &= ~val;
|
||||
iowrite32(reg, port->membase + addr);
|
||||
|
||||
spin_unlock_irqrestore(&uart->lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* men_z135_handle_modem_status() - Handle change of modem status
|
||||
* @port: The UART port
|
||||
*
|
||||
* Handle change of modem status register. This is done by reading the "delta"
|
||||
* versions of DCD (Data Carrier Detect) and CTS (Clear To Send).
|
||||
*/
|
||||
static void men_z135_handle_modem_status(struct men_z135_port *uart)
|
||||
{
|
||||
if (uart->stat_reg & MEN_Z135_MSR_DDCD)
|
||||
uart_handle_dcd_change(&uart->port,
|
||||
uart->stat_reg & ~MEN_Z135_MSR_DCD);
|
||||
if (uart->stat_reg & MEN_Z135_MSR_DCTS)
|
||||
uart_handle_cts_change(&uart->port,
|
||||
uart->stat_reg & ~MEN_Z135_MSR_CTS);
|
||||
}
|
||||
|
||||
static void men_z135_handle_lsr(struct men_z135_port *uart)
|
||||
{
|
||||
struct uart_port *port = &uart->port;
|
||||
u8 lsr;
|
||||
|
||||
lsr = (uart->stat_reg >> 16) & 0xff;
|
||||
|
||||
if (lsr & MEN_Z135_LSR_OE)
|
||||
port->icount.overrun++;
|
||||
if (lsr & MEN_Z135_LSR_PE)
|
||||
port->icount.parity++;
|
||||
if (lsr & MEN_Z135_LSR_FE)
|
||||
port->icount.frame++;
|
||||
if (lsr & MEN_Z135_LSR_BI) {
|
||||
port->icount.brk++;
|
||||
uart_handle_break(port);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get_rx_fifo_content() - Get the number of bytes in RX FIFO
|
||||
* @uart: The UART port
|
||||
*
|
||||
* Read RXC register from hardware and return current FIFO fill size.
|
||||
*/
|
||||
static u16 get_rx_fifo_content(struct men_z135_port *uart)
|
||||
{
|
||||
struct uart_port *port = &uart->port;
|
||||
u32 stat_reg;
|
||||
u16 rxc;
|
||||
u8 rxc_lo;
|
||||
u8 rxc_hi;
|
||||
|
||||
stat_reg = ioread32(port->membase + MEN_Z135_STAT_REG);
|
||||
rxc_lo = stat_reg >> 24;
|
||||
rxc_hi = (stat_reg & 0xC0) >> 6;
|
||||
|
||||
rxc = rxc_lo | (rxc_hi << 8);
|
||||
|
||||
return rxc;
|
||||
}
|
||||
|
||||
/**
|
||||
* men_z135_handle_rx() - RX tasklet routine
|
||||
* @arg: Pointer to struct men_z135_port
|
||||
*
|
||||
* Copy from RX FIFO and acknowledge number of bytes copied.
|
||||
*/
|
||||
static void men_z135_handle_rx(struct men_z135_port *uart)
|
||||
{
|
||||
struct uart_port *port = &uart->port;
|
||||
struct tty_port *tport = &port->state->port;
|
||||
int copied;
|
||||
u16 size;
|
||||
int room;
|
||||
|
||||
size = get_rx_fifo_content(uart);
|
||||
|
||||
if (size == 0)
|
||||
return;
|
||||
|
||||
/* Avoid accidently accessing TX FIFO instead of RX FIFO. Last
|
||||
* longword in RX FIFO cannot be read.(0x004-0x3FF)
|
||||
*/
|
||||
if (size > MEN_Z135_FIFO_WATERMARK)
|
||||
size = MEN_Z135_FIFO_WATERMARK;
|
||||
|
||||
room = tty_buffer_request_room(tport, size);
|
||||
if (room != size)
|
||||
dev_warn(&uart->mdev->dev,
|
||||
"Not enough room in flip buffer, truncating to %d\n",
|
||||
room);
|
||||
|
||||
if (room == 0)
|
||||
return;
|
||||
|
||||
memcpy_fromio(uart->rxbuf, port->membase + MEN_Z135_RX_RAM, room);
|
||||
/* Be sure to first copy all data and then acknowledge it */
|
||||
mb();
|
||||
iowrite32(room, port->membase + MEN_Z135_RX_CTRL);
|
||||
|
||||
copied = tty_insert_flip_string(tport, uart->rxbuf, room);
|
||||
if (copied != room)
|
||||
dev_warn(&uart->mdev->dev,
|
||||
"Only copied %d instead of %d bytes\n",
|
||||
copied, room);
|
||||
|
||||
port->icount.rx += copied;
|
||||
|
||||
tty_flip_buffer_push(tport);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* men_z135_handle_tx() - TX tasklet routine
|
||||
* @arg: Pointer to struct men_z135_port
|
||||
*
|
||||
*/
|
||||
static void men_z135_handle_tx(struct men_z135_port *uart)
|
||||
{
|
||||
struct uart_port *port = &uart->port;
|
||||
struct circ_buf *xmit = &port->state->xmit;
|
||||
u32 txc;
|
||||
u32 wptr;
|
||||
int qlen;
|
||||
int n;
|
||||
int txfree;
|
||||
int head;
|
||||
int tail;
|
||||
int s;
|
||||
|
||||
if (uart_circ_empty(xmit))
|
||||
goto out;
|
||||
|
||||
if (uart_tx_stopped(port))
|
||||
goto out;
|
||||
|
||||
if (port->x_char)
|
||||
goto out;
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(port);
|
||||
|
||||
/* calculate bytes to copy */
|
||||
qlen = uart_circ_chars_pending(xmit);
|
||||
if (qlen <= 0)
|
||||
goto out;
|
||||
|
||||
wptr = ioread32(port->membase + MEN_Z135_TX_CTRL);
|
||||
txc = (wptr >> 16) & 0x3ff;
|
||||
wptr &= 0x3ff;
|
||||
|
||||
if (txc > MEN_Z135_FIFO_WATERMARK)
|
||||
txc = MEN_Z135_FIFO_WATERMARK;
|
||||
|
||||
txfree = MEN_Z135_FIFO_WATERMARK - txc;
|
||||
if (txfree <= 0) {
|
||||
pr_err("Not enough room in TX FIFO have %d, need %d\n",
|
||||
txfree, qlen);
|
||||
goto irq_en;
|
||||
}
|
||||
|
||||
/* if we're not aligned, it's better to copy only 1 or 2 bytes and
|
||||
* then the rest.
|
||||
*/
|
||||
if (align && qlen >= 3 && BYTES_TO_ALIGN(wptr))
|
||||
n = 4 - BYTES_TO_ALIGN(wptr);
|
||||
else if (qlen > txfree)
|
||||
n = txfree;
|
||||
else
|
||||
n = qlen;
|
||||
|
||||
if (n <= 0)
|
||||
goto irq_en;
|
||||
|
||||
head = xmit->head & (UART_XMIT_SIZE - 1);
|
||||
tail = xmit->tail & (UART_XMIT_SIZE - 1);
|
||||
|
||||
s = ((head >= tail) ? head : UART_XMIT_SIZE) - tail;
|
||||
n = min(n, s);
|
||||
|
||||
memcpy_toio(port->membase + MEN_Z135_TX_RAM, &xmit->buf[xmit->tail], n);
|
||||
xmit->tail = (xmit->tail + n) & (UART_XMIT_SIZE - 1);
|
||||
mmiowb();
|
||||
|
||||
iowrite32(n & 0x3ff, port->membase + MEN_Z135_TX_CTRL);
|
||||
|
||||
port->icount.tx += n;
|
||||
|
||||
irq_en:
|
||||
if (!uart_circ_empty(xmit))
|
||||
men_z135_reg_set(uart, MEN_Z135_CONF_REG, MEN_Z135_IER_TXCIEN);
|
||||
else
|
||||
men_z135_reg_clr(uart, MEN_Z135_CONF_REG, MEN_Z135_IER_TXCIEN);
|
||||
|
||||
out:
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* men_z135_intr() - Handle legacy IRQs
|
||||
* @irq: The IRQ number
|
||||
* @data: Pointer to UART port
|
||||
*
|
||||
* Check IIR register to see which tasklet to start.
|
||||
*/
|
||||
static irqreturn_t men_z135_intr(int irq, void *data)
|
||||
{
|
||||
struct men_z135_port *uart = (struct men_z135_port *)data;
|
||||
struct uart_port *port = &uart->port;
|
||||
int irq_id;
|
||||
|
||||
uart->stat_reg = ioread32(port->membase + MEN_Z135_STAT_REG);
|
||||
/* IRQ pending is low active */
|
||||
if (IS_IRQ(uart->stat_reg))
|
||||
return IRQ_NONE;
|
||||
|
||||
irq_id = IRQ_ID(uart->stat_reg);
|
||||
switch (irq_id) {
|
||||
case MEN_Z135_IRQ_ID_MST:
|
||||
men_z135_handle_modem_status(uart);
|
||||
break;
|
||||
case MEN_Z135_IRQ_ID_TSA:
|
||||
men_z135_handle_tx(uart);
|
||||
break;
|
||||
case MEN_Z135_IRQ_ID_CTI:
|
||||
dev_dbg(&uart->mdev->dev, "Character Timeout Indication\n");
|
||||
/* Fallthrough */
|
||||
case MEN_Z135_IRQ_ID_RDA:
|
||||
/* Reading data clears RX IRQ */
|
||||
men_z135_handle_rx(uart);
|
||||
break;
|
||||
case MEN_Z135_IRQ_ID_RLS:
|
||||
men_z135_handle_lsr(uart);
|
||||
break;
|
||||
default:
|
||||
dev_warn(&uart->mdev->dev, "Unknown IRQ id %d\n", irq_id);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* men_z135_request_irq() - Request IRQ for 16z135 core
|
||||
* @uart: z135 private uart port structure
|
||||
*
|
||||
* Request an IRQ for 16z135 to use. First try using MSI, if it fails
|
||||
* fall back to using legacy interrupts.
|
||||
*/
|
||||
static int men_z135_request_irq(struct men_z135_port *uart)
|
||||
{
|
||||
struct device *dev = &uart->mdev->dev;
|
||||
struct uart_port *port = &uart->port;
|
||||
int err = 0;
|
||||
|
||||
err = request_irq(port->irq, men_z135_intr, IRQF_SHARED,
|
||||
"men_z135_intr", uart);
|
||||
if (err)
|
||||
dev_err(dev, "Error %d getting interrupt\n", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* men_z135_tx_empty() - Handle tx_empty call
|
||||
* @port: The UART port
|
||||
*
|
||||
* This function tests whether the TX FIFO and shifter for the port
|
||||
* described by @port is empty.
|
||||
*/
|
||||
static unsigned int men_z135_tx_empty(struct uart_port *port)
|
||||
{
|
||||
u32 wptr;
|
||||
u16 txc;
|
||||
|
||||
wptr = ioread32(port->membase + MEN_Z135_TX_CTRL);
|
||||
txc = (wptr >> 16) & 0x3ff;
|
||||
|
||||
if (txc == 0)
|
||||
return TIOCSER_TEMT;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* men_z135_set_mctrl() - Set modem control lines
|
||||
* @port: The UART port
|
||||
* @mctrl: The modem control lines
|
||||
*
|
||||
* This function sets the modem control lines for a port described by @port
|
||||
* to the state described by @mctrl
|
||||
*/
|
||||
static void men_z135_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
{
|
||||
struct men_z135_port *uart = to_men_z135(port);
|
||||
u32 conf_reg = 0;
|
||||
|
||||
if (mctrl & TIOCM_RTS)
|
||||
conf_reg |= MEN_Z135_MCR_RTS;
|
||||
if (mctrl & TIOCM_DTR)
|
||||
conf_reg |= MEN_Z135_MCR_DTR;
|
||||
if (mctrl & TIOCM_OUT1)
|
||||
conf_reg |= MEN_Z135_MCR_OUT1;
|
||||
if (mctrl & TIOCM_OUT2)
|
||||
conf_reg |= MEN_Z135_MCR_OUT2;
|
||||
if (mctrl & TIOCM_LOOP)
|
||||
conf_reg |= MEN_Z135_MCR_LOOP;
|
||||
|
||||
men_z135_reg_set(uart, MEN_Z135_CONF_REG, conf_reg);
|
||||
}
|
||||
|
||||
/**
|
||||
* men_z135_get_mctrl() - Get modem control lines
|
||||
* @port: The UART port
|
||||
*
|
||||
* Retruns the current state of modem control inputs.
|
||||
*/
|
||||
static unsigned int men_z135_get_mctrl(struct uart_port *port)
|
||||
{
|
||||
unsigned int mctrl = 0;
|
||||
u32 stat_reg;
|
||||
u8 msr;
|
||||
|
||||
stat_reg = ioread32(port->membase + MEN_Z135_STAT_REG);
|
||||
|
||||
msr = ~((stat_reg >> 8) & 0xff);
|
||||
|
||||
if (msr & MEN_Z135_MSR_CTS)
|
||||
mctrl |= TIOCM_CTS;
|
||||
if (msr & MEN_Z135_MSR_DSR)
|
||||
mctrl |= TIOCM_DSR;
|
||||
if (msr & MEN_Z135_MSR_RI)
|
||||
mctrl |= TIOCM_RI;
|
||||
if (msr & MEN_Z135_MSR_DCD)
|
||||
mctrl |= TIOCM_CAR;
|
||||
|
||||
return mctrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* men_z135_stop_tx() - Stop transmitting characters
|
||||
* @port: The UART port
|
||||
*
|
||||
* Stop transmitting characters. This might be due to CTS line becomming
|
||||
* inactive or the tty layer indicating we want to stop transmission due to
|
||||
* an XOFF character.
|
||||
*/
|
||||
static void men_z135_stop_tx(struct uart_port *port)
|
||||
{
|
||||
struct men_z135_port *uart = to_men_z135(port);
|
||||
|
||||
men_z135_reg_clr(uart, MEN_Z135_CONF_REG, MEN_Z135_IER_TXCIEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* men_z135_start_tx() - Start transmitting characters
|
||||
* @port: The UART port
|
||||
*
|
||||
* Start transmitting character. This actually doesn't transmit anything, but
|
||||
* fires off the TX tasklet.
|
||||
*/
|
||||
static void men_z135_start_tx(struct uart_port *port)
|
||||
{
|
||||
struct men_z135_port *uart = to_men_z135(port);
|
||||
|
||||
men_z135_handle_tx(uart);
|
||||
}
|
||||
|
||||
/**
|
||||
* men_z135_stop_rx() - Stop receiving characters
|
||||
* @port: The UART port
|
||||
*
|
||||
* Stop receiving characters; the port is in the process of being closed.
|
||||
*/
|
||||
static void men_z135_stop_rx(struct uart_port *port)
|
||||
{
|
||||
struct men_z135_port *uart = to_men_z135(port);
|
||||
|
||||
men_z135_reg_clr(uart, MEN_Z135_CONF_REG, MEN_Z135_IER_RXCIEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* men_z135_enable_ms() - Enable Modem Status
|
||||
* port:
|
||||
*
|
||||
* Enable Modem Status IRQ.
|
||||
*/
|
||||
static void men_z135_enable_ms(struct uart_port *port)
|
||||
{
|
||||
struct men_z135_port *uart = to_men_z135(port);
|
||||
|
||||
men_z135_reg_set(uart, MEN_Z135_CONF_REG, MEN_Z135_IER_MSIEN);
|
||||
}
|
||||
|
||||
static int men_z135_startup(struct uart_port *port)
|
||||
{
|
||||
struct men_z135_port *uart = to_men_z135(port);
|
||||
int err;
|
||||
u32 conf_reg = 0;
|
||||
|
||||
err = men_z135_request_irq(uart);
|
||||
if (err)
|
||||
return -ENODEV;
|
||||
|
||||
conf_reg = ioread32(port->membase + MEN_Z135_CONF_REG);
|
||||
|
||||
conf_reg |= MEN_Z135_ALL_IRQS;
|
||||
conf_reg &= ~(0xff << 16);
|
||||
conf_reg |= (txlvl << 16);
|
||||
conf_reg |= (rxlvl << 20);
|
||||
|
||||
iowrite32(conf_reg, port->membase + MEN_Z135_CONF_REG);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void men_z135_shutdown(struct uart_port *port)
|
||||
{
|
||||
struct men_z135_port *uart = to_men_z135(port);
|
||||
u32 conf_reg = 0;
|
||||
|
||||
conf_reg |= MEN_Z135_ALL_IRQS;
|
||||
|
||||
men_z135_reg_clr(uart, MEN_Z135_CONF_REG, conf_reg);
|
||||
|
||||
free_irq(uart->port.irq, uart);
|
||||
}
|
||||
|
||||
static void men_z135_set_termios(struct uart_port *port,
|
||||
struct ktermios *termios,
|
||||
struct ktermios *old)
|
||||
{
|
||||
unsigned int baud;
|
||||
u32 conf_reg;
|
||||
u32 bd_reg;
|
||||
u32 uart_freq;
|
||||
u8 lcr;
|
||||
|
||||
conf_reg = ioread32(port->membase + MEN_Z135_CONF_REG);
|
||||
lcr = LCR(conf_reg);
|
||||
|
||||
/* byte size */
|
||||
switch (termios->c_cflag & CSIZE) {
|
||||
case CS5:
|
||||
lcr |= MEN_Z135_WL5;
|
||||
break;
|
||||
case CS6:
|
||||
lcr |= MEN_Z135_WL6;
|
||||
break;
|
||||
case CS7:
|
||||
lcr |= MEN_Z135_WL7;
|
||||
break;
|
||||
case CS8:
|
||||
lcr |= MEN_Z135_WL8;
|
||||
break;
|
||||
}
|
||||
|
||||
/* stop bits */
|
||||
if (termios->c_cflag & CSTOPB)
|
||||
lcr |= MEN_Z135_NSTB2 << MEN_Z135_STB_SHIFT;
|
||||
|
||||
/* parity */
|
||||
if (termios->c_cflag & PARENB) {
|
||||
lcr |= MEN_Z135_PAR_ENA << MEN_Z135_PEN_SHIFT;
|
||||
|
||||
if (termios->c_cflag & PARODD)
|
||||
lcr |= MEN_Z135_PTY_ODD << MEN_Z135_PTY_SHIFT;
|
||||
else
|
||||
lcr |= MEN_Z135_PTY_EVN << MEN_Z135_PTY_SHIFT;
|
||||
} else
|
||||
lcr |= MEN_Z135_PAR_DIS << MEN_Z135_PEN_SHIFT;
|
||||
|
||||
termios->c_cflag &= ~CMSPAR; /* Mark/Space parity is not supported */
|
||||
|
||||
conf_reg |= lcr << MEN_Z135_LCR_SHIFT;
|
||||
iowrite32(conf_reg, port->membase + MEN_Z135_CONF_REG);
|
||||
|
||||
uart_freq = ioread32(port->membase + MEN_Z135_UART_FREQ);
|
||||
if (uart_freq == 0)
|
||||
uart_freq = MEN_Z135_BASECLK;
|
||||
|
||||
baud = uart_get_baud_rate(port, termios, old, 0, uart_freq / 16);
|
||||
|
||||
spin_lock(&port->lock);
|
||||
if (tty_termios_baud_rate(termios))
|
||||
tty_termios_encode_baud_rate(termios, baud, baud);
|
||||
|
||||
bd_reg = uart_freq / (4 * baud);
|
||||
iowrite32(bd_reg, port->membase + MEN_Z135_BAUD_REG);
|
||||
|
||||
uart_update_timeout(port, termios->c_cflag, baud);
|
||||
spin_unlock(&port->lock);
|
||||
}
|
||||
|
||||
static const char *men_z135_type(struct uart_port *port)
|
||||
{
|
||||
return KBUILD_MODNAME;
|
||||
}
|
||||
|
||||
static void men_z135_release_port(struct uart_port *port)
|
||||
{
|
||||
iounmap(port->membase);
|
||||
port->membase = NULL;
|
||||
|
||||
release_mem_region(port->mapbase, MEN_Z135_MEM_SIZE);
|
||||
}
|
||||
|
||||
static int men_z135_request_port(struct uart_port *port)
|
||||
{
|
||||
int size = MEN_Z135_MEM_SIZE;
|
||||
|
||||
if (!request_mem_region(port->mapbase, size, "men_z135_port"))
|
||||
return -EBUSY;
|
||||
|
||||
port->membase = ioremap(port->mapbase, MEN_Z135_MEM_SIZE);
|
||||
if (port->membase == NULL) {
|
||||
release_mem_region(port->mapbase, MEN_Z135_MEM_SIZE);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void men_z135_config_port(struct uart_port *port, int type)
|
||||
{
|
||||
port->type = PORT_MEN_Z135;
|
||||
men_z135_request_port(port);
|
||||
}
|
||||
|
||||
static int men_z135_verify_port(struct uart_port *port,
|
||||
struct serial_struct *serinfo)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static struct uart_ops men_z135_ops = {
|
||||
.tx_empty = men_z135_tx_empty,
|
||||
.set_mctrl = men_z135_set_mctrl,
|
||||
.get_mctrl = men_z135_get_mctrl,
|
||||
.stop_tx = men_z135_stop_tx,
|
||||
.start_tx = men_z135_start_tx,
|
||||
.stop_rx = men_z135_stop_rx,
|
||||
.enable_ms = men_z135_enable_ms,
|
||||
.startup = men_z135_startup,
|
||||
.shutdown = men_z135_shutdown,
|
||||
.set_termios = men_z135_set_termios,
|
||||
.type = men_z135_type,
|
||||
.release_port = men_z135_release_port,
|
||||
.request_port = men_z135_request_port,
|
||||
.config_port = men_z135_config_port,
|
||||
.verify_port = men_z135_verify_port,
|
||||
};
|
||||
|
||||
static struct uart_driver men_z135_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.driver_name = KBUILD_MODNAME,
|
||||
.dev_name = "ttyHSU",
|
||||
.major = 0,
|
||||
.minor = 0,
|
||||
.nr = MEN_Z135_MAX_PORTS,
|
||||
};
|
||||
|
||||
/**
|
||||
* men_z135_probe() - Probe a z135 instance
|
||||
* @mdev: The MCB device
|
||||
* @id: The MCB device ID
|
||||
*
|
||||
* men_z135_probe does the basic setup of hardware resources and registers the
|
||||
* new uart port to the tty layer.
|
||||
*/
|
||||
static int men_z135_probe(struct mcb_device *mdev,
|
||||
const struct mcb_device_id *id)
|
||||
{
|
||||
struct men_z135_port *uart;
|
||||
struct resource *mem;
|
||||
struct device *dev;
|
||||
int err;
|
||||
|
||||
dev = &mdev->dev;
|
||||
|
||||
uart = devm_kzalloc(dev, sizeof(struct men_z135_port), GFP_KERNEL);
|
||||
if (!uart)
|
||||
return -ENOMEM;
|
||||
|
||||
uart->rxbuf = (unsigned char *)__get_free_page(GFP_KERNEL);
|
||||
if (!uart->rxbuf)
|
||||
return -ENOMEM;
|
||||
|
||||
mem = &mdev->mem;
|
||||
|
||||
mcb_set_drvdata(mdev, uart);
|
||||
|
||||
uart->port.uartclk = MEN_Z135_BASECLK * 16;
|
||||
uart->port.fifosize = MEN_Z135_FIFO_SIZE;
|
||||
uart->port.iotype = UPIO_MEM;
|
||||
uart->port.ops = &men_z135_ops;
|
||||
uart->port.irq = mcb_get_irq(mdev);
|
||||
uart->port.iotype = UPIO_MEM;
|
||||
uart->port.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP;
|
||||
uart->port.line = line++;
|
||||
uart->port.dev = dev;
|
||||
uart->port.type = PORT_MEN_Z135;
|
||||
uart->port.mapbase = mem->start;
|
||||
uart->port.membase = NULL;
|
||||
uart->mdev = mdev;
|
||||
|
||||
spin_lock_init(&uart->port.lock);
|
||||
spin_lock_init(&uart->lock);
|
||||
|
||||
err = uart_add_one_port(&men_z135_driver, &uart->port);
|
||||
if (err)
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
free_page((unsigned long) uart->rxbuf);
|
||||
dev_err(dev, "Failed to add UART: %d\n", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* men_z135_remove() - Remove a z135 instance from the system
|
||||
*
|
||||
* @mdev: The MCB device
|
||||
*/
|
||||
static void men_z135_remove(struct mcb_device *mdev)
|
||||
{
|
||||
struct men_z135_port *uart = mcb_get_drvdata(mdev);
|
||||
|
||||
line--;
|
||||
uart_remove_one_port(&men_z135_driver, &uart->port);
|
||||
free_page((unsigned long) uart->rxbuf);
|
||||
}
|
||||
|
||||
static const struct mcb_device_id men_z135_ids[] = {
|
||||
{ .device = 0x87 },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(mcb, men_z135_ids);
|
||||
|
||||
static struct mcb_driver mcb_driver = {
|
||||
.driver = {
|
||||
.name = "z135-uart",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = men_z135_probe,
|
||||
.remove = men_z135_remove,
|
||||
.id_table = men_z135_ids,
|
||||
};
|
||||
|
||||
/**
|
||||
* men_z135_init() - Driver Registration Routine
|
||||
*
|
||||
* men_z135_init is the first routine called when the driver is loaded. All it
|
||||
* does is register with the legacy MEN Chameleon subsystem.
|
||||
*/
|
||||
static int __init men_z135_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = uart_register_driver(&men_z135_driver);
|
||||
if (err) {
|
||||
pr_err("Failed to register UART: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = mcb_register_driver(&mcb_driver);
|
||||
if (err) {
|
||||
pr_err("Failed to register MCB driver: %d\n", err);
|
||||
uart_unregister_driver(&men_z135_driver);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
module_init(men_z135_init);
|
||||
|
||||
/**
|
||||
* men_z135_exit() - Driver Exit Routine
|
||||
*
|
||||
* men_z135_exit is called just before the driver is removed from memory.
|
||||
*/
|
||||
static void __exit men_z135_exit(void)
|
||||
{
|
||||
mcb_unregister_driver(&mcb_driver);
|
||||
uart_unregister_driver(&men_z135_driver);
|
||||
}
|
||||
module_exit(men_z135_exit);
|
||||
|
||||
MODULE_AUTHOR("Johannes Thumshirn <johannes.thumshirn@men.de>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("MEN 16z135 High Speed UART");
|
||||
MODULE_ALIAS("mcb:16z135");
|
|
@ -29,7 +29,7 @@
|
|||
#include <asm/irq.h>
|
||||
#include <asm/parisc-device.h>
|
||||
|
||||
#ifdef CONFIG_MAGIC_SYSRQ
|
||||
#if defined(CONFIG_SERIAL_MUX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
|
||||
#include <linux/sysrq.h>
|
||||
#define SUPPORT_SYSRQ
|
||||
#endif
|
||||
|
@ -613,7 +613,7 @@ static void __exit mux_exit(void)
|
|||
{
|
||||
/* Delete the Mux timer. */
|
||||
if(port_cnt > 0) {
|
||||
del_timer(&mux_timer);
|
||||
del_timer_sync(&mux_timer);
|
||||
#ifdef CONFIG_SERIAL_MUX_CONSOLE
|
||||
unregister_console(&mux_console);
|
||||
#endif
|
||||
|
|
|
@ -163,10 +163,6 @@ struct uart_omap_port {
|
|||
u8 wakeups_enabled;
|
||||
u32 features;
|
||||
|
||||
int DTR_gpio;
|
||||
int DTR_inverted;
|
||||
int DTR_active;
|
||||
|
||||
struct serial_rs485 rs485;
|
||||
int rts_gpio;
|
||||
|
||||
|
@ -184,8 +180,6 @@ static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
|
|||
/* Forward declaration of functions */
|
||||
static void serial_omap_mdr1_errataset(struct uart_omap_port *up, u8 mdr1);
|
||||
|
||||
static struct workqueue_struct *serial_omap_uart_wq;
|
||||
|
||||
static inline unsigned int serial_in(struct uart_omap_port *up, int offset)
|
||||
{
|
||||
offset <<= up->port.regshift;
|
||||
|
@ -398,11 +392,8 @@ static void transmit_chars(struct uart_omap_port *up, unsigned int lsr)
|
|||
break;
|
||||
} while (--count > 0);
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) {
|
||||
spin_unlock(&up->port.lock);
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(&up->port);
|
||||
spin_lock(&up->port.lock);
|
||||
}
|
||||
|
||||
if (uart_circ_empty(xmit))
|
||||
serial_omap_stop_tx(&up->port);
|
||||
|
@ -697,16 +688,6 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
|||
serial_out(up, UART_MCR, up->mcr);
|
||||
pm_runtime_mark_last_busy(up->dev);
|
||||
pm_runtime_put_autosuspend(up->dev);
|
||||
|
||||
if (gpio_is_valid(up->DTR_gpio) &&
|
||||
!!(mctrl & TIOCM_DTR) != up->DTR_active) {
|
||||
up->DTR_active = !up->DTR_active;
|
||||
if (gpio_cansleep(up->DTR_gpio))
|
||||
schedule_work(&up->qos_work);
|
||||
else
|
||||
gpio_set_value(up->DTR_gpio,
|
||||
up->DTR_active != up->DTR_inverted);
|
||||
}
|
||||
}
|
||||
|
||||
static void serial_omap_break_ctl(struct uart_port *port, int break_state)
|
||||
|
@ -850,9 +831,6 @@ static void serial_omap_uart_qos_work(struct work_struct *work)
|
|||
qos_work);
|
||||
|
||||
pm_qos_update_request(&up->pm_qos_request, up->latency);
|
||||
if (gpio_is_valid(up->DTR_gpio))
|
||||
gpio_set_value_cansleep(up->DTR_gpio,
|
||||
up->DTR_active != up->DTR_inverted);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1420,7 +1398,7 @@ serial_omap_ioctl(struct uart_port *port, unsigned int cmd, unsigned long arg)
|
|||
|
||||
switch (cmd) {
|
||||
case TIOCSRS485:
|
||||
if (copy_from_user(&rs485conf, (struct serial_rs485 *) arg,
|
||||
if (copy_from_user(&rs485conf, (void __user *) arg,
|
||||
sizeof(rs485conf)))
|
||||
return -EFAULT;
|
||||
|
||||
|
@ -1428,7 +1406,7 @@ serial_omap_ioctl(struct uart_port *port, unsigned int cmd, unsigned long arg)
|
|||
break;
|
||||
|
||||
case TIOCGRS485:
|
||||
if (copy_to_user((struct serial_rs485 *) arg,
|
||||
if (copy_to_user((void __user *) arg,
|
||||
&(to_uart_omap_port(port)->rs485),
|
||||
sizeof(rs485conf)))
|
||||
return -EFAULT;
|
||||
|
@ -1614,7 +1592,7 @@ static int serial_omap_probe_rs485(struct uart_omap_port *up,
|
|||
/* check for tx enable gpio */
|
||||
up->rts_gpio = of_get_named_gpio_flags(np, "rts-gpio", 0, &flags);
|
||||
if (gpio_is_valid(up->rts_gpio)) {
|
||||
ret = gpio_request(up->rts_gpio, "omap-serial");
|
||||
ret = devm_gpio_request(up->dev, up->rts_gpio, "omap-serial");
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = gpio_direction_output(up->rts_gpio,
|
||||
|
@ -1644,10 +1622,13 @@ static int serial_omap_probe_rs485(struct uart_omap_port *up,
|
|||
|
||||
static int serial_omap_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct uart_omap_port *up;
|
||||
struct resource *mem, *irq;
|
||||
struct omap_uart_port_info *omap_up_info = dev_get_platdata(&pdev->dev);
|
||||
int ret, uartirq = 0, wakeirq = 0;
|
||||
struct uart_omap_port *up;
|
||||
struct resource *mem;
|
||||
void __iomem *base;
|
||||
int uartirq = 0;
|
||||
int wakeirq = 0;
|
||||
int ret;
|
||||
|
||||
/* The optional wakeirq may be specified in the board dts file */
|
||||
if (pdev->dev.of_node) {
|
||||
|
@ -1658,48 +1639,19 @@ static int serial_omap_probe(struct platform_device *pdev)
|
|||
omap_up_info = of_get_uart_port_info(&pdev->dev);
|
||||
pdev->dev.platform_data = omap_up_info;
|
||||
} else {
|
||||
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
if (!irq) {
|
||||
dev_err(&pdev->dev, "no irq resource?\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
uartirq = irq->start;
|
||||
}
|
||||
|
||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!mem) {
|
||||
dev_err(&pdev->dev, "no mem resource?\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!devm_request_mem_region(&pdev->dev, mem->start, resource_size(mem),
|
||||
pdev->dev.driver->name)) {
|
||||
dev_err(&pdev->dev, "memory region already claimed\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (gpio_is_valid(omap_up_info->DTR_gpio) &&
|
||||
omap_up_info->DTR_present) {
|
||||
ret = gpio_request(omap_up_info->DTR_gpio, "omap-serial");
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = gpio_direction_output(omap_up_info->DTR_gpio,
|
||||
omap_up_info->DTR_inverted);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
uartirq = platform_get_irq(pdev, 0);
|
||||
if (uartirq < 0)
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
up = devm_kzalloc(&pdev->dev, sizeof(*up), GFP_KERNEL);
|
||||
if (!up)
|
||||
return -ENOMEM;
|
||||
|
||||
if (gpio_is_valid(omap_up_info->DTR_gpio) &&
|
||||
omap_up_info->DTR_present) {
|
||||
up->DTR_gpio = omap_up_info->DTR_gpio;
|
||||
up->DTR_inverted = omap_up_info->DTR_inverted;
|
||||
} else
|
||||
up->DTR_gpio = -EINVAL;
|
||||
up->DTR_active = 0;
|
||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
base = devm_ioremap_resource(&pdev->dev, mem);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
||||
up->dev = &pdev->dev;
|
||||
up->port.dev = &pdev->dev;
|
||||
|
@ -1733,14 +1685,7 @@ static int serial_omap_probe(struct platform_device *pdev)
|
|||
|
||||
sprintf(up->name, "OMAP UART%d", up->port.line);
|
||||
up->port.mapbase = mem->start;
|
||||
up->port.membase = devm_ioremap(&pdev->dev, mem->start,
|
||||
resource_size(mem));
|
||||
if (!up->port.membase) {
|
||||
dev_err(&pdev->dev, "can't ioremap UART\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_ioremap;
|
||||
}
|
||||
|
||||
up->port.membase = base;
|
||||
up->port.flags = omap_up_info->flags;
|
||||
up->port.uartclk = omap_up_info->uartclk;
|
||||
if (!up->port.uartclk) {
|
||||
|
@ -1754,12 +1699,12 @@ static int serial_omap_probe(struct platform_device *pdev)
|
|||
up->calc_latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
|
||||
pm_qos_add_request(&up->pm_qos_request,
|
||||
PM_QOS_CPU_DMA_LATENCY, up->latency);
|
||||
serial_omap_uart_wq = create_singlethread_workqueue(up->name);
|
||||
INIT_WORK(&up->qos_work, serial_omap_uart_qos_work);
|
||||
|
||||
platform_set_drvdata(pdev, up);
|
||||
if (omap_up_info->autosuspend_timeout == 0)
|
||||
omap_up_info->autosuspend_timeout = -1;
|
||||
|
||||
device_init_wakeup(up->dev, true);
|
||||
pm_runtime_use_autosuspend(&pdev->dev);
|
||||
pm_runtime_set_autosuspend_delay(&pdev->dev,
|
||||
|
@ -1786,7 +1731,6 @@ static int serial_omap_probe(struct platform_device *pdev)
|
|||
err_add_port:
|
||||
pm_runtime_put(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
err_ioremap:
|
||||
err_rs485:
|
||||
err_port_line:
|
||||
dev_err(&pdev->dev, "[UART%d]: failure [%s]: %d\n",
|
||||
|
|
|
@ -257,6 +257,8 @@ struct eg20t_port {
|
|||
dma_addr_t rx_buf_dma;
|
||||
|
||||
struct dentry *debugfs;
|
||||
#define IRQ_NAME_SIZE 17
|
||||
char irq_name[IRQ_NAME_SIZE];
|
||||
|
||||
/* protect the eg20t_port private structure and io access to membase */
|
||||
spinlock_t lock;
|
||||
|
@ -1343,7 +1345,7 @@ static int pch_uart_startup(struct uart_port *port)
|
|||
return ret;
|
||||
|
||||
ret = request_irq(priv->port.irq, pch_uart_interrupt, IRQF_SHARED,
|
||||
KBUILD_MODNAME, priv);
|
||||
priv->irq_name, priv);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -1588,13 +1590,8 @@ static void pch_uart_put_poll_char(struct uart_port *port,
|
|||
wait_for_xmitr(priv, UART_LSR_THRE);
|
||||
/*
|
||||
* Send the character out.
|
||||
* If a LF, also do CR...
|
||||
*/
|
||||
iowrite8(c, priv->membase + PCH_UART_THR);
|
||||
if (c == 10) {
|
||||
wait_for_xmitr(priv, UART_LSR_THRE);
|
||||
iowrite8(13, priv->membase + PCH_UART_THR);
|
||||
}
|
||||
|
||||
/*
|
||||
* Finally, wait for transmitter to become empty
|
||||
|
@ -1818,6 +1815,10 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
|
|||
priv->port.line = board->line_no;
|
||||
priv->trigger = PCH_UART_HAL_TRIGGER_M;
|
||||
|
||||
snprintf(priv->irq_name, IRQ_NAME_SIZE,
|
||||
KBUILD_MODNAME ":" PCH_UART_DRIVER_DEVICE "%d",
|
||||
priv->port.line);
|
||||
|
||||
spin_lock_init(&priv->port.lock);
|
||||
|
||||
pci_set_drvdata(pdev, priv);
|
||||
|
|
|
@ -711,13 +711,8 @@ static void serial_pxa_put_poll_char(struct uart_port *port,
|
|||
wait_for_xmitr(up);
|
||||
/*
|
||||
* Send the character out.
|
||||
* If a LF, also do CR...
|
||||
*/
|
||||
serial_out(up, UART_TX, c);
|
||||
if (c == 10) {
|
||||
wait_for_xmitr(up);
|
||||
serial_out(up, UART_TX, 13);
|
||||
}
|
||||
|
||||
/*
|
||||
* Finally, wait for transmitter to become empty
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2239,6 +2239,9 @@ static void uart_poll_put_char(struct tty_driver *driver, int line, char ch)
|
|||
return;
|
||||
|
||||
port = state->uart_port;
|
||||
|
||||
if (ch == '\n')
|
||||
port->ops->poll_put_char(port, '\r');
|
||||
port->ops->poll_put_char(port, ch);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -535,13 +535,8 @@ static void serial_txx9_put_poll_char(struct uart_port *port, unsigned char c)
|
|||
wait_for_xmitr(up);
|
||||
/*
|
||||
* Send the character out.
|
||||
* If a LF, also do CR...
|
||||
*/
|
||||
sio_out(up, TXX9_SITFIFO, c);
|
||||
if (c == 10) {
|
||||
wait_for_xmitr(up);
|
||||
sio_out(up, TXX9_SITFIFO, 13);
|
||||
}
|
||||
|
||||
/*
|
||||
* Finally, wait for transmitter to become empty
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -285,6 +285,22 @@ static inline int uart_poll_timeout(struct uart_port *port)
|
|||
/*
|
||||
* Console helpers.
|
||||
*/
|
||||
struct earlycon_device {
|
||||
struct console *con;
|
||||
struct uart_port port;
|
||||
char options[16]; /* e.g., 115200n8 */
|
||||
unsigned int baud;
|
||||
};
|
||||
int setup_earlycon(char *buf, const char *match,
|
||||
int (*setup)(struct earlycon_device *, const char *));
|
||||
|
||||
#define EARLYCON_DECLARE(name, func) \
|
||||
static int __init name ## _setup_earlycon(char *buf) \
|
||||
{ \
|
||||
return setup_earlycon(buf, __stringify(name), func); \
|
||||
} \
|
||||
early_param("earlycon", name ## _setup_earlycon);
|
||||
|
||||
struct uart_port *uart_get_console(struct uart_port *ports, int nr,
|
||||
struct console *c);
|
||||
void uart_parse_options(char *options, int *baud, int *parity, int *bits,
|
||||
|
|
|
@ -92,7 +92,10 @@
|
|||
* This function is called by the low-level tty driver to signal
|
||||
* that line discpline should try to send more characters to the
|
||||
* low-level driver for transmission. If the line discpline does
|
||||
* not have any more data to send, it can just return.
|
||||
* not have any more data to send, it can just return. If the line
|
||||
* discipline does have some data to send, please arise a tasklet
|
||||
* or workqueue to do the real data transfer. Do not send data in
|
||||
* this hook, it may leads to a deadlock.
|
||||
*
|
||||
* int (*hangup)(struct tty_struct *)
|
||||
*
|
||||
|
|
|
@ -211,7 +211,7 @@
|
|||
/* VIA VT8500 SoC */
|
||||
#define PORT_VT8500 97
|
||||
|
||||
/* Xilinx PSS UART */
|
||||
/* Cadence (Xilinx Zynq) UART */
|
||||
#define PORT_XUARTPS 98
|
||||
|
||||
/* Atheros AR933X SoC */
|
||||
|
@ -238,4 +238,10 @@
|
|||
/* Tilera TILE-Gx UART */
|
||||
#define PORT_TILEGX 106
|
||||
|
||||
/* MEN 16z135 UART */
|
||||
#define PORT_MEN_Z135 107
|
||||
|
||||
/* SC16IS74xx */
|
||||
#define PORT_SC16IS7XX 108
|
||||
|
||||
#endif /* _UAPILINUX_SERIAL_CORE_H */
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
#define UART_IIR 2 /* In: Interrupt ID Register */
|
||||
#define UART_IIR_NO_INT 0x01 /* No interrupts pending */
|
||||
#define UART_IIR_ID 0x06 /* Mask for the interrupt ID */
|
||||
#define UART_IIR_ID 0x0e /* Mask for the interrupt ID */
|
||||
#define UART_IIR_MSI 0x00 /* Modem status interrupt */
|
||||
#define UART_IIR_THRI 0x02 /* Transmitter holding register empty */
|
||||
#define UART_IIR_RDI 0x04 /* Receiver data interrupt */
|
||||
|
|
Loading…
Reference in New Issue