From 0e125a5facf857567f8bb6dbb1ceefac14b2fa64 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Fri, 8 Jul 2016 17:00:39 +0800 Subject: tty: amba-pl011: define flag register bits for ZTE device For some reason we do not really understand, ZTE hardware designers choose to define PL011 Flag Register bit positions differently from standard ones as below. Bit Standard ZTE ----------------------------------- CTS 0 1 DSR 1 3 BUSY 3 8 RI 8 0 Let's define these bits into vendor data and get ZTE PL011 supported properly. Signed-off-by: Shawn Guo Acked-by: Russell King Signed-off-by: Greg Kroah-Hartman --- include/linux/amba/serial.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'include') diff --git a/include/linux/amba/serial.h b/include/linux/amba/serial.h index d76a19ba2cff..ad0965e21a5e 100644 --- a/include/linux/amba/serial.h +++ b/include/linux/amba/serial.h @@ -104,6 +104,15 @@ #define UART01x_FR_CTS 0x001 #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_RTSEN 0x4000 /* RTS hardware flow control */ #define UART011_CR_OUT2 0x2000 /* OUT2 */ -- cgit v1.2.3-71-gd317 From 2426fbc77faef57c80a573303af6543531e2efa3 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Fri, 8 Jul 2016 17:00:41 +0800 Subject: tty: amba-pl011: probe ZTE device from AMBA bus with a pseudo-ID There is no Peripheral Identification Registers on ZTE PL011 device, so although the driver amba-pl011 is ready to work for ZTE device, the device cannot be probed by the driver at all. With arm,primecell-periphid DT bindings (bindings/arm/primecell.txt) in place, it should be the cleanest the way to use a pseudo-ID to probe the device from AMBA bus. We create an unofficial vendor number AMBA_VENDOR_LINUX, which will practically never become an official vendor ID, and takes Configuration, Revision number, and Part number as input to compose a pseudo-ID for ZTE device. Also, since we start using vendor_zte to probe ZTE device, the __maybe_unused for vendor_zte is removed. Signed-off-by: Russell King Signed-off-by: Shawn Guo Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 7 ++++++- include/linux/amba/bus.h | 6 ++++++ 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 055fe27e364f..0b78b04e895e 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -209,7 +209,7 @@ static unsigned int get_fifosize_zte(struct amba_device *dev) return 16; } -static struct vendor_data vendor_zte __maybe_unused = { +static struct vendor_data vendor_zte = { .reg_offset = pl011_zte_offsets, .access_32b = true, .ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8, @@ -2652,6 +2652,11 @@ static struct amba_id pl011_ids[] = { .mask = 0x00ffffff, .data = &vendor_st, }, + { + .id = AMBA_LINUX_ID(0x00, 0x1, 0xffe), + .mask = 0x00ffffff, + .data = &vendor_zte, + }, { 0, 0 }, }; diff --git a/include/linux/amba/bus.h b/include/linux/amba/bus.h index 3d8dcdd1aeae..d143c13bed26 100644 --- a/include/linux/amba/bus.h +++ b/include/linux/amba/bus.h @@ -53,8 +53,14 @@ enum amba_vendor { AMBA_VENDOR_ST = 0x80, AMBA_VENDOR_QCOM = 0x51, 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; #define to_amba_device(d) container_of(d, struct amba_device, dev) -- cgit v1.2.3-71-gd317 From 5bf5635ac1705b8d58fdef5ff0666ef0e72b4629 Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Thu, 25 Aug 2016 15:47:56 +0200 Subject: tty/serial: atmel: add fractional baud rate support The USART device provides a fractional baud rate generator to get a more accurate baud rate. It can be used only when the USART is configured in 'normal mode' and this feature is not available on AT91RM9200 SoC. Signed-off-by: Ludovic Desroches Acked-by: Nicolas Ferre Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/atmel_serial.c | 41 +++++++++++++++++++++++++++++++-------- include/linux/atmel_serial.h | 1 + 2 files changed, 34 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 2eaa18ddef61..17592390e85c 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -166,6 +166,7 @@ struct atmel_uart_port { u32 rts_low; bool ms_irq_enabled; u32 rtor; /* address of receiver timeout register if it exists */ + bool has_frac_baudrate; bool has_hw_timer; struct timer_list uart_timer; @@ -1745,6 +1746,11 @@ static void atmel_get_ip_name(struct uart_port *port) dbgu_uart = 0x44424755; /* DBGU */ 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; if (name == new_uart) { @@ -1753,6 +1759,7 @@ static void atmel_get_ip_name(struct uart_port *port) atmel_port->rtor = ATMEL_UA_RTOR; } else if (name == usart) { dev_dbg(port->dev, "Usart\n"); + atmel_port->has_frac_baudrate = true; atmel_port->has_hw_timer = true; atmel_port->rtor = ATMEL_US_RTOR; } else if (name == dbgu_uart) { @@ -1764,6 +1771,7 @@ static void atmel_get_ip_name(struct uart_port *port) case 0x302: case 0x10213: dev_dbg(port->dev, "This version is usart\n"); + atmel_port->has_frac_baudrate = true; atmel_port->has_hw_timer = true; atmel_port->rtor = ATMEL_US_RTOR; break; @@ -2025,8 +2033,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, struct ktermios *old) { + struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); 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 */ mode = old_mode = atmel_uart_readl(port, ATMEL_US_MR); @@ -2036,12 +2045,6 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, ATMEL_US_PAR | ATMEL_US_USMODE); 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 */ switch (termios->c_cflag & CSIZE) { @@ -2160,7 +2163,29 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, 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)) + */ + if (atmel_port->has_frac_baudrate && + (mode & ATMEL_US_USMODE) == ATMEL_US_USMODE_NORMAL) { + div = DIV_ROUND_CLOSEST(port->uartclk, baud); + cd = div / 16; + fp = DIV_ROUND_CLOSEST(div % 16, 2); + } 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_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX); atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN); diff --git a/include/linux/atmel_serial.h b/include/linux/atmel_serial.h index 5a4d664af87a..f8e452aa48d7 100644 --- a/include/linux/atmel_serial.h +++ b/include/linux/atmel_serial.h @@ -118,6 +118,7 @@ #define ATMEL_US_BRGR 0x20 /* Baud Rate Generator Register */ #define ATMEL_US_CD GENMASK(15, 0) /* Clock Divider */ +#define ATMEL_US_FP_OFFSET 16 /* Fractional Part */ #define ATMEL_US_RTOR 0x24 /* Receiver Time-out Register for USART */ #define ATMEL_UA_RTOR 0x28 /* Receiver Time-out Register for UART */ -- cgit v1.2.3-71-gd317 From c072e113b8fbd6b2bf325e92379a0da6dea619b3 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 17 Aug 2016 19:20:21 +0300 Subject: dmaengine: dw: set polarity of handshake interface Intel Quark UART uses DesignWare DMA IP. Though the DMA IP is connected in such way that handshake interface uses inverted polarity. We have to provide a possibility to set this in the DMA driver when configuring a channel. Introduce a new member of custom slave configuration called 'hs_polarity' and set active low polarity in case this value is 'true'. Acked-by: Vinod Koul Signed-off-by: Andy Shevchenko Tested-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman --- drivers/dma/dw/core.c | 4 ++++ include/linux/platform_data/dma-dw.h | 2 ++ 2 files changed, 6 insertions(+) (limited to 'include') diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index 81b06dfd7e06..80e74216cd56 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c @@ -143,6 +143,7 @@ static void dwc_initialize(struct dw_dma_chan *dwc) struct dw_dma *dw = to_dw_dma(dwc->chan.device); u32 cfghi = DWC_CFGH_FIFO_MODE; u32 cfglo = DWC_CFGL_CH_PRIOR(dwc->priority); + bool hs_polarity = dwc->dws.hs_polarity; if (test_bit(DW_DMA_IS_INITIALIZED, &dwc->flags)) return; @@ -150,6 +151,9 @@ static void dwc_initialize(struct dw_dma_chan *dwc) cfghi |= DWC_CFGH_DST_PER(dwc->dws.dst_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_HI, cfghi); diff --git a/include/linux/platform_data/dma-dw.h b/include/linux/platform_data/dma-dw.h index d15d8ba8cc24..4636c9335305 100644 --- a/include/linux/platform_data/dma-dw.h +++ b/include/linux/platform_data/dma-dw.h @@ -23,6 +23,7 @@ * @dst_id: dst request line * @m_master: memory master for transfers on allocated channel * @p_master: peripheral master for transfers on allocated channel + * @hs_polarity:set active low polarity of handshake interface */ struct dw_dma_slave { struct device *dma_dev; @@ -30,6 +31,7 @@ struct dw_dma_slave { u8 dst_id; u8 m_master; u8 p_master; + bool hs_polarity; }; /** -- cgit v1.2.3-71-gd317 From 5fb23e35cacffb7b99ed5b97a002ddb8c9144bb6 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 17 Aug 2016 19:20:22 +0300 Subject: dmaengine: dw: override LLP support if asked in platform data There are at least two known devices, e.g. DMA controller found on ARC AXS101 SDP board, that have LLP register and no multi block transfer support at the same time. Override autodetection by user provided data. Reported-by: Eugeniy Paltsev Reviewed-by: Eugeniy Paltsev Signed-off-by: Andy Shevchenko Tested-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman --- drivers/dma/dw/core.c | 6 +----- include/linux/platform_data/dma-dw.h | 2 ++ 2 files changed, 3 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index 80e74216cd56..da18b18561c4 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c @@ -1571,11 +1571,7 @@ int dw_dma_probe(struct dw_dma_chip *chip) (dwc_params >> DWC_PARAMS_MBLK_EN & 0x1) == 0; } else { dwc->block_size = pdata->block_size; - - /* 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); + dwc->nollp = pdata->is_nollp; } } diff --git a/include/linux/platform_data/dma-dw.h b/include/linux/platform_data/dma-dw.h index 4636c9335305..5f0e11e7354c 100644 --- a/include/linux/platform_data/dma-dw.h +++ b/include/linux/platform_data/dma-dw.h @@ -40,6 +40,7 @@ struct dw_dma_slave { * @is_private: The device channels should be marked as private and not for * by the general purpose DMA channel allocator. * @is_memcpy: The device channels do support memory-to-memory transfers. + * @is_nollp: The device channels does not support multi block transfers. * @chan_allocation_order: Allocate channels starting from 0 or 7 * @chan_priority: Set channel priority increasing from 0 to 7 or 7 to 0. * @block_size: Maximum block size supported by the controller @@ -51,6 +52,7 @@ struct dw_dma_platform_data { unsigned int nr_channels; bool is_private; bool is_memcpy; + bool is_nollp; #define CHAN_ALLOCATION_ASCENDING 0 /* zero to seven */ #define CHAN_ALLOCATION_DESCENDING 1 /* seven to zero */ unsigned char chan_allocation_order; -- cgit v1.2.3-71-gd317 From 19d82910c07173872bd2869f0077e290a7a466a6 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 17 Aug 2016 19:20:23 +0300 Subject: dmaengine: dw: provide probe(), remove() stubs for users Some users consider DMA optional, thus when driver is not compiled we shouldn't prevent compilation of the users. Add stubs for dw_dma_probe() and dw_dma_remove(). Acked-by: Vinod Koul Signed-off-by: Andy Shevchenko Tested-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman --- include/linux/dma/dw.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include') diff --git a/include/linux/dma/dw.h b/include/linux/dma/dw.h index f2e538aaddad..ccfd0c3777df 100644 --- a/include/linux/dma/dw.h +++ b/include/linux/dma/dw.h @@ -40,8 +40,13 @@ struct dw_dma_chip { }; /* Export to the platform drivers */ +#if IS_ENABLED(CONFIG_DW_DMAC_CORE) int dw_dma_probe(struct dw_dma_chip *chip); int dw_dma_remove(struct dw_dma_chip *chip); +#else +static inline int dw_dma_probe(struct dw_dma_chip *chip) { return -ENODEV; } +static inline int dw_dma_remove(struct dw_dma_chip *chip) { return 0; } +#endif /* CONFIG_DW_DMAC_CORE */ /* DMA API extensions */ struct dw_desc; -- cgit v1.2.3-71-gd317 From 46e36683f433528bfb7e5754ca5c5c86c204c40a Mon Sep 17 00:00:00 2001 From: Alexander Sverdlin Date: Fri, 2 Sep 2016 13:20:21 +0200 Subject: serial: earlycon: Extend earlycon command line option to support 64-bit addresses earlycon implementation used "unsigned long" internally, but there are systems (ARM with LPAE) where sizeof(unsigned long) == 4 and uart is mapped beyond 4GiB address range. Switch to resource_size_t internally and replace obsoleted simple_strtoul() with kstrtoull(). Signed-off-by: Alexander Sverdlin Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_core.c | 2 +- drivers/tty/serial/earlycon.c | 7 +++---- drivers/tty/serial/serial_core.c | 12 +++++++++--- include/linux/serial_core.h | 2 +- 4 files changed, 14 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 13ad5c3d2e68..f64d6cd311ed 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -639,7 +639,7 @@ static int univ8250_console_match(struct console *co, char *name, int idx, { char match[] = "uart"; /* 8250-specific earlycon name */ unsigned char iotype; - unsigned long addr; + resource_size_t addr; int i; if (strncmp(name, match, 4) != 0) diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c index 067783f0523c..3940280afa9c 100644 --- a/drivers/tty/serial/earlycon.c +++ b/drivers/tty/serial/earlycon.c @@ -38,7 +38,7 @@ static struct earlycon_device early_console_dev = { .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; #ifdef CONFIG_FIX_EARLYCON_MEM @@ -49,8 +49,7 @@ static void __iomem * __init earlycon_map(unsigned long paddr, size_t size) base = ioremap(paddr, size); #endif if (!base) - pr_err("%s: Couldn't map 0x%llx\n", __func__, - (unsigned long long)paddr); + pr_err("%s: Couldn't map %pa\n", __func__, &paddr); return base; } @@ -92,7 +91,7 @@ static int __init parse_options(struct earlycon_device *device, char *options) { struct uart_port *port = &device->port; int length; - unsigned long addr; + resource_size_t addr; if (uart_parse_earlycon(options, &port->iotype, &addr, &options)) return -EINVAL; diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index e183d2eff16d..240d3e7a548c 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1892,11 +1892,14 @@ uart_get_console(struct uart_port *ports, int nr, struct console *co) * console=,0x, * is also accepted; the returned @iotype will be UPIO_MEM. * - * Returns 0 on success or -EINVAL on failure + * Returns 0 on success, -EINVAL or -ERANGE 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) { + int ret; + unsigned long long tmp; + if (strncmp(p, "mmio,", 5) == 0) { *iotype = UPIO_MEM; p += 5; @@ -1922,7 +1925,10 @@ int uart_parse_earlycon(char *p, unsigned char *iotype, unsigned long *addr, return -EINVAL; } - *addr = simple_strtoul(p, NULL, 0); + ret = kstrtoull(p, 0, &tmp); + if (ret) + return ret; + *addr = tmp; p = strchr(p, ','); if (p) p++; diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 2f44e2013654..cdba6f144f72 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -374,7 +374,7 @@ extern int of_setup_earlycon(const struct earlycon_id *match, struct uart_port *uart_get_console(struct uart_port *ports, int nr, struct console *c); -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); void uart_parse_options(char *options, int *baud, int *parity, int *bits, int *flow); -- cgit v1.2.3-71-gd317 From d2f5a7311bcaed681a41cb3419b8fe92a7b68bf5 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 23 Aug 2016 16:09:40 +0300 Subject: dmaengine: hsu: refactor hsu_dma_do_irq() to return int Since we have nice macro IRQ_RETVAL() we would use it to convert a flag of handled interrupt from int to irqreturn_t. The rationale of doing this is: a) hence we implicitly mark hsu_dma_do_irq() as an auxiliary function that can't be used as interrupt handler directly, and b) to be in align with serial driver which is using serial8250_handle_irq() that returns plain int by design. Signed-off-by: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- drivers/dma/hsu/hsu.c | 9 ++++----- drivers/dma/hsu/pci.c | 6 +++--- drivers/tty/serial/8250/8250_mid.c | 8 ++++---- include/linux/dma/hsu.h | 9 ++++----- 4 files changed, 15 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/drivers/dma/hsu/hsu.c b/drivers/dma/hsu/hsu.c index c5f21efd6090..29d04ca71d52 100644 --- a/drivers/dma/hsu/hsu.c +++ b/drivers/dma/hsu/hsu.c @@ -200,10 +200,9 @@ EXPORT_SYMBOL_GPL(hsu_dma_get_status); * is not a normal timeout interrupt, ie. hsu_dma_get_status() returned 0. * * 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, - u32 status) +int hsu_dma_do_irq(struct hsu_dma_chip *chip, unsigned short nr, u32 status) { struct hsu_dma_chan *hsuc; struct hsu_dma_desc *desc; @@ -211,7 +210,7 @@ irqreturn_t hsu_dma_do_irq(struct hsu_dma_chip *chip, unsigned short nr, /* Sanity check */ if (nr >= chip->hsu->nr_channels) - return IRQ_NONE; + return 0; hsuc = &chip->hsu->chan[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); - return IRQ_HANDLED; + return 1; } EXPORT_SYMBOL_GPL(hsu_dma_do_irq); diff --git a/drivers/dma/hsu/pci.c b/drivers/dma/hsu/pci.c index 9916058531d9..b51639f045ed 100644 --- a/drivers/dma/hsu/pci.c +++ b/drivers/dma/hsu/pci.c @@ -29,7 +29,7 @@ static irqreturn_t hsu_pci_irq(int irq, void *dev) u32 dmaisr; u32 status; unsigned short i; - irqreturn_t ret = IRQ_NONE; + int ret = 0; int err; dmaisr = readl(chip->regs + HSU_PCI_DMAISR); @@ -37,14 +37,14 @@ static irqreturn_t hsu_pci_irq(int irq, void *dev) if (dmaisr & 0x1) { err = hsu_dma_get_status(chip, i, &status); if (err > 0) - ret |= IRQ_HANDLED; + ret |= 1; else if (err == 0) ret |= hsu_dma_do_irq(chip, i, status); } dmaisr >>= 1; } - return ret; + return IRQ_RETVAL(ret); } static int hsu_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) diff --git a/drivers/tty/serial/8250/8250_mid.c b/drivers/tty/serial/8250/8250_mid.c index 339de9cd0866..121a7f2d4697 100644 --- a/drivers/tty/serial/8250/8250_mid.c +++ b/drivers/tty/serial/8250/8250_mid.c @@ -99,27 +99,27 @@ static int dnv_handle_irq(struct uart_port *p) struct uart_8250_port *up = up_to_u8250p(p); unsigned int fisr = serial_port_in(p, INTEL_MID_UART_DNV_FISR); u32 status; - int ret = IRQ_NONE; + int ret = 0; int err; if (fisr & BIT(2)) { err = hsu_dma_get_status(&mid->dma_chip, 1, &status); if (err > 0) { serial8250_rx_dma_flush(up); - ret |= IRQ_HANDLED; + ret |= 1; } else if (err == 0) ret |= hsu_dma_do_irq(&mid->dma_chip, 1, status); } if (fisr & BIT(1)) { err = hsu_dma_get_status(&mid->dma_chip, 0, &status); if (err > 0) - ret |= IRQ_HANDLED; + ret |= 1; else if (err == 0) ret |= hsu_dma_do_irq(&mid->dma_chip, 0, status); } if (fisr & BIT(0)) ret |= serial8250_handle_irq(p, serial_port_in(p, UART_IIR)); - return ret; + return IRQ_RETVAL(ret); } #define DNV_DMA_CHAN_OFFSET 0x80 diff --git a/include/linux/dma/hsu.h b/include/linux/dma/hsu.h index aaff68efba5d..197eec63e501 100644 --- a/include/linux/dma/hsu.h +++ b/include/linux/dma/hsu.h @@ -41,8 +41,7 @@ struct hsu_dma_chip { /* Export to the internal users */ int hsu_dma_get_status(struct hsu_dma_chip *chip, unsigned short nr, u32 *status); -irqreturn_t hsu_dma_do_irq(struct hsu_dma_chip *chip, unsigned short nr, - u32 status); +int hsu_dma_do_irq(struct hsu_dma_chip *chip, unsigned short nr, u32 status); /* Export to the platform drivers */ int hsu_dma_probe(struct hsu_dma_chip *chip); @@ -53,10 +52,10 @@ static inline int hsu_dma_get_status(struct hsu_dma_chip *chip, { return 0; } -static inline irqreturn_t hsu_dma_do_irq(struct hsu_dma_chip *chip, - unsigned short nr, u32 status) +static inline int hsu_dma_do_irq(struct hsu_dma_chip *chip, unsigned short nr, + u32 status) { - return IRQ_NONE; + return 0; } static inline int hsu_dma_probe(struct hsu_dma_chip *chip) { return -ENODEV; } static inline int hsu_dma_remove(struct hsu_dma_chip *chip) { return 0; } -- cgit v1.2.3-71-gd317 From a727b025f43d7952c0697562f5cecda9f42758aa Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 9 Sep 2016 17:37:02 -0500 Subject: tty: serial_core: add tty NULL check to uart_tx_stopped Commit 761ed4a94582 ("tty: serial_core: convert uart_close to use tty_port_close") created a case where a port used for a console does not get shutdown on tty closing. Then a call to uart_tx_stopped() segfaults because the tty is NULL. This could be fixed to restore old behavior, but we also want to allow tty_ports to work without a tty attached. So this change to allow a NULL tty_struct is needed either way. Fixes: 761ed4a94582 ("tty: serial_core: convert uart_close to use tty_port_close") Reported-by: kernel test robot Signed-off-by: Rob Herring Signed-off-by: Greg Kroah-Hartman --- include/linux/serial_core.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index cdba6f144f72..378d80a8dd43 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -412,7 +412,7 @@ int uart_resume_port(struct uart_driver *reg, struct uart_port *port); static inline int uart_tx_stopped(struct uart_port *port) { struct tty_struct *tty = port->state->port.tty; - if (tty->stopped || port->hw_stopped) + if ((tty && tty->stopped) || port->hw_stopped) return 1; return 0; } -- cgit v1.2.3-71-gd317 From 36131cdfef5aef7f4a9a36423a7a338bd6f68ad6 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Wed, 21 Sep 2016 12:44:14 +0200 Subject: tty/serial: atmel: fix fractional baud rate computation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The problem with previous code was it rounded values in wrong place and produced wrong baud rate in some cases. Signed-off-by: Alexey Starikovskiy [nicolas.ferre@atmel.com: port to newer kernel and add commit log] Signed-off-by: Nicolas Ferre Reviewed-by: Boris Brezillon Reviewed-by: Uwe Kleine-König Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/atmel_serial.c | 10 ++++++---- include/linux/atmel_serial.h | 1 + 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 5f550d9feed9..fd8aa1f4ba78 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -2170,13 +2170,15 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, * 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)) + * 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); - cd = div / 16; - fp = DIV_ROUND_CLOSEST(div % 16, 2); + div = DIV_ROUND_CLOSEST(port->uartclk, baud * 2); + cd = div >> 3; + fp = div & ATMEL_US_FP_MASK; } else { cd = uart_get_divisor(port, baud); } diff --git a/include/linux/atmel_serial.h b/include/linux/atmel_serial.h index f8e452aa48d7..bd2560502f3c 100644 --- a/include/linux/atmel_serial.h +++ b/include/linux/atmel_serial.h @@ -119,6 +119,7 @@ #define ATMEL_US_BRGR 0x20 /* Baud Rate Generator Register */ #define ATMEL_US_CD GENMASK(15, 0) /* Clock Divider */ #define ATMEL_US_FP_OFFSET 16 /* Fractional Part */ +#define ATMEL_US_FP_MASK 0x7 #define ATMEL_US_RTOR 0x24 /* Receiver Time-out Register for USART */ #define ATMEL_UA_RTOR 0x28 /* Receiver Time-out Register for UART */ -- cgit v1.2.3-71-gd317 From 8e5470c9839caff94fe334e67ff7e7ace587282a Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Thu, 22 Sep 2016 14:56:16 -0500 Subject: serial: 8250: Set Altera 16550 TX FIFO Threshold The Altera 16550 soft IP UART requires 2 additional registers for TX FIFO threshold support. These 2 registers enable the TX FIFO Low Watermark and set the TX FIFO Low Watermark. Set the TX FIFO threshold to the FIFO size - tx_loadsz. Signed-off-by: Thor Thayer Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_port.c | 43 +++++++++++++++++++++++++++++++++++++ include/uapi/linux/serial_reg.h | 8 +++++++ 2 files changed, 51 insertions(+) (limited to 'include') diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 28d29fac1973..1bfb6fdbaa20 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1870,6 +1870,30 @@ static int exar_handle_irq(struct uart_port *port) 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) { struct uart_8250_port *up = up_to_u8250p(port); @@ -2159,6 +2183,25 @@ int serial8250_do_startup(struct uart_port *port) 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) { unsigned char iir1; /* diff --git a/include/uapi/linux/serial_reg.h b/include/uapi/linux/serial_reg.h index 1e5ac4e776da..b4c04842a8c0 100644 --- a/include/uapi/linux/serial_reg.h +++ b/include/uapi/linux/serial_reg.h @@ -376,5 +376,13 @@ #define UART_EXAR_TXTRG 0x0a /* Tx FIFO trigger level write-only */ #define UART_EXAR_RXTRG 0x0b /* Rx FIFO trigger level write-only */ +/* + * These are definitions for the Altera ALTR_16550_F32/F64/F128 + * Normalized from 0x100 to 0x40 because of shift by 2 (32 bit regs). + */ +#define UART_ALTR_AFR 0x40 /* Additional Features Register */ +#define UART_ALTR_EN_TXFIFO_LW 0x01 /* Enable the TX FIFO Low Watermark */ +#define UART_ALTR_TX_LOW 0x41 /* Tx FIFO Low Watermark */ + #endif /* _LINUX_SERIAL_REG_H */ -- cgit v1.2.3-71-gd317 From d503187b6cc4e41c21c02e695e0e7b5acdd066de Mon Sep 17 00:00:00 2001 From: Leif Lindholm Date: Tue, 27 Sep 2016 23:54:12 +0300 Subject: of/serial: move earlycon early_param handling to serial We have multiple "earlycon" early_param handlers - merge the DT one into the main earlycon one. It's a cleanup that also will be useful to defer setting up DT console until ACPI/DT decision is made. Rename the exported function to avoid clashing with the function from arch/microblaze/kernel/prom.c Signed-off-by: Leif Lindholm Signed-off-by: Aleksey Makarov Acked-by: Rob Herring Acked-by: Greg Kroah-Hartman Reviewed-by: Peter Hurley Tested-by: Kefeng Wang Tested-by: Christopher Covington Signed-off-by: Greg Kroah-Hartman --- drivers/of/fdt.c | 11 +---------- drivers/tty/serial/earlycon.c | 2 +- include/linux/of_fdt.h | 3 +++ 3 files changed, 5 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 085c6389afd1..c89d5d231a0e 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -924,7 +924,7 @@ static inline void early_init_dt_check_for_initrd(unsigned long node) #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; const char *p, *q, *options = NULL; @@ -968,15 +968,6 @@ static int __init early_init_dt_scan_chosen_serial(void) } 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 /** diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c index 3940280afa9c..836cad222fcc 100644 --- a/drivers/tty/serial/earlycon.c +++ b/drivers/tty/serial/earlycon.c @@ -208,7 +208,7 @@ static int __init param_setup_earlycon(char *buf) * don't generate a warning from parse_early_params() in that case */ if (!buf || !buf[0]) - return 0; + return early_init_dt_scan_chosen_stdout(); err = setup_earlycon(buf); if (err == -ENOENT || err == -EALREADY) diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h index 26c3302ae58f..4341f32516d8 100644 --- a/include/linux/of_fdt.h +++ b/include/linux/of_fdt.h @@ -14,6 +14,7 @@ #include #include +#include /* Definitions used by the flattened device tree */ #define OF_DT_HEADER 0xd00dfeed /* marker */ @@ -66,6 +67,7 @@ extern int early_init_dt_scan_chosen(unsigned long node, const char *uname, int depth, void *data); extern int early_init_dt_scan_memory(unsigned long node, const char *uname, int depth, void *data); +extern int early_init_dt_scan_chosen_stdout(void); extern void early_init_fdt_scan_reserved_mem(void); extern void early_init_fdt_reserve_self(void); extern void early_init_dt_add_memory_arch(u64 base, u64 size); @@ -94,6 +96,7 @@ extern void early_get_first_memblock_info(void *, phys_addr_t *); extern u64 of_flat_dt_translate_address(unsigned long node); extern void of_fdt_limit_memory(int limit); #else /* CONFIG_OF_FLATTREE */ +static inline int early_init_dt_scan_chosen_stdout(void) { return -ENODEV; } static inline void early_init_fdt_scan_reserved_mem(void) {} static inline void early_init_fdt_reserve_self(void) {} static inline const char *of_flat_dt_get_machine_name(void) { return NULL; } -- cgit v1.2.3-71-gd317 From ad1696f6f09daacfdf2bf04bc83cd8f48d80e34a Mon Sep 17 00:00:00 2001 From: Aleksey Makarov Date: Tue, 27 Sep 2016 23:54:13 +0300 Subject: ACPI: parse SPCR and enable matching console 'ARM Server Base Boot Requiremets' [1] mentions SPCR (Serial Port Console Redirection Table) [2] as a mandatory ACPI table that specifies the configuration of serial console. Defer initialization of DT earlycon until ACPI/DT decision is made. Parse the ACPI SPCR table, setup earlycon if required, enable specified console. Thanks to Peter Hurley for explaining how this should work. [1] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0044a/index.html [2] https://msdn.microsoft.com/en-us/library/windows/hardware/dn639132(v=vs.85).aspx Signed-off-by: Aleksey Makarov Acked-by: Rafael J. Wysocki Reviewed-by: Peter Hurley Tested-by: Kefeng Wang Tested-by: Christopher Covington Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/Kconfig | 3 ++ drivers/acpi/Makefile | 1 + drivers/acpi/spcr.c | 111 ++++++++++++++++++++++++++++++++++++++++++ drivers/tty/serial/earlycon.c | 19 +++++++- include/linux/acpi.h | 6 +++ include/linux/serial_core.h | 9 +++- 6 files changed, 146 insertions(+), 3 deletions(-) create mode 100644 drivers/acpi/spcr.c (limited to 'include') diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 445ce28475b3..a984cc7dcba4 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -77,6 +77,9 @@ config ACPI_DEBUGGER_USER endif +config ACPI_SPCR_TABLE + bool + config ACPI_SLEEP bool depends on SUSPEND || HIBERNATION diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 5ae9d85c5159..c469516062c6 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -81,6 +81,7 @@ obj-$(CONFIG_ACPI_EC_DEBUGFS) += ec_sys.o obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o obj-$(CONFIG_ACPI_BGRT) += bgrt.o obj-$(CONFIG_ACPI_CPPC_LIB) += cppc_acpi.o +obj-$(CONFIG_ACPI_SPCR_TABLE) += spcr.o obj-$(CONFIG_ACPI_DEBUGGER_USER) += acpi_dbg.o # processor has its own "processor." module_param namespace diff --git a/drivers/acpi/spcr.c b/drivers/acpi/spcr.c new file mode 100644 index 000000000000..e8d7bc7d4da8 --- /dev/null +++ b/drivers/acpi/spcr.c @@ -0,0 +1,111 @@ +/* + * 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 +#include +#include +#include + +/** + * 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; +} diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c index 836cad222fcc..c3651540e1ba 100644 --- a/drivers/tty/serial/earlycon.c +++ b/drivers/tty/serial/earlycon.c @@ -21,6 +21,7 @@ #include #include #include +#include #ifdef CONFIG_FIX_EARLYCON_MEM #include @@ -198,6 +199,14 @@ int __init setup_earlycon(char *buf) 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() */ static int __init param_setup_earlycon(char *buf) { @@ -207,8 +216,14 @@ static int __init param_setup_earlycon(char *buf) * Just 'earlycon' is a valid param for devicetree earlycons; * don't generate a warning from parse_early_params() in that case */ - if (!buf || !buf[0]) - return early_init_dt_scan_chosen_stdout(); + if (!buf || !buf[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); if (err == -ENOENT || err == -EALREADY) diff --git a/include/linux/acpi.h b/include/linux/acpi.h index c5eaf2f80a4c..2353827731d2 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -1074,4 +1074,10 @@ void acpi_table_upgrade(void); static inline void acpi_table_upgrade(void) { } #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*/ diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 378d80a8dd43..344201437017 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -367,11 +367,18 @@ extern const struct earlycon_id __earlycon_table_end[]; #define EARLYCON_DECLARE(_name, fn) OF_EARLYCON_DECLARE(_name, "", fn) -extern int setup_earlycon(char *buf); extern int of_setup_earlycon(const struct earlycon_id *match, unsigned long node, const char *options); +#ifdef CONFIG_SERIAL_EARLYCON +extern bool earlycon_init_is_deferred __initdata; +int setup_earlycon(char *buf); +#else +static const bool earlycon_init_is_deferred; +static inline int setup_earlycon(char *buf) { return 0; } +#endif + struct uart_port *uart_get_console(struct uart_port *ports, int nr, struct console *c); int uart_parse_earlycon(char *p, unsigned char *iotype, resource_size_t *addr, -- cgit v1.2.3-71-gd317