提交 e6dce825 编写于 作者: L Linus Torvalds

Merge tag 'tty-4.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty

Pull tty and serial updates from Greg KH:
 "Here is the big tty and serial patch set for 4.9-rc1.

  It also includes some drivers/dma/ changes, as those were needed by
  some serial drivers, and they were all acked by the DMA maintainer.

  Also in here is the long-suffering ACPI SPCR patchset, which was
  passed around from maintainer to maintainer like a hot-potato. Seems I
  was the sucker^Wlucky one. All of those patches have been acked by the
  various subsystem maintainers as well.

  All of this has been in linux-next with no reported issues"

* tag 'tty-4.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (111 commits)
  Revert "serial: pl011: add console matching function"
  MAINTAINERS: update entry for atmel_serial driver
  serial: pl011: add console matching function
  ARM64: ACPI: enable ACPI_SPCR_TABLE
  ACPI: parse SPCR and enable matching console
  of/serial: move earlycon early_param handling to serial
  Revert "drivers/tty: Explicitly pass current to show_stack"
  tty: amba-pl011: Don't complain on -EPROBE_DEFER when no irq
  nios2: dts: 10m50: Add tx-threshold parameter
  serial: 8250: Set Altera 16550 TX FIFO Threshold
  serial: 8250: of: Load TX FIFO Threshold from DT
  Documentation: dt: serial: Add TX FIFO threshold parameter
  drivers/tty: Explicitly pass current to show_stack
  serial: imx: Fix DCD reading
  serial: stm32: mark symbols static where possible
  serial: xuartps: Add some register initialisation to cdns_early_console_setup()
  serial: xuartps: Removed unwanted checks while reading the error conditions
  serial: xuartps: Rewrite the interrupt handling logic
  serial: stm32: use mapbase instead of membase for DMA
  tty/serial: atmel: fix fractional baud rate computation
  ...
...@@ -42,6 +42,8 @@ Optional properties: ...@@ -42,6 +42,8 @@ Optional properties:
- auto-flow-control: one way to enable automatic flow control support. The - auto-flow-control: one way to enable automatic flow control support. The
driver is allowed to detect support for the capability even without this driver is allowed to detect support for the capability even without this
property. property.
- tx-threshold: Specify the TX FIFO low water indication for parts with
programmable TX FIFO thresholds.
Note: Note:
* fsl,ns16550: * fsl,ns16550:
......
* STMicroelectronics STM32 USART
Required properties:
- compatible: Can be either "st,stm32-usart", "st,stm32-uart",
"st,stm32f7-usart" or "st,stm32f7-uart" depending on whether
the device supports synchronous mode and is compatible with
stm32(f4) or stm32f7.
- reg: The address and length of the peripheral registers space
- interrupts: The interrupt line of the USART instance
- clocks: The input clock of the USART instance
Optional properties:
- pinctrl: The reference on the pins configuration
- st,hw-flow-ctrl: bool flag to enable hardware flow control.
- dmas: phandle(s) to DMA controller node(s). Refer to stm32-dma.txt
- dma-names: "rx" and/or "tx"
Examples:
usart4: serial@40004c00 {
compatible = "st,stm32-uart";
reg = <0x40004c00 0x400>;
interrupts = <52>;
clocks = <&clk_pclk1>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usart4>;
};
usart2: serial@40004400 {
compatible = "st,stm32-usart", "st,stm32-uart";
reg = <0x40004400 0x400>;
interrupts = <38>;
clocks = <&clk_pclk1>;
st,hw-flow-ctrl;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usart2 &pinctrl_usart2_rtscts>;
};
usart1: serial@40011000 {
compatible = "st,stm32-usart", "st,stm32-uart";
reg = <0x40011000 0x400>;
interrupts = <37>;
clocks = <&rcc 0 164>;
dmas = <&dma2 2 4 0x414 0x0>,
<&dma2 7 4 0x414 0x0>;
dma-names = "rx", "tx";
};
...@@ -1054,11 +1054,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted. ...@@ -1054,11 +1054,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
determined by the stdout-path property in device determined by the stdout-path property in device
tree's chosen node. tree's chosen node.
cdns,<addr> cdns,<addr>[,options]
Start an early, polled-mode console on a cadence serial Start an early, polled-mode console on a Cadence
port at the specified address. The cadence serial port (xuartps) serial port at the specified address. Only
must already be setup and configured. Options are not supported option is baud rate. If baud rate is not
yet supported. specified, the serial port must already be setup and
configured.
uart[8250],io,<addr>[,options] uart[8250],io,<addr>[,options]
uart[8250],mmio,<addr>[,options] uart[8250],mmio,<addr>[,options]
......
...@@ -2121,11 +2121,6 @@ M: Ludovic Desroches <ludovic.desroches@atmel.com> ...@@ -2121,11 +2121,6 @@ M: Ludovic Desroches <ludovic.desroches@atmel.com>
S: Maintained S: Maintained
F: drivers/mmc/host/atmel-mci.c F: drivers/mmc/host/atmel-mci.c
ATMEL AT91 / AT32 SERIAL DRIVER
M: Nicolas Ferre <nicolas.ferre@atmel.com>
S: Supported
F: drivers/tty/serial/atmel_serial.c
ATMEL AT91 SAMA5D2-Compatible Shutdown Controller ATMEL AT91 SAMA5D2-Compatible Shutdown Controller
M: Nicolas Ferre <nicolas.ferre@atmel.com> M: Nicolas Ferre <nicolas.ferre@atmel.com>
S: Supported S: Supported
...@@ -7774,6 +7769,12 @@ T: git git://git.monstr.eu/linux-2.6-microblaze.git ...@@ -7774,6 +7769,12 @@ T: git git://git.monstr.eu/linux-2.6-microblaze.git
S: Supported S: Supported
F: arch/microblaze/ F: arch/microblaze/
MICROCHIP / ATMEL AT91 / AT32 SERIAL DRIVER
M: Richard Genoud <richard.genoud@gmail.com>
S: Maintained
F: drivers/tty/serial/atmel_serial.c
F: include/linux/atmel_serial.h
MICROSOFT SURFACE PRO 3 BUTTON DRIVER MICROSOFT SURFACE PRO 3 BUTTON DRIVER
M: Chen Yu <yu.c.chen@intel.com> M: Chen Yu <yu.c.chen@intel.com>
L: platform-driver-x86@vger.kernel.org L: platform-driver-x86@vger.kernel.org
......
...@@ -4,6 +4,7 @@ config ARM64 ...@@ -4,6 +4,7 @@ config ARM64
select ACPI_GENERIC_GSI if ACPI select ACPI_GENERIC_GSI if ACPI
select ACPI_REDUCED_HARDWARE_ONLY if ACPI select ACPI_REDUCED_HARDWARE_ONLY if ACPI
select ACPI_MCFG if ACPI select ACPI_MCFG if ACPI
select ACPI_SPCR_TABLE if ACPI
select ARCH_CLOCKSOURCE_DATA select ARCH_CLOCKSOURCE_DATA
select ARCH_HAS_DEVMEM_IS_ALLOWED select ARCH_HAS_DEVMEM_IS_ALLOWED
select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/memblock.h> #include <linux/memblock.h>
#include <linux/of_fdt.h> #include <linux/of_fdt.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/serial_core.h>
#include <asm/cputype.h> #include <asm/cputype.h>
#include <asm/cpu_ops.h> #include <asm/cpu_ops.h>
...@@ -206,7 +207,7 @@ void __init acpi_boot_table_init(void) ...@@ -206,7 +207,7 @@ void __init acpi_boot_table_init(void)
if (param_acpi_off || if (param_acpi_off ||
(!param_acpi_on && !param_acpi_force && (!param_acpi_on && !param_acpi_force &&
of_scan_flat_dt(dt_scan_depth1_nodes, NULL))) of_scan_flat_dt(dt_scan_depth1_nodes, NULL)))
return; goto done;
/* /*
* ACPI is disabled at this point. Enable it in order to parse * ACPI is disabled at this point. Enable it in order to parse
...@@ -226,6 +227,14 @@ void __init acpi_boot_table_init(void) ...@@ -226,6 +227,14 @@ void __init acpi_boot_table_init(void)
if (!param_acpi_force) if (!param_acpi_force)
disable_acpi(); disable_acpi();
} }
done:
if (acpi_disabled) {
if (earlycon_init_is_deferred)
early_init_dt_scan_chosen_stdout();
} else {
parse_spcr(earlycon_init_is_deferred);
}
} }
#ifdef CONFIG_ACPI_APEI #ifdef CONFIG_ACPI_APEI
......
...@@ -83,6 +83,7 @@ ...@@ -83,6 +83,7 @@
fifo-size = <32>; fifo-size = <32>;
reg-io-width = <4>; reg-io-width = <4>;
reg-shift = <2>; reg-shift = <2>;
tx-threshold = <16>;
}; };
sysid: sysid@18001528 { sysid: sysid@18001528 {
......
...@@ -77,6 +77,9 @@ config ACPI_DEBUGGER_USER ...@@ -77,6 +77,9 @@ config ACPI_DEBUGGER_USER
endif endif
config ACPI_SPCR_TABLE
bool
config ACPI_SLEEP config ACPI_SLEEP
bool bool
depends on SUSPEND || HIBERNATION depends on SUSPEND || HIBERNATION
......
...@@ -82,6 +82,7 @@ obj-$(CONFIG_ACPI_EC_DEBUGFS) += ec_sys.o ...@@ -82,6 +82,7 @@ obj-$(CONFIG_ACPI_EC_DEBUGFS) += ec_sys.o
obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o
obj-$(CONFIG_ACPI_BGRT) += bgrt.o obj-$(CONFIG_ACPI_BGRT) += bgrt.o
obj-$(CONFIG_ACPI_CPPC_LIB) += cppc_acpi.o obj-$(CONFIG_ACPI_CPPC_LIB) += cppc_acpi.o
obj-$(CONFIG_ACPI_SPCR_TABLE) += spcr.o
obj-$(CONFIG_ACPI_DEBUGGER_USER) += acpi_dbg.o obj-$(CONFIG_ACPI_DEBUGGER_USER) += acpi_dbg.o
# processor has its own "processor." module_param namespace # processor has its own "processor." module_param namespace
......
/*
* Copyright (c) 2012, Intel Corporation
* Copyright (c) 2015, Red Hat, Inc.
* Copyright (c) 2015, 2016 Linaro Ltd.
*
* 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.
*
*/
#define pr_fmt(fmt) "ACPI: SPCR: " fmt
#include <linux/acpi.h>
#include <linux/console.h>
#include <linux/kernel.h>
#include <linux/serial_core.h>
/**
* parse_spcr() - parse ACPI SPCR table and add preferred console
*
* @earlycon: set up earlycon for the console specified by the table
*
* For the architectures with support for ACPI, CONFIG_ACPI_SPCR_TABLE may be
* defined to parse ACPI SPCR table. As a result of the parsing preferred
* console is registered and if @earlycon is true, earlycon is set up.
*
* When CONFIG_ACPI_SPCR_TABLE is defined, this function should be called
* from arch inintialization code as soon as the DT/ACPI decision is made.
*
*/
int __init parse_spcr(bool earlycon)
{
static char opts[64];
struct acpi_table_spcr *table;
acpi_size table_size;
acpi_status status;
char *uart;
char *iotype;
int baud_rate;
int err;
if (acpi_disabled)
return -ENODEV;
status = acpi_get_table_with_size(ACPI_SIG_SPCR, 0,
(struct acpi_table_header **)&table,
&table_size);
if (ACPI_FAILURE(status))
return -ENOENT;
if (table->header.revision < 2) {
err = -ENOENT;
pr_err("wrong table version\n");
goto done;
}
iotype = table->serial_port.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY ?
"mmio" : "io";
switch (table->interface_type) {
case ACPI_DBG2_ARM_SBSA_32BIT:
iotype = "mmio32";
/* fall through */
case ACPI_DBG2_ARM_PL011:
case ACPI_DBG2_ARM_SBSA_GENERIC:
case ACPI_DBG2_BCM2835:
uart = "pl011";
break;
case ACPI_DBG2_16550_COMPATIBLE:
case ACPI_DBG2_16550_SUBSET:
uart = "uart";
break;
default:
err = -ENOENT;
goto done;
}
switch (table->baud_rate) {
case 3:
baud_rate = 9600;
break;
case 4:
baud_rate = 19200;
break;
case 6:
baud_rate = 57600;
break;
case 7:
baud_rate = 115200;
break;
default:
err = -ENOENT;
goto done;
}
snprintf(opts, sizeof(opts), "%s,%s,0x%llx,%d", uart, iotype,
table->serial_port.address, baud_rate);
pr_info("console: %s\n", opts);
if (earlycon)
setup_earlycon(opts);
err = add_preferred_console(uart, 0, opts + strlen(uart) + 1);
done:
early_acpi_os_unmap_memory((void __iomem *)table, table_size);
return err;
}
...@@ -46,9 +46,9 @@ ...@@ -46,9 +46,9 @@
u8 _dmsize = _is_slave ? _sconfig->dst_maxburst : \ u8 _dmsize = _is_slave ? _sconfig->dst_maxburst : \
DW_DMA_MSIZE_16; \ DW_DMA_MSIZE_16; \
u8 _dms = (_dwc->direction == DMA_MEM_TO_DEV) ? \ u8 _dms = (_dwc->direction == DMA_MEM_TO_DEV) ? \
_dwc->p_master : _dwc->m_master; \ _dwc->dws.p_master : _dwc->dws.m_master; \
u8 _sms = (_dwc->direction == DMA_DEV_TO_MEM) ? \ u8 _sms = (_dwc->direction == DMA_DEV_TO_MEM) ? \
_dwc->p_master : _dwc->m_master; \ _dwc->dws.p_master : _dwc->dws.m_master; \
\ \
(DWC_CTLL_DST_MSIZE(_dmsize) \ (DWC_CTLL_DST_MSIZE(_dmsize) \
| DWC_CTLL_SRC_MSIZE(_smsize) \ | DWC_CTLL_SRC_MSIZE(_smsize) \
...@@ -143,12 +143,16 @@ static void dwc_initialize(struct dw_dma_chan *dwc) ...@@ -143,12 +143,16 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
struct dw_dma *dw = to_dw_dma(dwc->chan.device); struct dw_dma *dw = to_dw_dma(dwc->chan.device);
u32 cfghi = DWC_CFGH_FIFO_MODE; u32 cfghi = DWC_CFGH_FIFO_MODE;
u32 cfglo = DWC_CFGL_CH_PRIOR(dwc->priority); u32 cfglo = DWC_CFGL_CH_PRIOR(dwc->priority);
bool hs_polarity = dwc->dws.hs_polarity;
if (test_bit(DW_DMA_IS_INITIALIZED, &dwc->flags)) if (test_bit(DW_DMA_IS_INITIALIZED, &dwc->flags))
return; return;
cfghi |= DWC_CFGH_DST_PER(dwc->dst_id); cfghi |= DWC_CFGH_DST_PER(dwc->dws.dst_id);
cfghi |= DWC_CFGH_SRC_PER(dwc->src_id); cfghi |= DWC_CFGH_SRC_PER(dwc->dws.src_id);
/* Set polarity of handshake interface */
cfglo |= hs_polarity ? DWC_CFGL_HS_DST_POL | DWC_CFGL_HS_SRC_POL : 0;
channel_writel(dwc, CFG_LO, cfglo); channel_writel(dwc, CFG_LO, cfglo);
channel_writel(dwc, CFG_HI, cfghi); channel_writel(dwc, CFG_HI, cfghi);
...@@ -209,7 +213,7 @@ static inline void dwc_do_single_block(struct dw_dma_chan *dwc, ...@@ -209,7 +213,7 @@ static inline void dwc_do_single_block(struct dw_dma_chan *dwc,
static void dwc_dostart(struct dw_dma_chan *dwc, struct dw_desc *first) static void dwc_dostart(struct dw_dma_chan *dwc, struct dw_desc *first)
{ {
struct dw_dma *dw = to_dw_dma(dwc->chan.device); struct dw_dma *dw = to_dw_dma(dwc->chan.device);
u8 lms = DWC_LLP_LMS(dwc->m_master); u8 lms = DWC_LLP_LMS(dwc->dws.m_master);
unsigned long was_soft_llp; unsigned long was_soft_llp;
/* ASSERT: channel is idle */ /* ASSERT: channel is idle */
...@@ -662,7 +666,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, ...@@ -662,7 +666,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
struct dw_desc *prev; struct dw_desc *prev;
size_t xfer_count; size_t xfer_count;
size_t offset; size_t offset;
u8 m_master = dwc->m_master; u8 m_master = dwc->dws.m_master;
unsigned int src_width; unsigned int src_width;
unsigned int dst_width; unsigned int dst_width;
unsigned int data_width = dw->pdata->data_width[m_master]; unsigned int data_width = dw->pdata->data_width[m_master];
...@@ -740,7 +744,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, ...@@ -740,7 +744,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
struct dw_desc *prev; struct dw_desc *prev;
struct dw_desc *first; struct dw_desc *first;
u32 ctllo; u32 ctllo;
u8 m_master = dwc->m_master; u8 m_master = dwc->dws.m_master;
u8 lms = DWC_LLP_LMS(m_master); u8 lms = DWC_LLP_LMS(m_master);
dma_addr_t reg; dma_addr_t reg;
unsigned int reg_width; unsigned int reg_width;
...@@ -895,12 +899,7 @@ bool dw_dma_filter(struct dma_chan *chan, void *param) ...@@ -895,12 +899,7 @@ bool dw_dma_filter(struct dma_chan *chan, void *param)
return false; return false;
/* We have to copy data since dws can be temporary storage */ /* We have to copy data since dws can be temporary storage */
memcpy(&dwc->dws, dws, sizeof(struct dw_dma_slave));
dwc->src_id = dws->src_id;
dwc->dst_id = dws->dst_id;
dwc->m_master = dws->m_master;
dwc->p_master = dws->p_master;
return true; return true;
} }
...@@ -1167,11 +1166,7 @@ static void dwc_free_chan_resources(struct dma_chan *chan) ...@@ -1167,11 +1166,7 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
spin_lock_irqsave(&dwc->lock, flags); spin_lock_irqsave(&dwc->lock, flags);
/* Clear custom channel configuration */ /* Clear custom channel configuration */
dwc->src_id = 0; memset(&dwc->dws, 0, sizeof(struct dw_dma_slave));
dwc->dst_id = 0;
dwc->m_master = 0;
dwc->p_master = 0;
clear_bit(DW_DMA_IS_INITIALIZED, &dwc->flags); clear_bit(DW_DMA_IS_INITIALIZED, &dwc->flags);
...@@ -1264,7 +1259,7 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan, ...@@ -1264,7 +1259,7 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan,
struct dw_cyclic_desc *retval = NULL; struct dw_cyclic_desc *retval = NULL;
struct dw_desc *desc; struct dw_desc *desc;
struct dw_desc *last = NULL; struct dw_desc *last = NULL;
u8 lms = DWC_LLP_LMS(dwc->m_master); u8 lms = DWC_LLP_LMS(dwc->dws.m_master);
unsigned long was_cyclic; unsigned long was_cyclic;
unsigned int reg_width; unsigned int reg_width;
unsigned int periods; unsigned int periods;
...@@ -1576,11 +1571,7 @@ int dw_dma_probe(struct dw_dma_chip *chip) ...@@ -1576,11 +1571,7 @@ int dw_dma_probe(struct dw_dma_chip *chip)
(dwc_params >> DWC_PARAMS_MBLK_EN & 0x1) == 0; (dwc_params >> DWC_PARAMS_MBLK_EN & 0x1) == 0;
} else { } else {
dwc->block_size = pdata->block_size; dwc->block_size = pdata->block_size;
dwc->nollp = pdata->is_nollp;
/* Check if channel supports multi block transfer */
channel_writel(dwc, LLP, DWC_LLP_LOC(0xffffffff));
dwc->nollp = DWC_LLP_LOC(channel_readl(dwc, LLP)) == 0;
channel_writel(dwc, LLP, 0);
} }
} }
......
...@@ -245,10 +245,7 @@ struct dw_dma_chan { ...@@ -245,10 +245,7 @@ struct dw_dma_chan {
bool nollp; bool nollp;
/* custom slave configuration */ /* custom slave configuration */
u8 src_id; struct dw_dma_slave dws;
u8 dst_id;
u8 m_master;
u8 p_master;
/* configuration passed via .device_config */ /* configuration passed via .device_config */
struct dma_slave_config dma_sconfig; struct dma_slave_config dma_sconfig;
......
...@@ -200,10 +200,9 @@ EXPORT_SYMBOL_GPL(hsu_dma_get_status); ...@@ -200,10 +200,9 @@ EXPORT_SYMBOL_GPL(hsu_dma_get_status);
* is not a normal timeout interrupt, ie. hsu_dma_get_status() returned 0. * is not a normal timeout interrupt, ie. hsu_dma_get_status() returned 0.
* *
* Return: * Return:
* IRQ_NONE for invalid channel number, IRQ_HANDLED otherwise. * 0 for invalid channel number, 1 otherwise.
*/ */
irqreturn_t hsu_dma_do_irq(struct hsu_dma_chip *chip, unsigned short nr, int hsu_dma_do_irq(struct hsu_dma_chip *chip, unsigned short nr, u32 status)
u32 status)
{ {
struct hsu_dma_chan *hsuc; struct hsu_dma_chan *hsuc;
struct hsu_dma_desc *desc; struct hsu_dma_desc *desc;
...@@ -211,7 +210,7 @@ irqreturn_t hsu_dma_do_irq(struct hsu_dma_chip *chip, unsigned short nr, ...@@ -211,7 +210,7 @@ irqreturn_t hsu_dma_do_irq(struct hsu_dma_chip *chip, unsigned short nr,
/* Sanity check */ /* Sanity check */
if (nr >= chip->hsu->nr_channels) if (nr >= chip->hsu->nr_channels)
return IRQ_NONE; return 0;
hsuc = &chip->hsu->chan[nr]; hsuc = &chip->hsu->chan[nr];
...@@ -230,7 +229,7 @@ irqreturn_t hsu_dma_do_irq(struct hsu_dma_chip *chip, unsigned short nr, ...@@ -230,7 +229,7 @@ irqreturn_t hsu_dma_do_irq(struct hsu_dma_chip *chip, unsigned short nr,
} }
spin_unlock_irqrestore(&hsuc->vchan.lock, flags); spin_unlock_irqrestore(&hsuc->vchan.lock, flags);
return IRQ_HANDLED; return 1;
} }
EXPORT_SYMBOL_GPL(hsu_dma_do_irq); EXPORT_SYMBOL_GPL(hsu_dma_do_irq);
......
...@@ -29,7 +29,7 @@ static irqreturn_t hsu_pci_irq(int irq, void *dev) ...@@ -29,7 +29,7 @@ static irqreturn_t hsu_pci_irq(int irq, void *dev)
u32 dmaisr; u32 dmaisr;
u32 status; u32 status;
unsigned short i; unsigned short i;
irqreturn_t ret = IRQ_NONE; int ret = 0;
int err; int err;
dmaisr = readl(chip->regs + HSU_PCI_DMAISR); dmaisr = readl(chip->regs + HSU_PCI_DMAISR);
...@@ -37,14 +37,14 @@ static irqreturn_t hsu_pci_irq(int irq, void *dev) ...@@ -37,14 +37,14 @@ static irqreturn_t hsu_pci_irq(int irq, void *dev)
if (dmaisr & 0x1) { if (dmaisr & 0x1) {
err = hsu_dma_get_status(chip, i, &status); err = hsu_dma_get_status(chip, i, &status);
if (err > 0) if (err > 0)
ret |= IRQ_HANDLED; ret |= 1;
else if (err == 0) else if (err == 0)
ret |= hsu_dma_do_irq(chip, i, status); ret |= hsu_dma_do_irq(chip, i, status);
} }
dmaisr >>= 1; dmaisr >>= 1;
} }
return ret; return IRQ_RETVAL(ret);
} }
static int hsu_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) static int hsu_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
......
...@@ -648,15 +648,11 @@ static void sdma_event_disable(struct sdma_channel *sdmac, unsigned int event) ...@@ -648,15 +648,11 @@ static void sdma_event_disable(struct sdma_channel *sdmac, unsigned int event)
writel_relaxed(val, sdma->regs + chnenbl); writel_relaxed(val, sdma->regs + chnenbl);
} }
static void sdma_handle_channel_loop(struct sdma_channel *sdmac)
{
if (sdmac->desc.callback)
sdmac->desc.callback(sdmac->desc.callback_param);
}
static void sdma_update_channel_loop(struct sdma_channel *sdmac) static void sdma_update_channel_loop(struct sdma_channel *sdmac)
{ {
struct sdma_buffer_descriptor *bd; struct sdma_buffer_descriptor *bd;
int error = 0;
enum dma_status old_status = sdmac->status;
/* /*
* loop mode. Iterate over descriptors, re-setup them and * loop mode. Iterate over descriptors, re-setup them and
...@@ -668,17 +664,42 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac) ...@@ -668,17 +664,42 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
if (bd->mode.status & BD_DONE) if (bd->mode.status & BD_DONE)
break; break;
if (bd->mode.status & BD_RROR) if (bd->mode.status & BD_RROR) {
bd->mode.status &= ~BD_RROR;
sdmac->status = DMA_ERROR; sdmac->status = DMA_ERROR;
error = -EIO;
}
/*
* We use bd->mode.count to calculate the residue, since contains
* the number of bytes present in the current buffer descriptor.
*/
sdmac->chn_real_count = bd->mode.count;
bd->mode.status |= BD_DONE; bd->mode.status |= BD_DONE;
bd->mode.count = sdmac->period_len;
/*
* The callback is called from the interrupt context in order
* to reduce latency and to avoid the risk of altering the
* SDMA transaction status by the time the client tasklet is
* executed.
*/
if (sdmac->desc.callback)
sdmac->desc.callback(sdmac->desc.callback_param);
sdmac->buf_tail++; sdmac->buf_tail++;
sdmac->buf_tail %= sdmac->num_bd; sdmac->buf_tail %= sdmac->num_bd;
if (error)
sdmac->status = old_status;
} }
} }
static void mxc_sdma_handle_channel_normal(struct sdma_channel *sdmac) static void mxc_sdma_handle_channel_normal(unsigned long data)
{ {
struct sdma_channel *sdmac = (struct sdma_channel *) data;
struct sdma_buffer_descriptor *bd; struct sdma_buffer_descriptor *bd;
int i, error = 0; int i, error = 0;
...@@ -705,16 +726,6 @@ static void mxc_sdma_handle_channel_normal(struct sdma_channel *sdmac) ...@@ -705,16 +726,6 @@ static void mxc_sdma_handle_channel_normal(struct sdma_channel *sdmac)
sdmac->desc.callback(sdmac->desc.callback_param); sdmac->desc.callback(sdmac->desc.callback_param);
} }
static void sdma_tasklet(unsigned long data)
{
struct sdma_channel *sdmac = (struct sdma_channel *) data;
if (sdmac->flags & IMX_DMA_SG_LOOP)
sdma_handle_channel_loop(sdmac);
else
mxc_sdma_handle_channel_normal(sdmac);
}
static irqreturn_t sdma_int_handler(int irq, void *dev_id) static irqreturn_t sdma_int_handler(int irq, void *dev_id)
{ {
struct sdma_engine *sdma = dev_id; struct sdma_engine *sdma = dev_id;
...@@ -731,8 +742,8 @@ static irqreturn_t sdma_int_handler(int irq, void *dev_id) ...@@ -731,8 +742,8 @@ static irqreturn_t sdma_int_handler(int irq, void *dev_id)
if (sdmac->flags & IMX_DMA_SG_LOOP) if (sdmac->flags & IMX_DMA_SG_LOOP)
sdma_update_channel_loop(sdmac); sdma_update_channel_loop(sdmac);
else
tasklet_schedule(&sdmac->tasklet); tasklet_schedule(&sdmac->tasklet);
__clear_bit(channel, &stat); __clear_bit(channel, &stat);
} }
...@@ -1353,7 +1364,8 @@ static enum dma_status sdma_tx_status(struct dma_chan *chan, ...@@ -1353,7 +1364,8 @@ static enum dma_status sdma_tx_status(struct dma_chan *chan,
u32 residue; u32 residue;
if (sdmac->flags & IMX_DMA_SG_LOOP) if (sdmac->flags & IMX_DMA_SG_LOOP)
residue = (sdmac->num_bd - sdmac->buf_tail) * sdmac->period_len; residue = (sdmac->num_bd - sdmac->buf_tail) *
sdmac->period_len - sdmac->chn_real_count;
else else
residue = sdmac->chn_count - sdmac->chn_real_count; residue = sdmac->chn_count - sdmac->chn_real_count;
...@@ -1732,7 +1744,7 @@ static int sdma_probe(struct platform_device *pdev) ...@@ -1732,7 +1744,7 @@ static int sdma_probe(struct platform_device *pdev)
dma_cookie_init(&sdmac->chan); dma_cookie_init(&sdmac->chan);
sdmac->channel = i; sdmac->channel = i;
tasklet_init(&sdmac->tasklet, sdma_tasklet, tasklet_init(&sdmac->tasklet, mxc_sdma_handle_channel_normal,
(unsigned long) sdmac); (unsigned long) sdmac);
/* /*
* Add the channel to the DMAC list. Do not add channel 0 though * Add the channel to the DMAC list. Do not add channel 0 though
......
...@@ -924,7 +924,7 @@ static inline void early_init_dt_check_for_initrd(unsigned long node) ...@@ -924,7 +924,7 @@ static inline void early_init_dt_check_for_initrd(unsigned long node)
#ifdef CONFIG_SERIAL_EARLYCON #ifdef CONFIG_SERIAL_EARLYCON
static int __init early_init_dt_scan_chosen_serial(void) int __init early_init_dt_scan_chosen_stdout(void)
{ {
int offset; int offset;
const char *p, *q, *options = NULL; const char *p, *q, *options = NULL;
...@@ -968,15 +968,6 @@ static int __init early_init_dt_scan_chosen_serial(void) ...@@ -968,15 +968,6 @@ static int __init early_init_dt_scan_chosen_serial(void)
} }
return -ENODEV; return -ENODEV;
} }
static int __init setup_of_earlycon(char *buf)
{
if (buf)
return 0;
return early_init_dt_scan_chosen_serial();
}
early_param("earlycon", setup_of_earlycon);
#endif #endif
/** /**
......
...@@ -800,7 +800,7 @@ static int ptmx_open(struct inode *inode, struct file *filp) ...@@ -800,7 +800,7 @@ static int ptmx_open(struct inode *inode, struct file *filp)
return retval; return retval;
} }
static struct file_operations ptmx_fops; static struct file_operations ptmx_fops __ro_after_init;
static void __init unix98_pty_init(void) static void __init unix98_pty_init(void)
{ {
......
...@@ -31,6 +31,11 @@ struct uart_8250_dma { ...@@ -31,6 +31,11 @@ struct uart_8250_dma {
struct dma_chan *rxchan; struct dma_chan *rxchan;
struct dma_chan *txchan; struct dma_chan *txchan;
/* Device address base for DMA operations */
phys_addr_t rx_dma_addr;
phys_addr_t tx_dma_addr;
/* DMA address of the buffer in memory */
dma_addr_t rx_addr; dma_addr_t rx_addr;
dma_addr_t tx_addr; dma_addr_t tx_addr;
......
...@@ -639,7 +639,7 @@ static int univ8250_console_match(struct console *co, char *name, int idx, ...@@ -639,7 +639,7 @@ static int univ8250_console_match(struct console *co, char *name, int idx,
{ {
char match[] = "uart"; /* 8250-specific earlycon name */ char match[] = "uart"; /* 8250-specific earlycon name */
unsigned char iotype; unsigned char iotype;
unsigned long addr; resource_size_t addr;
int i; int i;
if (strncmp(name, match, 4) != 0) if (strncmp(name, match, 4) != 0)
......
...@@ -142,7 +142,7 @@ void serial8250_rx_dma_flush(struct uart_8250_port *p) ...@@ -142,7 +142,7 @@ void serial8250_rx_dma_flush(struct uart_8250_port *p)
if (dma->rx_running) { if (dma->rx_running) {
dmaengine_pause(dma->rxchan); dmaengine_pause(dma->rxchan);
__dma_rx_complete(p); __dma_rx_complete(p);
dmaengine_terminate_all(dma->rxchan); dmaengine_terminate_async(dma->rxchan);
} }
} }
EXPORT_SYMBOL_GPL(serial8250_rx_dma_flush); EXPORT_SYMBOL_GPL(serial8250_rx_dma_flush);
...@@ -150,6 +150,10 @@ EXPORT_SYMBOL_GPL(serial8250_rx_dma_flush); ...@@ -150,6 +150,10 @@ EXPORT_SYMBOL_GPL(serial8250_rx_dma_flush);
int serial8250_request_dma(struct uart_8250_port *p) int serial8250_request_dma(struct uart_8250_port *p)
{ {
struct uart_8250_dma *dma = p->dma; struct uart_8250_dma *dma = p->dma;
phys_addr_t rx_dma_addr = dma->rx_dma_addr ?
dma->rx_dma_addr : p->port.mapbase;
phys_addr_t tx_dma_addr = dma->tx_dma_addr ?
dma->tx_dma_addr : p->port.mapbase;
dma_cap_mask_t mask; dma_cap_mask_t mask;
struct dma_slave_caps caps; struct dma_slave_caps caps;
int ret; int ret;
...@@ -157,11 +161,11 @@ int serial8250_request_dma(struct uart_8250_port *p) ...@@ -157,11 +161,11 @@ int serial8250_request_dma(struct uart_8250_port *p)
/* Default slave configuration parameters */ /* Default slave configuration parameters */
dma->rxconf.direction = DMA_DEV_TO_MEM; dma->rxconf.direction = DMA_DEV_TO_MEM;
dma->rxconf.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; dma->rxconf.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
dma->rxconf.src_addr = p->port.mapbase + UART_RX; dma->rxconf.src_addr = rx_dma_addr + UART_RX;
dma->txconf.direction = DMA_MEM_TO_DEV; dma->txconf.direction = DMA_MEM_TO_DEV;
dma->txconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; dma->txconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
dma->txconf.dst_addr = p->port.mapbase + UART_TX; dma->txconf.dst_addr = tx_dma_addr + UART_TX;
dma_cap_zero(mask); dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask); dma_cap_set(DMA_SLAVE, mask);
...@@ -247,14 +251,14 @@ void serial8250_release_dma(struct uart_8250_port *p) ...@@ -247,14 +251,14 @@ void serial8250_release_dma(struct uart_8250_port *p)
return; return;
/* Release RX resources */ /* Release RX resources */
dmaengine_terminate_all(dma->rxchan); dmaengine_terminate_sync(dma->rxchan);
dma_free_coherent(dma->rxchan->device->dev, dma->rx_size, dma->rx_buf, dma_free_coherent(dma->rxchan->device->dev, dma->rx_size, dma->rx_buf,
dma->rx_addr); dma->rx_addr);
dma_release_channel(dma->rxchan); dma_release_channel(dma->rxchan);
dma->rxchan = NULL; dma->rxchan = NULL;
/* Release TX resources */ /* Release TX resources */
dmaengine_terminate_all(dma->txchan); dmaengine_terminate_sync(dma->txchan);
dma_unmap_single(dma->txchan->device->dev, dma->tx_addr, dma_unmap_single(dma->txchan->device->dev, dma->tx_addr,
UART_XMIT_SIZE, DMA_TO_DEVICE); UART_XMIT_SIZE, DMA_TO_DEVICE);
dma_release_channel(dma->txchan); dma_release_channel(dma->txchan);
......
...@@ -365,18 +365,19 @@ static int dw8250_probe(struct platform_device *pdev) ...@@ -365,18 +365,19 @@ static int dw8250_probe(struct platform_device *pdev)
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
int irq = platform_get_irq(pdev, 0); int irq = platform_get_irq(pdev, 0);
struct uart_port *p = &uart.port; struct uart_port *p = &uart.port;
struct device *dev = &pdev->dev;
struct dw8250_data *data; struct dw8250_data *data;
int err; int err;
u32 val; u32 val;
if (!regs) { if (!regs) {
dev_err(&pdev->dev, "no registers defined\n"); dev_err(dev, "no registers defined\n");
return -EINVAL; return -EINVAL;
} }
if (irq < 0) { if (irq < 0) {
if (irq != -EPROBE_DEFER) if (irq != -EPROBE_DEFER)
dev_err(&pdev->dev, "cannot get irq\n"); dev_err(dev, "cannot get irq\n");
return irq; return irq;
} }
...@@ -387,16 +388,16 @@ static int dw8250_probe(struct platform_device *pdev) ...@@ -387,16 +388,16 @@ static int dw8250_probe(struct platform_device *pdev)
p->pm = dw8250_do_pm; p->pm = dw8250_do_pm;
p->type = PORT_8250; p->type = PORT_8250;
p->flags = UPF_SHARE_IRQ | UPF_FIXED_PORT; p->flags = UPF_SHARE_IRQ | UPF_FIXED_PORT;
p->dev = &pdev->dev; p->dev = dev;
p->iotype = UPIO_MEM; p->iotype = UPIO_MEM;
p->serial_in = dw8250_serial_in; p->serial_in = dw8250_serial_in;
p->serial_out = dw8250_serial_out; p->serial_out = dw8250_serial_out;
p->membase = devm_ioremap(&pdev->dev, regs->start, resource_size(regs)); p->membase = devm_ioremap(dev, regs->start, resource_size(regs));
if (!p->membase) if (!p->membase)
return -ENOMEM; return -ENOMEM;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data) if (!data)
return -ENOMEM; return -ENOMEM;
...@@ -404,57 +405,57 @@ static int dw8250_probe(struct platform_device *pdev) ...@@ -404,57 +405,57 @@ static int dw8250_probe(struct platform_device *pdev)
data->usr_reg = DW_UART_USR; data->usr_reg = DW_UART_USR;
p->private_data = data; p->private_data = data;
data->uart_16550_compatible = device_property_read_bool(p->dev, data->uart_16550_compatible = device_property_read_bool(dev,
"snps,uart-16550-compatible"); "snps,uart-16550-compatible");
err = device_property_read_u32(p->dev, "reg-shift", &val); err = device_property_read_u32(dev, "reg-shift", &val);
if (!err) if (!err)
p->regshift = val; p->regshift = val;
err = device_property_read_u32(p->dev, "reg-io-width", &val); err = device_property_read_u32(dev, "reg-io-width", &val);
if (!err && val == 4) { if (!err && val == 4) {
p->iotype = UPIO_MEM32; p->iotype = UPIO_MEM32;
p->serial_in = dw8250_serial_in32; p->serial_in = dw8250_serial_in32;
p->serial_out = dw8250_serial_out32; p->serial_out = dw8250_serial_out32;
} }
if (device_property_read_bool(p->dev, "dcd-override")) { if (device_property_read_bool(dev, "dcd-override")) {
/* Always report DCD as active */ /* Always report DCD as active */
data->msr_mask_on |= UART_MSR_DCD; data->msr_mask_on |= UART_MSR_DCD;
data->msr_mask_off |= UART_MSR_DDCD; data->msr_mask_off |= UART_MSR_DDCD;
} }
if (device_property_read_bool(p->dev, "dsr-override")) { if (device_property_read_bool(dev, "dsr-override")) {
/* Always report DSR as active */ /* Always report DSR as active */
data->msr_mask_on |= UART_MSR_DSR; data->msr_mask_on |= UART_MSR_DSR;
data->msr_mask_off |= UART_MSR_DDSR; data->msr_mask_off |= UART_MSR_DDSR;
} }
if (device_property_read_bool(p->dev, "cts-override")) { if (device_property_read_bool(dev, "cts-override")) {
/* Always report CTS as active */ /* Always report CTS as active */
data->msr_mask_on |= UART_MSR_CTS; data->msr_mask_on |= UART_MSR_CTS;
data->msr_mask_off |= UART_MSR_DCTS; data->msr_mask_off |= UART_MSR_DCTS;
} }
if (device_property_read_bool(p->dev, "ri-override")) { if (device_property_read_bool(dev, "ri-override")) {
/* Always report Ring indicator as inactive */ /* Always report Ring indicator as inactive */
data->msr_mask_off |= UART_MSR_RI; data->msr_mask_off |= UART_MSR_RI;
data->msr_mask_off |= UART_MSR_TERI; data->msr_mask_off |= UART_MSR_TERI;
} }
/* Always ask for fixed clock rate from a property. */ /* Always ask for fixed clock rate from a property. */
device_property_read_u32(p->dev, "clock-frequency", &p->uartclk); device_property_read_u32(dev, "clock-frequency", &p->uartclk);
/* If there is separate baudclk, get the rate from it. */ /* If there is separate baudclk, get the rate from it. */
data->clk = devm_clk_get(&pdev->dev, "baudclk"); data->clk = devm_clk_get(dev, "baudclk");
if (IS_ERR(data->clk) && PTR_ERR(data->clk) != -EPROBE_DEFER) if (IS_ERR(data->clk) && PTR_ERR(data->clk) != -EPROBE_DEFER)
data->clk = devm_clk_get(&pdev->dev, NULL); data->clk = devm_clk_get(dev, NULL);
if (IS_ERR(data->clk) && PTR_ERR(data->clk) == -EPROBE_DEFER) if (IS_ERR(data->clk) && PTR_ERR(data->clk) == -EPROBE_DEFER)
return -EPROBE_DEFER; return -EPROBE_DEFER;
if (!IS_ERR_OR_NULL(data->clk)) { if (!IS_ERR_OR_NULL(data->clk)) {
err = clk_prepare_enable(data->clk); err = clk_prepare_enable(data->clk);
if (err) if (err)
dev_warn(&pdev->dev, "could not enable optional baudclk: %d\n", dev_warn(dev, "could not enable optional baudclk: %d\n",
err); err);
else else
p->uartclk = clk_get_rate(data->clk); p->uartclk = clk_get_rate(data->clk);
...@@ -462,24 +463,24 @@ static int dw8250_probe(struct platform_device *pdev) ...@@ -462,24 +463,24 @@ static int dw8250_probe(struct platform_device *pdev)
/* If no clock rate is defined, fail. */ /* If no clock rate is defined, fail. */
if (!p->uartclk) { if (!p->uartclk) {
dev_err(&pdev->dev, "clock rate not defined\n"); dev_err(dev, "clock rate not defined\n");
return -EINVAL; return -EINVAL;
} }
data->pclk = devm_clk_get(&pdev->dev, "apb_pclk"); data->pclk = devm_clk_get(dev, "apb_pclk");
if (IS_ERR(data->clk) && PTR_ERR(data->clk) == -EPROBE_DEFER) { if (IS_ERR(data->pclk) && PTR_ERR(data->pclk) == -EPROBE_DEFER) {
err = -EPROBE_DEFER; err = -EPROBE_DEFER;
goto err_clk; goto err_clk;
} }
if (!IS_ERR(data->pclk)) { if (!IS_ERR(data->pclk)) {
err = clk_prepare_enable(data->pclk); err = clk_prepare_enable(data->pclk);
if (err) { if (err) {
dev_err(&pdev->dev, "could not enable apb_pclk\n"); dev_err(dev, "could not enable apb_pclk\n");
goto err_clk; goto err_clk;
} }
} }
data->rst = devm_reset_control_get_optional(&pdev->dev, NULL); data->rst = devm_reset_control_get_optional(dev, NULL);
if (IS_ERR(data->rst) && PTR_ERR(data->rst) == -EPROBE_DEFER) { if (IS_ERR(data->rst) && PTR_ERR(data->rst) == -EPROBE_DEFER) {
err = -EPROBE_DEFER; err = -EPROBE_DEFER;
goto err_pclk; goto err_pclk;
...@@ -511,8 +512,8 @@ static int dw8250_probe(struct platform_device *pdev) ...@@ -511,8 +512,8 @@ static int dw8250_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, data); platform_set_drvdata(pdev, data);
pm_runtime_set_active(&pdev->dev); pm_runtime_set_active(dev);
pm_runtime_enable(&pdev->dev); pm_runtime_enable(dev);
return 0; return 0;
...@@ -624,6 +625,7 @@ static const struct acpi_device_id dw8250_acpi_match[] = { ...@@ -624,6 +625,7 @@ static const struct acpi_device_id dw8250_acpi_match[] = {
{ "APMC0D08", 0}, { "APMC0D08", 0},
{ "AMD0020", 0 }, { "AMD0020", 0 },
{ "AMDI0020", 0 }, { "AMDI0020", 0 },
{ "HISI0031", 0 },
{ }, { },
}; };
MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match); MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match);
......
/*
* 8250_lpss.c - Driver for UART on Intel Braswell and various other Intel SoCs
*
* Copyright (C) 2016 Intel Corporation
* Author: Andy Shevchenko <andriy.shevchenko@linux.intel.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/bitops.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/rational.h>
#include <linux/dmaengine.h>
#include <linux/dma/dw.h>
#include "8250.h"
#define PCI_DEVICE_ID_INTEL_QRK_UARTx 0x0936
#define PCI_DEVICE_ID_INTEL_BYT_UART1 0x0f0a
#define PCI_DEVICE_ID_INTEL_BYT_UART2 0x0f0c
#define PCI_DEVICE_ID_INTEL_BSW_UART1 0x228a
#define PCI_DEVICE_ID_INTEL_BSW_UART2 0x228c
#define PCI_DEVICE_ID_INTEL_BDW_UART1 0x9ce3
#define PCI_DEVICE_ID_INTEL_BDW_UART2 0x9ce4
/* Intel LPSS specific registers */
#define BYT_PRV_CLK 0x800
#define BYT_PRV_CLK_EN BIT(0)
#define BYT_PRV_CLK_M_VAL_SHIFT 1
#define BYT_PRV_CLK_N_VAL_SHIFT 16
#define BYT_PRV_CLK_UPDATE BIT(31)
#define BYT_TX_OVF_INT 0x820
#define BYT_TX_OVF_INT_MASK BIT(1)
struct lpss8250;
struct lpss8250_board {
unsigned long freq;
unsigned int base_baud;
int (*setup)(struct lpss8250 *, struct uart_port *p);
void (*exit)(struct lpss8250 *);
};
struct lpss8250 {
int line;
struct lpss8250_board *board;
/* DMA parameters */
struct uart_8250_dma dma;
struct dw_dma_chip dma_chip;
struct dw_dma_slave dma_param;
u8 dma_maxburst;
};
static void byt_set_termios(struct uart_port *p, struct ktermios *termios,
struct ktermios *old)
{
unsigned int baud = tty_termios_baud_rate(termios);
struct lpss8250 *lpss = p->private_data;
unsigned long fref = lpss->board->freq, fuart = baud * 16;
unsigned long w = BIT(15) - 1;
unsigned long m, n;
u32 reg;
/* Gracefully handle the B0 case: fall back to B9600 */
fuart = fuart ? fuart : 9600 * 16;
/* Get Fuart closer to Fref */
fuart *= rounddown_pow_of_two(fref / fuart);
/*
* 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
*/
rational_best_approximation(fuart, fref, w, w, &m, &n);
p->uartclk = fuart;
/* 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);
p->status &= ~UPSTAT_AUTOCTS;
if (termios->c_cflag & CRTSCTS)
p->status |= UPSTAT_AUTOCTS;
serial8250_do_set_termios(p, termios, old);
}
static unsigned int byt_get_mctrl(struct uart_port *port)
{
unsigned int ret = serial8250_do_get_mctrl(port);
/* Force DCD and DSR signals to permanently be reported as active */
ret |= TIOCM_CAR | TIOCM_DSR;
return ret;
}
static int byt_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
{
struct dw_dma_slave *param = &lpss->dma_param;
struct uart_8250_port *up = up_to_u8250p(port);
struct pci_dev *pdev = to_pci_dev(port->dev);
unsigned int dma_devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
struct pci_dev *dma_dev = pci_get_slot(pdev->bus, dma_devfn);
switch (pdev->device) {
case PCI_DEVICE_ID_INTEL_BYT_UART1:
case PCI_DEVICE_ID_INTEL_BSW_UART1:
case PCI_DEVICE_ID_INTEL_BDW_UART1:
param->src_id = 3;
param->dst_id = 2;
break;
case PCI_DEVICE_ID_INTEL_BYT_UART2:
case PCI_DEVICE_ID_INTEL_BSW_UART2:
case PCI_DEVICE_ID_INTEL_BDW_UART2:
param->src_id = 5;
param->dst_id = 4;
break;
default:
return -EINVAL;
}
param->dma_dev = &dma_dev->dev;
param->m_master = 0;
param->p_master = 1;
/* TODO: Detect FIFO size automaticaly for DesignWare 8250 */
port->fifosize = 64;
up->tx_loadsz = 64;
lpss->dma_maxburst = 16;
port->set_termios = byt_set_termios;
port->get_mctrl = byt_get_mctrl;
/* Disable TX counter interrupts */
writel(BYT_TX_OVF_INT_MASK, port->membase + BYT_TX_OVF_INT);
return 0;
}
#ifdef CONFIG_SERIAL_8250_DMA
static const struct dw_dma_platform_data qrk_serial_dma_pdata = {
.nr_channels = 2,
.is_private = true,
.is_nollp = true,
.chan_allocation_order = CHAN_ALLOCATION_ASCENDING,
.chan_priority = CHAN_PRIORITY_ASCENDING,
.block_size = 4095,
.nr_masters = 1,
.data_width = {4},
};
static void qrk_serial_setup_dma(struct lpss8250 *lpss, struct uart_port *port)
{
struct uart_8250_dma *dma = &lpss->dma;
struct dw_dma_chip *chip = &lpss->dma_chip;
struct dw_dma_slave *param = &lpss->dma_param;
struct pci_dev *pdev = to_pci_dev(port->dev);
int ret;
chip->dev = &pdev->dev;
chip->irq = pdev->irq;
chip->regs = pci_ioremap_bar(pdev, 1);
chip->pdata = &qrk_serial_dma_pdata;
/* Falling back to PIO mode if DMA probing fails */
ret = dw_dma_probe(chip);
if (ret)
return;
/* Special DMA address for UART */
dma->rx_dma_addr = 0xfffff000;
dma->tx_dma_addr = 0xfffff000;
param->dma_dev = &pdev->dev;
param->src_id = 0;
param->dst_id = 1;
param->hs_polarity = true;
lpss->dma_maxburst = 8;
}
static void qrk_serial_exit_dma(struct lpss8250 *lpss)
{
struct dw_dma_slave *param = &lpss->dma_param;
if (!param->dma_dev)
return;
dw_dma_remove(&lpss->dma_chip);
}
#else /* CONFIG_SERIAL_8250_DMA */
static void qrk_serial_setup_dma(struct lpss8250 *lpss, struct uart_port *port) {}
static void qrk_serial_exit_dma(struct lpss8250 *lpss) {}
#endif /* !CONFIG_SERIAL_8250_DMA */
static int qrk_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
{
struct pci_dev *pdev = to_pci_dev(port->dev);
int ret;
ret = pci_alloc_irq_vectors(pdev, 1, 1, 0);
if (ret < 0)
return ret;
port->irq = pci_irq_vector(pdev, 0);
qrk_serial_setup_dma(lpss, port);
return 0;
}
static void qrk_serial_exit(struct lpss8250 *lpss)
{
qrk_serial_exit_dma(lpss);
}
static bool lpss8250_dma_filter(struct dma_chan *chan, void *param)
{
struct dw_dma_slave *dws = param;
if (dws->dma_dev != chan->device->dev)
return false;
chan->private = dws;
return true;
}
static int lpss8250_dma_setup(struct lpss8250 *lpss, struct uart_8250_port *port)
{
struct uart_8250_dma *dma = &lpss->dma;
struct dw_dma_slave *rx_param, *tx_param;
struct device *dev = port->port.dev;
if (!lpss->dma_param.dma_dev)
return 0;
rx_param = devm_kzalloc(dev, sizeof(*rx_param), GFP_KERNEL);
if (!rx_param)
return -ENOMEM;
tx_param = devm_kzalloc(dev, sizeof(*tx_param), GFP_KERNEL);
if (!tx_param)
return -ENOMEM;
*rx_param = lpss->dma_param;
dma->rxconf.src_maxburst = lpss->dma_maxburst;
*tx_param = lpss->dma_param;
dma->txconf.dst_maxburst = lpss->dma_maxburst;
dma->fn = lpss8250_dma_filter;
dma->rx_param = rx_param;
dma->tx_param = tx_param;
port->dma = dma;
return 0;
}
static int lpss8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct uart_8250_port uart;
struct lpss8250 *lpss;
int ret;
ret = pcim_enable_device(pdev);
if (ret)
return ret;
pci_set_master(pdev);
lpss = devm_kzalloc(&pdev->dev, sizeof(*lpss), GFP_KERNEL);
if (!lpss)
return -ENOMEM;
lpss->board = (struct lpss8250_board *)id->driver_data;
memset(&uart, 0, sizeof(struct uart_8250_port));
uart.port.dev = &pdev->dev;
uart.port.irq = pdev->irq;
uart.port.private_data = lpss;
uart.port.type = PORT_16550A;
uart.port.iotype = UPIO_MEM;
uart.port.regshift = 2;
uart.port.uartclk = lpss->board->base_baud * 16;
uart.port.flags = UPF_SHARE_IRQ | UPF_FIXED_PORT | UPF_FIXED_TYPE;
uart.capabilities = UART_CAP_FIFO | UART_CAP_AFE;
uart.port.mapbase = pci_resource_start(pdev, 0);
uart.port.membase = pcim_iomap(pdev, 0, 0);
if (!uart.port.membase)
return -ENOMEM;
ret = lpss->board->setup(lpss, &uart.port);
if (ret)
return ret;
ret = lpss8250_dma_setup(lpss, &uart);
if (ret)
goto err_exit;
ret = serial8250_register_8250_port(&uart);
if (ret < 0)
goto err_exit;
lpss->line = ret;
pci_set_drvdata(pdev, lpss);
return 0;
err_exit:
if (lpss->board->exit)
lpss->board->exit(lpss);
return ret;
}
static void lpss8250_remove(struct pci_dev *pdev)
{
struct lpss8250 *lpss = pci_get_drvdata(pdev);
if (lpss->board->exit)
lpss->board->exit(lpss);
serial8250_unregister_port(lpss->line);
}
static const struct lpss8250_board byt_board = {
.freq = 100000000,
.base_baud = 2764800,
.setup = byt_serial_setup,
};
static const struct lpss8250_board qrk_board = {
.freq = 44236800,
.base_baud = 2764800,
.setup = qrk_serial_setup,
.exit = qrk_serial_exit,
};
#define LPSS_DEVICE(id, board) { PCI_VDEVICE(INTEL, id), (kernel_ulong_t)&board }
static const struct pci_device_id pci_ids[] = {
LPSS_DEVICE(PCI_DEVICE_ID_INTEL_QRK_UARTx, qrk_board),
LPSS_DEVICE(PCI_DEVICE_ID_INTEL_BYT_UART1, byt_board),
LPSS_DEVICE(PCI_DEVICE_ID_INTEL_BYT_UART2, byt_board),
LPSS_DEVICE(PCI_DEVICE_ID_INTEL_BSW_UART1, byt_board),
LPSS_DEVICE(PCI_DEVICE_ID_INTEL_BSW_UART2, byt_board),
LPSS_DEVICE(PCI_DEVICE_ID_INTEL_BDW_UART1, byt_board),
LPSS_DEVICE(PCI_DEVICE_ID_INTEL_BDW_UART2, byt_board),
{ },
};
MODULE_DEVICE_TABLE(pci, pci_ids);
static struct pci_driver lpss8250_pci_driver = {
.name = "8250_lpss",
.id_table = pci_ids,
.probe = lpss8250_probe,
.remove = lpss8250_remove,
};
module_pci_driver(lpss8250_pci_driver);
MODULE_AUTHOR("Intel Corporation");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Intel LPSS UART driver");
...@@ -99,27 +99,27 @@ static int dnv_handle_irq(struct uart_port *p) ...@@ -99,27 +99,27 @@ static int dnv_handle_irq(struct uart_port *p)
struct uart_8250_port *up = up_to_u8250p(p); struct uart_8250_port *up = up_to_u8250p(p);
unsigned int fisr = serial_port_in(p, INTEL_MID_UART_DNV_FISR); unsigned int fisr = serial_port_in(p, INTEL_MID_UART_DNV_FISR);
u32 status; u32 status;
int ret = IRQ_NONE; int ret = 0;
int err; int err;
if (fisr & BIT(2)) { if (fisr & BIT(2)) {
err = hsu_dma_get_status(&mid->dma_chip, 1, &status); err = hsu_dma_get_status(&mid->dma_chip, 1, &status);
if (err > 0) { if (err > 0) {
serial8250_rx_dma_flush(up); serial8250_rx_dma_flush(up);
ret |= IRQ_HANDLED; ret |= 1;
} else if (err == 0) } else if (err == 0)
ret |= hsu_dma_do_irq(&mid->dma_chip, 1, status); ret |= hsu_dma_do_irq(&mid->dma_chip, 1, status);
} }
if (fisr & BIT(1)) { if (fisr & BIT(1)) {
err = hsu_dma_get_status(&mid->dma_chip, 0, &status); err = hsu_dma_get_status(&mid->dma_chip, 0, &status);
if (err > 0) if (err > 0)
ret |= IRQ_HANDLED; ret |= 1;
else if (err == 0) else if (err == 0)
ret |= hsu_dma_do_irq(&mid->dma_chip, 0, status); ret |= hsu_dma_do_irq(&mid->dma_chip, 0, status);
} }
if (fisr & BIT(0)) if (fisr & BIT(0))
ret |= serial8250_handle_irq(p, serial_port_in(p, UART_IIR)); ret |= serial8250_handle_irq(p, serial_port_in(p, UART_IIR));
return ret; return IRQ_RETVAL(ret);
} }
#define DNV_DMA_CHAN_OFFSET 0x80 #define DNV_DMA_CHAN_OFFSET 0x80
......
...@@ -62,7 +62,7 @@ mtk8250_set_termios(struct uart_port *port, struct ktermios *termios, ...@@ -62,7 +62,7 @@ mtk8250_set_termios(struct uart_port *port, struct ktermios *termios,
*/ */
baud = uart_get_baud_rate(port, termios, old, baud = uart_get_baud_rate(port, termios, old,
port->uartclk / 16 / 0xffff, port->uartclk / 16 / 0xffff,
port->uartclk / 16); port->uartclk);
if (baud <= 115200) { if (baud <= 115200) {
serial_port_out(port, UART_MTK_HIGHS, 0x0); serial_port_out(port, UART_MTK_HIGHS, 0x0);
...@@ -76,10 +76,6 @@ mtk8250_set_termios(struct uart_port *port, struct ktermios *termios, ...@@ -76,10 +76,6 @@ mtk8250_set_termios(struct uart_port *port, struct ktermios *termios,
quot = DIV_ROUND_UP(port->uartclk, 4 * baud); quot = DIV_ROUND_UP(port->uartclk, 4 * baud);
} else { } else {
serial_port_out(port, UART_MTK_HIGHS, 0x3); serial_port_out(port, UART_MTK_HIGHS, 0x3);
/* Set to highest baudrate supported */
if (baud >= 1152000)
baud = 921600;
quot = DIV_ROUND_UP(port->uartclk, 256 * baud); quot = DIV_ROUND_UP(port->uartclk, 256 * baud);
} }
......
...@@ -195,6 +195,7 @@ static int of_platform_serial_probe(struct platform_device *ofdev) ...@@ -195,6 +195,7 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
switch (port_type) { switch (port_type) {
case PORT_8250 ... PORT_MAX_8250: case PORT_8250 ... PORT_MAX_8250:
{ {
u32 tx_threshold;
struct uart_8250_port port8250; struct uart_8250_port port8250;
memset(&port8250, 0, sizeof(port8250)); memset(&port8250, 0, sizeof(port8250));
port8250.port = port; port8250.port = port;
...@@ -202,6 +203,12 @@ static int of_platform_serial_probe(struct platform_device *ofdev) ...@@ -202,6 +203,12 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
if (port.fifosize) if (port.fifosize)
port8250.capabilities = UART_CAP_FIFO; port8250.capabilities = UART_CAP_FIFO;
/* Check for TX FIFO threshold & set tx_loadsz */
if ((of_property_read_u32(ofdev->dev.of_node, "tx-threshold",
&tx_threshold) == 0) &&
(tx_threshold < port.fifosize))
port8250.tx_loadsz = port.fifosize - tx_threshold;
if (of_property_read_bool(ofdev->dev.of_node, if (of_property_read_bool(ofdev->dev.of_node,
"auto-flow-control")) "auto-flow-control"))
port8250.capabilities |= UART_CAP_AFE; port8250.capabilities |= UART_CAP_AFE;
......
...@@ -21,14 +21,10 @@ ...@@ -21,14 +21,10 @@
#include <linux/serial_core.h> #include <linux/serial_core.h>
#include <linux/8250_pci.h> #include <linux/8250_pci.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/rational.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <asm/io.h> #include <asm/io.h>
#include <linux/dmaengine.h>
#include <linux/platform_data/dma-dw.h>
#include "8250.h" #include "8250.h"
/* /*
...@@ -1349,160 +1345,6 @@ ce4100_serial_setup(struct serial_private *priv, ...@@ -1349,160 +1345,6 @@ ce4100_serial_setup(struct serial_private *priv,
return ret; return ret;
} }
#define PCI_DEVICE_ID_INTEL_BYT_UART1 0x0f0a
#define PCI_DEVICE_ID_INTEL_BYT_UART2 0x0f0c
#define PCI_DEVICE_ID_INTEL_BSW_UART1 0x228a
#define PCI_DEVICE_ID_INTEL_BSW_UART2 0x228c
#define PCI_DEVICE_ID_INTEL_BDW_UART1 0x9ce3
#define PCI_DEVICE_ID_INTEL_BDW_UART2 0x9ce4
#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)
#define BYT_TX_OVF_INT 0x820
#define BYT_TX_OVF_INT_MASK (1 << 1)
static void
byt_set_termios(struct uart_port *p, struct ktermios *termios,
struct ktermios *old)
{
unsigned int baud = tty_termios_baud_rate(termios);
unsigned long fref = 100000000, fuart = baud * 16;
unsigned long w = BIT(15) - 1;
unsigned long m, n;
u32 reg;
/* Gracefully handle the B0 case: fall back to B9600 */
fuart = fuart ? fuart : 9600 * 16;
/* Get Fuart closer to Fref */
fuart *= rounddown_pow_of_two(fref / fuart);
/*
* 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
*/
rational_best_approximation(fuart, fref, w, w, &m, &n);
p->uartclk = fuart;
/* 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);
p->status &= ~UPSTAT_AUTOCTS;
if (termios->c_cflag & CRTSCTS)
p->status |= UPSTAT_AUTOCTS;
serial8250_do_set_termios(p, termios, old);
}
static bool byt_dma_filter(struct dma_chan *chan, void *param)
{
struct dw_dma_slave *dws = param;
if (dws->dma_dev != chan->device->dev)
return false;
chan->private = dws;
return true;
}
static unsigned int
byt_get_mctrl(struct uart_port *port)
{
unsigned int ret = serial8250_do_get_mctrl(port);
/* Force DCD and DSR signals to permanently be reported as active. */
ret |= TIOCM_CAR | TIOCM_DSR;
return ret;
}
static int
byt_serial_setup(struct serial_private *priv,
const struct pciserial_board *board,
struct uart_8250_port *port, int idx)
{
struct pci_dev *pdev = priv->dev;
struct device *dev = port->port.dev;
struct uart_8250_dma *dma;
struct dw_dma_slave *tx_param, *rx_param;
struct pci_dev *dma_dev;
int ret;
dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL);
if (!dma)
return -ENOMEM;
tx_param = devm_kzalloc(dev, sizeof(*tx_param), GFP_KERNEL);
if (!tx_param)
return -ENOMEM;
rx_param = devm_kzalloc(dev, sizeof(*rx_param), GFP_KERNEL);
if (!rx_param)
return -ENOMEM;
switch (pdev->device) {
case PCI_DEVICE_ID_INTEL_BYT_UART1:
case PCI_DEVICE_ID_INTEL_BSW_UART1:
case PCI_DEVICE_ID_INTEL_BDW_UART1:
rx_param->src_id = 3;
tx_param->dst_id = 2;
break;
case PCI_DEVICE_ID_INTEL_BYT_UART2:
case PCI_DEVICE_ID_INTEL_BSW_UART2:
case PCI_DEVICE_ID_INTEL_BDW_UART2:
rx_param->src_id = 5;
tx_param->dst_id = 4;
break;
default:
return -EINVAL;
}
rx_param->m_master = 0;
rx_param->p_master = 1;
dma->rxconf.src_maxburst = 16;
tx_param->m_master = 0;
tx_param->p_master = 1;
dma->txconf.dst_maxburst = 16;
dma_dev = pci_get_slot(pdev->bus, PCI_DEVFN(PCI_SLOT(pdev->devfn), 0));
rx_param->dma_dev = &dma_dev->dev;
tx_param->dma_dev = &dma_dev->dev;
dma->fn = byt_dma_filter;
dma->rx_param = rx_param;
dma->tx_param = tx_param;
ret = pci_default_setup(priv, board, port, idx);
port->port.iotype = UPIO_MEM;
port->port.type = PORT_16550A;
port->port.flags = (port->port.flags | UPF_FIXED_PORT | UPF_FIXED_TYPE);
port->port.set_termios = byt_set_termios;
port->port.get_mctrl = byt_get_mctrl;
port->port.fifosize = 64;
port->tx_loadsz = 64;
port->dma = dma;
port->capabilities = UART_CAP_FIFO | UART_CAP_AFE;
/* Disable Tx counter interrupts */
writel(BYT_TX_OVF_INT_MASK, port->port.membase + BYT_TX_OVF_INT);
return ret;
}
static int static int
pci_omegapci_setup(struct serial_private *priv, pci_omegapci_setup(struct serial_private *priv,
const struct pciserial_board *board, const struct pciserial_board *board,
...@@ -1741,6 +1583,19 @@ static int pci_eg20t_init(struct pci_dev *dev) ...@@ -1741,6 +1583,19 @@ static int pci_eg20t_init(struct pci_dev *dev)
#define PCI_DEVICE_ID_EXAR_XR17V4358 0x4358 #define PCI_DEVICE_ID_EXAR_XR17V4358 0x4358
#define PCI_DEVICE_ID_EXAR_XR17V8358 0x8358 #define PCI_DEVICE_ID_EXAR_XR17V8358 0x8358
#define UART_EXAR_MPIOINT_7_0 0x8f /* MPIOINT[7:0] */
#define UART_EXAR_MPIOLVL_7_0 0x90 /* MPIOLVL[7:0] */
#define UART_EXAR_MPIO3T_7_0 0x91 /* MPIO3T[7:0] */
#define UART_EXAR_MPIOINV_7_0 0x92 /* MPIOINV[7:0] */
#define UART_EXAR_MPIOSEL_7_0 0x93 /* MPIOSEL[7:0] */
#define UART_EXAR_MPIOOD_7_0 0x94 /* MPIOOD[7:0] */
#define UART_EXAR_MPIOINT_15_8 0x95 /* MPIOINT[15:8] */
#define UART_EXAR_MPIOLVL_15_8 0x96 /* MPIOLVL[15:8] */
#define UART_EXAR_MPIO3T_15_8 0x97 /* MPIO3T[15:8] */
#define UART_EXAR_MPIOINV_15_8 0x98 /* MPIOINV[15:8] */
#define UART_EXAR_MPIOSEL_15_8 0x99 /* MPIOSEL[15:8] */
#define UART_EXAR_MPIOOD_15_8 0x9a /* MPIOOD[15:8] */
static int static int
pci_xr17c154_setup(struct serial_private *priv, pci_xr17c154_setup(struct serial_private *priv,
const struct pciserial_board *board, const struct pciserial_board *board,
...@@ -1783,18 +1638,18 @@ pci_xr17v35x_setup(struct serial_private *priv, ...@@ -1783,18 +1638,18 @@ pci_xr17v35x_setup(struct serial_private *priv,
* Setup Multipurpose Input/Output pins. * Setup Multipurpose Input/Output pins.
*/ */
if (idx == 0) { if (idx == 0) {
writeb(0x00, p + 0x8f); /*MPIOINT[7:0]*/ writeb(0x00, p + UART_EXAR_MPIOINT_7_0);
writeb(0x00, p + 0x90); /*MPIOLVL[7:0]*/ writeb(0x00, p + UART_EXAR_MPIOLVL_7_0);
writeb(0x00, p + 0x91); /*MPIO3T[7:0]*/ writeb(0x00, p + UART_EXAR_MPIO3T_7_0);
writeb(0x00, p + 0x92); /*MPIOINV[7:0]*/ writeb(0x00, p + UART_EXAR_MPIOINV_7_0);
writeb(0x00, p + 0x93); /*MPIOSEL[7:0]*/ writeb(0x00, p + UART_EXAR_MPIOSEL_7_0);
writeb(0x00, p + 0x94); /*MPIOOD[7:0]*/ writeb(0x00, p + UART_EXAR_MPIOOD_7_0);
writeb(0x00, p + 0x95); /*MPIOINT[15:8]*/ writeb(0x00, p + UART_EXAR_MPIOINT_15_8);
writeb(0x00, p + 0x96); /*MPIOLVL[15:8]*/ writeb(0x00, p + UART_EXAR_MPIOLVL_15_8);
writeb(0x00, p + 0x97); /*MPIO3T[15:8]*/ writeb(0x00, p + UART_EXAR_MPIO3T_15_8);
writeb(0x00, p + 0x98); /*MPIOINV[15:8]*/ writeb(0x00, p + UART_EXAR_MPIOINV_15_8);
writeb(0x00, p + 0x99); /*MPIOSEL[15:8]*/ writeb(0x00, p + UART_EXAR_MPIOSEL_15_8);
writeb(0x00, p + 0x9a); /*MPIOOD[15:8]*/ writeb(0x00, p + UART_EXAR_MPIOOD_15_8);
} }
writeb(0x00, p + UART_EXAR_8XMODE); writeb(0x00, p + UART_EXAR_8XMODE);
writeb(UART_FCTR_EXAR_TRGD, p + UART_EXAR_FCTR); writeb(UART_FCTR_EXAR_TRGD, p + UART_EXAR_FCTR);
...@@ -1830,20 +1685,20 @@ pci_fastcom335_setup(struct serial_private *priv, ...@@ -1830,20 +1685,20 @@ pci_fastcom335_setup(struct serial_private *priv,
switch (priv->dev->device) { switch (priv->dev->device) {
case PCI_DEVICE_ID_COMMTECH_4222PCI335: case PCI_DEVICE_ID_COMMTECH_4222PCI335:
case PCI_DEVICE_ID_COMMTECH_4224PCI335: case PCI_DEVICE_ID_COMMTECH_4224PCI335:
writeb(0x78, p + 0x90); /* MPIOLVL[7:0] */ writeb(0x78, p + UART_EXAR_MPIOLVL_7_0);
writeb(0x00, p + 0x92); /* MPIOINV[7:0] */ writeb(0x00, p + UART_EXAR_MPIOINV_7_0);
writeb(0x00, p + 0x93); /* MPIOSEL[7:0] */ writeb(0x00, p + UART_EXAR_MPIOSEL_7_0);
break; break;
case PCI_DEVICE_ID_COMMTECH_2324PCI335: case PCI_DEVICE_ID_COMMTECH_2324PCI335:
case PCI_DEVICE_ID_COMMTECH_2328PCI335: case PCI_DEVICE_ID_COMMTECH_2328PCI335:
writeb(0x00, p + 0x90); /* MPIOLVL[7:0] */ writeb(0x00, p + UART_EXAR_MPIOLVL_7_0);
writeb(0xc0, p + 0x92); /* MPIOINV[7:0] */ writeb(0xc0, p + UART_EXAR_MPIOINV_7_0);
writeb(0xc0, p + 0x93); /* MPIOSEL[7:0] */ writeb(0xc0, p + UART_EXAR_MPIOSEL_7_0);
break; break;
} }
writeb(0x00, p + 0x8f); /* MPIOINT[7:0] */ writeb(0x00, p + UART_EXAR_MPIOINT_7_0);
writeb(0x00, p + 0x91); /* MPIO3T[7:0] */ writeb(0x00, p + UART_EXAR_MPIO3T_7_0);
writeb(0x00, p + 0x94); /* MPIOOD[7:0] */ writeb(0x00, p + UART_EXAR_MPIOOD_7_0);
} }
writeb(0x00, p + UART_EXAR_8XMODE); writeb(0x00, p + UART_EXAR_8XMODE);
writeb(UART_FCTR_EXAR_TRGD, p + UART_EXAR_FCTR); writeb(UART_FCTR_EXAR_TRGD, p + UART_EXAR_FCTR);
...@@ -1934,7 +1789,6 @@ pci_wch_ch38x_setup(struct serial_private *priv, ...@@ -1934,7 +1789,6 @@ pci_wch_ch38x_setup(struct serial_private *priv,
#define PCI_DEVICE_ID_COMMTECH_4222PCIE 0x0022 #define PCI_DEVICE_ID_COMMTECH_4222PCIE 0x0022
#define PCI_DEVICE_ID_BROADCOM_TRUMANAGE 0x160a #define PCI_DEVICE_ID_BROADCOM_TRUMANAGE 0x160a
#define PCI_DEVICE_ID_AMCC_ADDIDATA_APCI7800 0x818e #define PCI_DEVICE_ID_AMCC_ADDIDATA_APCI7800 0x818e
#define PCI_DEVICE_ID_INTEL_QRK_UART 0x0936
#define PCI_VENDOR_ID_SUNIX 0x1fd4 #define PCI_VENDOR_ID_SUNIX 0x1fd4
#define PCI_DEVICE_ID_SUNIX_1999 0x1999 #define PCI_DEVICE_ID_SUNIX_1999 0x1999
...@@ -2078,48 +1932,6 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { ...@@ -2078,48 +1932,6 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
.setup = kt_serial_setup, .setup = kt_serial_setup,
}, },
{
.vendor = PCI_VENDOR_ID_INTEL,
.device = PCI_DEVICE_ID_INTEL_BYT_UART1,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = byt_serial_setup,
},
{
.vendor = PCI_VENDOR_ID_INTEL,
.device = PCI_DEVICE_ID_INTEL_BYT_UART2,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = byt_serial_setup,
},
{
.vendor = PCI_VENDOR_ID_INTEL,
.device = PCI_DEVICE_ID_INTEL_BSW_UART1,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = byt_serial_setup,
},
{
.vendor = PCI_VENDOR_ID_INTEL,
.device = PCI_DEVICE_ID_INTEL_BSW_UART2,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = byt_serial_setup,
},
{
.vendor = PCI_VENDOR_ID_INTEL,
.device = PCI_DEVICE_ID_INTEL_BDW_UART1,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = byt_serial_setup,
},
{
.vendor = PCI_VENDOR_ID_INTEL,
.device = PCI_DEVICE_ID_INTEL_BDW_UART2,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = byt_serial_setup,
},
/* /*
* ITE * ITE
*/ */
...@@ -2992,8 +2804,6 @@ enum pci_board_num_t { ...@@ -2992,8 +2804,6 @@ enum pci_board_num_t {
pbn_ADDIDATA_PCIe_4_3906250, pbn_ADDIDATA_PCIe_4_3906250,
pbn_ADDIDATA_PCIe_8_3906250, pbn_ADDIDATA_PCIe_8_3906250,
pbn_ce4100_1_115200, pbn_ce4100_1_115200,
pbn_byt,
pbn_qrk,
pbn_omegapci, pbn_omegapci,
pbn_NETMOS9900_2s_115200, pbn_NETMOS9900_2s_115200,
pbn_brcm_trumanage, pbn_brcm_trumanage,
...@@ -3769,18 +3579,6 @@ static struct pciserial_board pci_boards[] = { ...@@ -3769,18 +3579,6 @@ static struct pciserial_board pci_boards[] = {
.base_baud = 921600, .base_baud = 921600,
.reg_shift = 2, .reg_shift = 2,
}, },
[pbn_byt] = {
.flags = FL_BASE0,
.num_ports = 1,
.base_baud = 2764800,
.reg_shift = 2,
},
[pbn_qrk] = {
.flags = FL_BASE0,
.num_ports = 1,
.base_baud = 2764800,
.reg_shift = 2,
},
[pbn_omegapci] = { [pbn_omegapci] = {
.flags = FL_BASE0, .flags = FL_BASE0,
.num_ports = 8, .num_ports = 8,
...@@ -3892,6 +3690,15 @@ static const struct pci_device_id blacklist[] = { ...@@ -3892,6 +3690,15 @@ static const struct pci_device_id blacklist[] = {
{ PCI_VDEVICE(INTEL, 0x081d), }, { PCI_VDEVICE(INTEL, 0x081d), },
{ PCI_VDEVICE(INTEL, 0x1191), }, { PCI_VDEVICE(INTEL, 0x1191), },
{ PCI_VDEVICE(INTEL, 0x19d8), }, { PCI_VDEVICE(INTEL, 0x19d8), },
/* Intel platforms with DesignWare UART */
{ PCI_VDEVICE(INTEL, 0x0936), },
{ PCI_VDEVICE(INTEL, 0x0f0a), },
{ PCI_VDEVICE(INTEL, 0x0f0c), },
{ PCI_VDEVICE(INTEL, 0x228a), },
{ PCI_VDEVICE(INTEL, 0x228c), },
{ PCI_VDEVICE(INTEL, 0x9ce3), },
{ PCI_VDEVICE(INTEL, 0x9ce4), },
}; };
/* /*
...@@ -5659,40 +5466,7 @@ static struct pci_device_id serial_pci_tbl[] = { ...@@ -5659,40 +5466,7 @@ static struct pci_device_id serial_pci_tbl[] = {
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CE4100_UART, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CE4100_UART,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_ce4100_1_115200 }, pbn_ce4100_1_115200 },
/* Intel BayTrail */
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT_UART1,
PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000,
pbn_byt },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT_UART2,
PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000,
pbn_byt },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BSW_UART1,
PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000,
pbn_byt },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BSW_UART2,
PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000,
pbn_byt },
/* Intel Broadwell */
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BDW_UART1,
PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000,
pbn_byt },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BDW_UART2,
PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000,
pbn_byt },
/*
* Intel Quark x1000
*/
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_QRK_UART,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_qrk },
/* /*
* Cronyx Omega PCI * Cronyx Omega PCI
*/ */
......
...@@ -178,7 +178,7 @@ static const struct serial8250_config uart_config[] = { ...@@ -178,7 +178,7 @@ static const struct serial8250_config uart_config[] = {
.fifo_size = 16, .fifo_size = 16,
.tx_loadsz = 16, .tx_loadsz = 16,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00, .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00,
.flags = UART_CAP_FIFO | UART_CAP_AFE, .flags = UART_CAP_FIFO /* | UART_CAP_AFE */,
}, },
[PORT_U6_16550A] = { [PORT_U6_16550A] = {
.name = "U6_16550A", .name = "U6_16550A",
...@@ -585,11 +585,11 @@ EXPORT_SYMBOL_GPL(serial8250_rpm_put); ...@@ -585,11 +585,11 @@ EXPORT_SYMBOL_GPL(serial8250_rpm_put);
*/ */
int serial8250_em485_init(struct uart_8250_port *p) int serial8250_em485_init(struct uart_8250_port *p)
{ {
if (p->em485 != NULL) if (p->em485)
return 0; return 0;
p->em485 = kmalloc(sizeof(struct uart_8250_em485), GFP_ATOMIC); p->em485 = kmalloc(sizeof(struct uart_8250_em485), GFP_ATOMIC);
if (p->em485 == NULL) if (!p->em485)
return -ENOMEM; return -ENOMEM;
setup_timer(&p->em485->stop_tx_timer, setup_timer(&p->em485->stop_tx_timer,
...@@ -619,7 +619,7 @@ EXPORT_SYMBOL_GPL(serial8250_em485_init); ...@@ -619,7 +619,7 @@ EXPORT_SYMBOL_GPL(serial8250_em485_init);
*/ */
void serial8250_em485_destroy(struct uart_8250_port *p) void serial8250_em485_destroy(struct uart_8250_port *p)
{ {
if (p->em485 == NULL) if (!p->em485)
return; return;
del_timer(&p->em485->start_tx_timer); del_timer(&p->em485->start_tx_timer);
...@@ -1402,10 +1402,8 @@ static void serial8250_stop_rx(struct uart_port *port) ...@@ -1402,10 +1402,8 @@ static void serial8250_stop_rx(struct uart_port *port)
static void __do_stop_tx_rs485(struct uart_8250_port *p) static void __do_stop_tx_rs485(struct uart_8250_port *p)
{ {
if (!p->em485)
return;
serial8250_em485_rts_after_send(p); serial8250_em485_rts_after_send(p);
/* /*
* Empty the RX FIFO, we are not interested in anything * Empty the RX FIFO, we are not interested in anything
* received during the half-duplex transmission. * received during the half-duplex transmission.
...@@ -1414,12 +1412,8 @@ static void __do_stop_tx_rs485(struct uart_8250_port *p) ...@@ -1414,12 +1412,8 @@ static void __do_stop_tx_rs485(struct uart_8250_port *p)
if (!(p->port.rs485.flags & SER_RS485_RX_DURING_TX)) { if (!(p->port.rs485.flags & SER_RS485_RX_DURING_TX)) {
serial8250_clear_fifos(p); serial8250_clear_fifos(p);
serial8250_rpm_get(p);
p->ier |= UART_IER_RLSI | UART_IER_RDI; p->ier |= UART_IER_RLSI | UART_IER_RDI;
serial_port_out(&p->port, UART_IER, p->ier); serial_port_out(&p->port, UART_IER, p->ier);
serial8250_rpm_put(p);
} }
} }
...@@ -1429,6 +1423,7 @@ static void serial8250_em485_handle_stop_tx(unsigned long arg) ...@@ -1429,6 +1423,7 @@ static void serial8250_em485_handle_stop_tx(unsigned long arg)
struct uart_8250_em485 *em485 = p->em485; struct uart_8250_em485 *em485 = p->em485;
unsigned long flags; unsigned long flags;
serial8250_rpm_get(p);
spin_lock_irqsave(&p->port.lock, flags); spin_lock_irqsave(&p->port.lock, flags);
if (em485 && if (em485 &&
em485->active_timer == &em485->stop_tx_timer) { em485->active_timer == &em485->stop_tx_timer) {
...@@ -1436,15 +1431,13 @@ static void serial8250_em485_handle_stop_tx(unsigned long arg) ...@@ -1436,15 +1431,13 @@ static void serial8250_em485_handle_stop_tx(unsigned long arg)
em485->active_timer = NULL; em485->active_timer = NULL;
} }
spin_unlock_irqrestore(&p->port.lock, flags); spin_unlock_irqrestore(&p->port.lock, flags);
serial8250_rpm_put(p);
} }
static void __stop_tx_rs485(struct uart_8250_port *p) static void __stop_tx_rs485(struct uart_8250_port *p)
{ {
struct uart_8250_em485 *em485 = p->em485; struct uart_8250_em485 *em485 = p->em485;
if (!em485)
return;
/* /*
* __do_stop_tx_rs485 is going to set RTS according to config * __do_stop_tx_rs485 is going to set RTS according to config
* AND flush RX FIFO if required. * AND flush RX FIFO if required.
...@@ -1475,7 +1468,7 @@ static inline void __stop_tx(struct uart_8250_port *p) ...@@ -1475,7 +1468,7 @@ static inline void __stop_tx(struct uart_8250_port *p)
unsigned char lsr = serial_in(p, UART_LSR); unsigned char lsr = serial_in(p, UART_LSR);
/* /*
* To provide required timeing and allow FIFO transfer, * To provide required timeing and allow FIFO transfer,
* __stop_tx_rs485 must be called only when both FIFO and * __stop_tx_rs485() must be called only when both FIFO and
* shift register are empty. It is for device driver to enable * shift register are empty. It is for device driver to enable
* interrupt on TEMT. * interrupt on TEMT.
*/ */
...@@ -1484,9 +1477,10 @@ static inline void __stop_tx(struct uart_8250_port *p) ...@@ -1484,9 +1477,10 @@ static inline void __stop_tx(struct uart_8250_port *p)
del_timer(&em485->start_tx_timer); del_timer(&em485->start_tx_timer);
em485->active_timer = NULL; em485->active_timer = NULL;
__stop_tx_rs485(p);
} }
__do_stop_tx(p); __do_stop_tx(p);
__stop_tx_rs485(p);
} }
static void serial8250_stop_tx(struct uart_port *port) static void serial8250_stop_tx(struct uart_port *port)
...@@ -1876,6 +1870,30 @@ static int exar_handle_irq(struct uart_port *port) ...@@ -1876,6 +1870,30 @@ static int exar_handle_irq(struct uart_port *port)
return ret; return ret;
} }
/*
* Newer 16550 compatible parts such as the SC16C650 & Altera 16550 Soft IP
* have a programmable TX threshold that triggers the THRE interrupt in
* the IIR register. In this case, the THRE interrupt indicates the FIFO
* has space available. Load it up with tx_loadsz bytes.
*/
static int serial8250_tx_threshold_handle_irq(struct uart_port *port)
{
unsigned long flags;
unsigned int iir = serial_port_in(port, UART_IIR);
/* TX Threshold IRQ triggered so load up FIFO */
if ((iir & UART_IIR_ID) == UART_IIR_THRI) {
struct uart_8250_port *up = up_to_u8250p(port);
spin_lock_irqsave(&port->lock, flags);
serial8250_tx_chars(up);
spin_unlock_irqrestore(&port->lock, flags);
}
iir = serial_port_in(port, UART_IIR);
return serial8250_handle_irq(port, iir);
}
static unsigned int serial8250_tx_empty(struct uart_port *port) static unsigned int serial8250_tx_empty(struct uart_port *port)
{ {
struct uart_8250_port *up = up_to_u8250p(port); struct uart_8250_port *up = up_to_u8250p(port);
...@@ -1988,6 +2006,7 @@ static void wait_for_xmitr(struct uart_8250_port *up, int bits) ...@@ -1988,6 +2006,7 @@ static void wait_for_xmitr(struct uart_8250_port *up, int bits)
if (--tmout == 0) if (--tmout == 0)
break; break;
udelay(1); udelay(1);
touch_nmi_watchdog();
} }
/* Wait up to 1s for flow control if necessary */ /* Wait up to 1s for flow control if necessary */
...@@ -2164,6 +2183,25 @@ int serial8250_do_startup(struct uart_port *port) ...@@ -2164,6 +2183,25 @@ int serial8250_do_startup(struct uart_port *port)
serial_port_out(port, UART_LCR, 0); serial_port_out(port, UART_LCR, 0);
} }
/*
* For the Altera 16550 variants, set TX threshold trigger level.
*/
if (((port->type == PORT_ALTR_16550_F32) ||
(port->type == PORT_ALTR_16550_F64) ||
(port->type == PORT_ALTR_16550_F128)) && (port->fifosize > 1)) {
/* Bounds checking of TX threshold (valid 0 to fifosize-2) */
if ((up->tx_loadsz < 2) || (up->tx_loadsz > port->fifosize)) {
pr_err("ttyS%d TX FIFO Threshold errors, skipping\n",
serial_index(port));
} else {
serial_port_out(port, UART_ALTR_AFR,
UART_ALTR_EN_TXFIFO_LW);
serial_port_out(port, UART_ALTR_TX_LOW,
port->fifosize - up->tx_loadsz);
port->handle_irq = serial8250_tx_threshold_handle_irq;
}
}
if (port->irq) { if (port->irq) {
unsigned char iir1; unsigned char iir1;
/* /*
...@@ -2499,8 +2537,6 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port, ...@@ -2499,8 +2537,6 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port,
struct ktermios *termios, struct ktermios *termios,
struct ktermios *old) struct ktermios *old)
{ {
unsigned int tolerance = port->uartclk / 100;
/* /*
* Ask the core to calculate the divisor for us. * Ask the core to calculate the divisor for us.
* Allow 1% tolerance at the upper limit so uart clks marginally * Allow 1% tolerance at the upper limit so uart clks marginally
...@@ -2509,7 +2545,7 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port, ...@@ -2509,7 +2545,7 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port,
*/ */
return uart_get_baud_rate(port, termios, old, return uart_get_baud_rate(port, termios, old,
port->uartclk / 16 / 0xffff, port->uartclk / 16 / 0xffff,
(port->uartclk + tolerance) / 16); port->uartclk);
} }
void void
...@@ -2546,12 +2582,9 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, ...@@ -2546,12 +2582,9 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
/* /*
* MCR-based auto flow control. When AFE is enabled, RTS will be * MCR-based auto flow control. When AFE is enabled, RTS will be
* deasserted when the receive FIFO contains more characters than * deasserted when the receive FIFO contains more characters than
* the trigger, or the MCR RTS bit is cleared. In the case where * the trigger, or the MCR RTS bit is cleared.
* the remote UART is not using CTS auto flow control, we must
* have sufficient FIFO entries for the latency of the remote
* UART to respond. IOW, at least 32 bytes of FIFO.
*/ */
if (up->capabilities & UART_CAP_AFE && port->fifosize >= 32) { if (up->capabilities & UART_CAP_AFE) {
up->mcr &= ~UART_MCR_AFE; up->mcr &= ~UART_MCR_AFE;
if (termios->c_cflag & CRTSCTS) if (termios->c_cflag & CRTSCTS)
up->mcr |= UART_MCR_AFE; up->mcr |= UART_MCR_AFE;
......
...@@ -120,7 +120,6 @@ config SERIAL_8250_PCI ...@@ -120,7 +120,6 @@ config SERIAL_8250_PCI
tristate "8250/16550 PCI device support" if EXPERT tristate "8250/16550 PCI device support" if EXPERT
depends on SERIAL_8250 && PCI depends on SERIAL_8250 && PCI
default SERIAL_8250 default SERIAL_8250
select RATIONAL
help help
This builds standard PCI serial support. You may be able to This builds standard PCI serial support. You may be able to
disable this feature if you only need legacy serial support. disable this feature if you only need legacy serial support.
...@@ -402,6 +401,21 @@ config SERIAL_8250_INGENIC ...@@ -402,6 +401,21 @@ config SERIAL_8250_INGENIC
If you have a system using an Ingenic SoC and wish to make use of If you have a system using an Ingenic SoC and wish to make use of
its UARTs, say Y to this option. If unsure, say N. its UARTs, say Y to this option. If unsure, say N.
config SERIAL_8250_LPSS
tristate "Support for serial ports on Intel LPSS platforms" if EXPERT
default SERIAL_8250
depends on SERIAL_8250 && PCI
depends on X86 || COMPILE_TEST
select DW_DMAC_CORE if SERIAL_8250_DMA
select DW_DMAC_PCI if (SERIAL_8250_DMA && X86_INTEL_LPSS)
select RATIONAL
help
Selecting this option will enable handling of the extra features
present on the UART found on various Intel platforms such as:
- Intel Baytrail SoC
- Intel Braswell SoC
- Intel Quark X1000 SoC
config SERIAL_8250_MID config SERIAL_8250_MID
tristate "Support for serial ports on Intel MID platforms" if EXPERT tristate "Support for serial ports on Intel MID platforms" if EXPERT
default SERIAL_8250 default SERIAL_8250
......
...@@ -28,6 +28,7 @@ obj-$(CONFIG_SERIAL_8250_LPC18XX) += 8250_lpc18xx.o ...@@ -28,6 +28,7 @@ obj-$(CONFIG_SERIAL_8250_LPC18XX) += 8250_lpc18xx.o
obj-$(CONFIG_SERIAL_8250_MT6577) += 8250_mtk.o obj-$(CONFIG_SERIAL_8250_MT6577) += 8250_mtk.o
obj-$(CONFIG_SERIAL_8250_UNIPHIER) += 8250_uniphier.o obj-$(CONFIG_SERIAL_8250_UNIPHIER) += 8250_uniphier.o
obj-$(CONFIG_SERIAL_8250_INGENIC) += 8250_ingenic.o obj-$(CONFIG_SERIAL_8250_INGENIC) += 8250_ingenic.o
obj-$(CONFIG_SERIAL_8250_LPSS) += 8250_lpss.o
obj-$(CONFIG_SERIAL_8250_MID) += 8250_mid.o obj-$(CONFIG_SERIAL_8250_MID) += 8250_mid.o
obj-$(CONFIG_SERIAL_8250_MOXA) += 8250_moxa.o obj-$(CONFIG_SERIAL_8250_MOXA) += 8250_moxa.o
obj-$(CONFIG_SERIAL_OF_PLATFORM) += 8250_of.o obj-$(CONFIG_SERIAL_OF_PLATFORM) += 8250_of.o
......
...@@ -280,7 +280,7 @@ static int altera_jtaguart_verify_port(struct uart_port *port, ...@@ -280,7 +280,7 @@ static int altera_jtaguart_verify_port(struct uart_port *port,
/* /*
* Define the basic serial functions we support. * Define the basic serial functions we support.
*/ */
static struct uart_ops altera_jtaguart_ops = { static const struct uart_ops altera_jtaguart_ops = {
.tx_empty = altera_jtaguart_tx_empty, .tx_empty = altera_jtaguart_tx_empty,
.get_mctrl = altera_jtaguart_get_mctrl, .get_mctrl = altera_jtaguart_get_mctrl,
.set_mctrl = altera_jtaguart_set_mctrl, .set_mctrl = altera_jtaguart_set_mctrl,
......
...@@ -404,7 +404,7 @@ static void altera_uart_poll_put_char(struct uart_port *port, unsigned char c) ...@@ -404,7 +404,7 @@ static void altera_uart_poll_put_char(struct uart_port *port, unsigned char c)
/* /*
* Define the basic serial functions we support. * Define the basic serial functions we support.
*/ */
static struct uart_ops altera_uart_ops = { static const struct uart_ops altera_uart_ops = {
.tx_empty = altera_uart_tx_empty, .tx_empty = altera_uart_tx_empty,
.get_mctrl = altera_uart_get_mctrl, .get_mctrl = altera_uart_get_mctrl,
.set_mctrl = altera_uart_set_mctrl, .set_mctrl = altera_uart_set_mctrl,
......
...@@ -93,6 +93,10 @@ static u16 pl011_std_offsets[REG_ARRAY_SIZE] = { ...@@ -93,6 +93,10 @@ static u16 pl011_std_offsets[REG_ARRAY_SIZE] = {
struct vendor_data { struct vendor_data {
const u16 *reg_offset; const u16 *reg_offset;
unsigned int ifls; unsigned int ifls;
unsigned int fr_busy;
unsigned int fr_dsr;
unsigned int fr_cts;
unsigned int fr_ri;
bool access_32b; bool access_32b;
bool oversampling; bool oversampling;
bool dma_threshold; bool dma_threshold;
...@@ -111,6 +115,10 @@ static unsigned int get_fifosize_arm(struct amba_device *dev) ...@@ -111,6 +115,10 @@ static unsigned int get_fifosize_arm(struct amba_device *dev)
static struct vendor_data vendor_arm = { static struct vendor_data vendor_arm = {
.reg_offset = pl011_std_offsets, .reg_offset = pl011_std_offsets,
.ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8, .ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
.fr_busy = UART01x_FR_BUSY,
.fr_dsr = UART01x_FR_DSR,
.fr_cts = UART01x_FR_CTS,
.fr_ri = UART011_FR_RI,
.oversampling = false, .oversampling = false,
.dma_threshold = false, .dma_threshold = false,
.cts_event_workaround = false, .cts_event_workaround = false,
...@@ -121,6 +129,10 @@ static struct vendor_data vendor_arm = { ...@@ -121,6 +129,10 @@ static struct vendor_data vendor_arm = {
static struct vendor_data vendor_sbsa = { static struct vendor_data vendor_sbsa = {
.reg_offset = pl011_std_offsets, .reg_offset = pl011_std_offsets,
.fr_busy = UART01x_FR_BUSY,
.fr_dsr = UART01x_FR_DSR,
.fr_cts = UART01x_FR_CTS,
.fr_ri = UART011_FR_RI,
.access_32b = true, .access_32b = true,
.oversampling = false, .oversampling = false,
.dma_threshold = false, .dma_threshold = false,
...@@ -164,6 +176,10 @@ static unsigned int get_fifosize_st(struct amba_device *dev) ...@@ -164,6 +176,10 @@ static unsigned int get_fifosize_st(struct amba_device *dev)
static struct vendor_data vendor_st = { static struct vendor_data vendor_st = {
.reg_offset = pl011_st_offsets, .reg_offset = pl011_st_offsets,
.ifls = UART011_IFLS_RX_HALF|UART011_IFLS_TX_HALF, .ifls = UART011_IFLS_RX_HALF|UART011_IFLS_TX_HALF,
.fr_busy = UART01x_FR_BUSY,
.fr_dsr = UART01x_FR_DSR,
.fr_cts = UART01x_FR_CTS,
.fr_ri = UART011_FR_RI,
.oversampling = true, .oversampling = true,
.dma_threshold = true, .dma_threshold = true,
.cts_event_workaround = true, .cts_event_workaround = true,
...@@ -188,11 +204,20 @@ static const u16 pl011_zte_offsets[REG_ARRAY_SIZE] = { ...@@ -188,11 +204,20 @@ static const u16 pl011_zte_offsets[REG_ARRAY_SIZE] = {
[REG_DMACR] = ZX_UART011_DMACR, [REG_DMACR] = ZX_UART011_DMACR,
}; };
static struct vendor_data vendor_zte __maybe_unused = { static unsigned int get_fifosize_zte(struct amba_device *dev)
{
return 16;
}
static struct vendor_data vendor_zte = {
.reg_offset = pl011_zte_offsets, .reg_offset = pl011_zte_offsets,
.access_32b = true, .access_32b = true,
.ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8, .ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
.get_fifosize = get_fifosize_arm, .fr_busy = ZX_UART01x_FR_BUSY,
.fr_dsr = ZX_UART01x_FR_DSR,
.fr_cts = ZX_UART01x_FR_CTS,
.fr_ri = ZX_UART011_FR_RI,
.get_fifosize = get_fifosize_zte,
}; };
/* Deals with DMA transactions */ /* Deals with DMA transactions */
...@@ -1167,7 +1192,7 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap) ...@@ -1167,7 +1192,7 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap)
return; return;
/* Disable RX and TX DMA */ /* Disable RX and TX DMA */
while (pl011_read(uap, REG_FR) & UART01x_FR_BUSY) while (pl011_read(uap, REG_FR) & uap->vendor->fr_busy)
cpu_relax(); cpu_relax();
spin_lock_irq(&uap->port.lock); spin_lock_irq(&uap->port.lock);
...@@ -1416,11 +1441,12 @@ static void pl011_modem_status(struct uart_amba_port *uap) ...@@ -1416,11 +1441,12 @@ static void pl011_modem_status(struct uart_amba_port *uap)
if (delta & UART01x_FR_DCD) if (delta & UART01x_FR_DCD)
uart_handle_dcd_change(&uap->port, status & UART01x_FR_DCD); uart_handle_dcd_change(&uap->port, status & UART01x_FR_DCD);
if (delta & UART01x_FR_DSR) if (delta & uap->vendor->fr_dsr)
uap->port.icount.dsr++; uap->port.icount.dsr++;
if (delta & UART01x_FR_CTS) if (delta & uap->vendor->fr_cts)
uart_handle_cts_change(&uap->port, status & UART01x_FR_CTS); uart_handle_cts_change(&uap->port,
status & uap->vendor->fr_cts);
wake_up_interruptible(&uap->port.state->port.delta_msr_wait); wake_up_interruptible(&uap->port.state->port.delta_msr_wait);
} }
...@@ -1493,7 +1519,8 @@ static unsigned int pl011_tx_empty(struct uart_port *port) ...@@ -1493,7 +1519,8 @@ static unsigned int pl011_tx_empty(struct uart_port *port)
struct uart_amba_port *uap = struct uart_amba_port *uap =
container_of(port, struct uart_amba_port, port); container_of(port, struct uart_amba_port, port);
unsigned int status = pl011_read(uap, REG_FR); unsigned int status = pl011_read(uap, REG_FR);
return status & (UART01x_FR_BUSY|UART01x_FR_TXFF) ? 0 : TIOCSER_TEMT; return status & (uap->vendor->fr_busy | UART01x_FR_TXFF) ?
0 : TIOCSER_TEMT;
} }
static unsigned int pl011_get_mctrl(struct uart_port *port) static unsigned int pl011_get_mctrl(struct uart_port *port)
...@@ -1508,9 +1535,9 @@ static unsigned int pl011_get_mctrl(struct uart_port *port) ...@@ -1508,9 +1535,9 @@ static unsigned int pl011_get_mctrl(struct uart_port *port)
result |= tiocmbit result |= tiocmbit
TIOCMBIT(UART01x_FR_DCD, TIOCM_CAR); TIOCMBIT(UART01x_FR_DCD, TIOCM_CAR);
TIOCMBIT(UART01x_FR_DSR, TIOCM_DSR); TIOCMBIT(uap->vendor->fr_dsr, TIOCM_DSR);
TIOCMBIT(UART01x_FR_CTS, TIOCM_CTS); TIOCMBIT(uap->vendor->fr_cts, TIOCM_CTS);
TIOCMBIT(UART011_FR_RI, TIOCM_RNG); TIOCMBIT(uap->vendor->fr_ri, TIOCM_RNG);
#undef TIOCMBIT #undef TIOCMBIT
return result; return result;
} }
...@@ -2191,7 +2218,7 @@ pl011_console_write(struct console *co, const char *s, unsigned int count) ...@@ -2191,7 +2218,7 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
* Finally, wait for transmitter to become empty * Finally, wait for transmitter to become empty
* and restore the TCR * and restore the TCR
*/ */
while (pl011_read(uap, REG_FR) & UART01x_FR_BUSY) while (pl011_read(uap, REG_FR) & uap->vendor->fr_busy)
cpu_relax(); cpu_relax();
if (!uap->vendor->always_enabled) if (!uap->vendor->always_enabled)
pl011_write(old_cr, uap, REG_CR); pl011_write(old_cr, uap, REG_CR);
...@@ -2555,7 +2582,8 @@ static int sbsa_uart_probe(struct platform_device *pdev) ...@@ -2555,7 +2582,8 @@ static int sbsa_uart_probe(struct platform_device *pdev)
ret = platform_get_irq(pdev, 0); ret = platform_get_irq(pdev, 0);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "cannot obtain irq\n"); if (ret != -EPROBE_DEFER)
dev_err(&pdev->dev, "cannot obtain irq\n");
return ret; return ret;
} }
uap->port.irq = ret; uap->port.irq = ret;
...@@ -2622,6 +2650,11 @@ static struct amba_id pl011_ids[] = { ...@@ -2622,6 +2650,11 @@ static struct amba_id pl011_ids[] = {
.mask = 0x00ffffff, .mask = 0x00ffffff,
.data = &vendor_st, .data = &vendor_st,
}, },
{
.id = AMBA_LINUX_ID(0x00, 0x1, 0xffe),
.mask = 0x00ffffff,
.data = &vendor_zte,
},
{ 0, 0 }, { 0, 0 },
}; };
......
...@@ -464,7 +464,7 @@ static int arc_serial_poll_getchar(struct uart_port *port) ...@@ -464,7 +464,7 @@ static int arc_serial_poll_getchar(struct uart_port *port)
} }
#endif #endif
static struct uart_ops arc_serial_pops = { static const struct uart_ops arc_serial_pops = {
.tx_empty = arc_serial_tx_empty, .tx_empty = arc_serial_tx_empty,
.set_mctrl = arc_serial_set_mctrl, .set_mctrl = arc_serial_set_mctrl,
.get_mctrl = arc_serial_get_mctrl, .get_mctrl = arc_serial_get_mctrl,
......
...@@ -166,6 +166,7 @@ struct atmel_uart_port { ...@@ -166,6 +166,7 @@ struct atmel_uart_port {
u32 rts_low; u32 rts_low;
bool ms_irq_enabled; bool ms_irq_enabled;
u32 rtor; /* address of receiver timeout register if it exists */ u32 rtor; /* address of receiver timeout register if it exists */
bool has_frac_baudrate;
bool has_hw_timer; bool has_hw_timer;
struct timer_list uart_timer; struct timer_list uart_timer;
...@@ -1634,8 +1635,8 @@ static void atmel_init_property(struct atmel_uart_port *atmel_port, ...@@ -1634,8 +1635,8 @@ static void atmel_init_property(struct atmel_uart_port *atmel_port,
if (np) { if (np) {
/* DMA/PDC usage specification */ /* DMA/PDC usage specification */
if (of_get_property(np, "atmel,use-dma-rx", NULL)) { if (of_property_read_bool(np, "atmel,use-dma-rx")) {
if (of_get_property(np, "dmas", NULL)) { if (of_property_read_bool(np, "dmas")) {
atmel_port->use_dma_rx = true; atmel_port->use_dma_rx = true;
atmel_port->use_pdc_rx = false; atmel_port->use_pdc_rx = false;
} else { } else {
...@@ -1647,8 +1648,8 @@ static void atmel_init_property(struct atmel_uart_port *atmel_port, ...@@ -1647,8 +1648,8 @@ static void atmel_init_property(struct atmel_uart_port *atmel_port,
atmel_port->use_pdc_rx = false; atmel_port->use_pdc_rx = false;
} }
if (of_get_property(np, "atmel,use-dma-tx", NULL)) { if (of_property_read_bool(np, "atmel,use-dma-tx")) {
if (of_get_property(np, "dmas", NULL)) { if (of_property_read_bool(np, "dmas")) {
atmel_port->use_dma_tx = true; atmel_port->use_dma_tx = true;
atmel_port->use_pdc_tx = false; atmel_port->use_pdc_tx = false;
} else { } else {
...@@ -1745,6 +1746,11 @@ static void atmel_get_ip_name(struct uart_port *port) ...@@ -1745,6 +1746,11 @@ static void atmel_get_ip_name(struct uart_port *port)
dbgu_uart = 0x44424755; /* DBGU */ dbgu_uart = 0x44424755; /* DBGU */
new_uart = 0x55415254; /* UART */ new_uart = 0x55415254; /* UART */
/*
* Only USART devices from at91sam9260 SOC implement fractional
* baudrate.
*/
atmel_port->has_frac_baudrate = false;
atmel_port->has_hw_timer = false; atmel_port->has_hw_timer = false;
if (name == new_uart) { if (name == new_uart) {
...@@ -1753,6 +1759,7 @@ static void atmel_get_ip_name(struct uart_port *port) ...@@ -1753,6 +1759,7 @@ static void atmel_get_ip_name(struct uart_port *port)
atmel_port->rtor = ATMEL_UA_RTOR; atmel_port->rtor = ATMEL_UA_RTOR;
} else if (name == usart) { } else if (name == usart) {
dev_dbg(port->dev, "Usart\n"); dev_dbg(port->dev, "Usart\n");
atmel_port->has_frac_baudrate = true;
atmel_port->has_hw_timer = true; atmel_port->has_hw_timer = true;
atmel_port->rtor = ATMEL_US_RTOR; atmel_port->rtor = ATMEL_US_RTOR;
} else if (name == dbgu_uart) { } else if (name == dbgu_uart) {
...@@ -1764,6 +1771,7 @@ static void atmel_get_ip_name(struct uart_port *port) ...@@ -1764,6 +1771,7 @@ static void atmel_get_ip_name(struct uart_port *port)
case 0x302: case 0x302:
case 0x10213: case 0x10213:
dev_dbg(port->dev, "This version is usart\n"); dev_dbg(port->dev, "This version is usart\n");
atmel_port->has_frac_baudrate = true;
atmel_port->has_hw_timer = true; atmel_port->has_hw_timer = true;
atmel_port->rtor = ATMEL_US_RTOR; atmel_port->rtor = ATMEL_US_RTOR;
break; break;
...@@ -1929,6 +1937,9 @@ static void atmel_shutdown(struct uart_port *port) ...@@ -1929,6 +1937,9 @@ static void atmel_shutdown(struct uart_port *port)
{ {
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
/* Disable modem control lines interrupts */
atmel_disable_ms(port);
/* Disable interrupts at device level */ /* Disable interrupts at device level */
atmel_uart_writel(port, ATMEL_US_IDR, -1); atmel_uart_writel(port, ATMEL_US_IDR, -1);
...@@ -1979,8 +1990,6 @@ static void atmel_shutdown(struct uart_port *port) ...@@ -1979,8 +1990,6 @@ static void atmel_shutdown(struct uart_port *port)
*/ */
free_irq(port->irq, port); free_irq(port->irq, port);
atmel_port->ms_irq_enabled = false;
atmel_flush_buffer(port); atmel_flush_buffer(port);
} }
...@@ -2025,8 +2034,9 @@ static void atmel_serial_pm(struct uart_port *port, unsigned int state, ...@@ -2025,8 +2034,9 @@ static void atmel_serial_pm(struct uart_port *port, unsigned int state,
static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old) struct ktermios *old)
{ {
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
unsigned long flags; unsigned long flags;
unsigned int old_mode, mode, imr, quot, baud; unsigned int old_mode, mode, imr, quot, baud, div, cd, fp = 0;
/* save the current mode register */ /* save the current mode register */
mode = old_mode = atmel_uart_readl(port, ATMEL_US_MR); mode = old_mode = atmel_uart_readl(port, ATMEL_US_MR);
...@@ -2036,12 +2046,6 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, ...@@ -2036,12 +2046,6 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
ATMEL_US_PAR | ATMEL_US_USMODE); ATMEL_US_PAR | ATMEL_US_USMODE);
baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16); baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
quot = uart_get_divisor(port, baud);
if (quot > 65535) { /* BRGR is 16-bit, so switch to slower clock */
quot /= 8;
mode |= ATMEL_US_USCLKS_MCK_DIV8;
}
/* byte size */ /* byte size */
switch (termios->c_cflag & CSIZE) { switch (termios->c_cflag & CSIZE) {
...@@ -2160,7 +2164,31 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, ...@@ -2160,7 +2164,31 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
atmel_uart_writel(port, ATMEL_US_CR, rts_state); atmel_uart_writel(port, ATMEL_US_CR, rts_state);
} }
/* set the baud rate */ /*
* Set the baud rate:
* Fractional baudrate allows to setup output frequency more
* accurately. This feature is enabled only when using normal mode.
* baudrate = selected clock / (8 * (2 - OVER) * (CD + FP / 8))
* Currently, OVER is always set to 0 so we get
* baudrate = selected clock / (16 * (CD + FP / 8))
* then
* 8 CD + FP = selected clock / (2 * baudrate)
*/
if (atmel_port->has_frac_baudrate &&
(mode & ATMEL_US_USMODE) == ATMEL_US_USMODE_NORMAL) {
div = DIV_ROUND_CLOSEST(port->uartclk, baud * 2);
cd = div >> 3;
fp = div & ATMEL_US_FP_MASK;
} else {
cd = uart_get_divisor(port, baud);
}
if (cd > 65535) { /* BRGR is 16-bit, so switch to slower clock */
cd /= 8;
mode |= ATMEL_US_USCLKS_MCK_DIV8;
}
quot = cd | fp << ATMEL_US_FP_OFFSET;
atmel_uart_writel(port, ATMEL_US_BRGR, quot); atmel_uart_writel(port, ATMEL_US_BRGR, quot);
atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX); atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN); atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN);
...@@ -2292,7 +2320,7 @@ static void atmel_poll_put_char(struct uart_port *port, unsigned char ch) ...@@ -2292,7 +2320,7 @@ static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
} }
#endif #endif
static struct uart_ops atmel_pops = { static const struct uart_ops atmel_pops = {
.tx_empty = atmel_tx_empty, .tx_empty = atmel_tx_empty,
.set_mctrl = atmel_set_mctrl, .set_mctrl = atmel_set_mctrl,
.get_mctrl = atmel_get_mctrl, .get_mctrl = atmel_get_mctrl,
......
...@@ -631,7 +631,7 @@ static int bcm_uart_verify_port(struct uart_port *port, ...@@ -631,7 +631,7 @@ static int bcm_uart_verify_port(struct uart_port *port,
} }
/* serial core callbacks */ /* serial core callbacks */
static struct uart_ops bcm_uart_ops = { static const struct uart_ops bcm_uart_ops = {
.tx_empty = bcm_uart_tx_empty, .tx_empty = bcm_uart_tx_empty,
.get_mctrl = bcm_uart_get_mctrl, .get_mctrl = bcm_uart_get_mctrl,
.set_mctrl = bcm_uart_set_mctrl, .set_mctrl = bcm_uart_set_mctrl,
......
...@@ -53,7 +53,8 @@ static void smh_write(struct console *con, const char *s, unsigned n) ...@@ -53,7 +53,8 @@ static void smh_write(struct console *con, const char *s, unsigned n)
uart_console_write(&dev->port, s, n, smh_putc); uart_console_write(&dev->port, s, n, smh_putc);
} }
int __init early_smh_setup(struct earlycon_device *device, const char *opt) static int
__init early_smh_setup(struct earlycon_device *device, const char *opt)
{ {
device->con->write = smh_write; device->con->write = smh_write;
return 0; return 0;
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/sizes.h> #include <linux/sizes.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_fdt.h> #include <linux/of_fdt.h>
#include <linux/acpi.h>
#ifdef CONFIG_FIX_EARLYCON_MEM #ifdef CONFIG_FIX_EARLYCON_MEM
#include <asm/fixmap.h> #include <asm/fixmap.h>
...@@ -38,7 +39,7 @@ static struct earlycon_device early_console_dev = { ...@@ -38,7 +39,7 @@ static struct earlycon_device early_console_dev = {
.con = &early_con, .con = &early_con,
}; };
static void __iomem * __init earlycon_map(unsigned long paddr, size_t size) static void __iomem * __init earlycon_map(resource_size_t paddr, size_t size)
{ {
void __iomem *base; void __iomem *base;
#ifdef CONFIG_FIX_EARLYCON_MEM #ifdef CONFIG_FIX_EARLYCON_MEM
...@@ -49,8 +50,7 @@ static void __iomem * __init earlycon_map(unsigned long paddr, size_t size) ...@@ -49,8 +50,7 @@ static void __iomem * __init earlycon_map(unsigned long paddr, size_t size)
base = ioremap(paddr, size); base = ioremap(paddr, size);
#endif #endif
if (!base) if (!base)
pr_err("%s: Couldn't map 0x%llx\n", __func__, pr_err("%s: Couldn't map %pa\n", __func__, &paddr);
(unsigned long long)paddr);
return base; return base;
} }
...@@ -92,7 +92,7 @@ static int __init parse_options(struct earlycon_device *device, char *options) ...@@ -92,7 +92,7 @@ static int __init parse_options(struct earlycon_device *device, char *options)
{ {
struct uart_port *port = &device->port; struct uart_port *port = &device->port;
int length; int length;
unsigned long addr; resource_size_t addr;
if (uart_parse_earlycon(options, &port->iotype, &addr, &options)) if (uart_parse_earlycon(options, &port->iotype, &addr, &options))
return -EINVAL; return -EINVAL;
...@@ -199,6 +199,14 @@ int __init setup_earlycon(char *buf) ...@@ -199,6 +199,14 @@ int __init setup_earlycon(char *buf)
return -ENOENT; return -ENOENT;
} }
/*
* When CONFIG_ACPI_SPCR_TABLE is defined, "earlycon" without parameters in
* command line does not start DT earlycon immediately, instead it defers
* starting it until DT/ACPI decision is made. At that time if ACPI is enabled
* call parse_spcr(), else call early_init_dt_scan_chosen_stdout()
*/
bool earlycon_init_is_deferred __initdata;
/* early_param wrapper for setup_earlycon() */ /* early_param wrapper for setup_earlycon() */
static int __init param_setup_earlycon(char *buf) static int __init param_setup_earlycon(char *buf)
{ {
...@@ -208,8 +216,14 @@ static int __init param_setup_earlycon(char *buf) ...@@ -208,8 +216,14 @@ static int __init param_setup_earlycon(char *buf)
* Just 'earlycon' is a valid param for devicetree earlycons; * Just 'earlycon' is a valid param for devicetree earlycons;
* don't generate a warning from parse_early_params() in that case * don't generate a warning from parse_early_params() in that case
*/ */
if (!buf || !buf[0]) if (!buf || !buf[0]) {
return 0; if (IS_ENABLED(CONFIG_ACPI_SPCR_TABLE)) {
earlycon_init_is_deferred = true;
return 0;
} else {
return early_init_dt_scan_chosen_stdout();
}
}
err = setup_earlycon(buf); err = setup_earlycon(buf);
if (err == -ENOENT || err == -EALREADY) if (err == -ENOENT || err == -EALREADY)
......
此差异已折叠。
...@@ -190,6 +190,7 @@ ...@@ -190,6 +190,7 @@
enum imx_uart_type { enum imx_uart_type {
IMX1_UART, IMX1_UART,
IMX21_UART, IMX21_UART,
IMX53_UART,
IMX6Q_UART, IMX6Q_UART,
}; };
...@@ -222,6 +223,9 @@ struct imx_port { ...@@ -222,6 +223,9 @@ struct imx_port {
struct dma_chan *dma_chan_rx, *dma_chan_tx; struct dma_chan *dma_chan_rx, *dma_chan_tx;
struct scatterlist rx_sgl, tx_sgl[2]; struct scatterlist rx_sgl, tx_sgl[2];
void *rx_buf; void *rx_buf;
struct circ_buf rx_ring;
unsigned int rx_periods;
dma_cookie_t rx_cookie;
unsigned int tx_bytes; unsigned int tx_bytes;
unsigned int dma_tx_nents; unsigned int dma_tx_nents;
wait_queue_head_t dma_wait; wait_queue_head_t dma_wait;
...@@ -244,6 +248,10 @@ static struct imx_uart_data imx_uart_devdata[] = { ...@@ -244,6 +248,10 @@ static struct imx_uart_data imx_uart_devdata[] = {
.uts_reg = IMX21_UTS, .uts_reg = IMX21_UTS,
.devtype = IMX21_UART, .devtype = IMX21_UART,
}, },
[IMX53_UART] = {
.uts_reg = IMX21_UTS,
.devtype = IMX53_UART,
},
[IMX6Q_UART] = { [IMX6Q_UART] = {
.uts_reg = IMX21_UTS, .uts_reg = IMX21_UTS,
.devtype = IMX6Q_UART, .devtype = IMX6Q_UART,
...@@ -257,6 +265,9 @@ static const struct platform_device_id imx_uart_devtype[] = { ...@@ -257,6 +265,9 @@ static const struct platform_device_id imx_uart_devtype[] = {
}, { }, {
.name = "imx21-uart", .name = "imx21-uart",
.driver_data = (kernel_ulong_t) &imx_uart_devdata[IMX21_UART], .driver_data = (kernel_ulong_t) &imx_uart_devdata[IMX21_UART],
}, {
.name = "imx53-uart",
.driver_data = (kernel_ulong_t) &imx_uart_devdata[IMX53_UART],
}, { }, {
.name = "imx6q-uart", .name = "imx6q-uart",
.driver_data = (kernel_ulong_t) &imx_uart_devdata[IMX6Q_UART], .driver_data = (kernel_ulong_t) &imx_uart_devdata[IMX6Q_UART],
...@@ -268,6 +279,7 @@ MODULE_DEVICE_TABLE(platform, imx_uart_devtype); ...@@ -268,6 +279,7 @@ MODULE_DEVICE_TABLE(platform, imx_uart_devtype);
static const struct of_device_id imx_uart_dt_ids[] = { static const struct of_device_id imx_uart_dt_ids[] = {
{ .compatible = "fsl,imx6q-uart", .data = &imx_uart_devdata[IMX6Q_UART], }, { .compatible = "fsl,imx6q-uart", .data = &imx_uart_devdata[IMX6Q_UART], },
{ .compatible = "fsl,imx53-uart", .data = &imx_uart_devdata[IMX53_UART], },
{ .compatible = "fsl,imx1-uart", .data = &imx_uart_devdata[IMX1_UART], }, { .compatible = "fsl,imx1-uart", .data = &imx_uart_devdata[IMX1_UART], },
{ .compatible = "fsl,imx21-uart", .data = &imx_uart_devdata[IMX21_UART], }, { .compatible = "fsl,imx21-uart", .data = &imx_uart_devdata[IMX21_UART], },
{ /* sentinel */ } { /* sentinel */ }
...@@ -289,6 +301,11 @@ static inline int is_imx21_uart(struct imx_port *sport) ...@@ -289,6 +301,11 @@ static inline int is_imx21_uart(struct imx_port *sport)
return sport->devdata->devtype == IMX21_UART; return sport->devdata->devtype == IMX21_UART;
} }
static inline int is_imx53_uart(struct imx_port *sport)
{
return sport->devdata->devtype == IMX53_UART;
}
static inline int is_imx6q_uart(struct imx_port *sport) static inline int is_imx6q_uart(struct imx_port *sport)
{ {
return sport->devdata->devtype == IMX6Q_UART; return sport->devdata->devtype == IMX6Q_UART;
...@@ -701,6 +718,7 @@ static irqreturn_t imx_rxint(int irq, void *dev_id) ...@@ -701,6 +718,7 @@ static irqreturn_t imx_rxint(int irq, void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static void clear_rx_errors(struct imx_port *sport);
static int start_rx_dma(struct imx_port *sport); static int start_rx_dma(struct imx_port *sport);
/* /*
* If the RXFIFO is filled with some data, and then we * If the RXFIFO is filled with some data, and then we
...@@ -726,6 +744,11 @@ static void imx_dma_rxint(struct imx_port *sport) ...@@ -726,6 +744,11 @@ static void imx_dma_rxint(struct imx_port *sport)
temp &= ~(UCR2_ATEN); temp &= ~(UCR2_ATEN);
writel(temp, sport->port.membase + UCR2); writel(temp, sport->port.membase + UCR2);
/* disable the rx errors interrupts */
temp = readl(sport->port.membase + UCR4);
temp &= ~UCR4_OREN;
writel(temp, sport->port.membase + UCR4);
/* tell the DMA to receive the data. */ /* tell the DMA to receive the data. */
start_rx_dma(sport); start_rx_dma(sport);
} }
...@@ -740,12 +763,13 @@ static unsigned int imx_get_hwmctrl(struct imx_port *sport) ...@@ -740,12 +763,13 @@ static unsigned int imx_get_hwmctrl(struct imx_port *sport)
{ {
unsigned int tmp = TIOCM_DSR; unsigned int tmp = TIOCM_DSR;
unsigned usr1 = readl(sport->port.membase + USR1); unsigned usr1 = readl(sport->port.membase + USR1);
unsigned usr2 = readl(sport->port.membase + USR2);
if (usr1 & USR1_RTSS) if (usr1 & USR1_RTSS)
tmp |= TIOCM_CTS; tmp |= TIOCM_CTS;
/* in DCE mode DCDIN is always 0 */ /* in DCE mode DCDIN is always 0 */
if (!(usr1 & USR2_DCDIN)) if (!(usr2 & USR2_DCDIN))
tmp |= TIOCM_CAR; tmp |= TIOCM_CAR;
if (sport->dte_mode) if (sport->dte_mode)
...@@ -932,30 +956,6 @@ static void imx_timeout(unsigned long data) ...@@ -932,30 +956,6 @@ static void imx_timeout(unsigned long data)
} }
#define RX_BUF_SIZE (PAGE_SIZE) #define RX_BUF_SIZE (PAGE_SIZE)
static void imx_rx_dma_done(struct imx_port *sport)
{
unsigned long temp;
unsigned long flags;
spin_lock_irqsave(&sport->port.lock, flags);
/* re-enable interrupts to get notified when new symbols are incoming */
temp = readl(sport->port.membase + UCR1);
temp |= UCR1_RRDYEN;
writel(temp, sport->port.membase + UCR1);
temp = readl(sport->port.membase + UCR2);
temp |= UCR2_ATEN;
writel(temp, sport->port.membase + UCR2);
sport->dma_is_rxing = 0;
/* Is the shutdown waiting for us? */
if (waitqueue_active(&sport->dma_wait))
wake_up(&sport->dma_wait);
spin_unlock_irqrestore(&sport->port.lock, flags);
}
/* /*
* There are two kinds of RX DMA interrupts(such as in the MX6Q): * There are two kinds of RX DMA interrupts(such as in the MX6Q):
...@@ -972,43 +972,76 @@ static void dma_rx_callback(void *data) ...@@ -972,43 +972,76 @@ static void dma_rx_callback(void *data)
struct scatterlist *sgl = &sport->rx_sgl; struct scatterlist *sgl = &sport->rx_sgl;
struct tty_port *port = &sport->port.state->port; struct tty_port *port = &sport->port.state->port;
struct dma_tx_state state; struct dma_tx_state state;
struct circ_buf *rx_ring = &sport->rx_ring;
enum dma_status status; enum dma_status status;
unsigned int count; unsigned int w_bytes = 0;
unsigned int r_bytes;
/* unmap it first */ unsigned int bd_size;
dma_unmap_sg(sport->port.dev, sgl, 1, DMA_FROM_DEVICE);
status = dmaengine_tx_status(chan, (dma_cookie_t)0, &state); status = dmaengine_tx_status(chan, (dma_cookie_t)0, &state);
count = RX_BUF_SIZE - state.residue;
dev_dbg(sport->port.dev, "We get %d bytes.\n", count); if (status == DMA_ERROR) {
dev_err(sport->port.dev, "DMA transaction error.\n");
clear_rx_errors(sport);
return;
}
if (!(sport->port.ignore_status_mask & URXD_DUMMY_READ)) {
/*
* The state-residue variable represents the empty space
* relative to the entire buffer. Taking this in consideration
* the head is always calculated base on the buffer total
* length - DMA transaction residue. The UART script from the
* SDMA firmware will jump to the next buffer descriptor,
* once a DMA transaction if finalized (IMX53 RM - A.4.1.2.4).
* Taking this in consideration the tail is always at the
* beginning of the buffer descriptor that contains the head.
*/
/* Calculate the head */
rx_ring->head = sg_dma_len(sgl) - state.residue;
/* Calculate the tail. */
bd_size = sg_dma_len(sgl) / sport->rx_periods;
rx_ring->tail = ((rx_ring->head-1) / bd_size) * bd_size;
if (rx_ring->head <= sg_dma_len(sgl) &&
rx_ring->head > rx_ring->tail) {
/* Move data from tail to head */
r_bytes = rx_ring->head - rx_ring->tail;
if (count) { /* CPU claims ownership of RX DMA buffer */
if (!(sport->port.ignore_status_mask & URXD_DUMMY_READ)) { dma_sync_sg_for_cpu(sport->port.dev, sgl, 1,
int bytes = tty_insert_flip_string(port, sport->rx_buf, DMA_FROM_DEVICE);
count);
if (bytes != count) w_bytes = tty_insert_flip_string(port,
sport->rx_buf + rx_ring->tail, r_bytes);
/* UART retrieves ownership of RX DMA buffer */
dma_sync_sg_for_device(sport->port.dev, sgl, 1,
DMA_FROM_DEVICE);
if (w_bytes != r_bytes)
sport->port.icount.buf_overrun++; sport->port.icount.buf_overrun++;
sport->port.icount.rx += w_bytes;
} else {
WARN_ON(rx_ring->head > sg_dma_len(sgl));
WARN_ON(rx_ring->head <= rx_ring->tail);
} }
tty_flip_buffer_push(port);
sport->port.icount.rx += count;
} }
/* if (w_bytes) {
* Restart RX DMA directly if more data is available in order to skip tty_flip_buffer_push(port);
* the roundtrip through the IRQ handler. If there is some data already dev_dbg(sport->port.dev, "We get %d bytes.\n", w_bytes);
* in the FIFO, DMA needs to be restarted soon anyways. }
*
* Otherwise stop the DMA and reactivate FIFO IRQs to restart DMA once
* data starts to arrive again.
*/
if (readl(sport->port.membase + USR2) & USR2_RDR)
start_rx_dma(sport);
else
imx_rx_dma_done(sport);
} }
/* RX DMA buffer periods */
#define RX_DMA_PERIODS 4
static int start_rx_dma(struct imx_port *sport) static int start_rx_dma(struct imx_port *sport)
{ {
struct scatterlist *sgl = &sport->rx_sgl; struct scatterlist *sgl = &sport->rx_sgl;
...@@ -1017,14 +1050,21 @@ static int start_rx_dma(struct imx_port *sport) ...@@ -1017,14 +1050,21 @@ static int start_rx_dma(struct imx_port *sport)
struct dma_async_tx_descriptor *desc; struct dma_async_tx_descriptor *desc;
int ret; int ret;
sport->rx_ring.head = 0;
sport->rx_ring.tail = 0;
sport->rx_periods = RX_DMA_PERIODS;
sg_init_one(sgl, sport->rx_buf, RX_BUF_SIZE); sg_init_one(sgl, sport->rx_buf, RX_BUF_SIZE);
ret = dma_map_sg(dev, sgl, 1, DMA_FROM_DEVICE); ret = dma_map_sg(dev, sgl, 1, DMA_FROM_DEVICE);
if (ret == 0) { if (ret == 0) {
dev_err(dev, "DMA mapping error for RX.\n"); dev_err(dev, "DMA mapping error for RX.\n");
return -EINVAL; return -EINVAL;
} }
desc = dmaengine_prep_slave_sg(chan, sgl, 1, DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT); desc = dmaengine_prep_dma_cyclic(chan, sg_dma_address(sgl),
sg_dma_len(sgl), sg_dma_len(sgl) / sport->rx_periods,
DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT);
if (!desc) { if (!desc) {
dma_unmap_sg(dev, sgl, 1, DMA_FROM_DEVICE); dma_unmap_sg(dev, sgl, 1, DMA_FROM_DEVICE);
dev_err(dev, "We cannot prepare for the RX slave dma!\n"); dev_err(dev, "We cannot prepare for the RX slave dma!\n");
...@@ -1034,11 +1074,36 @@ static int start_rx_dma(struct imx_port *sport) ...@@ -1034,11 +1074,36 @@ static int start_rx_dma(struct imx_port *sport)
desc->callback_param = sport; desc->callback_param = sport;
dev_dbg(dev, "RX: prepare for the DMA.\n"); dev_dbg(dev, "RX: prepare for the DMA.\n");
dmaengine_submit(desc); sport->rx_cookie = dmaengine_submit(desc);
dma_async_issue_pending(chan); dma_async_issue_pending(chan);
return 0; return 0;
} }
static void clear_rx_errors(struct imx_port *sport)
{
unsigned int status_usr1, status_usr2;
status_usr1 = readl(sport->port.membase + USR1);
status_usr2 = readl(sport->port.membase + USR2);
if (status_usr2 & USR2_BRCD) {
sport->port.icount.brk++;
writel(USR2_BRCD, sport->port.membase + USR2);
} else if (status_usr1 & USR1_FRAMERR) {
sport->port.icount.frame++;
writel(USR1_FRAMERR, sport->port.membase + USR1);
} else if (status_usr1 & USR1_PARITYERR) {
sport->port.icount.parity++;
writel(USR1_PARITYERR, sport->port.membase + USR1);
}
if (status_usr2 & USR2_ORE) {
sport->port.icount.overrun++;
writel(USR2_ORE, sport->port.membase + USR2);
}
}
#define TXTL_DEFAULT 2 /* reset default */ #define TXTL_DEFAULT 2 /* reset default */
#define RXTL_DEFAULT 1 /* reset default */ #define RXTL_DEFAULT 1 /* reset default */
#define TXTL_DMA 8 /* DMA burst setting */ #define TXTL_DMA 8 /* DMA burst setting */
...@@ -1058,14 +1123,16 @@ static void imx_setup_ufcr(struct imx_port *sport, ...@@ -1058,14 +1123,16 @@ static void imx_setup_ufcr(struct imx_port *sport,
static void imx_uart_dma_exit(struct imx_port *sport) static void imx_uart_dma_exit(struct imx_port *sport)
{ {
if (sport->dma_chan_rx) { if (sport->dma_chan_rx) {
dmaengine_terminate_sync(sport->dma_chan_rx);
dma_release_channel(sport->dma_chan_rx); dma_release_channel(sport->dma_chan_rx);
sport->dma_chan_rx = NULL; sport->dma_chan_rx = NULL;
sport->rx_cookie = -EINVAL;
kfree(sport->rx_buf); kfree(sport->rx_buf);
sport->rx_buf = NULL; sport->rx_buf = NULL;
} }
if (sport->dma_chan_tx) { if (sport->dma_chan_tx) {
dmaengine_terminate_sync(sport->dma_chan_tx);
dma_release_channel(sport->dma_chan_tx); dma_release_channel(sport->dma_chan_tx);
sport->dma_chan_tx = NULL; sport->dma_chan_tx = NULL;
} }
...@@ -1103,6 +1170,7 @@ static int imx_uart_dma_init(struct imx_port *sport) ...@@ -1103,6 +1170,7 @@ static int imx_uart_dma_init(struct imx_port *sport)
ret = -ENOMEM; ret = -ENOMEM;
goto err; goto err;
} }
sport->rx_ring.buf = sport->rx_buf;
/* Prepare for TX : */ /* Prepare for TX : */
sport->dma_chan_tx = dma_request_slave_channel(dev, "tx"); sport->dma_chan_tx = dma_request_slave_channel(dev, "tx");
...@@ -1201,8 +1269,7 @@ static int imx_startup(struct uart_port *port) ...@@ -1201,8 +1269,7 @@ static int imx_startup(struct uart_port *port)
writel(temp & ~UCR4_DREN, sport->port.membase + UCR4); writel(temp & ~UCR4_DREN, sport->port.membase + UCR4);
/* Can we enable the DMA support? */ /* Can we enable the DMA support? */
if (is_imx6q_uart(sport) && !uart_console(port) && if (!uart_console(port) && !sport->dma_is_inited)
!sport->dma_is_inited)
imx_uart_dma_init(sport); imx_uart_dma_init(sport);
spin_lock_irqsave(&sport->port.lock, flags); spin_lock_irqsave(&sport->port.lock, flags);
...@@ -1283,17 +1350,11 @@ static void imx_shutdown(struct uart_port *port) ...@@ -1283,17 +1350,11 @@ static void imx_shutdown(struct uart_port *port)
unsigned long flags; unsigned long flags;
if (sport->dma_is_enabled) { if (sport->dma_is_enabled) {
int ret; sport->dma_is_rxing = 0;
sport->dma_is_txing = 0;
dmaengine_terminate_sync(sport->dma_chan_tx);
dmaengine_terminate_sync(sport->dma_chan_rx);
/* We have to wait for the DMA to finish. */
ret = wait_event_interruptible(sport->dma_wait,
!sport->dma_is_rxing && !sport->dma_is_txing);
if (ret != 0) {
sport->dma_is_rxing = 0;
sport->dma_is_txing = 0;
dmaengine_terminate_all(sport->dma_chan_tx);
dmaengine_terminate_all(sport->dma_chan_rx);
}
spin_lock_irqsave(&sport->port.lock, flags); spin_lock_irqsave(&sport->port.lock, flags);
imx_stop_tx(port); imx_stop_tx(port);
imx_stop_rx(port); imx_stop_rx(port);
...@@ -1690,7 +1751,7 @@ static int imx_rs485_config(struct uart_port *port, ...@@ -1690,7 +1751,7 @@ static int imx_rs485_config(struct uart_port *port,
return 0; return 0;
} }
static struct uart_ops imx_pops = { static const struct uart_ops imx_pops = {
.tx_empty = imx_tx_empty, .tx_empty = imx_tx_empty,
.set_mctrl = imx_set_mctrl, .set_mctrl = imx_set_mctrl,
.get_mctrl = imx_get_mctrl, .get_mctrl = imx_get_mctrl,
...@@ -2077,8 +2138,10 @@ static int serial_imx_probe(struct platform_device *pdev) ...@@ -2077,8 +2138,10 @@ static int serial_imx_probe(struct platform_device *pdev)
/* For register access, we only need to enable the ipg clock. */ /* For register access, we only need to enable the ipg clock. */
ret = clk_prepare_enable(sport->clk_ipg); ret = clk_prepare_enable(sport->clk_ipg);
if (ret) if (ret) {
dev_err(&pdev->dev, "failed to enable per clk: %d\n", ret);
return ret; return ret;
}
/* Disable interrupts before requesting them */ /* Disable interrupts before requesting them */
reg = readl_relaxed(sport->port.membase + UCR1); reg = readl_relaxed(sport->port.membase + UCR1);
...@@ -2095,18 +2158,26 @@ static int serial_imx_probe(struct platform_device *pdev) ...@@ -2095,18 +2158,26 @@ static int serial_imx_probe(struct platform_device *pdev)
if (txirq > 0) { if (txirq > 0) {
ret = devm_request_irq(&pdev->dev, rxirq, imx_rxint, 0, ret = devm_request_irq(&pdev->dev, rxirq, imx_rxint, 0,
dev_name(&pdev->dev), sport); dev_name(&pdev->dev), sport);
if (ret) if (ret) {
dev_err(&pdev->dev, "failed to request rx irq: %d\n",
ret);
return ret; return ret;
}
ret = devm_request_irq(&pdev->dev, txirq, imx_txint, 0, ret = devm_request_irq(&pdev->dev, txirq, imx_txint, 0,
dev_name(&pdev->dev), sport); dev_name(&pdev->dev), sport);
if (ret) if (ret) {
dev_err(&pdev->dev, "failed to request tx irq: %d\n",
ret);
return ret; return ret;
}
} else { } else {
ret = devm_request_irq(&pdev->dev, rxirq, imx_int, 0, ret = devm_request_irq(&pdev->dev, rxirq, imx_int, 0,
dev_name(&pdev->dev), sport); dev_name(&pdev->dev), sport);
if (ret) if (ret) {
dev_err(&pdev->dev, "failed to request irq: %d\n", ret);
return ret; return ret;
}
} }
imx_ports[sport->port.line] = sport; imx_ports[sport->port.line] = sport;
......
...@@ -346,7 +346,7 @@ static void jsm_config_port(struct uart_port *port, int flags) ...@@ -346,7 +346,7 @@ static void jsm_config_port(struct uart_port *port, int flags)
port->type = PORT_JSM; port->type = PORT_JSM;
} }
static struct uart_ops jsm_ops = { static const struct uart_ops jsm_ops = {
.tx_empty = jsm_tty_tx_empty, .tx_empty = jsm_tty_tx_empty,
.set_mctrl = jsm_tty_set_mctrl, .set_mctrl = jsm_tty_set_mctrl,
.get_mctrl = jsm_tty_get_mctrl, .get_mctrl = jsm_tty_get_mctrl,
......
...@@ -712,7 +712,7 @@ static void max3100_break_ctl(struct uart_port *port, int break_state) ...@@ -712,7 +712,7 @@ static void max3100_break_ctl(struct uart_port *port, int break_state)
dev_dbg(&s->spi->dev, "%s\n", __func__); dev_dbg(&s->spi->dev, "%s\n", __func__);
} }
static struct uart_ops max3100_ops = { static const struct uart_ops max3100_ops = {
.tx_empty = max3100_tx_empty, .tx_empty = max3100_tx_empty,
.set_mctrl = max3100_set_mctrl, .set_mctrl = max3100_set_mctrl,
.get_mctrl = max3100_get_mctrl, .get_mctrl = max3100_get_mctrl,
......
...@@ -1329,9 +1329,9 @@ static int max310x_spi_probe(struct spi_device *spi) ...@@ -1329,9 +1329,9 @@ static int max310x_spi_probe(struct spi_device *spi)
const struct spi_device_id *id_entry = spi_get_device_id(spi); const struct spi_device_id *id_entry = spi_get_device_id(spi);
devtype = (struct max310x_devtype *)id_entry->driver_data; devtype = (struct max310x_devtype *)id_entry->driver_data;
flags = IRQF_TRIGGER_FALLING;
} }
flags = IRQF_TRIGGER_FALLING;
regcfg.max_register = devtype->nr * 0x20 - 1; regcfg.max_register = devtype->nr * 0x20 - 1;
regmap = devm_regmap_init_spi(spi, &regcfg); regmap = devm_regmap_init_spi(spi, &regcfg);
......
...@@ -775,7 +775,7 @@ static int men_z135_verify_port(struct uart_port *port, ...@@ -775,7 +775,7 @@ static int men_z135_verify_port(struct uart_port *port,
return -EINVAL; return -EINVAL;
} }
static struct uart_ops men_z135_ops = { static const struct uart_ops men_z135_ops = {
.tx_empty = men_z135_tx_empty, .tx_empty = men_z135_tx_empty,
.set_mctrl = men_z135_set_mctrl, .set_mctrl = men_z135_set_mctrl,
.get_mctrl = men_z135_get_mctrl, .get_mctrl = men_z135_get_mctrl,
......
...@@ -1317,7 +1317,7 @@ static void mxs_auart_break_ctl(struct uart_port *u, int ctl) ...@@ -1317,7 +1317,7 @@ static void mxs_auart_break_ctl(struct uart_port *u, int ctl)
mxs_clr(AUART_LINECTRL_BRK, s, REG_LINECTRL); mxs_clr(AUART_LINECTRL_BRK, s, REG_LINECTRL);
} }
static struct uart_ops mxs_auart_ops = { static const struct uart_ops mxs_auart_ops = {
.tx_empty = mxs_auart_tx_empty, .tx_empty = mxs_auart_tx_empty,
.start_tx = mxs_auart_start_tx, .start_tx = mxs_auart_start_tx,
.stop_tx = mxs_auart_stop_tx, .stop_tx = mxs_auart_stop_tx,
...@@ -1510,10 +1510,7 @@ static int mxs_get_clks(struct mxs_auart_port *s, ...@@ -1510,10 +1510,7 @@ static int mxs_get_clks(struct mxs_auart_port *s,
if (!is_asm9260_auart(s)) { if (!is_asm9260_auart(s)) {
s->clk = devm_clk_get(&pdev->dev, NULL); s->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(s->clk)) return PTR_ERR_OR_ZERO(s->clk);
return PTR_ERR(s->clk);
return 0;
} }
s->clk = devm_clk_get(s->dev, "mod"); s->clk = devm_clk_get(s->dev, "mod");
...@@ -1537,16 +1534,20 @@ static int mxs_get_clks(struct mxs_auart_port *s, ...@@ -1537,16 +1534,20 @@ static int mxs_get_clks(struct mxs_auart_port *s,
err = clk_set_rate(s->clk, clk_get_rate(s->clk_ahb)); err = clk_set_rate(s->clk, clk_get_rate(s->clk_ahb));
if (err) { if (err) {
dev_err(s->dev, "Failed to set rate!\n"); dev_err(s->dev, "Failed to set rate!\n");
return err; goto disable_clk_ahb;
} }
err = clk_prepare_enable(s->clk); err = clk_prepare_enable(s->clk);
if (err) { if (err) {
dev_err(s->dev, "Failed to enable clk!\n"); dev_err(s->dev, "Failed to enable clk!\n");
return err; goto disable_clk_ahb;
} }
return 0; return 0;
disable_clk_ahb:
clk_disable_unprepare(s->clk_ahb);
return err;
} }
/* /*
......
...@@ -1604,7 +1604,7 @@ static void pch_uart_put_poll_char(struct uart_port *port, ...@@ -1604,7 +1604,7 @@ static void pch_uart_put_poll_char(struct uart_port *port,
} }
#endif /* CONFIG_CONSOLE_POLL */ #endif /* CONFIG_CONSOLE_POLL */
static struct uart_ops pch_uart_ops = { static const struct uart_ops pch_uart_ops = {
.tx_empty = pch_uart_tx_empty, .tx_empty = pch_uart_tx_empty,
.set_mctrl = pch_uart_set_mctrl, .set_mctrl = pch_uart_set_mctrl,
.get_mctrl = pch_uart_get_mctrl, .get_mctrl = pch_uart_get_mctrl,
......
...@@ -1577,7 +1577,7 @@ static void s3c24xx_serial_resetport(struct uart_port *port, ...@@ -1577,7 +1577,7 @@ static void s3c24xx_serial_resetport(struct uart_port *port,
} }
#ifdef CONFIG_CPU_FREQ #ifdef CONFIG_ARM_S3C24XX_CPUFREQ
static int s3c24xx_serial_cpufreq_transition(struct notifier_block *nb, static int s3c24xx_serial_cpufreq_transition(struct notifier_block *nb,
unsigned long val, void *data) unsigned long val, void *data)
......
...@@ -102,7 +102,7 @@ struct s3c24xx_uart_port { ...@@ -102,7 +102,7 @@ struct s3c24xx_uart_port {
struct s3c24xx_uart_dma *dma; struct s3c24xx_uart_dma *dma;
#ifdef CONFIG_CPU_FREQ #ifdef CONFIG_ARM_S3C24XX_CPUFREQ
struct notifier_block freq_transition; struct notifier_block freq_transition;
#endif #endif
}; };
......
...@@ -1205,6 +1205,10 @@ static int sc16is7xx_probe(struct device *dev, ...@@ -1205,6 +1205,10 @@ static int sc16is7xx_probe(struct device *dev,
} }
#endif #endif
/* reset device, purging any pending irq / data */
regmap_write(s->regmap, SC16IS7XX_IOCONTROL_REG << SC16IS7XX_REG_SHIFT,
SC16IS7XX_IOCONTROL_SRESET_BIT);
for (i = 0; i < devtype->nr_uart; ++i) { for (i = 0; i < devtype->nr_uart; ++i) {
s->p[i].line = i; s->p[i].line = i;
/* Initialize port data */ /* Initialize port data */
...@@ -1234,6 +1238,22 @@ static int sc16is7xx_probe(struct device *dev, ...@@ -1234,6 +1238,22 @@ static int sc16is7xx_probe(struct device *dev,
init_kthread_work(&s->p[i].reg_work, sc16is7xx_reg_proc); init_kthread_work(&s->p[i].reg_work, sc16is7xx_reg_proc);
/* Register port */ /* Register port */
uart_add_one_port(&sc16is7xx_uart, &s->p[i].port); uart_add_one_port(&sc16is7xx_uart, &s->p[i].port);
/* Enable EFR */
sc16is7xx_port_write(&s->p[i].port, SC16IS7XX_LCR_REG,
SC16IS7XX_LCR_CONF_MODE_B);
regcache_cache_bypass(s->regmap, true);
/* Enable write access to enhanced features */
sc16is7xx_port_write(&s->p[i].port, SC16IS7XX_EFR_REG,
SC16IS7XX_EFR_ENABLE_BIT);
regcache_cache_bypass(s->regmap, false);
/* Restore access to general registers */
sc16is7xx_port_write(&s->p[i].port, SC16IS7XX_LCR_REG, 0x00);
/* Go to suspend mode */ /* Go to suspend mode */
sc16is7xx_power(&s->p[i].port, 0); sc16is7xx_power(&s->p[i].port, 0);
} }
......
...@@ -235,18 +235,9 @@ static int uart_startup(struct tty_struct *tty, struct uart_state *state, ...@@ -235,18 +235,9 @@ static int uart_startup(struct tty_struct *tty, struct uart_state *state,
if (tty_port_initialized(port)) if (tty_port_initialized(port))
return 0; return 0;
/*
* Set the TTY IO error marker - we will only clear this
* once we have successfully opened the port.
*/
set_bit(TTY_IO_ERROR, &tty->flags);
retval = uart_port_startup(tty, state, init_hw); retval = uart_port_startup(tty, state, init_hw);
if (!retval) { if (retval)
tty_port_set_initialized(port, 1); set_bit(TTY_IO_ERROR, &tty->flags);
clear_bit(TTY_IO_ERROR, &tty->flags);
} else if (retval > 0)
retval = 0;
return retval; return retval;
} }
...@@ -972,8 +963,11 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port, ...@@ -972,8 +963,11 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
} }
uart_change_speed(tty, state, NULL); uart_change_speed(tty, state, NULL);
} }
} else } else {
retval = uart_startup(tty, state, 1); retval = uart_startup(tty, state, 1);
if (retval > 0)
retval = 0;
}
exit: exit:
return retval; return retval;
} }
...@@ -1139,6 +1133,8 @@ static int uart_do_autoconfig(struct tty_struct *tty,struct uart_state *state) ...@@ -1139,6 +1133,8 @@ static int uart_do_autoconfig(struct tty_struct *tty,struct uart_state *state)
uport->ops->config_port(uport, flags); uport->ops->config_port(uport, flags);
ret = uart_startup(tty, state, 1); ret = uart_startup(tty, state, 1);
if (ret > 0)
ret = 0;
} }
out: out:
mutex_unlock(&port->mutex); mutex_unlock(&port->mutex);
...@@ -1465,7 +1461,6 @@ static void uart_close(struct tty_struct *tty, struct file *filp) ...@@ -1465,7 +1461,6 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
{ {
struct uart_state *state = tty->driver_data; struct uart_state *state = tty->driver_data;
struct tty_port *port; struct tty_port *port;
struct uart_port *uport;
if (!state) { if (!state) {
struct uart_driver *drv = tty->driver->driver_state; struct uart_driver *drv = tty->driver->driver_state;
...@@ -1481,56 +1476,36 @@ static void uart_close(struct tty_struct *tty, struct file *filp) ...@@ -1481,56 +1476,36 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
port = &state->port; port = &state->port;
pr_debug("uart_close(%d) called\n", tty->index); pr_debug("uart_close(%d) called\n", tty->index);
if (tty_port_close_start(port, tty, filp) == 0) tty_port_close(tty->port, tty, filp);
return; }
mutex_lock(&port->mutex); static void uart_tty_port_shutdown(struct tty_port *port)
uport = uart_port_check(state); {
struct uart_state *state = container_of(port, struct uart_state, port);
struct uart_port *uport = uart_port_check(state);
/* /*
* At this point, we stop accepting input. To do this, we * At this point, we stop accepting input. To do this, we
* disable the receive line status interrupts. * disable the receive line status interrupts.
*/ */
if (tty_port_initialized(port) && if (WARN(!uport, "detached port still initialized!\n"))
!WARN(!uport, "detached port still initialized!\n")) { return;
spin_lock_irq(&uport->lock);
uport->ops->stop_rx(uport);
spin_unlock_irq(&uport->lock);
/*
* Before we drop DTR, make sure the UART transmitter
* has completely drained; this is especially
* important if there is a transmit FIFO!
*/
uart_wait_until_sent(tty, uport->timeout);
}
uart_shutdown(tty, state);
tty_port_tty_set(port, NULL);
spin_lock_irq(&port->lock); spin_lock_irq(&uport->lock);
uport->ops->stop_rx(uport);
spin_unlock_irq(&uport->lock);
if (port->blocked_open) { uart_port_shutdown(port);
spin_unlock_irq(&port->lock);
if (port->close_delay)
msleep_interruptible(jiffies_to_msecs(port->close_delay));
spin_lock_irq(&port->lock);
} else if (uport && !uart_console(uport)) {
spin_unlock_irq(&port->lock);
uart_change_pm(state, UART_PM_STATE_OFF);
spin_lock_irq(&port->lock);
}
spin_unlock_irq(&port->lock);
tty_port_set_active(port, 0);
/* /*
* Wake up anyone trying to open this port. * It's possible for shutdown to be called after suspend if we get
* a DCD drop (hangup) at just the right time. Clear suspended bit so
* we don't try to resume a port that has been shutdown.
*/ */
wake_up_interruptible(&port->open_wait); tty_port_set_suspended(port, 0);
mutex_unlock(&port->mutex); uart_change_pm(state, UART_PM_STATE_OFF);
tty_ldisc_flush(tty);
tty->closing = 0;
} }
static void uart_wait_until_sent(struct tty_struct *tty, int timeout) static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
...@@ -1711,52 +1686,31 @@ static int uart_open(struct tty_struct *tty, struct file *filp) ...@@ -1711,52 +1686,31 @@ static int uart_open(struct tty_struct *tty, struct file *filp)
struct uart_driver *drv = tty->driver->driver_state; struct uart_driver *drv = tty->driver->driver_state;
int retval, line = tty->index; int retval, line = tty->index;
struct uart_state *state = drv->state + line; struct uart_state *state = drv->state + line;
struct tty_port *port = &state->port;
struct uart_port *uport;
pr_debug("uart_open(%d) called\n", line); tty->driver_data = state;
spin_lock_irq(&port->lock); retval = tty_port_open(&state->port, tty, filp);
++port->count; if (retval > 0)
spin_unlock_irq(&port->lock); retval = 0;
/* return retval;
* We take the semaphore here to guarantee that we won't be re-entered }
* while allocating the state structure, or while we request any IRQs
* that the driver may need. This also has the nice side-effect that static int uart_port_activate(struct tty_port *port, struct tty_struct *tty)
* it delays the action of uart_hangup, so we can guarantee that {
* state->port.tty will always contain something reasonable. struct uart_state *state = container_of(port, struct uart_state, port);
*/ struct uart_port *uport;
if (mutex_lock_interruptible(&port->mutex)) {
retval = -ERESTARTSYS;
goto end;
}
uport = uart_port_check(state); uport = uart_port_check(state);
if (!uport || uport->flags & UPF_DEAD) { if (!uport || uport->flags & UPF_DEAD)
retval = -ENXIO; return -ENXIO;
goto err_unlock;
}
tty->driver_data = state;
uport->state = state;
port->low_latency = (uport->flags & UPF_LOW_LATENCY) ? 1 : 0; port->low_latency = (uport->flags & UPF_LOW_LATENCY) ? 1 : 0;
tty_port_tty_set(port, tty);
/* /*
* Start up the serial port. * Start up the serial port.
*/ */
retval = uart_startup(tty, state, 0); return uart_startup(tty, state, 0);
/*
* If we succeeded, wait until the port is ready.
*/
err_unlock:
mutex_unlock(&port->mutex);
if (retval == 0)
retval = tty_port_block_til_ready(port, tty, filp);
end:
return retval;
} }
static const char *uart_type(struct uart_port *port) static const char *uart_type(struct uart_port *port)
...@@ -1940,7 +1894,7 @@ uart_get_console(struct uart_port *ports, int nr, struct console *co) ...@@ -1940,7 +1894,7 @@ uart_get_console(struct uart_port *ports, int nr, struct console *co)
* *
* Returns 0 on success or -EINVAL on failure * Returns 0 on success or -EINVAL on failure
*/ */
int uart_parse_earlycon(char *p, unsigned char *iotype, unsigned long *addr, int uart_parse_earlycon(char *p, unsigned char *iotype, resource_size_t *addr,
char **options) char **options)
{ {
if (strncmp(p, "mmio,", 5) == 0) { if (strncmp(p, "mmio,", 5) == 0) {
...@@ -1968,7 +1922,11 @@ int uart_parse_earlycon(char *p, unsigned char *iotype, unsigned long *addr, ...@@ -1968,7 +1922,11 @@ int uart_parse_earlycon(char *p, unsigned char *iotype, unsigned long *addr,
return -EINVAL; return -EINVAL;
} }
*addr = simple_strtoul(p, NULL, 0); /*
* Before you replace it with kstrtoull(), think about options separator
* (',') it will not tolerate
*/
*addr = simple_strtoull(p, NULL, 0);
p = strchr(p, ','); p = strchr(p, ',');
if (p) if (p)
p++; p++;
...@@ -2470,6 +2428,8 @@ static const struct tty_operations uart_ops = { ...@@ -2470,6 +2428,8 @@ static const struct tty_operations uart_ops = {
static const struct tty_port_operations uart_port_ops = { static const struct tty_port_operations uart_port_ops = {
.carrier_raised = uart_carrier_raised, .carrier_raised = uart_carrier_raised,
.dtr_rts = uart_dtr_rts, .dtr_rts = uart_dtr_rts,
.activate = uart_port_activate,
.shutdown = uart_tty_port_shutdown,
}; };
/** /**
...@@ -2786,6 +2746,8 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport) ...@@ -2786,6 +2746,8 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
uport->cons = drv->cons; uport->cons = drv->cons;
uport->minor = drv->tty_driver->minor_start + uport->line; uport->minor = drv->tty_driver->minor_start + uport->line;
port->console = uart_console(uport);
/* /*
* If this port is a console, then the spinlock is already * If this port is a console, then the spinlock is already
* initialised. * initialised.
......
...@@ -2533,7 +2533,7 @@ static int sci_verify_port(struct uart_port *port, struct serial_struct *ser) ...@@ -2533,7 +2533,7 @@ static int sci_verify_port(struct uart_port *port, struct serial_struct *ser)
return 0; return 0;
} }
static struct uart_ops sci_uart_ops = { static const struct uart_ops sci_uart_ops = {
.tx_empty = sci_tx_empty, .tx_empty = sci_tx_empty,
.set_mctrl = sci_set_mctrl, .set_mctrl = sci_set_mctrl,
.get_mctrl = sci_get_mctrl, .get_mctrl = sci_get_mctrl,
......
...@@ -639,7 +639,7 @@ static void asc_put_poll_char(struct uart_port *port, unsigned char c) ...@@ -639,7 +639,7 @@ static void asc_put_poll_char(struct uart_port *port, unsigned char c)
/*---------------------------------------------------------------------*/ /*---------------------------------------------------------------------*/
static struct uart_ops asc_uart_ops = { static const struct uart_ops asc_uart_ops = {
.tx_empty = asc_tx_empty, .tx_empty = asc_tx_empty,
.set_mctrl = asc_set_mctrl, .set_mctrl = asc_set_mctrl,
.get_mctrl = asc_get_mctrl, .get_mctrl = asc_get_mctrl,
......
此差异已折叠。
此差异已折叠。
...@@ -394,7 +394,7 @@ static int timbuart_verify_port(struct uart_port *port, ...@@ -394,7 +394,7 @@ static int timbuart_verify_port(struct uart_port *port,
return -EINVAL; return -EINVAL;
} }
static struct uart_ops timbuart_ops = { static const struct uart_ops timbuart_ops = {
.tx_empty = timbuart_tx_empty, .tx_empty = timbuart_tx_empty,
.set_mctrl = timbuart_set_mctrl, .set_mctrl = timbuart_set_mctrl,
.get_mctrl = timbuart_get_mctrl, .get_mctrl = timbuart_get_mctrl,
......
...@@ -387,7 +387,7 @@ static void ulite_put_poll_char(struct uart_port *port, unsigned char ch) ...@@ -387,7 +387,7 @@ static void ulite_put_poll_char(struct uart_port *port, unsigned char ch)
} }
#endif #endif
static struct uart_ops ulite_ops = { static const struct uart_ops ulite_ops = {
.tx_empty = ulite_tx_empty, .tx_empty = ulite_tx_empty,
.set_mctrl = ulite_set_mctrl, .set_mctrl = ulite_set_mctrl,
.get_mctrl = ulite_get_mctrl, .get_mctrl = ulite_get_mctrl,
......
...@@ -118,7 +118,7 @@ struct vt8500_port { ...@@ -118,7 +118,7 @@ struct vt8500_port {
* have been allocated as we can't use pdev->id in * have been allocated as we can't use pdev->id in
* devicetree * devicetree
*/ */
static unsigned long vt8500_ports_in_use; static DECLARE_BITMAP(vt8500_ports_in_use, VT8500_MAX_PORTS);
static inline void vt8500_write(struct uart_port *port, unsigned int val, static inline void vt8500_write(struct uart_port *port, unsigned int val,
unsigned int off) unsigned int off)
...@@ -663,15 +663,15 @@ static int vt8500_serial_probe(struct platform_device *pdev) ...@@ -663,15 +663,15 @@ static int vt8500_serial_probe(struct platform_device *pdev)
if (port < 0) { if (port < 0) {
/* calculate the port id */ /* calculate the port id */
port = find_first_zero_bit(&vt8500_ports_in_use, port = find_first_zero_bit(vt8500_ports_in_use,
sizeof(vt8500_ports_in_use)); VT8500_MAX_PORTS);
} }
if (port >= VT8500_MAX_PORTS) if (port >= VT8500_MAX_PORTS)
return -ENODEV; return -ENODEV;
/* reserve the port id */ /* reserve the port id */
if (test_and_set_bit(port, &vt8500_ports_in_use)) { if (test_and_set_bit(port, vt8500_ports_in_use)) {
/* port already in use - shouldn't really happen */ /* port already in use - shouldn't really happen */
return -EBUSY; return -EBUSY;
} }
......
此差异已折叠。
...@@ -1312,12 +1312,12 @@ static int vc_t416_color(struct vc_data *vc, int i, ...@@ -1312,12 +1312,12 @@ static int vc_t416_color(struct vc_data *vc, int i,
if (i > vc->vc_npar) if (i > vc->vc_npar)
return i; return i;
if (vc->vc_par[i] == 5 && i < vc->vc_npar) { if (vc->vc_par[i] == 5 && i + 1 <= vc->vc_npar) {
/* 256 colours -- ubiquitous */ /* 256 colours */
i++; i++;
rgb_from_256(vc->vc_par[i], &c); rgb_from_256(vc->vc_par[i], &c);
} else if (vc->vc_par[i] == 2 && i <= vc->vc_npar + 3) { } else if (vc->vc_par[i] == 2 && i + 3 <= vc->vc_npar) {
/* 24 bit -- extremely rare */ /* 24 bit */
c.r = vc->vc_par[i + 1]; c.r = vc->vc_par[i + 1];
c.g = vc->vc_par[i + 2]; c.g = vc->vc_par[i + 2];
c.b = vc->vc_par[i + 3]; c.b = vc->vc_par[i + 3];
...@@ -1415,6 +1415,11 @@ static void csi_m(struct vc_data *vc) ...@@ -1415,6 +1415,11 @@ static void csi_m(struct vc_data *vc)
(vc->vc_color & 0x0f); (vc->vc_color & 0x0f);
break; break;
default: default:
if (vc->vc_par[i] >= 90 && vc->vc_par[i] <= 107) {
if (vc->vc_par[i] < 100)
vc->vc_intensity = 2;
vc->vc_par[i] -= 60;
}
if (vc->vc_par[i] >= 30 && vc->vc_par[i] <= 37) if (vc->vc_par[i] >= 30 && vc->vc_par[i] <= 37)
vc->vc_color = color_table[vc->vc_par[i] - 30] vc->vc_color = color_table[vc->vc_par[i] - 30]
| (vc->vc_color & 0xf0); | (vc->vc_color & 0xf0);
......
此差异已折叠。
...@@ -1099,4 +1099,10 @@ extern bool acpi_has_watchdog(void); ...@@ -1099,4 +1099,10 @@ extern bool acpi_has_watchdog(void);
static inline bool acpi_has_watchdog(void) { return false; } static inline bool acpi_has_watchdog(void) { return false; }
#endif #endif
#ifdef CONFIG_ACPI_SPCR_TABLE
int parse_spcr(bool earlycon);
#else
static inline int parse_spcr(bool earlycon) { return 0; }
#endif
#endif /*_LINUX_ACPI_H*/ #endif /*_LINUX_ACPI_H*/
...@@ -53,8 +53,14 @@ enum amba_vendor { ...@@ -53,8 +53,14 @@ enum amba_vendor {
AMBA_VENDOR_ST = 0x80, AMBA_VENDOR_ST = 0x80,
AMBA_VENDOR_QCOM = 0x51, AMBA_VENDOR_QCOM = 0x51,
AMBA_VENDOR_LSI = 0xb6, AMBA_VENDOR_LSI = 0xb6,
AMBA_VENDOR_LINUX = 0xfe, /* This value is not official */
}; };
/* This is used to generate pseudo-ID for AMBA device */
#define AMBA_LINUX_ID(conf, rev, part) \
(((conf) & 0xff) << 24 | ((rev) & 0xf) << 20 | \
AMBA_VENDOR_LINUX << 12 | ((part) & 0xfff))
extern struct bus_type amba_bustype; extern struct bus_type amba_bustype;
#define to_amba_device(d) container_of(d, struct amba_device, dev) #define to_amba_device(d) container_of(d, struct amba_device, dev)
......
...@@ -104,6 +104,15 @@ ...@@ -104,6 +104,15 @@
#define UART01x_FR_CTS 0x001 #define UART01x_FR_CTS 0x001
#define UART01x_FR_TMSK (UART01x_FR_TXFF + UART01x_FR_BUSY) #define UART01x_FR_TMSK (UART01x_FR_TXFF + UART01x_FR_BUSY)
/*
* Some bits of Flag Register on ZTE device have different position from
* standard ones.
*/
#define ZX_UART01x_FR_BUSY 0x100
#define ZX_UART01x_FR_DSR 0x008
#define ZX_UART01x_FR_CTS 0x002
#define ZX_UART011_FR_RI 0x001
#define UART011_CR_CTSEN 0x8000 /* CTS hardware flow control */ #define UART011_CR_CTSEN 0x8000 /* CTS hardware flow control */
#define UART011_CR_RTSEN 0x4000 /* RTS hardware flow control */ #define UART011_CR_RTSEN 0x4000 /* RTS hardware flow control */
#define UART011_CR_OUT2 0x2000 /* OUT2 */ #define UART011_CR_OUT2 0x2000 /* OUT2 */
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册