mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-24 20:54:10 +08:00
TTY/Serial driver update for 4.8-rc1
Here is the big tty and serial driver update for 4.8-rc1. Lots of good cleanups from Jiri on a number of vt and other tty related things, and the normal driver updates. Full details are in the shortlog. All of these have been in linux-next for a while with no reported issues. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iFYEABECABYFAleVPbQPHGdyZWdAa3JvYWguY29tAAoJEDFH1A3bLfspWXgAn046 QCMeFya4J1zjYjcGXJzNfGMUAKCHxha8Xe65cc0LDz8mNB0MgzjHEg== =ED8v -----END PGP SIGNATURE----- Merge tag 'tty-4.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty Pull tty/serial driver updates from Greg KH: "Here is the big tty and serial driver update for 4.8-rc1. Lots of good cleanups from Jiri on a number of vt and other tty related things, and the normal driver updates. Full details are in the shortlog. All of these have been in linux-next for a while with no reported issues" * tag 'tty-4.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (90 commits) tty/serial: atmel: enforce tasklet init and termination sequences serial: sh-sci: Stop transfers in sci_shutdown() serial: 8250_ingenic: drop #if conditional surrounding earlycon code serial: 8250_mtk: drop !defined(MODULE) conditional serial: 8250_uniphier: drop !defined(MODULE) conditional earlycon: mark earlycon code as __used iif the caller is built-in tty/serial/8250: use mctrl_gpio helpers serial: mctrl_gpio: enable API usage only for initialized mctrl_gpios struct serial: mctrl_gpio: add modem control read routine tty/serial/8250: make UART_MCR register access consistent serial: 8250_mid: Read RX buffer on RX DMA timeout for DNV serial: 8250_dma: Export serial8250_rx_dma_flush() dmaengine: hsu: Export hsu_dma_get_status() tty: serial: 8250: add CON_CONSDEV to flags tty: serial: samsung: add byte-order aware bit functions tty: serial: samsung: fixup accessors for endian serial: sirf: make fifo functions static serial: mps2-uart: make driver explicitly non-modular serial: mvebu-uart: free the IRQ in ->shutdown() serial/bcm63xx_uart: use correct alias naming ...
This commit is contained in:
commit
721413aff2
@ -42,6 +42,9 @@ Optional properties:
|
||||
- auto-flow-control: one way to enable automatic flow control support. The
|
||||
driver is allowed to detect support for the capability even without this
|
||||
property.
|
||||
- {rts,cts,dtr,dsr,rng,dcd}-gpios: specify a GPIO for RTS/CTS/DTR/DSR/RI/DCD
|
||||
line respectively. It will use specified GPIO instead of the peripheral
|
||||
function pin for the UART feature. If unsure, don't specify this property.
|
||||
|
||||
Note:
|
||||
* fsl,ns16550:
|
||||
@ -63,3 +66,19 @@ Example:
|
||||
interrupts = <10>;
|
||||
reg-shift = <2>;
|
||||
};
|
||||
|
||||
Example for OMAP UART using GPIO-based modem control signals:
|
||||
|
||||
uart4: serial@49042000 {
|
||||
compatible = "ti,omap3-uart";
|
||||
reg = <0x49042000 0x400>;
|
||||
interrupts = <80>;
|
||||
ti,hwmods = "uart4";
|
||||
clock-frequency = <48000000>;
|
||||
cts-gpios = <&gpio3 5 GPIO_ACTIVE_LOW>;
|
||||
rts-gpios = <&gpio3 6 GPIO_ACTIVE_LOW>;
|
||||
dtr-gpios = <&gpio1 12 GPIO_ACTIVE_LOW>;
|
||||
dsr-gpios = <&gpio1 13 GPIO_ACTIVE_LOW>;
|
||||
dcd-gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
|
||||
rng-gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
@ -31,6 +31,8 @@ Required properties:
|
||||
- "renesas,hscif-r8a7794" for R8A7794 (R-Car E2) HSCIF compatible UART.
|
||||
- "renesas,scif-r8a7795" for R8A7795 (R-Car H3) SCIF compatible UART.
|
||||
- "renesas,hscif-r8a7795" for R8A7795 (R-Car H3) HSCIF compatible UART.
|
||||
- "renesas,scif-r8a7796" for R8A7796 (R-Car M3-W) SCIF compatible UART.
|
||||
- "renesas,hscif-r8a7796" for R8A7796 (R-Car M3-W) HSCIF compatible UART.
|
||||
- "renesas,scifa-sh73a0" for SH73A0 (SH-Mobile AG5) SCIFA compatible UART.
|
||||
- "renesas,scifb-sh73a0" for SH73A0 (SH-Mobile AG5) SCIFB compatible UART.
|
||||
- "renesas,rcar-gen1-scif" for R-Car Gen1 SCIF compatible UART,
|
||||
@ -76,6 +78,10 @@ Optional properties:
|
||||
- dmas: Must contain a list of two references to DMA specifiers, one for
|
||||
transmission, and one for reception.
|
||||
- dma-names: Must contain a list of two DMA names, "tx" and "rx".
|
||||
- {cts,dsr,dcd,rng,rts,dtr}-gpios: Specify GPIOs for modem lines, cfr. the
|
||||
generic serial DT bindings in serial.txt.
|
||||
- uart-has-rtscts: Indicates dedicated lines for RTS/CTS hardware flow
|
||||
control, cfr. the generic serial DT bindings in serial.txt.
|
||||
|
||||
Example:
|
||||
aliases {
|
||||
|
@ -10003,6 +10003,7 @@ SERIAL DRIVERS
|
||||
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
L: linux-serial@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/serial/
|
||||
F: drivers/tty/serial/
|
||||
|
||||
SYNOPSYS DESIGNWARE DMAC DRIVER
|
||||
|
@ -12,7 +12,3 @@
|
||||
* the base baud is derived from the clock speed and so is variable
|
||||
*/
|
||||
#define BASE_BAUD 0
|
||||
|
||||
#define STD_COM_FLAGS UPF_BOOT_AUTOCONF
|
||||
|
||||
#define SERIAL_PORT_DFNS
|
||||
|
@ -113,7 +113,6 @@ void platform_heartbeat(void)
|
||||
}
|
||||
|
||||
//#define RS_TABLE_SIZE 2
|
||||
//#define STD_COM_FLAGS (UPF_BOOT_AUTOCONF|UPF_SKIP_TEST)
|
||||
|
||||
#define _SERIAL_PORT(_base,_irq) \
|
||||
{ \
|
||||
|
@ -126,28 +126,33 @@ static void hsu_dma_start_transfer(struct hsu_dma_chan *hsuc)
|
||||
hsu_dma_start_channel(hsuc);
|
||||
}
|
||||
|
||||
static u32 hsu_dma_chan_get_sr(struct hsu_dma_chan *hsuc)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 sr;
|
||||
|
||||
spin_lock_irqsave(&hsuc->vchan.lock, flags);
|
||||
sr = hsu_chan_readl(hsuc, HSU_CH_SR);
|
||||
spin_unlock_irqrestore(&hsuc->vchan.lock, flags);
|
||||
|
||||
return sr & ~(HSU_CH_SR_DESCE_ANY | HSU_CH_SR_CDESC_ANY);
|
||||
}
|
||||
|
||||
irqreturn_t hsu_dma_irq(struct hsu_dma_chip *chip, unsigned short nr)
|
||||
/*
|
||||
* hsu_dma_get_status() - get DMA channel status
|
||||
* @chip: HSUART DMA chip
|
||||
* @nr: DMA channel number
|
||||
* @status: pointer for DMA Channel Status Register value
|
||||
*
|
||||
* Description:
|
||||
* The function reads and clears the DMA Channel Status Register, checks
|
||||
* if it was a timeout interrupt and returns a corresponding value.
|
||||
*
|
||||
* Caller should provide a valid pointer for the DMA Channel Status
|
||||
* Register value that will be returned in @status.
|
||||
*
|
||||
* Return:
|
||||
* 1 for DMA timeout status, 0 for other DMA status, or error code for
|
||||
* invalid parameters or no interrupt pending.
|
||||
*/
|
||||
int hsu_dma_get_status(struct hsu_dma_chip *chip, unsigned short nr,
|
||||
u32 *status)
|
||||
{
|
||||
struct hsu_dma_chan *hsuc;
|
||||
struct hsu_dma_desc *desc;
|
||||
unsigned long flags;
|
||||
u32 sr;
|
||||
|
||||
/* Sanity check */
|
||||
if (nr >= chip->hsu->nr_channels)
|
||||
return IRQ_NONE;
|
||||
return -EINVAL;
|
||||
|
||||
hsuc = &chip->hsu->chan[nr];
|
||||
|
||||
@ -155,22 +160,65 @@ irqreturn_t hsu_dma_irq(struct hsu_dma_chip *chip, unsigned short nr)
|
||||
* No matter what situation, need read clear the IRQ status
|
||||
* There is a bug, see Errata 5, HSD 2900918
|
||||
*/
|
||||
sr = hsu_dma_chan_get_sr(hsuc);
|
||||
spin_lock_irqsave(&hsuc->vchan.lock, flags);
|
||||
sr = hsu_chan_readl(hsuc, HSU_CH_SR);
|
||||
spin_unlock_irqrestore(&hsuc->vchan.lock, flags);
|
||||
|
||||
/* Check if any interrupt is pending */
|
||||
sr &= ~(HSU_CH_SR_DESCE_ANY | HSU_CH_SR_CDESC_ANY);
|
||||
if (!sr)
|
||||
return IRQ_NONE;
|
||||
return -EIO;
|
||||
|
||||
/* Timeout IRQ, need wait some time, see Errata 2 */
|
||||
if (sr & HSU_CH_SR_DESCTO_ANY)
|
||||
udelay(2);
|
||||
|
||||
/*
|
||||
* At this point, at least one of Descriptor Time Out, Channel Error
|
||||
* or Descriptor Done bits must be set. Clear the Descriptor Time Out
|
||||
* bits and if sr is still non-zero, it must be channel error or
|
||||
* descriptor done which are higher priority than timeout and handled
|
||||
* in hsu_dma_do_irq(). Else, it must be a timeout.
|
||||
*/
|
||||
sr &= ~HSU_CH_SR_DESCTO_ANY;
|
||||
if (!sr)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
*status = sr;
|
||||
|
||||
return sr ? 0 : 1;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hsu_dma_get_status);
|
||||
|
||||
/*
|
||||
* hsu_dma_do_irq() - DMA interrupt handler
|
||||
* @chip: HSUART DMA chip
|
||||
* @nr: DMA channel number
|
||||
* @status: Channel Status Register value
|
||||
*
|
||||
* Description:
|
||||
* This function handles Channel Error and Descriptor Done interrupts.
|
||||
* This function should be called after determining that the DMA interrupt
|
||||
* is not a normal timeout interrupt, ie. hsu_dma_get_status() returned 0.
|
||||
*
|
||||
* Return:
|
||||
* IRQ_NONE for invalid channel number, IRQ_HANDLED otherwise.
|
||||
*/
|
||||
irqreturn_t hsu_dma_do_irq(struct hsu_dma_chip *chip, unsigned short nr,
|
||||
u32 status)
|
||||
{
|
||||
struct hsu_dma_chan *hsuc;
|
||||
struct hsu_dma_desc *desc;
|
||||
unsigned long flags;
|
||||
|
||||
/* Sanity check */
|
||||
if (nr >= chip->hsu->nr_channels)
|
||||
return IRQ_NONE;
|
||||
|
||||
hsuc = &chip->hsu->chan[nr];
|
||||
|
||||
spin_lock_irqsave(&hsuc->vchan.lock, flags);
|
||||
desc = hsuc->desc;
|
||||
if (desc) {
|
||||
if (sr & HSU_CH_SR_CHE) {
|
||||
if (status & HSU_CH_SR_CHE) {
|
||||
desc->status = DMA_ERROR;
|
||||
} else if (desc->active < desc->nents) {
|
||||
hsu_dma_start_channel(hsuc);
|
||||
@ -184,7 +232,7 @@ irqreturn_t hsu_dma_irq(struct hsu_dma_chip *chip, unsigned short nr)
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hsu_dma_irq);
|
||||
EXPORT_SYMBOL_GPL(hsu_dma_do_irq);
|
||||
|
||||
static struct hsu_dma_desc *hsu_dma_alloc_desc(unsigned int nents)
|
||||
{
|
||||
|
@ -27,13 +27,20 @@ static irqreturn_t hsu_pci_irq(int irq, void *dev)
|
||||
{
|
||||
struct hsu_dma_chip *chip = dev;
|
||||
u32 dmaisr;
|
||||
u32 status;
|
||||
unsigned short i;
|
||||
irqreturn_t ret = IRQ_NONE;
|
||||
int err;
|
||||
|
||||
dmaisr = readl(chip->regs + HSU_PCI_DMAISR);
|
||||
for (i = 0; i < chip->hsu->nr_channels; i++) {
|
||||
if (dmaisr & 0x1)
|
||||
ret |= hsu_dma_irq(chip, i);
|
||||
if (dmaisr & 0x1) {
|
||||
err = hsu_dma_get_status(chip, i, &status);
|
||||
if (err > 0)
|
||||
ret |= IRQ_HANDLED;
|
||||
else if (err == 0)
|
||||
ret |= hsu_dma_do_irq(chip, i, status);
|
||||
}
|
||||
dmaisr >>= 1;
|
||||
}
|
||||
|
||||
|
@ -93,8 +93,6 @@ static void cy_send_xchar(struct tty_struct *tty, char ch);
|
||||
#define SERIAL_XMIT_SIZE (min(PAGE_SIZE, 4096))
|
||||
#endif
|
||||
|
||||
#define STD_COM_FLAGS (0)
|
||||
|
||||
/* firmware stuff */
|
||||
#define ZL_MAX_BLOCKS 16
|
||||
#define DRIVER_VERSION 0x02010203
|
||||
@ -2288,7 +2286,6 @@ static int cy_get_serial_info(struct cyclades_port *info,
|
||||
.closing_wait = info->port.closing_wait,
|
||||
.baud_base = info->baud,
|
||||
.custom_divisor = info->custom_divisor,
|
||||
.hub6 = 0, /*!!! */
|
||||
};
|
||||
return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;
|
||||
}
|
||||
@ -3084,7 +3081,6 @@ static int cy_init_card(struct cyclades_card *cinfo)
|
||||
|
||||
info->port.closing_wait = CLOSING_WAIT_DELAY;
|
||||
info->port.close_delay = 5 * HZ / 10;
|
||||
info->port.flags = STD_COM_FLAGS;
|
||||
init_completion(&info->shutdown_wait);
|
||||
|
||||
if (cy_is_Z(cinfo)) {
|
||||
|
@ -252,20 +252,11 @@ static int ipwireless_get_serial_info(struct ipw_tty *tty,
|
||||
{
|
||||
struct serial_struct tmp;
|
||||
|
||||
if (!retinfo)
|
||||
return (-EFAULT);
|
||||
|
||||
memset(&tmp, 0, sizeof(tmp));
|
||||
tmp.type = PORT_UNKNOWN;
|
||||
tmp.line = tty->index;
|
||||
tmp.port = 0;
|
||||
tmp.irq = 0;
|
||||
tmp.flags = 0;
|
||||
tmp.baud_base = 115200;
|
||||
tmp.close_delay = 0;
|
||||
tmp.closing_wait = 0;
|
||||
tmp.custom_divisor = 0;
|
||||
tmp.hub6 = 0;
|
||||
|
||||
if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
|
||||
return -EFAULT;
|
||||
|
||||
|
@ -1219,7 +1219,6 @@ static int mxser_get_serial_info(struct tty_struct *tty,
|
||||
.close_delay = info->port.close_delay,
|
||||
.closing_wait = info->port.closing_wait,
|
||||
.custom_divisor = info->custom_divisor,
|
||||
.hub6 = 0
|
||||
};
|
||||
if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
|
||||
return -EFAULT;
|
||||
|
@ -15,6 +15,8 @@
|
||||
#include <linux/serial_reg.h>
|
||||
#include <linux/dmaengine.h>
|
||||
|
||||
#include "../serial_mctrl_gpio.h"
|
||||
|
||||
struct uart_8250_dma {
|
||||
int (*tx_dma)(struct uart_8250_port *p);
|
||||
int (*rx_dma)(struct uart_8250_port *p);
|
||||
@ -53,11 +55,9 @@ struct old_serial_port {
|
||||
unsigned int port;
|
||||
unsigned int irq;
|
||||
upf_t flags;
|
||||
unsigned char hub6;
|
||||
unsigned char io_type;
|
||||
unsigned char __iomem *iomem_base;
|
||||
unsigned short iomem_reg_shift;
|
||||
unsigned long irqflags;
|
||||
};
|
||||
|
||||
struct serial8250_config {
|
||||
@ -131,6 +131,47 @@ void serial8250_rpm_put(struct uart_8250_port *p);
|
||||
int serial8250_em485_init(struct uart_8250_port *p);
|
||||
void serial8250_em485_destroy(struct uart_8250_port *p);
|
||||
|
||||
static inline void serial8250_out_MCR(struct uart_8250_port *up, int value)
|
||||
{
|
||||
int mctrl_gpio = 0;
|
||||
|
||||
serial_out(up, UART_MCR, value);
|
||||
|
||||
if (value & UART_MCR_RTS)
|
||||
mctrl_gpio |= TIOCM_RTS;
|
||||
if (value & UART_MCR_DTR)
|
||||
mctrl_gpio |= TIOCM_DTR;
|
||||
|
||||
mctrl_gpio_set(up->gpios, mctrl_gpio);
|
||||
}
|
||||
|
||||
static inline int serial8250_in_MCR(struct uart_8250_port *up)
|
||||
{
|
||||
int mctrl, mctrl_gpio = 0;
|
||||
|
||||
mctrl = serial_in(up, UART_MCR);
|
||||
|
||||
/* save current MCR values */
|
||||
if (mctrl & UART_MCR_RTS)
|
||||
mctrl_gpio |= TIOCM_RTS;
|
||||
if (mctrl & UART_MCR_DTR)
|
||||
mctrl_gpio |= TIOCM_DTR;
|
||||
|
||||
mctrl_gpio = mctrl_gpio_get_outputs(up->gpios, &mctrl_gpio);
|
||||
|
||||
if (mctrl_gpio & TIOCM_RTS)
|
||||
mctrl |= UART_MCR_RTS;
|
||||
else
|
||||
mctrl &= ~UART_MCR_RTS;
|
||||
|
||||
if (mctrl_gpio & TIOCM_DTR)
|
||||
mctrl |= UART_MCR_DTR;
|
||||
else
|
||||
mctrl &= ~UART_MCR_DTR;
|
||||
|
||||
return mctrl;
|
||||
}
|
||||
|
||||
#if defined(__alpha__) && !defined(CONFIG_PCI)
|
||||
/*
|
||||
* Digital did something really horribly wrong with the OUT1 and OUT2
|
||||
@ -237,9 +278,3 @@ static inline int serial_index(struct uart_port *port)
|
||||
{
|
||||
return port->minor - 64;
|
||||
}
|
||||
|
||||
#if 0
|
||||
#define DEBUG_INTR(fmt...) printk(fmt)
|
||||
#else
|
||||
#define DEBUG_INTR(fmt...) do { } while (0)
|
||||
#endif
|
||||
|
@ -114,7 +114,7 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id)
|
||||
struct list_head *l, *end = NULL;
|
||||
int pass_counter = 0, handled = 0;
|
||||
|
||||
DEBUG_INTR("serial8250_interrupt(%d)...", irq);
|
||||
pr_debug("%s(%d): start\n", __func__, irq);
|
||||
|
||||
spin_lock(&i->lock);
|
||||
|
||||
@ -144,7 +144,7 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id)
|
||||
|
||||
spin_unlock(&i->lock);
|
||||
|
||||
DEBUG_INTR("end.\n");
|
||||
pr_debug("%s(%d): end\n", __func__, irq);
|
||||
|
||||
return IRQ_RETVAL(handled);
|
||||
}
|
||||
@ -546,10 +546,10 @@ static void __init serial8250_isa_init_ports(void)
|
||||
|
||||
port->iobase = old_serial_port[i].port;
|
||||
port->irq = irq_canonicalize(old_serial_port[i].irq);
|
||||
port->irqflags = old_serial_port[i].irqflags;
|
||||
port->irqflags = 0;
|
||||
port->uartclk = old_serial_port[i].baud_base * 16;
|
||||
port->flags = old_serial_port[i].flags;
|
||||
port->hub6 = old_serial_port[i].hub6;
|
||||
port->hub6 = 0;
|
||||
port->membase = old_serial_port[i].iomem_base;
|
||||
port->iotype = old_serial_port[i].io_type;
|
||||
port->regshift = old_serial_port[i].iomem_reg_shift;
|
||||
@ -675,7 +675,7 @@ static struct console univ8250_console = {
|
||||
.device = uart_console_device,
|
||||
.setup = univ8250_console_setup,
|
||||
.match = univ8250_console_match,
|
||||
.flags = CON_PRINTBUFFER | CON_ANYTIME,
|
||||
.flags = CON_PRINTBUFFER | CON_ANYTIME | CON_CONSDEV,
|
||||
.index = -1,
|
||||
.data = &serial8250_reg,
|
||||
};
|
||||
@ -974,6 +974,8 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
|
||||
|
||||
uart = serial8250_find_match_or_unused(&up->port);
|
||||
if (uart && uart->port.type != PORT_8250_CIR) {
|
||||
struct mctrl_gpios *gpios;
|
||||
|
||||
if (uart->port.dev)
|
||||
uart_remove_one_port(&serial8250_reg, &uart->port);
|
||||
|
||||
@ -1011,6 +1013,13 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
|
||||
if (up->port.flags & UPF_FIXED_TYPE)
|
||||
uart->port.type = up->port.type;
|
||||
|
||||
gpios = mctrl_gpio_init(&uart->port, 0);
|
||||
if (IS_ERR(gpios)) {
|
||||
if (PTR_ERR(gpios) != -ENOSYS)
|
||||
return PTR_ERR(gpios);
|
||||
} else
|
||||
uart->gpios = gpios;
|
||||
|
||||
serial8250_set_defaults(uart);
|
||||
|
||||
/* Possibly override default I/O functions. */
|
||||
|
@ -145,6 +145,7 @@ void serial8250_rx_dma_flush(struct uart_8250_port *p)
|
||||
dmaengine_terminate_all(dma->rxchan);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(serial8250_rx_dma_flush);
|
||||
|
||||
int serial8250_request_dma(struct uart_8250_port *p)
|
||||
{
|
||||
|
@ -150,6 +150,7 @@ EARLYCON_DECLARE(uart, early_serial8250_setup);
|
||||
OF_EARLYCON_DECLARE(ns16550, "ns16550", early_serial8250_setup);
|
||||
OF_EARLYCON_DECLARE(ns16550a, "ns16550a", early_serial8250_setup);
|
||||
OF_EARLYCON_DECLARE(uart, "nvidia,tegra20-uart", early_serial8250_setup);
|
||||
OF_EARLYCON_DECLARE(uart, "snps,dw-apb-uart", early_serial8250_setup);
|
||||
|
||||
#ifdef CONFIG_SERIAL_8250_OMAP
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <linux/pnp.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/irq.h>
|
||||
#include "8250.h"
|
||||
|
||||
#define ADDR_PORT 0
|
||||
@ -30,6 +31,12 @@
|
||||
#define IO_ADDR2 0x60
|
||||
#define LDN 0x7
|
||||
|
||||
#define IRQ_MODE 0x70
|
||||
#define IRQ_SHARE BIT(4)
|
||||
#define IRQ_MODE_MASK (BIT(6) | BIT(5))
|
||||
#define IRQ_LEVEL_LOW 0
|
||||
#define IRQ_EDGE_HIGH BIT(5)
|
||||
|
||||
#define RS485 0xF0
|
||||
#define RTS_INVERT BIT(5)
|
||||
#define RS485_URA BIT(4)
|
||||
@ -176,10 +183,37 @@ static int find_base_port(struct fintek_8250 *pdata, u16 io_address)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int fintek_8250_set_irq_mode(struct fintek_8250 *pdata, bool level_mode)
|
||||
{
|
||||
int status;
|
||||
u8 tmp;
|
||||
|
||||
status = fintek_8250_enter_key(pdata->base_port, pdata->key);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
outb(LDN, pdata->base_port + ADDR_PORT);
|
||||
outb(pdata->index, pdata->base_port + DATA_PORT);
|
||||
|
||||
outb(IRQ_MODE, pdata->base_port + ADDR_PORT);
|
||||
tmp = inb(pdata->base_port + DATA_PORT);
|
||||
|
||||
tmp &= ~IRQ_MODE_MASK;
|
||||
tmp |= IRQ_SHARE;
|
||||
if (!level_mode)
|
||||
tmp |= IRQ_EDGE_HIGH;
|
||||
|
||||
outb(tmp, pdata->base_port + DATA_PORT);
|
||||
fintek_8250_exit_key(pdata->base_port);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fintek_8250_probe(struct uart_8250_port *uart)
|
||||
{
|
||||
struct fintek_8250 *pdata;
|
||||
struct fintek_8250 probe_data;
|
||||
struct irq_data *irq_data = irq_get_irq_data(uart->port.irq);
|
||||
bool level_mode = irqd_is_level_type(irq_data);
|
||||
|
||||
if (find_base_port(&probe_data, uart->port.iobase))
|
||||
return -ENODEV;
|
||||
@ -192,5 +226,5 @@ int fintek_8250_probe(struct uart_8250_port *uart)
|
||||
uart->port.rs485_config = fintek_8250_rs485_config;
|
||||
uart->port.private_data = pdata;
|
||||
|
||||
return 0;
|
||||
return fintek_8250_set_irq_mode(pdata, level_mode);
|
||||
}
|
||||
|
@ -48,7 +48,6 @@ static const struct of_device_id of_match[];
|
||||
#define UART_MCR_MDCE BIT(7)
|
||||
#define UART_MCR_FCM BIT(6)
|
||||
|
||||
#if defined(CONFIG_SERIAL_EARLYCON) && !defined(MODULE)
|
||||
static struct earlycon_device *early_device;
|
||||
|
||||
static uint8_t __init early_in(struct uart_port *port, int offset)
|
||||
@ -141,7 +140,6 @@ OF_EARLYCON_DECLARE(jz4775_uart, "ingenic,jz4775-uart",
|
||||
EARLYCON_DECLARE(jz4780_uart, ingenic_early_console_setup);
|
||||
OF_EARLYCON_DECLARE(jz4780_uart, "ingenic,jz4780-uart",
|
||||
ingenic_early_console_setup);
|
||||
#endif /* CONFIG_SERIAL_EARLYCON */
|
||||
|
||||
static void ingenic_uart_serial_out(struct uart_port *p, int offset, int value)
|
||||
{
|
||||
|
@ -96,13 +96,27 @@ static int tng_setup(struct mid8250 *mid, struct uart_port *p)
|
||||
static int dnv_handle_irq(struct uart_port *p)
|
||||
{
|
||||
struct mid8250 *mid = p->private_data;
|
||||
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 err;
|
||||
|
||||
if (fisr & BIT(2))
|
||||
ret |= hsu_dma_irq(&mid->dma_chip, 1);
|
||||
if (fisr & BIT(1))
|
||||
ret |= hsu_dma_irq(&mid->dma_chip, 0);
|
||||
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;
|
||||
} 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;
|
||||
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;
|
||||
|
@ -301,7 +301,7 @@ static struct platform_driver mtk8250_platform_driver = {
|
||||
};
|
||||
module_platform_driver(mtk8250_platform_driver);
|
||||
|
||||
#if defined(CONFIG_SERIAL_8250_CONSOLE) && !defined(MODULE)
|
||||
#ifdef CONFIG_SERIAL_8250_CONSOLE
|
||||
static int __init early_mtk8250_setup(struct earlycon_device *device,
|
||||
const char *options)
|
||||
{
|
||||
|
@ -134,18 +134,21 @@ static void omap8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
|
||||
serial8250_do_set_mctrl(port, mctrl);
|
||||
|
||||
/*
|
||||
* Turn off autoRTS if RTS is lowered and restore autoRTS setting
|
||||
* if RTS is raised
|
||||
*/
|
||||
lcr = serial_in(up, UART_LCR);
|
||||
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
|
||||
if ((mctrl & TIOCM_RTS) && (port->status & UPSTAT_AUTORTS))
|
||||
priv->efr |= UART_EFR_RTS;
|
||||
else
|
||||
priv->efr &= ~UART_EFR_RTS;
|
||||
serial_out(up, UART_EFR, priv->efr);
|
||||
serial_out(up, UART_LCR, lcr);
|
||||
if (IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(up->gpios,
|
||||
UART_GPIO_RTS))) {
|
||||
/*
|
||||
* Turn off autoRTS if RTS is lowered and restore autoRTS
|
||||
* setting if RTS is raised
|
||||
*/
|
||||
lcr = serial_in(up, UART_LCR);
|
||||
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
|
||||
if ((mctrl & TIOCM_RTS) && (port->status & UPSTAT_AUTORTS))
|
||||
priv->efr |= UART_EFR_RTS;
|
||||
else
|
||||
priv->efr &= ~UART_EFR_RTS;
|
||||
serial_out(up, UART_EFR, priv->efr);
|
||||
serial_out(up, UART_LCR, lcr);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -280,7 +283,7 @@ static void omap8250_restore_regs(struct uart_8250_port *up)
|
||||
serial_out(up, UART_EFR, UART_EFR_ECB);
|
||||
|
||||
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
|
||||
serial_out(up, UART_MCR, UART_MCR_TCRTLR);
|
||||
serial8250_out_MCR(up, UART_MCR_TCRTLR);
|
||||
serial_out(up, UART_FCR, up->fcr);
|
||||
|
||||
omap8250_update_scr(up, priv);
|
||||
@ -296,7 +299,7 @@ static void omap8250_restore_regs(struct uart_8250_port *up)
|
||||
serial_out(up, UART_LCR, 0);
|
||||
|
||||
/* drop TCR + TLR access, we setup XON/XOFF later */
|
||||
serial_out(up, UART_MCR, up->mcr);
|
||||
serial8250_out_MCR(up, up->mcr);
|
||||
serial_out(up, UART_IER, up->ier);
|
||||
|
||||
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
|
||||
@ -446,7 +449,9 @@ static void omap_8250_set_termios(struct uart_port *port,
|
||||
priv->efr = 0;
|
||||
up->port.status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS | UPSTAT_AUTOXOFF);
|
||||
|
||||
if (termios->c_cflag & CRTSCTS && up->port.flags & UPF_HARD_FLOW) {
|
||||
if (termios->c_cflag & CRTSCTS && up->port.flags & UPF_HARD_FLOW
|
||||
&& IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(up->gpios,
|
||||
UART_GPIO_RTS))) {
|
||||
/* Enable AUTOCTS (autoRTS is enabled when RTS is raised) */
|
||||
up->port.status |= UPSTAT_AUTOCTS | UPSTAT_AUTORTS;
|
||||
priv->efr |= UART_EFR_CTS;
|
||||
|
@ -1136,11 +1136,11 @@ static int pci_quatech_rqopr(struct uart_8250_port *port)
|
||||
static void pci_quatech_wqopr(struct uart_8250_port *port, u8 qopr)
|
||||
{
|
||||
unsigned long base = port->port.iobase;
|
||||
u8 LCR, val;
|
||||
u8 LCR;
|
||||
|
||||
LCR = inb(base + UART_LCR);
|
||||
outb(0xBF, base + UART_LCR);
|
||||
val = inb(base + UART_SCR);
|
||||
inb(base + UART_SCR);
|
||||
outb(qopr, base + UART_SCR);
|
||||
outb(LCR, base + UART_LCR);
|
||||
}
|
||||
@ -1864,6 +1864,16 @@ pci_wch_ch353_setup(struct serial_private *priv,
|
||||
return pci_default_setup(priv, board, port, idx);
|
||||
}
|
||||
|
||||
static int
|
||||
pci_wch_ch355_setup(struct serial_private *priv,
|
||||
const struct pciserial_board *board,
|
||||
struct uart_8250_port *port, int idx)
|
||||
{
|
||||
port->port.flags |= UPF_FIXED_TYPE;
|
||||
port->port.type = PORT_16550A;
|
||||
return pci_default_setup(priv, board, port, idx);
|
||||
}
|
||||
|
||||
static int
|
||||
pci_wch_ch38x_setup(struct serial_private *priv,
|
||||
const struct pciserial_board *board,
|
||||
@ -1915,6 +1925,7 @@ pci_wch_ch38x_setup(struct serial_private *priv,
|
||||
#define PCI_DEVICE_ID_WCH_CH353_2S1PF 0x5046
|
||||
#define PCI_DEVICE_ID_WCH_CH353_1S1P 0x5053
|
||||
#define PCI_DEVICE_ID_WCH_CH353_2S1P 0x7053
|
||||
#define PCI_DEVICE_ID_WCH_CH355_4S 0x7173
|
||||
#define PCI_VENDOR_ID_AGESTAR 0x5372
|
||||
#define PCI_DEVICE_ID_AGESTAR_9375 0x6872
|
||||
#define PCI_VENDOR_ID_ASIX 0x9710
|
||||
@ -2618,6 +2629,14 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.setup = pci_wch_ch353_setup,
|
||||
},
|
||||
/* WCH CH355 4S card (16550 clone) */
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_WCH,
|
||||
.device = PCI_DEVICE_ID_WCH_CH355_4S,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.setup = pci_wch_ch355_setup,
|
||||
},
|
||||
/* WCH CH382 2S card (16850 clone) */
|
||||
{
|
||||
.vendor = PCIE_VENDOR_ID_WCH,
|
||||
@ -3812,6 +3831,7 @@ static const struct pci_device_id blacklist[] = {
|
||||
/* multi-io cards handled by parport_serial */
|
||||
{ PCI_DEVICE(0x4348, 0x7053), }, /* WCH CH353 2S1P */
|
||||
{ PCI_DEVICE(0x4348, 0x5053), }, /* WCH CH353 1S1P */
|
||||
{ PCI_DEVICE(0x4348, 0x7173), }, /* WCH CH355 4S */
|
||||
{ PCI_DEVICE(0x1c00, 0x3250), }, /* WCH CH382 2S1P */
|
||||
{ PCI_DEVICE(0x1c00, 0x3470), }, /* WCH CH384 4S */
|
||||
|
||||
@ -5567,6 +5587,10 @@ static struct pci_device_id serial_pci_tbl[] = {
|
||||
PCI_ANY_ID, PCI_ANY_ID,
|
||||
0, 0, pbn_b0_bt_2_115200 },
|
||||
|
||||
{ PCI_VENDOR_ID_WCH, PCI_DEVICE_ID_WCH_CH355_4S,
|
||||
PCI_ANY_ID, PCI_ANY_ID,
|
||||
0, 0, pbn_b0_bt_4_115200 },
|
||||
|
||||
{ PCIE_VENDOR_ID_WCH, PCIE_DEVICE_ID_WCH_CH382_2S,
|
||||
PCI_ANY_ID, PCI_ANY_ID,
|
||||
0, 0, pbn_wch382_2 },
|
||||
|
@ -527,13 +527,13 @@ static void serial8250_clear_fifos(struct uart_8250_port *p)
|
||||
|
||||
static inline void serial8250_em485_rts_after_send(struct uart_8250_port *p)
|
||||
{
|
||||
unsigned char mcr = serial_in(p, UART_MCR);
|
||||
unsigned char mcr = serial8250_in_MCR(p);
|
||||
|
||||
if (p->port.rs485.flags & SER_RS485_RTS_AFTER_SEND)
|
||||
mcr |= UART_MCR_RTS;
|
||||
else
|
||||
mcr &= ~UART_MCR_RTS;
|
||||
serial_out(p, UART_MCR, mcr);
|
||||
serial8250_out_MCR(p, mcr);
|
||||
}
|
||||
|
||||
static void serial8250_em485_handle_start_tx(unsigned long arg);
|
||||
@ -785,10 +785,10 @@ static int size_fifo(struct uart_8250_port *up)
|
||||
old_lcr = serial_in(up, UART_LCR);
|
||||
serial_out(up, UART_LCR, 0);
|
||||
old_fcr = serial_in(up, UART_FCR);
|
||||
old_mcr = serial_in(up, UART_MCR);
|
||||
old_mcr = serial8250_in_MCR(up);
|
||||
serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
|
||||
UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
|
||||
serial_out(up, UART_MCR, UART_MCR_LOOP);
|
||||
serial8250_out_MCR(up, UART_MCR_LOOP);
|
||||
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
|
||||
old_dl = serial_dl_read(up);
|
||||
serial_dl_write(up, 0x0001);
|
||||
@ -800,7 +800,7 @@ static int size_fifo(struct uart_8250_port *up)
|
||||
(count < 256); count++)
|
||||
serial_in(up, UART_RX);
|
||||
serial_out(up, UART_FCR, old_fcr);
|
||||
serial_out(up, UART_MCR, old_mcr);
|
||||
serial8250_out_MCR(up, old_mcr);
|
||||
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
|
||||
serial_dl_write(up, old_dl);
|
||||
serial_out(up, UART_LCR, old_lcr);
|
||||
@ -1040,17 +1040,17 @@ static void autoconfig_16550a(struct uart_8250_port *up)
|
||||
* it's changed. If so, set baud_base in EXCR2 to 921600. -- dwmw2
|
||||
*/
|
||||
serial_out(up, UART_LCR, 0);
|
||||
status1 = serial_in(up, UART_MCR);
|
||||
status1 = serial8250_in_MCR(up);
|
||||
serial_out(up, UART_LCR, 0xE0);
|
||||
status2 = serial_in(up, 0x02); /* EXCR1 */
|
||||
|
||||
if (!((status2 ^ status1) & UART_MCR_LOOP)) {
|
||||
serial_out(up, UART_LCR, 0);
|
||||
serial_out(up, UART_MCR, status1 ^ UART_MCR_LOOP);
|
||||
serial8250_out_MCR(up, status1 ^ UART_MCR_LOOP);
|
||||
serial_out(up, UART_LCR, 0xE0);
|
||||
status2 = serial_in(up, 0x02); /* EXCR1 */
|
||||
serial_out(up, UART_LCR, 0);
|
||||
serial_out(up, UART_MCR, status1);
|
||||
serial8250_out_MCR(up, status1);
|
||||
|
||||
if ((status2 ^ status1) & UART_MCR_LOOP) {
|
||||
unsigned short quot;
|
||||
@ -1224,7 +1224,7 @@ static void autoconfig(struct uart_8250_port *up)
|
||||
}
|
||||
}
|
||||
|
||||
save_mcr = serial_in(up, UART_MCR);
|
||||
save_mcr = serial8250_in_MCR(up);
|
||||
save_lcr = serial_in(up, UART_LCR);
|
||||
|
||||
/*
|
||||
@ -1237,9 +1237,9 @@ static void autoconfig(struct uart_8250_port *up)
|
||||
* that conflicts with COM 1-4 --- we hope!
|
||||
*/
|
||||
if (!(port->flags & UPF_SKIP_TEST)) {
|
||||
serial_out(up, UART_MCR, UART_MCR_LOOP | 0x0A);
|
||||
serial8250_out_MCR(up, UART_MCR_LOOP | 0x0A);
|
||||
status1 = serial_in(up, UART_MSR) & 0xF0;
|
||||
serial_out(up, UART_MCR, save_mcr);
|
||||
serial8250_out_MCR(up, save_mcr);
|
||||
if (status1 != 0x90) {
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
DEBUG_AUTOCONF("LOOP test failed (%02x) ",
|
||||
@ -1305,7 +1305,7 @@ static void autoconfig(struct uart_8250_port *up)
|
||||
if (port->type == PORT_RSA)
|
||||
serial_out(up, UART_RSA_FRR, 0);
|
||||
#endif
|
||||
serial_out(up, UART_MCR, save_mcr);
|
||||
serial8250_out_MCR(up, save_mcr);
|
||||
serial8250_clear_fifos(up);
|
||||
serial_in(up, UART_RX);
|
||||
if (up->capabilities & UART_CAP_UUE)
|
||||
@ -1353,19 +1353,18 @@ static void autoconfig_irq(struct uart_8250_port *up)
|
||||
|
||||
/* forget possible initially masked and pending IRQ */
|
||||
probe_irq_off(probe_irq_on());
|
||||
save_mcr = serial_in(up, UART_MCR);
|
||||
save_mcr = serial8250_in_MCR(up);
|
||||
save_ier = serial_in(up, UART_IER);
|
||||
serial_out(up, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2);
|
||||
serial8250_out_MCR(up, UART_MCR_OUT1 | UART_MCR_OUT2);
|
||||
|
||||
irqs = probe_irq_on();
|
||||
serial_out(up, UART_MCR, 0);
|
||||
serial8250_out_MCR(up, 0);
|
||||
udelay(10);
|
||||
if (port->flags & UPF_FOURPORT) {
|
||||
serial_out(up, UART_MCR,
|
||||
UART_MCR_DTR | UART_MCR_RTS);
|
||||
serial8250_out_MCR(up, UART_MCR_DTR | UART_MCR_RTS);
|
||||
} else {
|
||||
serial_out(up, UART_MCR,
|
||||
UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2);
|
||||
serial8250_out_MCR(up,
|
||||
UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2);
|
||||
}
|
||||
serial_out(up, UART_IER, 0x0f); /* enable all intrs */
|
||||
serial_in(up, UART_LSR);
|
||||
@ -1376,7 +1375,7 @@ static void autoconfig_irq(struct uart_8250_port *up)
|
||||
udelay(20);
|
||||
irq = probe_irq_off(irqs);
|
||||
|
||||
serial_out(up, UART_MCR, save_mcr);
|
||||
serial8250_out_MCR(up, save_mcr);
|
||||
serial_out(up, UART_IER, save_ier);
|
||||
|
||||
if (port->flags & UPF_FOURPORT)
|
||||
@ -1549,14 +1548,14 @@ static inline void start_tx_rs485(struct uart_port *port)
|
||||
del_timer(&em485->stop_tx_timer);
|
||||
em485->active_timer = NULL;
|
||||
|
||||
mcr = serial_in(up, UART_MCR);
|
||||
mcr = serial8250_in_MCR(up);
|
||||
if (!!(up->port.rs485.flags & SER_RS485_RTS_ON_SEND) !=
|
||||
!!(mcr & UART_MCR_RTS)) {
|
||||
if (up->port.rs485.flags & SER_RS485_RTS_ON_SEND)
|
||||
mcr |= UART_MCR_RTS;
|
||||
else
|
||||
mcr &= ~UART_MCR_RTS;
|
||||
serial_out(up, UART_MCR, mcr);
|
||||
serial8250_out_MCR(up, mcr);
|
||||
|
||||
if (up->port.rs485.delay_rts_before_send > 0) {
|
||||
em485->active_timer = &em485->start_tx_timer;
|
||||
@ -1619,6 +1618,8 @@ static void serial8250_disable_ms(struct uart_port *port)
|
||||
if (up->bugs & UART_BUG_NOMSR)
|
||||
return;
|
||||
|
||||
mctrl_gpio_disable_ms(up->gpios);
|
||||
|
||||
up->ier &= ~UART_IER_MSI;
|
||||
serial_port_out(port, UART_IER, up->ier);
|
||||
}
|
||||
@ -1631,6 +1632,8 @@ static void serial8250_enable_ms(struct uart_port *port)
|
||||
if (up->bugs & UART_BUG_NOMSR)
|
||||
return;
|
||||
|
||||
mctrl_gpio_enable_ms(up->gpios);
|
||||
|
||||
up->ier |= UART_IER_MSI;
|
||||
|
||||
serial8250_rpm_get(up);
|
||||
@ -1686,7 +1689,7 @@ static void serial8250_read_char(struct uart_8250_port *up, unsigned char lsr)
|
||||
lsr &= port->read_status_mask;
|
||||
|
||||
if (lsr & UART_LSR_BI) {
|
||||
DEBUG_INTR("handling break....");
|
||||
pr_debug("%s: handling break\n", __func__);
|
||||
flag = TTY_BREAK;
|
||||
} else if (lsr & UART_LSR_PE)
|
||||
flag = TTY_PARITY;
|
||||
@ -1757,7 +1760,7 @@ void serial8250_tx_chars(struct uart_8250_port *up)
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(port);
|
||||
|
||||
DEBUG_INTR("THRE...");
|
||||
pr_debug("%s: THRE\n", __func__);
|
||||
|
||||
/*
|
||||
* With RPM enabled, we have to wait until the FIFO is empty before the
|
||||
@ -1823,7 +1826,7 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
|
||||
|
||||
status = serial_port_in(port, UART_LSR);
|
||||
|
||||
DEBUG_INTR("status = %x...", status);
|
||||
pr_debug("%s: status = %x\n", __func__, status);
|
||||
|
||||
if (status & (UART_LSR_DR | UART_LSR_BI)) {
|
||||
if (!up->dma || handle_rx_dma(up, iir))
|
||||
@ -1861,7 +1864,6 @@ static int serial8250_default_handle_irq(struct uart_port *port)
|
||||
*/
|
||||
static int exar_handle_irq(struct uart_port *port)
|
||||
{
|
||||
unsigned char int0, int1, int2, int3;
|
||||
unsigned int iir = serial_port_in(port, UART_IIR);
|
||||
int ret;
|
||||
|
||||
@ -1869,10 +1871,10 @@ static int exar_handle_irq(struct uart_port *port)
|
||||
|
||||
if ((port->type == PORT_XR17V35X) ||
|
||||
(port->type == PORT_XR17D15X)) {
|
||||
int0 = serial_port_in(port, 0x80);
|
||||
int1 = serial_port_in(port, 0x81);
|
||||
int2 = serial_port_in(port, 0x82);
|
||||
int3 = serial_port_in(port, 0x83);
|
||||
serial_port_in(port, 0x80);
|
||||
serial_port_in(port, 0x81);
|
||||
serial_port_in(port, 0x82);
|
||||
serial_port_in(port, 0x83);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -1915,7 +1917,8 @@ unsigned int serial8250_do_get_mctrl(struct uart_port *port)
|
||||
ret |= TIOCM_DSR;
|
||||
if (status & UART_MSR_CTS)
|
||||
ret |= TIOCM_CTS;
|
||||
return ret;
|
||||
|
||||
return mctrl_gpio_get(up->gpios, &ret);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(serial8250_do_get_mctrl);
|
||||
|
||||
@ -1944,7 +1947,7 @@ void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
|
||||
mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr;
|
||||
|
||||
serial_port_out(port, UART_MCR, mcr);
|
||||
serial8250_out_MCR(up, mcr);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(serial8250_do_set_mctrl);
|
||||
|
||||
@ -1994,8 +1997,6 @@ static void wait_for_xmitr(struct uart_8250_port *up, int bits)
|
||||
|
||||
/* Wait up to 1s for flow control if necessary */
|
||||
if (up->port.flags & UPF_CONS_FLOW) {
|
||||
unsigned int tmout;
|
||||
|
||||
for (tmout = 1000000; tmout; tmout--) {
|
||||
unsigned int msr = serial_in(up, UART_MSR);
|
||||
up->msr_saved_flags |= msr & MSR_SAVE_FLAGS;
|
||||
@ -3093,7 +3094,7 @@ static void serial8250_console_restore(struct uart_8250_port *up)
|
||||
|
||||
serial8250_set_divisor(port, baud, quot, frac);
|
||||
serial_port_out(port, UART_LCR, up->lcr);
|
||||
serial_port_out(port, UART_MCR, UART_MCR_DTR | UART_MCR_RTS);
|
||||
serial8250_out_MCR(up, UART_MCR_DTR | UART_MCR_RTS);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -35,7 +35,7 @@ struct uniphier8250_priv {
|
||||
spinlock_t atomic_write_lock;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_SERIAL_8250_CONSOLE) && !defined(MODULE)
|
||||
#ifdef CONFIG_SERIAL_8250_CONSOLE
|
||||
static int __init uniphier_early_console_setup(struct earlycon_device *device,
|
||||
const char *options)
|
||||
{
|
||||
|
@ -6,6 +6,7 @@
|
||||
config SERIAL_8250
|
||||
tristate "8250/16550 and compatible serial support"
|
||||
select SERIAL_CORE
|
||||
select SERIAL_MCTRL_GPIO if GPIOLIB
|
||||
---help---
|
||||
This selects whether you want to include the driver for the standard
|
||||
serial ports. The standard answer is Y. People who might say N
|
||||
@ -387,7 +388,8 @@ config SERIAL_8250_MT6577
|
||||
|
||||
config SERIAL_8250_UNIPHIER
|
||||
tristate "Support for UniPhier on-chip UART"
|
||||
depends on SERIAL_8250 && ARCH_UNIPHIER
|
||||
depends on SERIAL_8250
|
||||
depends on ARCH_UNIPHIER || COMPILE_TEST
|
||||
help
|
||||
If you have a UniPhier based board and want to use the on-chip
|
||||
serial ports, say Y to this option. If unsure, say N.
|
||||
@ -395,7 +397,7 @@ config SERIAL_8250_UNIPHIER
|
||||
config SERIAL_8250_INGENIC
|
||||
tristate "Support for Ingenic SoC serial ports"
|
||||
depends on SERIAL_8250
|
||||
depends on (OF_FLATTREE && SERIAL_8250_CONSOLE) || !SERIAL_EARLYCON
|
||||
depends on OF_FLATTREE
|
||||
depends on MIPS || COMPILE_TEST
|
||||
help
|
||||
If you have a system using an Ingenic SoC and wish to make use of
|
||||
|
@ -736,6 +736,7 @@ config SERIAL_SH_SCI
|
||||
tristate "SuperH SCI(F) serial port support"
|
||||
depends on SUPERH || ARCH_RENESAS || H8300 || COMPILE_TEST
|
||||
select SERIAL_CORE
|
||||
select SERIAL_MCTRL_GPIO if GPIOLIB
|
||||
|
||||
config SERIAL_SH_SCI_NR_UARTS
|
||||
int "Maximum number of SCI(F) serial ports"
|
||||
@ -1477,7 +1478,7 @@ config SERIAL_MPS2_UART_CONSOLE
|
||||
|
||||
config SERIAL_MPS2_UART
|
||||
bool "MPS2 UART port"
|
||||
depends on ARM || COMPILE_TEST
|
||||
depends on ARCH_MPS2 || COMPILE_TEST
|
||||
select SERIAL_CORE
|
||||
help
|
||||
This driver support the UART ports on ARM MPS2.
|
||||
|
@ -2553,11 +2553,17 @@ static int sbsa_uart_probe(struct platform_device *pdev)
|
||||
if (!uap)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = platform_get_irq(pdev, 0);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "cannot obtain irq\n");
|
||||
return ret;
|
||||
}
|
||||
uap->port.irq = ret;
|
||||
|
||||
uap->reg_offset = vendor_sbsa.reg_offset;
|
||||
uap->vendor = &vendor_sbsa;
|
||||
uap->fifosize = 32;
|
||||
uap->port.iotype = vendor_sbsa.access_32b ? UPIO_MEM32 : UPIO_MEM;
|
||||
uap->port.irq = platform_get_irq(pdev, 0);
|
||||
uap->port.ops = &sbsa_uart_pops;
|
||||
uap->fixed_baud = baudrate;
|
||||
|
||||
|
@ -108,6 +108,12 @@ struct atmel_uart_char {
|
||||
u16 ch;
|
||||
};
|
||||
|
||||
/*
|
||||
* Be careful, the real size of the ring buffer is
|
||||
* sizeof(atmel_uart_char) * ATMEL_SERIAL_RINGSIZE. It means that ring buffer
|
||||
* can contain up to 1024 characters in PIO mode and up to 4096 characters in
|
||||
* DMA mode.
|
||||
*/
|
||||
#define ATMEL_SERIAL_RINGSIZE 1024
|
||||
|
||||
/*
|
||||
@ -145,10 +151,10 @@ struct atmel_uart_port {
|
||||
dma_cookie_t cookie_rx;
|
||||
struct scatterlist sg_tx;
|
||||
struct scatterlist sg_rx;
|
||||
struct tasklet_struct tasklet;
|
||||
unsigned int irq_status;
|
||||
struct tasklet_struct tasklet_rx;
|
||||
struct tasklet_struct tasklet_tx;
|
||||
atomic_t tasklet_shutdown;
|
||||
unsigned int irq_status_prev;
|
||||
unsigned int status_change;
|
||||
unsigned int tx_len;
|
||||
|
||||
struct circ_buf rx_ring;
|
||||
@ -281,6 +287,13 @@ static bool atmel_use_fifo(struct uart_port *port)
|
||||
return atmel_port->fifo_size;
|
||||
}
|
||||
|
||||
static void atmel_tasklet_schedule(struct atmel_uart_port *atmel_port,
|
||||
struct tasklet_struct *t)
|
||||
{
|
||||
if (!atomic_read(&atmel_port->tasklet_shutdown))
|
||||
tasklet_schedule(t);
|
||||
}
|
||||
|
||||
static unsigned int atmel_get_lines_status(struct uart_port *port)
|
||||
{
|
||||
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
|
||||
@ -482,19 +495,21 @@ static void atmel_start_tx(struct uart_port *port)
|
||||
{
|
||||
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
|
||||
|
||||
if (atmel_use_pdc_tx(port)) {
|
||||
if (atmel_uart_readl(port, ATMEL_PDC_PTSR) & ATMEL_PDC_TXTEN)
|
||||
/* The transmitter is already running. Yes, we
|
||||
really need this.*/
|
||||
return;
|
||||
if (atmel_use_pdc_tx(port) && (atmel_uart_readl(port, ATMEL_PDC_PTSR)
|
||||
& ATMEL_PDC_TXTEN))
|
||||
/* The transmitter is already running. Yes, we
|
||||
really need this.*/
|
||||
return;
|
||||
|
||||
if (atmel_use_pdc_tx(port) || atmel_use_dma_tx(port))
|
||||
if ((port->rs485.flags & SER_RS485_ENABLED) &&
|
||||
!(port->rs485.flags & SER_RS485_RX_DURING_TX))
|
||||
atmel_stop_rx(port);
|
||||
|
||||
if (atmel_use_pdc_tx(port))
|
||||
/* re-enable PDC transmit */
|
||||
atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
|
||||
}
|
||||
|
||||
/* Enable interrupts */
|
||||
atmel_uart_writel(port, ATMEL_US_IER, atmel_port->tx_done_mask);
|
||||
}
|
||||
@ -710,7 +725,7 @@ static void atmel_rx_chars(struct uart_port *port)
|
||||
status = atmel_uart_readl(port, ATMEL_US_CSR);
|
||||
}
|
||||
|
||||
tasklet_schedule(&atmel_port->tasklet);
|
||||
atmel_tasklet_schedule(atmel_port, &atmel_port->tasklet_rx);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -781,7 +796,7 @@ static void atmel_complete_tx_dma(void *arg)
|
||||
* remaining data from the beginning of xmit->buf to xmit->head.
|
||||
*/
|
||||
if (!uart_circ_empty(xmit))
|
||||
tasklet_schedule(&atmel_port->tasklet);
|
||||
atmel_tasklet_schedule(atmel_port, &atmel_port->tasklet_tx);
|
||||
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
@ -966,7 +981,7 @@ static void atmel_complete_rx_dma(void *arg)
|
||||
struct uart_port *port = arg;
|
||||
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
|
||||
|
||||
tasklet_schedule(&atmel_port->tasklet);
|
||||
atmel_tasklet_schedule(atmel_port, &atmel_port->tasklet_rx);
|
||||
}
|
||||
|
||||
static void atmel_release_rx_dma(struct uart_port *port)
|
||||
@ -1006,7 +1021,7 @@ static void atmel_rx_from_dma(struct uart_port *port)
|
||||
if (dmastat == DMA_ERROR) {
|
||||
dev_dbg(port->dev, "Get residue error, restart tasklet\n");
|
||||
atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_TIMEOUT);
|
||||
tasklet_schedule(&atmel_port->tasklet);
|
||||
atmel_tasklet_schedule(atmel_port, &atmel_port->tasklet_rx);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1160,8 +1175,11 @@ static void atmel_uart_timer_callback(unsigned long data)
|
||||
struct uart_port *port = (void *)data;
|
||||
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
|
||||
|
||||
tasklet_schedule(&atmel_port->tasklet);
|
||||
mod_timer(&atmel_port->uart_timer, jiffies + uart_poll_timeout(port));
|
||||
if (!atomic_read(&atmel_port->tasklet_shutdown)) {
|
||||
tasklet_schedule(&atmel_port->tasklet_rx);
|
||||
mod_timer(&atmel_port->uart_timer,
|
||||
jiffies + uart_poll_timeout(port));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1183,7 +1201,8 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending)
|
||||
if (pending & (ATMEL_US_ENDRX | ATMEL_US_TIMEOUT)) {
|
||||
atmel_uart_writel(port, ATMEL_US_IDR,
|
||||
(ATMEL_US_ENDRX | ATMEL_US_TIMEOUT));
|
||||
tasklet_schedule(&atmel_port->tasklet);
|
||||
atmel_tasklet_schedule(atmel_port,
|
||||
&atmel_port->tasklet_rx);
|
||||
}
|
||||
|
||||
if (pending & (ATMEL_US_RXBRK | ATMEL_US_OVRE |
|
||||
@ -1195,7 +1214,8 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending)
|
||||
if (pending & ATMEL_US_TIMEOUT) {
|
||||
atmel_uart_writel(port, ATMEL_US_IDR,
|
||||
ATMEL_US_TIMEOUT);
|
||||
tasklet_schedule(&atmel_port->tasklet);
|
||||
atmel_tasklet_schedule(atmel_port,
|
||||
&atmel_port->tasklet_rx);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1225,7 +1245,7 @@ atmel_handle_transmit(struct uart_port *port, unsigned int pending)
|
||||
/* Either PDC or interrupt transmission */
|
||||
atmel_uart_writel(port, ATMEL_US_IDR,
|
||||
atmel_port->tx_done_mask);
|
||||
tasklet_schedule(&atmel_port->tasklet);
|
||||
atmel_tasklet_schedule(atmel_port, &atmel_port->tasklet_tx);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1237,14 +1257,27 @@ atmel_handle_status(struct uart_port *port, unsigned int pending,
|
||||
unsigned int status)
|
||||
{
|
||||
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
|
||||
unsigned int status_change;
|
||||
|
||||
if (pending & (ATMEL_US_RIIC | ATMEL_US_DSRIC | ATMEL_US_DCDIC
|
||||
| ATMEL_US_CTSIC)) {
|
||||
atmel_port->irq_status = status;
|
||||
atmel_port->status_change = atmel_port->irq_status ^
|
||||
atmel_port->irq_status_prev;
|
||||
status_change = status ^ atmel_port->irq_status_prev;
|
||||
atmel_port->irq_status_prev = status;
|
||||
tasklet_schedule(&atmel_port->tasklet);
|
||||
|
||||
if (status_change & (ATMEL_US_RI | ATMEL_US_DSR
|
||||
| ATMEL_US_DCD | ATMEL_US_CTS)) {
|
||||
/* TODO: All reads to CSR will clear these interrupts! */
|
||||
if (status_change & ATMEL_US_RI)
|
||||
port->icount.rng++;
|
||||
if (status_change & ATMEL_US_DSR)
|
||||
port->icount.dsr++;
|
||||
if (status_change & ATMEL_US_DCD)
|
||||
uart_handle_dcd_change(port, !(status & ATMEL_US_DCD));
|
||||
if (status_change & ATMEL_US_CTS)
|
||||
uart_handle_cts_change(port, !(status & ATMEL_US_CTS));
|
||||
|
||||
wake_up_interruptible(&port->state->port.delta_msr_wait);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1571,37 +1604,25 @@ static int atmel_prepare_rx_pdc(struct uart_port *port)
|
||||
/*
|
||||
* tasklet handling tty stuff outside the interrupt handler.
|
||||
*/
|
||||
static void atmel_tasklet_func(unsigned long data)
|
||||
static void atmel_tasklet_rx_func(unsigned long data)
|
||||
{
|
||||
struct uart_port *port = (struct uart_port *)data;
|
||||
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
|
||||
unsigned int status = atmel_port->irq_status;
|
||||
unsigned int status_change = atmel_port->status_change;
|
||||
|
||||
/* The interrupt handler does not take the lock */
|
||||
spin_lock(&port->lock);
|
||||
|
||||
atmel_port->schedule_tx(port);
|
||||
|
||||
if (status_change & (ATMEL_US_RI | ATMEL_US_DSR
|
||||
| ATMEL_US_DCD | ATMEL_US_CTS)) {
|
||||
/* TODO: All reads to CSR will clear these interrupts! */
|
||||
if (status_change & ATMEL_US_RI)
|
||||
port->icount.rng++;
|
||||
if (status_change & ATMEL_US_DSR)
|
||||
port->icount.dsr++;
|
||||
if (status_change & ATMEL_US_DCD)
|
||||
uart_handle_dcd_change(port, !(status & ATMEL_US_DCD));
|
||||
if (status_change & ATMEL_US_CTS)
|
||||
uart_handle_cts_change(port, !(status & ATMEL_US_CTS));
|
||||
|
||||
wake_up_interruptible(&port->state->port.delta_msr_wait);
|
||||
|
||||
atmel_port->status_change = 0;
|
||||
}
|
||||
|
||||
atmel_port->schedule_rx(port);
|
||||
spin_unlock(&port->lock);
|
||||
}
|
||||
|
||||
static void atmel_tasklet_tx_func(unsigned long data)
|
||||
{
|
||||
struct uart_port *port = (struct uart_port *)data;
|
||||
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
|
||||
|
||||
/* The interrupt handler does not take the lock */
|
||||
spin_lock(&port->lock);
|
||||
atmel_port->schedule_tx(port);
|
||||
spin_unlock(&port->lock);
|
||||
}
|
||||
|
||||
@ -1785,7 +1806,11 @@ static int atmel_startup(struct uart_port *port)
|
||||
return retval;
|
||||
}
|
||||
|
||||
tasklet_enable(&atmel_port->tasklet);
|
||||
atomic_set(&atmel_port->tasklet_shutdown, 0);
|
||||
tasklet_init(&atmel_port->tasklet_rx, atmel_tasklet_rx_func,
|
||||
(unsigned long)port);
|
||||
tasklet_init(&atmel_port->tasklet_tx, atmel_tasklet_tx_func,
|
||||
(unsigned long)port);
|
||||
|
||||
/*
|
||||
* Initialize DMA (if necessary)
|
||||
@ -1833,7 +1858,6 @@ static int atmel_startup(struct uart_port *port)
|
||||
|
||||
/* Save current CSR for comparison in atmel_tasklet_func() */
|
||||
atmel_port->irq_status_prev = atmel_get_lines_status(port);
|
||||
atmel_port->irq_status = atmel_port->irq_status_prev;
|
||||
|
||||
/*
|
||||
* Finally, enable the serial port
|
||||
@ -1905,29 +1929,36 @@ static void atmel_shutdown(struct uart_port *port)
|
||||
{
|
||||
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
|
||||
|
||||
/* Disable interrupts at device level */
|
||||
atmel_uart_writel(port, ATMEL_US_IDR, -1);
|
||||
|
||||
/* Prevent spurious interrupts from scheduling the tasklet */
|
||||
atomic_inc(&atmel_port->tasklet_shutdown);
|
||||
|
||||
/*
|
||||
* Prevent any tasklets being scheduled during
|
||||
* cleanup
|
||||
*/
|
||||
del_timer_sync(&atmel_port->uart_timer);
|
||||
|
||||
/* Make sure that no interrupt is on the fly */
|
||||
synchronize_irq(port->irq);
|
||||
|
||||
/*
|
||||
* Clear out any scheduled tasklets before
|
||||
* we destroy the buffers
|
||||
*/
|
||||
tasklet_disable(&atmel_port->tasklet);
|
||||
tasklet_kill(&atmel_port->tasklet);
|
||||
tasklet_kill(&atmel_port->tasklet_rx);
|
||||
tasklet_kill(&atmel_port->tasklet_tx);
|
||||
|
||||
/*
|
||||
* Ensure everything is stopped and
|
||||
* disable all interrupts, port and break condition.
|
||||
* disable port and break condition.
|
||||
*/
|
||||
atmel_stop_rx(port);
|
||||
atmel_stop_tx(port);
|
||||
|
||||
atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
|
||||
atmel_uart_writel(port, ATMEL_US_IDR, -1);
|
||||
|
||||
|
||||
/*
|
||||
* Shut-down the DMA.
|
||||
@ -2311,10 +2342,6 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port,
|
||||
port->irq = pdev->resource[1].start;
|
||||
port->rs485_config = atmel_config_rs485;
|
||||
|
||||
tasklet_init(&atmel_port->tasklet, atmel_tasklet_func,
|
||||
(unsigned long)port);
|
||||
tasklet_disable(&atmel_port->tasklet);
|
||||
|
||||
memset(&atmel_port->rx_ring, 0, sizeof(atmel_port->rx_ring));
|
||||
|
||||
if (pdata && pdata->regs) {
|
||||
@ -2699,6 +2726,7 @@ static int atmel_serial_probe(struct platform_device *pdev)
|
||||
atmel_port->uart.line = ret;
|
||||
atmel_serial_probe_fifos(atmel_port, pdev);
|
||||
|
||||
atomic_set(&atmel_port->tasklet_shutdown, 0);
|
||||
spin_lock_init(&atmel_port->lock_suspended);
|
||||
|
||||
ret = atmel_init_port(atmel_port, pdev);
|
||||
@ -2795,7 +2823,8 @@ static int atmel_serial_remove(struct platform_device *pdev)
|
||||
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
|
||||
int ret = 0;
|
||||
|
||||
tasklet_kill(&atmel_port->tasklet);
|
||||
tasklet_kill(&atmel_port->tasklet_rx);
|
||||
tasklet_kill(&atmel_port->tasklet_tx);
|
||||
|
||||
device_init_wakeup(&pdev->dev, 0);
|
||||
|
||||
|
@ -813,8 +813,12 @@ static int bcm_uart_probe(struct platform_device *pdev)
|
||||
struct clk *clk;
|
||||
int ret;
|
||||
|
||||
if (pdev->dev.of_node)
|
||||
pdev->id = of_alias_get_id(pdev->dev.of_node, "uart");
|
||||
if (pdev->dev.of_node) {
|
||||
pdev->id = of_alias_get_id(pdev->dev.of_node, "serial");
|
||||
|
||||
if (pdev->id < 0)
|
||||
pdev->id = of_alias_get_id(pdev->dev.of_node, "uart");
|
||||
}
|
||||
|
||||
if (pdev->id < 0 || pdev->id >= BCM63XX_NR_UARTS)
|
||||
return -EINVAL;
|
||||
|
@ -1830,7 +1830,13 @@ static int lpuart_probe(struct platform_device *pdev)
|
||||
sport->port.dev = &pdev->dev;
|
||||
sport->port.type = PORT_LPUART;
|
||||
sport->port.iotype = UPIO_MEM;
|
||||
sport->port.irq = platform_get_irq(pdev, 0);
|
||||
ret = platform_get_irq(pdev, 0);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "cannot obtain irq\n");
|
||||
return ret;
|
||||
}
|
||||
sport->port.irq = ret;
|
||||
|
||||
if (sport->lpuart32)
|
||||
sport->port.ops = &lpuart32_pops;
|
||||
else
|
||||
|
@ -30,7 +30,6 @@
|
||||
#define SUPPORT_SYSRQ
|
||||
#endif
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/ioport.h>
|
||||
@ -51,9 +50,6 @@
|
||||
|
||||
#define PASS_LIMIT 256
|
||||
|
||||
/* Standard COM flags */
|
||||
#define STD_COM_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST)
|
||||
|
||||
static const struct {
|
||||
unsigned int port;
|
||||
unsigned int irq;
|
||||
@ -892,7 +888,7 @@ static void __init m32r_sio_init_ports(void)
|
||||
up->port.iobase = old_serial_port[i].port;
|
||||
up->port.irq = irq_canonicalize(old_serial_port[i].irq);
|
||||
up->port.uartclk = BAUD_RATE * 16;
|
||||
up->port.flags = STD_COM_FLAGS;
|
||||
up->port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
|
||||
up->port.membase = 0;
|
||||
up->port.iotype = 0;
|
||||
up->port.regshift = 0;
|
||||
@ -1060,19 +1056,4 @@ static int __init m32r_sio_init(void)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit m32r_sio_exit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < UART_NR; i++)
|
||||
uart_remove_one_port(&m32r_sio_reg, &m32r_sio_ports[i].port);
|
||||
|
||||
uart_unregister_driver(&m32r_sio_reg);
|
||||
}
|
||||
|
||||
module_init(m32r_sio_init);
|
||||
module_exit(m32r_sio_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Generic M32R SIO serial driver");
|
||||
device_initcall(m32r_sio_init);
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Maxim (Dallas) MAX3107/8/9, MAX14830 serial driver
|
||||
*
|
||||
* Copyright (C) 2012-2014 Alexander Shiyan <shc_work@mail.ru>
|
||||
* Copyright (C) 2012-2016 Alexander Shiyan <shc_work@mail.ru>
|
||||
*
|
||||
* Based on max3100.c, by Christian Pellegrin <chripell@evolware.org>
|
||||
* Based on max3110.c, by Feng Tang <feng.tang@intel.com>
|
||||
@ -32,6 +32,7 @@
|
||||
#define MAX310X_NAME "max310x"
|
||||
#define MAX310X_MAJOR 204
|
||||
#define MAX310X_MINOR 209
|
||||
#define MAX310X_UART_NRMAX 16
|
||||
|
||||
/* MAX310X register definitions */
|
||||
#define MAX310X_RHR_REG (0x00) /* RX FIFO */
|
||||
@ -155,10 +156,6 @@
|
||||
#define MAX310X_LCR_FORCEPARITY_BIT (1 << 5) /* 9-bit multidrop parity */
|
||||
#define MAX310X_LCR_TXBREAK_BIT (1 << 6) /* TX break enable */
|
||||
#define MAX310X_LCR_RTS_BIT (1 << 7) /* RTS pin control */
|
||||
#define MAX310X_LCR_WORD_LEN_5 (0x00)
|
||||
#define MAX310X_LCR_WORD_LEN_6 (0x01)
|
||||
#define MAX310X_LCR_WORD_LEN_7 (0x02)
|
||||
#define MAX310X_LCR_WORD_LEN_8 (0x03)
|
||||
|
||||
/* IRDA register bits */
|
||||
#define MAX310X_IRDA_IRDAEN_BIT (1 << 0) /* IRDA mode enable */
|
||||
@ -262,10 +259,10 @@ struct max310x_one {
|
||||
struct uart_port port;
|
||||
struct work_struct tx_work;
|
||||
struct work_struct md_work;
|
||||
struct work_struct rs_work;
|
||||
};
|
||||
|
||||
struct max310x_port {
|
||||
struct uart_driver uart;
|
||||
struct max310x_devtype *devtype;
|
||||
struct regmap *regmap;
|
||||
struct mutex mutex;
|
||||
@ -276,6 +273,17 @@ struct max310x_port {
|
||||
struct max310x_one p[0];
|
||||
};
|
||||
|
||||
static struct uart_driver max310x_uart = {
|
||||
.owner = THIS_MODULE,
|
||||
.driver_name = MAX310X_NAME,
|
||||
.dev_name = "ttyMAX",
|
||||
.major = MAX310X_MAJOR,
|
||||
.minor = MAX310X_MINOR,
|
||||
.nr = MAX310X_UART_NRMAX,
|
||||
};
|
||||
|
||||
static DECLARE_BITMAP(max310x_lines, MAX310X_UART_NRMAX);
|
||||
|
||||
static u8 max310x_port_read(struct uart_port *port, u8 reg)
|
||||
{
|
||||
struct max310x_port *s = dev_get_drvdata(port->dev);
|
||||
@ -594,9 +602,7 @@ static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen)
|
||||
unsigned int sts, ch, flag;
|
||||
|
||||
if (unlikely(rxlen >= port->fifosize)) {
|
||||
dev_warn_ratelimited(port->dev,
|
||||
"Port %i: Possible RX FIFO overrun\n",
|
||||
port->line);
|
||||
dev_warn_ratelimited(port->dev, "Possible RX FIFO overrun\n");
|
||||
port->icount.buf_overrun++;
|
||||
/* Ensure sanity of RX level */
|
||||
rxlen = port->fifosize;
|
||||
@ -715,13 +721,13 @@ static irqreturn_t max310x_ist(int irq, void *dev_id)
|
||||
{
|
||||
struct max310x_port *s = (struct max310x_port *)dev_id;
|
||||
|
||||
if (s->uart.nr > 1) {
|
||||
if (s->devtype->nr > 1) {
|
||||
do {
|
||||
unsigned int val = ~0;
|
||||
|
||||
WARN_ON_ONCE(regmap_read(s->regmap,
|
||||
MAX310X_GLOBALIRQ_REG, &val));
|
||||
val = ((1 << s->uart.nr) - 1) & ~val;
|
||||
val = ((1 << s->devtype->nr) - 1) & ~val;
|
||||
if (!val)
|
||||
break;
|
||||
max310x_port_irq(s, fls(val) - 1);
|
||||
@ -796,7 +802,7 @@ static void max310x_set_termios(struct uart_port *port,
|
||||
struct ktermios *termios,
|
||||
struct ktermios *old)
|
||||
{
|
||||
unsigned int lcr, flow = 0;
|
||||
unsigned int lcr = 0, flow = 0;
|
||||
int baud;
|
||||
|
||||
/* Mask termios capabilities we don't support */
|
||||
@ -805,17 +811,16 @@ static void max310x_set_termios(struct uart_port *port,
|
||||
/* Word size */
|
||||
switch (termios->c_cflag & CSIZE) {
|
||||
case CS5:
|
||||
lcr = MAX310X_LCR_WORD_LEN_5;
|
||||
break;
|
||||
case CS6:
|
||||
lcr = MAX310X_LCR_WORD_LEN_6;
|
||||
lcr = MAX310X_LCR_LENGTH0_BIT;
|
||||
break;
|
||||
case CS7:
|
||||
lcr = MAX310X_LCR_WORD_LEN_7;
|
||||
lcr = MAX310X_LCR_LENGTH1_BIT;
|
||||
break;
|
||||
case CS8:
|
||||
default:
|
||||
lcr = MAX310X_LCR_WORD_LEN_8;
|
||||
lcr = MAX310X_LCR_LENGTH1_BIT | MAX310X_LCR_LENGTH0_BIT;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -877,36 +882,45 @@ static void max310x_set_termios(struct uart_port *port,
|
||||
uart_update_timeout(port, termios->c_cflag, baud);
|
||||
}
|
||||
|
||||
static int max310x_rs485_config(struct uart_port *port,
|
||||
struct serial_rs485 *rs485)
|
||||
static void max310x_rs_proc(struct work_struct *ws)
|
||||
{
|
||||
struct max310x_one *one = container_of(ws, struct max310x_one, rs_work);
|
||||
unsigned int val;
|
||||
|
||||
if (rs485->delay_rts_before_send > 0x0f ||
|
||||
rs485->delay_rts_after_send > 0x0f)
|
||||
return -ERANGE;
|
||||
val = (one->port.rs485.delay_rts_before_send << 4) |
|
||||
one->port.rs485.delay_rts_after_send;
|
||||
max310x_port_write(&one->port, MAX310X_HDPIXDELAY_REG, val);
|
||||
|
||||
val = (rs485->delay_rts_before_send << 4) |
|
||||
rs485->delay_rts_after_send;
|
||||
max310x_port_write(port, MAX310X_HDPIXDELAY_REG, val);
|
||||
if (rs485->flags & SER_RS485_ENABLED) {
|
||||
max310x_port_update(port, MAX310X_MODE1_REG,
|
||||
if (one->port.rs485.flags & SER_RS485_ENABLED) {
|
||||
max310x_port_update(&one->port, MAX310X_MODE1_REG,
|
||||
MAX310X_MODE1_TRNSCVCTRL_BIT,
|
||||
MAX310X_MODE1_TRNSCVCTRL_BIT);
|
||||
max310x_port_update(port, MAX310X_MODE2_REG,
|
||||
max310x_port_update(&one->port, MAX310X_MODE2_REG,
|
||||
MAX310X_MODE2_ECHOSUPR_BIT,
|
||||
MAX310X_MODE2_ECHOSUPR_BIT);
|
||||
} else {
|
||||
max310x_port_update(port, MAX310X_MODE1_REG,
|
||||
max310x_port_update(&one->port, MAX310X_MODE1_REG,
|
||||
MAX310X_MODE1_TRNSCVCTRL_BIT, 0);
|
||||
max310x_port_update(port, MAX310X_MODE2_REG,
|
||||
max310x_port_update(&one->port, MAX310X_MODE2_REG,
|
||||
MAX310X_MODE2_ECHOSUPR_BIT, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static int max310x_rs485_config(struct uart_port *port,
|
||||
struct serial_rs485 *rs485)
|
||||
{
|
||||
struct max310x_one *one = container_of(port, struct max310x_one, port);
|
||||
|
||||
if ((rs485->delay_rts_before_send > 0x0f) ||
|
||||
(rs485->delay_rts_after_send > 0x0f))
|
||||
return -ERANGE;
|
||||
|
||||
rs485->flags &= SER_RS485_RTS_ON_SEND | SER_RS485_ENABLED;
|
||||
memset(rs485->padding, 0, sizeof(rs485->padding));
|
||||
port->rs485 = *rs485;
|
||||
|
||||
schedule_work(&one->rs_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1009,8 +1023,8 @@ static int __maybe_unused max310x_suspend(struct device *dev)
|
||||
struct max310x_port *s = dev_get_drvdata(dev);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < s->uart.nr; i++) {
|
||||
uart_suspend_port(&s->uart, &s->p[i].port);
|
||||
for (i = 0; i < s->devtype->nr; i++) {
|
||||
uart_suspend_port(&max310x_uart, &s->p[i].port);
|
||||
s->devtype->power(&s->p[i].port, 0);
|
||||
}
|
||||
|
||||
@ -1022,9 +1036,9 @@ static int __maybe_unused max310x_resume(struct device *dev)
|
||||
struct max310x_port *s = dev_get_drvdata(dev);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < s->uart.nr; i++) {
|
||||
for (i = 0; i < s->devtype->nr; i++) {
|
||||
s->devtype->power(&s->p[i].port, 1);
|
||||
uart_resume_port(&s->uart, &s->p[i].port);
|
||||
uart_resume_port(&max310x_uart, &s->p[i].port);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1159,18 +1173,6 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
|
||||
uartclk = max310x_set_ref_clk(s, freq, xtal);
|
||||
dev_dbg(dev, "Reference clock set to %i Hz\n", uartclk);
|
||||
|
||||
/* Register UART driver */
|
||||
s->uart.owner = THIS_MODULE;
|
||||
s->uart.dev_name = "ttyMAX";
|
||||
s->uart.major = MAX310X_MAJOR;
|
||||
s->uart.minor = MAX310X_MINOR;
|
||||
s->uart.nr = devtype->nr;
|
||||
ret = uart_register_driver(&s->uart);
|
||||
if (ret) {
|
||||
dev_err(dev, "Registering UART driver failed\n");
|
||||
goto out_clk;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_GPIOLIB
|
||||
/* Setup GPIO cotroller */
|
||||
s->gpio.owner = THIS_MODULE;
|
||||
@ -1183,16 +1185,24 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
|
||||
s->gpio.base = -1;
|
||||
s->gpio.ngpio = devtype->nr * 4;
|
||||
s->gpio.can_sleep = 1;
|
||||
ret = gpiochip_add_data(&s->gpio, s);
|
||||
ret = devm_gpiochip_add_data(dev, &s->gpio, s);
|
||||
if (ret)
|
||||
goto out_uart;
|
||||
goto out_clk;
|
||||
#endif
|
||||
|
||||
mutex_init(&s->mutex);
|
||||
|
||||
for (i = 0; i < devtype->nr; i++) {
|
||||
unsigned int line;
|
||||
|
||||
line = find_first_zero_bit(max310x_lines, MAX310X_UART_NRMAX);
|
||||
if (line == MAX310X_UART_NRMAX) {
|
||||
ret = -ERANGE;
|
||||
goto out_uart;
|
||||
}
|
||||
|
||||
/* Initialize port data */
|
||||
s->p[i].port.line = i;
|
||||
s->p[i].port.line = line;
|
||||
s->p[i].port.dev = dev;
|
||||
s->p[i].port.irq = irq;
|
||||
s->p[i].port.type = PORT_MAX310X;
|
||||
@ -1214,10 +1224,19 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
|
||||
MAX310X_MODE1_IRQSEL_BIT);
|
||||
/* Initialize queue for start TX */
|
||||
INIT_WORK(&s->p[i].tx_work, max310x_wq_proc);
|
||||
/* Initialize queue for changing mode */
|
||||
/* Initialize queue for changing LOOPBACK mode */
|
||||
INIT_WORK(&s->p[i].md_work, max310x_md_proc);
|
||||
/* Initialize queue for changing RS485 mode */
|
||||
INIT_WORK(&s->p[i].rs_work, max310x_rs_proc);
|
||||
|
||||
/* Register port */
|
||||
uart_add_one_port(&s->uart, &s->p[i].port);
|
||||
ret = uart_add_one_port(&max310x_uart, &s->p[i].port);
|
||||
if (ret) {
|
||||
s->p[i].port.dev = NULL;
|
||||
goto out_uart;
|
||||
}
|
||||
set_bit(line, max310x_lines);
|
||||
|
||||
/* Go to suspend mode */
|
||||
devtype->power(&s->p[i].port, 0);
|
||||
}
|
||||
@ -1230,14 +1249,15 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
|
||||
|
||||
dev_err(dev, "Unable to reguest IRQ %i\n", irq);
|
||||
|
||||
mutex_destroy(&s->mutex);
|
||||
|
||||
#ifdef CONFIG_GPIOLIB
|
||||
gpiochip_remove(&s->gpio);
|
||||
|
||||
out_uart:
|
||||
#endif
|
||||
uart_unregister_driver(&s->uart);
|
||||
for (i = 0; i < devtype->nr; i++) {
|
||||
if (s->p[i].port.dev) {
|
||||
uart_remove_one_port(&max310x_uart, &s->p[i].port);
|
||||
clear_bit(s->p[i].port.line, max310x_lines);
|
||||
}
|
||||
}
|
||||
|
||||
mutex_destroy(&s->mutex);
|
||||
|
||||
out_clk:
|
||||
clk_disable_unprepare(s->clk);
|
||||
@ -1250,19 +1270,16 @@ static int max310x_remove(struct device *dev)
|
||||
struct max310x_port *s = dev_get_drvdata(dev);
|
||||
int i;
|
||||
|
||||
#ifdef CONFIG_GPIOLIB
|
||||
gpiochip_remove(&s->gpio);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < s->uart.nr; i++) {
|
||||
for (i = 0; i < s->devtype->nr; i++) {
|
||||
cancel_work_sync(&s->p[i].tx_work);
|
||||
cancel_work_sync(&s->p[i].md_work);
|
||||
uart_remove_one_port(&s->uart, &s->p[i].port);
|
||||
cancel_work_sync(&s->p[i].rs_work);
|
||||
uart_remove_one_port(&max310x_uart, &s->p[i].port);
|
||||
clear_bit(s->p[i].port.line, max310x_lines);
|
||||
s->devtype->power(&s->p[i].port, 0);
|
||||
}
|
||||
|
||||
mutex_destroy(&s->mutex);
|
||||
uart_unregister_driver(&s->uart);
|
||||
clk_disable_unprepare(s->clk);
|
||||
|
||||
return 0;
|
||||
@ -1335,7 +1352,7 @@ static const struct spi_device_id max310x_id_table[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, max310x_id_table);
|
||||
|
||||
static struct spi_driver max310x_uart_driver = {
|
||||
static struct spi_driver max310x_spi_driver = {
|
||||
.driver = {
|
||||
.name = MAX310X_NAME,
|
||||
.of_match_table = of_match_ptr(max310x_dt_ids),
|
||||
@ -1345,9 +1362,36 @@ static struct spi_driver max310x_uart_driver = {
|
||||
.remove = max310x_spi_remove,
|
||||
.id_table = max310x_id_table,
|
||||
};
|
||||
module_spi_driver(max310x_uart_driver);
|
||||
#endif
|
||||
|
||||
static int __init max310x_uart_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
bitmap_zero(max310x_lines, MAX310X_UART_NRMAX);
|
||||
|
||||
ret = uart_register_driver(&max310x_uart);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
#ifdef CONFIG_SPI_MASTER
|
||||
spi_register_driver(&max310x_spi_driver);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
module_init(max310x_uart_init);
|
||||
|
||||
static void __exit max310x_uart_exit(void)
|
||||
{
|
||||
#ifdef CONFIG_SPI_MASTER
|
||||
spi_unregister_driver(&max310x_spi_driver);
|
||||
#endif
|
||||
|
||||
uart_unregister_driver(&max310x_uart);
|
||||
}
|
||||
module_exit(max310x_uart_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>");
|
||||
MODULE_DESCRIPTION("MAX310X serial driver");
|
||||
|
@ -1,4 +1,6 @@
|
||||
/*
|
||||
* MPS2 UART driver
|
||||
*
|
||||
* Copyright (C) 2015 ARM Limited
|
||||
*
|
||||
* Author: Vladimir Murzin <vladimir.murzin@arm.com>
|
||||
@ -17,7 +19,6 @@
|
||||
#include <linux/console.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
@ -569,30 +570,20 @@ static int mps2_serial_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mps2_serial_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct mps2_uart_port *mps_port = platform_get_drvdata(pdev);
|
||||
|
||||
uart_remove_one_port(&mps2_uart_driver, &mps_port->port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id mps2_match[] = {
|
||||
{ .compatible = "arm,mps2-uart", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mps2_match);
|
||||
#endif
|
||||
|
||||
static struct platform_driver mps2_serial_driver = {
|
||||
.probe = mps2_serial_probe,
|
||||
.remove = mps2_serial_remove,
|
||||
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.of_match_table = of_match_ptr(mps2_match),
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
};
|
||||
|
||||
@ -610,16 +601,4 @@ static int __init mps2_uart_init(void)
|
||||
|
||||
return ret;
|
||||
}
|
||||
module_init(mps2_uart_init);
|
||||
|
||||
static void __exit mps2_uart_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&mps2_serial_driver);
|
||||
uart_unregister_driver(&mps2_uart_driver);
|
||||
}
|
||||
module_exit(mps2_uart_exit);
|
||||
|
||||
MODULE_AUTHOR("Vladimir Murzin <vladimir.murzin@arm.com>");
|
||||
MODULE_DESCRIPTION("MPS2 UART driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_ALIAS("platform:" DRIVER_NAME);
|
||||
arch_initcall(mps2_uart_init);
|
||||
|
@ -19,33 +19,147 @@
|
||||
# define SUPPORT_SYSRQ
|
||||
#endif
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/hrtimer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/wait.h>
|
||||
|
||||
#include "msm_serial.h"
|
||||
#define UART_MR1 0x0000
|
||||
|
||||
#define UARTDM_BURST_SIZE 16 /* in bytes */
|
||||
#define UARTDM_TX_AIGN(x) ((x) & ~0x3) /* valid for > 1p3 */
|
||||
#define UARTDM_TX_MAX 256 /* in bytes, valid for <= 1p3 */
|
||||
#define UARTDM_RX_SIZE (UART_XMIT_SIZE / 4)
|
||||
#define UART_MR1_AUTO_RFR_LEVEL0 0x3F
|
||||
#define UART_MR1_AUTO_RFR_LEVEL1 0x3FF00
|
||||
#define UART_DM_MR1_AUTO_RFR_LEVEL1 0xFFFFFF00
|
||||
#define UART_MR1_RX_RDY_CTL BIT(7)
|
||||
#define UART_MR1_CTS_CTL BIT(6)
|
||||
|
||||
#define UART_MR2 0x0004
|
||||
#define UART_MR2_ERROR_MODE BIT(6)
|
||||
#define UART_MR2_BITS_PER_CHAR 0x30
|
||||
#define UART_MR2_BITS_PER_CHAR_5 (0x0 << 4)
|
||||
#define UART_MR2_BITS_PER_CHAR_6 (0x1 << 4)
|
||||
#define UART_MR2_BITS_PER_CHAR_7 (0x2 << 4)
|
||||
#define UART_MR2_BITS_PER_CHAR_8 (0x3 << 4)
|
||||
#define UART_MR2_STOP_BIT_LEN_ONE (0x1 << 2)
|
||||
#define UART_MR2_STOP_BIT_LEN_TWO (0x3 << 2)
|
||||
#define UART_MR2_PARITY_MODE_NONE 0x0
|
||||
#define UART_MR2_PARITY_MODE_ODD 0x1
|
||||
#define UART_MR2_PARITY_MODE_EVEN 0x2
|
||||
#define UART_MR2_PARITY_MODE_SPACE 0x3
|
||||
#define UART_MR2_PARITY_MODE 0x3
|
||||
|
||||
#define UART_CSR 0x0008
|
||||
|
||||
#define UART_TF 0x000C
|
||||
#define UARTDM_TF 0x0070
|
||||
|
||||
#define UART_CR 0x0010
|
||||
#define UART_CR_CMD_NULL (0 << 4)
|
||||
#define UART_CR_CMD_RESET_RX (1 << 4)
|
||||
#define UART_CR_CMD_RESET_TX (2 << 4)
|
||||
#define UART_CR_CMD_RESET_ERR (3 << 4)
|
||||
#define UART_CR_CMD_RESET_BREAK_INT (4 << 4)
|
||||
#define UART_CR_CMD_START_BREAK (5 << 4)
|
||||
#define UART_CR_CMD_STOP_BREAK (6 << 4)
|
||||
#define UART_CR_CMD_RESET_CTS (7 << 4)
|
||||
#define UART_CR_CMD_RESET_STALE_INT (8 << 4)
|
||||
#define UART_CR_CMD_PACKET_MODE (9 << 4)
|
||||
#define UART_CR_CMD_MODE_RESET (12 << 4)
|
||||
#define UART_CR_CMD_SET_RFR (13 << 4)
|
||||
#define UART_CR_CMD_RESET_RFR (14 << 4)
|
||||
#define UART_CR_CMD_PROTECTION_EN (16 << 4)
|
||||
#define UART_CR_CMD_STALE_EVENT_DISABLE (6 << 8)
|
||||
#define UART_CR_CMD_STALE_EVENT_ENABLE (80 << 4)
|
||||
#define UART_CR_CMD_FORCE_STALE (4 << 8)
|
||||
#define UART_CR_CMD_RESET_TX_READY (3 << 8)
|
||||
#define UART_CR_TX_DISABLE BIT(3)
|
||||
#define UART_CR_TX_ENABLE BIT(2)
|
||||
#define UART_CR_RX_DISABLE BIT(1)
|
||||
#define UART_CR_RX_ENABLE BIT(0)
|
||||
#define UART_CR_CMD_RESET_RXBREAK_START ((1 << 11) | (2 << 4))
|
||||
|
||||
#define UART_IMR 0x0014
|
||||
#define UART_IMR_TXLEV BIT(0)
|
||||
#define UART_IMR_RXSTALE BIT(3)
|
||||
#define UART_IMR_RXLEV BIT(4)
|
||||
#define UART_IMR_DELTA_CTS BIT(5)
|
||||
#define UART_IMR_CURRENT_CTS BIT(6)
|
||||
#define UART_IMR_RXBREAK_START BIT(10)
|
||||
|
||||
#define UART_IPR_RXSTALE_LAST 0x20
|
||||
#define UART_IPR_STALE_LSB 0x1F
|
||||
#define UART_IPR_STALE_TIMEOUT_MSB 0x3FF80
|
||||
#define UART_DM_IPR_STALE_TIMEOUT_MSB 0xFFFFFF80
|
||||
|
||||
#define UART_IPR 0x0018
|
||||
#define UART_TFWR 0x001C
|
||||
#define UART_RFWR 0x0020
|
||||
#define UART_HCR 0x0024
|
||||
|
||||
#define UART_MREG 0x0028
|
||||
#define UART_NREG 0x002C
|
||||
#define UART_DREG 0x0030
|
||||
#define UART_MNDREG 0x0034
|
||||
#define UART_IRDA 0x0038
|
||||
#define UART_MISR_MODE 0x0040
|
||||
#define UART_MISR_RESET 0x0044
|
||||
#define UART_MISR_EXPORT 0x0048
|
||||
#define UART_MISR_VAL 0x004C
|
||||
#define UART_TEST_CTRL 0x0050
|
||||
|
||||
#define UART_SR 0x0008
|
||||
#define UART_SR_HUNT_CHAR BIT(7)
|
||||
#define UART_SR_RX_BREAK BIT(6)
|
||||
#define UART_SR_PAR_FRAME_ERR BIT(5)
|
||||
#define UART_SR_OVERRUN BIT(4)
|
||||
#define UART_SR_TX_EMPTY BIT(3)
|
||||
#define UART_SR_TX_READY BIT(2)
|
||||
#define UART_SR_RX_FULL BIT(1)
|
||||
#define UART_SR_RX_READY BIT(0)
|
||||
|
||||
#define UART_RF 0x000C
|
||||
#define UARTDM_RF 0x0070
|
||||
#define UART_MISR 0x0010
|
||||
#define UART_ISR 0x0014
|
||||
#define UART_ISR_TX_READY BIT(7)
|
||||
|
||||
#define UARTDM_RXFS 0x50
|
||||
#define UARTDM_RXFS_BUF_SHIFT 0x7
|
||||
#define UARTDM_RXFS_BUF_MASK 0x7
|
||||
|
||||
#define UARTDM_DMEN 0x3C
|
||||
#define UARTDM_DMEN_RX_SC_ENABLE BIT(5)
|
||||
#define UARTDM_DMEN_TX_SC_ENABLE BIT(4)
|
||||
|
||||
#define UARTDM_DMEN_TX_BAM_ENABLE BIT(2) /* UARTDM_1P4 */
|
||||
#define UARTDM_DMEN_TX_DM_ENABLE BIT(0) /* < UARTDM_1P4 */
|
||||
|
||||
#define UARTDM_DMEN_RX_BAM_ENABLE BIT(3) /* UARTDM_1P4 */
|
||||
#define UARTDM_DMEN_RX_DM_ENABLE BIT(1) /* < UARTDM_1P4 */
|
||||
|
||||
#define UARTDM_DMRX 0x34
|
||||
#define UARTDM_NCF_TX 0x40
|
||||
#define UARTDM_RX_TOTAL_SNAP 0x38
|
||||
|
||||
#define UARTDM_BURST_SIZE 16 /* in bytes */
|
||||
#define UARTDM_TX_AIGN(x) ((x) & ~0x3) /* valid for > 1p3 */
|
||||
#define UARTDM_TX_MAX 256 /* in bytes, valid for <= 1p3 */
|
||||
#define UARTDM_RX_SIZE (UART_XMIT_SIZE / 4)
|
||||
|
||||
enum {
|
||||
UARTDM_1P1 = 1,
|
||||
@ -78,10 +192,65 @@ struct msm_port {
|
||||
struct msm_dma rx_dma;
|
||||
};
|
||||
|
||||
#define UART_TO_MSM(uart_port) container_of(uart_port, struct msm_port, uart)
|
||||
|
||||
static
|
||||
void msm_write(struct uart_port *port, unsigned int val, unsigned int off)
|
||||
{
|
||||
writel_relaxed(val, port->membase + off);
|
||||
}
|
||||
|
||||
static
|
||||
unsigned int msm_read(struct uart_port *port, unsigned int off)
|
||||
{
|
||||
return readl_relaxed(port->membase + off);
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup the MND registers to use the TCXO clock.
|
||||
*/
|
||||
static void msm_serial_set_mnd_regs_tcxo(struct uart_port *port)
|
||||
{
|
||||
msm_write(port, 0x06, UART_MREG);
|
||||
msm_write(port, 0xF1, UART_NREG);
|
||||
msm_write(port, 0x0F, UART_DREG);
|
||||
msm_write(port, 0x1A, UART_MNDREG);
|
||||
port->uartclk = 1843200;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup the MND registers to use the TCXO clock divided by 4.
|
||||
*/
|
||||
static void msm_serial_set_mnd_regs_tcxoby4(struct uart_port *port)
|
||||
{
|
||||
msm_write(port, 0x18, UART_MREG);
|
||||
msm_write(port, 0xF6, UART_NREG);
|
||||
msm_write(port, 0x0F, UART_DREG);
|
||||
msm_write(port, 0x0A, UART_MNDREG);
|
||||
port->uartclk = 1843200;
|
||||
}
|
||||
|
||||
static void msm_serial_set_mnd_regs(struct uart_port *port)
|
||||
{
|
||||
struct msm_port *msm_port = UART_TO_MSM(port);
|
||||
|
||||
/*
|
||||
* These registers don't exist so we change the clk input rate
|
||||
* on uartdm hardware instead
|
||||
*/
|
||||
if (msm_port->is_uartdm)
|
||||
return;
|
||||
|
||||
if (port->uartclk == 19200000)
|
||||
msm_serial_set_mnd_regs_tcxo(port);
|
||||
else if (port->uartclk == 4800000)
|
||||
msm_serial_set_mnd_regs_tcxoby4(port);
|
||||
}
|
||||
|
||||
static void msm_handle_tx(struct uart_port *port);
|
||||
static void msm_start_rx_dma(struct msm_port *msm_port);
|
||||
|
||||
void msm_stop_dma(struct uart_port *port, struct msm_dma *dma)
|
||||
static void msm_stop_dma(struct uart_port *port, struct msm_dma *dma)
|
||||
{
|
||||
struct device *dev = port->dev;
|
||||
unsigned int mapped;
|
||||
@ -388,10 +557,6 @@ static void msm_complete_rx_dma(void *args)
|
||||
val &= ~dma->enable_bit;
|
||||
msm_write(port, val, UARTDM_DMEN);
|
||||
|
||||
/* Restore interrupts */
|
||||
msm_port->imr |= UART_IMR_RXLEV | UART_IMR_RXSTALE;
|
||||
msm_write(port, msm_port->imr, UART_IMR);
|
||||
|
||||
if (msm_read(port, UART_SR) & UART_SR_OVERRUN) {
|
||||
port->icount.overrun++;
|
||||
tty_insert_flip_char(tport, 0, TTY_OVERRUN);
|
||||
@ -726,7 +891,7 @@ static void msm_handle_tx(struct uart_port *port)
|
||||
return;
|
||||
}
|
||||
|
||||
pio_count = CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE);
|
||||
pio_count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
|
||||
dma_count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
|
||||
|
||||
dma_min = 1; /* Always DMA */
|
||||
|
@ -1,184 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 Google, Inc.
|
||||
* Author: Robert Love <rlove@google.com>
|
||||
* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __DRIVERS_SERIAL_MSM_SERIAL_H
|
||||
#define __DRIVERS_SERIAL_MSM_SERIAL_H
|
||||
|
||||
#define UART_MR1 0x0000
|
||||
|
||||
#define UART_MR1_AUTO_RFR_LEVEL0 0x3F
|
||||
#define UART_MR1_AUTO_RFR_LEVEL1 0x3FF00
|
||||
#define UART_DM_MR1_AUTO_RFR_LEVEL1 0xFFFFFF00
|
||||
#define UART_MR1_RX_RDY_CTL BIT(7)
|
||||
#define UART_MR1_CTS_CTL BIT(6)
|
||||
|
||||
#define UART_MR2 0x0004
|
||||
#define UART_MR2_ERROR_MODE BIT(6)
|
||||
#define UART_MR2_BITS_PER_CHAR 0x30
|
||||
#define UART_MR2_BITS_PER_CHAR_5 (0x0 << 4)
|
||||
#define UART_MR2_BITS_PER_CHAR_6 (0x1 << 4)
|
||||
#define UART_MR2_BITS_PER_CHAR_7 (0x2 << 4)
|
||||
#define UART_MR2_BITS_PER_CHAR_8 (0x3 << 4)
|
||||
#define UART_MR2_STOP_BIT_LEN_ONE (0x1 << 2)
|
||||
#define UART_MR2_STOP_BIT_LEN_TWO (0x3 << 2)
|
||||
#define UART_MR2_PARITY_MODE_NONE 0x0
|
||||
#define UART_MR2_PARITY_MODE_ODD 0x1
|
||||
#define UART_MR2_PARITY_MODE_EVEN 0x2
|
||||
#define UART_MR2_PARITY_MODE_SPACE 0x3
|
||||
#define UART_MR2_PARITY_MODE 0x3
|
||||
|
||||
#define UART_CSR 0x0008
|
||||
|
||||
#define UART_TF 0x000C
|
||||
#define UARTDM_TF 0x0070
|
||||
|
||||
#define UART_CR 0x0010
|
||||
#define UART_CR_CMD_NULL (0 << 4)
|
||||
#define UART_CR_CMD_RESET_RX (1 << 4)
|
||||
#define UART_CR_CMD_RESET_TX (2 << 4)
|
||||
#define UART_CR_CMD_RESET_ERR (3 << 4)
|
||||
#define UART_CR_CMD_RESET_BREAK_INT (4 << 4)
|
||||
#define UART_CR_CMD_START_BREAK (5 << 4)
|
||||
#define UART_CR_CMD_STOP_BREAK (6 << 4)
|
||||
#define UART_CR_CMD_RESET_CTS (7 << 4)
|
||||
#define UART_CR_CMD_RESET_STALE_INT (8 << 4)
|
||||
#define UART_CR_CMD_PACKET_MODE (9 << 4)
|
||||
#define UART_CR_CMD_MODE_RESET (12 << 4)
|
||||
#define UART_CR_CMD_SET_RFR (13 << 4)
|
||||
#define UART_CR_CMD_RESET_RFR (14 << 4)
|
||||
#define UART_CR_CMD_PROTECTION_EN (16 << 4)
|
||||
#define UART_CR_CMD_STALE_EVENT_DISABLE (6 << 8)
|
||||
#define UART_CR_CMD_STALE_EVENT_ENABLE (80 << 4)
|
||||
#define UART_CR_CMD_FORCE_STALE (4 << 8)
|
||||
#define UART_CR_CMD_RESET_TX_READY (3 << 8)
|
||||
#define UART_CR_TX_DISABLE BIT(3)
|
||||
#define UART_CR_TX_ENABLE BIT(2)
|
||||
#define UART_CR_RX_DISABLE BIT(1)
|
||||
#define UART_CR_RX_ENABLE BIT(0)
|
||||
#define UART_CR_CMD_RESET_RXBREAK_START ((1 << 11) | (2 << 4))
|
||||
|
||||
#define UART_IMR 0x0014
|
||||
#define UART_IMR_TXLEV BIT(0)
|
||||
#define UART_IMR_RXSTALE BIT(3)
|
||||
#define UART_IMR_RXLEV BIT(4)
|
||||
#define UART_IMR_DELTA_CTS BIT(5)
|
||||
#define UART_IMR_CURRENT_CTS BIT(6)
|
||||
#define UART_IMR_RXBREAK_START BIT(10)
|
||||
|
||||
#define UART_IPR_RXSTALE_LAST 0x20
|
||||
#define UART_IPR_STALE_LSB 0x1F
|
||||
#define UART_IPR_STALE_TIMEOUT_MSB 0x3FF80
|
||||
#define UART_DM_IPR_STALE_TIMEOUT_MSB 0xFFFFFF80
|
||||
|
||||
#define UART_IPR 0x0018
|
||||
#define UART_TFWR 0x001C
|
||||
#define UART_RFWR 0x0020
|
||||
#define UART_HCR 0x0024
|
||||
|
||||
#define UART_MREG 0x0028
|
||||
#define UART_NREG 0x002C
|
||||
#define UART_DREG 0x0030
|
||||
#define UART_MNDREG 0x0034
|
||||
#define UART_IRDA 0x0038
|
||||
#define UART_MISR_MODE 0x0040
|
||||
#define UART_MISR_RESET 0x0044
|
||||
#define UART_MISR_EXPORT 0x0048
|
||||
#define UART_MISR_VAL 0x004C
|
||||
#define UART_TEST_CTRL 0x0050
|
||||
|
||||
#define UART_SR 0x0008
|
||||
#define UART_SR_HUNT_CHAR BIT(7)
|
||||
#define UART_SR_RX_BREAK BIT(6)
|
||||
#define UART_SR_PAR_FRAME_ERR BIT(5)
|
||||
#define UART_SR_OVERRUN BIT(4)
|
||||
#define UART_SR_TX_EMPTY BIT(3)
|
||||
#define UART_SR_TX_READY BIT(2)
|
||||
#define UART_SR_RX_FULL BIT(1)
|
||||
#define UART_SR_RX_READY BIT(0)
|
||||
|
||||
#define UART_RF 0x000C
|
||||
#define UARTDM_RF 0x0070
|
||||
#define UART_MISR 0x0010
|
||||
#define UART_ISR 0x0014
|
||||
#define UART_ISR_TX_READY BIT(7)
|
||||
|
||||
#define UARTDM_RXFS 0x50
|
||||
#define UARTDM_RXFS_BUF_SHIFT 0x7
|
||||
#define UARTDM_RXFS_BUF_MASK 0x7
|
||||
|
||||
#define UARTDM_DMEN 0x3C
|
||||
#define UARTDM_DMEN_RX_SC_ENABLE BIT(5)
|
||||
#define UARTDM_DMEN_TX_SC_ENABLE BIT(4)
|
||||
|
||||
#define UARTDM_DMEN_TX_BAM_ENABLE BIT(2) /* UARTDM_1P4 */
|
||||
#define UARTDM_DMEN_TX_DM_ENABLE BIT(0) /* < UARTDM_1P4 */
|
||||
|
||||
#define UARTDM_DMEN_RX_BAM_ENABLE BIT(3) /* UARTDM_1P4 */
|
||||
#define UARTDM_DMEN_RX_DM_ENABLE BIT(1) /* < UARTDM_1P4 */
|
||||
|
||||
#define UARTDM_DMRX 0x34
|
||||
#define UARTDM_NCF_TX 0x40
|
||||
#define UARTDM_RX_TOTAL_SNAP 0x38
|
||||
|
||||
#define UART_TO_MSM(uart_port) ((struct msm_port *) uart_port)
|
||||
|
||||
static inline
|
||||
void msm_write(struct uart_port *port, unsigned int val, unsigned int off)
|
||||
{
|
||||
writel_relaxed(val, port->membase + off);
|
||||
}
|
||||
|
||||
static inline
|
||||
unsigned int msm_read(struct uart_port *port, unsigned int off)
|
||||
{
|
||||
return readl_relaxed(port->membase + off);
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup the MND registers to use the TCXO clock.
|
||||
*/
|
||||
static inline void msm_serial_set_mnd_regs_tcxo(struct uart_port *port)
|
||||
{
|
||||
msm_write(port, 0x06, UART_MREG);
|
||||
msm_write(port, 0xF1, UART_NREG);
|
||||
msm_write(port, 0x0F, UART_DREG);
|
||||
msm_write(port, 0x1A, UART_MNDREG);
|
||||
port->uartclk = 1843200;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup the MND registers to use the TCXO clock divided by 4.
|
||||
*/
|
||||
static inline void msm_serial_set_mnd_regs_tcxoby4(struct uart_port *port)
|
||||
{
|
||||
msm_write(port, 0x18, UART_MREG);
|
||||
msm_write(port, 0xF6, UART_NREG);
|
||||
msm_write(port, 0x0F, UART_DREG);
|
||||
msm_write(port, 0x0A, UART_MNDREG);
|
||||
port->uartclk = 1843200;
|
||||
}
|
||||
|
||||
static inline
|
||||
void msm_serial_set_mnd_regs_from_uartclk(struct uart_port *port)
|
||||
{
|
||||
if (port->uartclk == 19200000)
|
||||
msm_serial_set_mnd_regs_tcxo(port);
|
||||
else if (port->uartclk == 4800000)
|
||||
msm_serial_set_mnd_regs_tcxoby4(port);
|
||||
}
|
||||
|
||||
#define msm_serial_set_mnd_regs msm_serial_set_mnd_regs_from_uartclk
|
||||
|
||||
#endif /* __DRIVERS_SERIAL_MSM_SERIAL_H */
|
@ -300,6 +300,8 @@ static int mvebu_uart_startup(struct uart_port *port)
|
||||
static void mvebu_uart_shutdown(struct uart_port *port)
|
||||
{
|
||||
writel(0, port->membase + UART_CTRL);
|
||||
|
||||
free_irq(port->irq, port);
|
||||
}
|
||||
|
||||
static void mvebu_uart_set_termios(struct uart_port *port,
|
||||
|
@ -445,7 +445,6 @@ static int pic32_uart_startup(struct uart_port *port)
|
||||
sport->idx);
|
||||
if (!sport->irq_rx_name) {
|
||||
dev_err(port->dev, "%s: kasprintf err!", __func__);
|
||||
kfree(sport->irq_fault_name);
|
||||
ret = -ENOMEM;
|
||||
goto out_f;
|
||||
}
|
||||
|
@ -1720,7 +1720,7 @@ static int __init pmz_init_port(struct uart_pmac_port *uap)
|
||||
|
||||
r_ports = platform_get_resource(uap->pdev, IORESOURCE_MEM, 0);
|
||||
irq = platform_get_irq(uap->pdev, 0);
|
||||
if (!r_ports || !irq)
|
||||
if (!r_ports || irq <= 0)
|
||||
return -ENODEV;
|
||||
|
||||
uap->port.mapbase = r_ports->start;
|
||||
|
@ -27,7 +27,6 @@
|
||||
#define SUPPORT_SYSRQ
|
||||
#endif
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/console.h>
|
||||
@ -829,7 +828,6 @@ static const struct of_device_id serial_pxa_dt_ids[] = {
|
||||
{ .compatible = "mrvl,mmp-uart", },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
|
||||
|
||||
static int serial_pxa_probe_dt(struct platform_device *pdev,
|
||||
struct uart_pxa_port *sport)
|
||||
@ -914,28 +912,15 @@ static int serial_pxa_probe(struct platform_device *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int serial_pxa_remove(struct platform_device *dev)
|
||||
{
|
||||
struct uart_pxa_port *sport = platform_get_drvdata(dev);
|
||||
|
||||
uart_remove_one_port(&serial_pxa_reg, &sport->port);
|
||||
|
||||
clk_unprepare(sport->clk);
|
||||
clk_put(sport->clk);
|
||||
kfree(sport);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver serial_pxa_driver = {
|
||||
.probe = serial_pxa_probe,
|
||||
.remove = serial_pxa_remove,
|
||||
|
||||
.driver = {
|
||||
.name = "pxa2xx-uart",
|
||||
#ifdef CONFIG_PM
|
||||
.pm = &serial_pxa_pm_ops,
|
||||
#endif
|
||||
.suppress_bind_attrs = true,
|
||||
.of_match_table = serial_pxa_dt_ids,
|
||||
},
|
||||
};
|
||||
@ -954,15 +939,4 @@ static int __init serial_pxa_init(void)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit serial_pxa_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&serial_pxa_driver);
|
||||
uart_unregister_driver(&serial_pxa_reg);
|
||||
}
|
||||
|
||||
module_init(serial_pxa_init);
|
||||
module_exit(serial_pxa_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:pxa2xx-uart");
|
||||
device_initcall(serial_pxa_init);
|
||||
|
@ -169,8 +169,7 @@ static void s3c24xx_serial_stop_tx(struct uart_port *port)
|
||||
return;
|
||||
|
||||
if (s3c24xx_serial_has_interrupt_mask(port))
|
||||
__set_bit(S3C64XX_UINTM_TXD,
|
||||
portaddrl(port, S3C64XX_UINTM));
|
||||
s3c24xx_set_bit(port, S3C64XX_UINTM_TXD, S3C64XX_UINTM);
|
||||
else
|
||||
disable_irq_nosync(ourport->tx_irq);
|
||||
|
||||
@ -235,8 +234,7 @@ static void enable_tx_dma(struct s3c24xx_uart_port *ourport)
|
||||
|
||||
/* Mask Tx interrupt */
|
||||
if (s3c24xx_serial_has_interrupt_mask(port))
|
||||
__set_bit(S3C64XX_UINTM_TXD,
|
||||
portaddrl(port, S3C64XX_UINTM));
|
||||
s3c24xx_set_bit(port, S3C64XX_UINTM_TXD, S3C64XX_UINTM);
|
||||
else
|
||||
disable_irq_nosync(ourport->tx_irq);
|
||||
|
||||
@ -269,8 +267,8 @@ static void enable_tx_pio(struct s3c24xx_uart_port *ourport)
|
||||
|
||||
/* Unmask Tx interrupt */
|
||||
if (s3c24xx_serial_has_interrupt_mask(port))
|
||||
__clear_bit(S3C64XX_UINTM_TXD,
|
||||
portaddrl(port, S3C64XX_UINTM));
|
||||
s3c24xx_clear_bit(port, S3C64XX_UINTM_TXD,
|
||||
S3C64XX_UINTM);
|
||||
else
|
||||
enable_irq(ourport->tx_irq);
|
||||
|
||||
@ -397,8 +395,8 @@ static void s3c24xx_serial_stop_rx(struct uart_port *port)
|
||||
if (rx_enabled(port)) {
|
||||
dbg("s3c24xx_serial_stop_rx: port=%p\n", port);
|
||||
if (s3c24xx_serial_has_interrupt_mask(port))
|
||||
__set_bit(S3C64XX_UINTM_RXD,
|
||||
portaddrl(port, S3C64XX_UINTM));
|
||||
s3c24xx_set_bit(port, S3C64XX_UINTM_RXD,
|
||||
S3C64XX_UINTM);
|
||||
else
|
||||
disable_irq_nosync(ourport->rx_irq);
|
||||
rx_enabled(port) = 0;
|
||||
@ -1069,7 +1067,7 @@ static int s3c64xx_serial_startup(struct uart_port *port)
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
|
||||
/* Enable Rx Interrupt */
|
||||
__clear_bit(S3C64XX_UINTM_RXD, portaddrl(port, S3C64XX_UINTM));
|
||||
s3c24xx_clear_bit(port, S3C64XX_UINTM_RXD, S3C64XX_UINTM);
|
||||
|
||||
dbg("s3c64xx_serial_startup ok\n");
|
||||
return ret;
|
||||
@ -1684,7 +1682,7 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
|
||||
return -ENODEV;
|
||||
|
||||
if (port->mapbase != 0)
|
||||
return 0;
|
||||
return -EINVAL;
|
||||
|
||||
/* setup info for port */
|
||||
port->dev = &platdev->dev;
|
||||
@ -1738,22 +1736,25 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
|
||||
ourport->dma = devm_kzalloc(port->dev,
|
||||
sizeof(*ourport->dma),
|
||||
GFP_KERNEL);
|
||||
if (!ourport->dma)
|
||||
return -ENOMEM;
|
||||
if (!ourport->dma) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
ourport->clk = clk_get(&platdev->dev, "uart");
|
||||
if (IS_ERR(ourport->clk)) {
|
||||
pr_err("%s: Controller clock not found\n",
|
||||
dev_name(&platdev->dev));
|
||||
return PTR_ERR(ourport->clk);
|
||||
ret = PTR_ERR(ourport->clk);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(ourport->clk);
|
||||
if (ret) {
|
||||
pr_err("uart: clock failed to prepare+enable: %d\n", ret);
|
||||
clk_put(ourport->clk);
|
||||
return ret;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Keep all interrupts masked and cleared */
|
||||
@ -1769,7 +1770,12 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
|
||||
|
||||
/* reset the fifos (and setup the uart) */
|
||||
s3c24xx_serial_resetport(port, cfg);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
port->mapbase = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Device driver serial port probe */
|
||||
@ -1836,8 +1842,6 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
|
||||
ourport->min_dma_size = max_t(int, ourport->port.fifosize,
|
||||
dma_get_cache_alignment());
|
||||
|
||||
probe_index++;
|
||||
|
||||
dbg("%s: initialising port %p...\n", __func__, ourport);
|
||||
|
||||
ret = s3c24xx_serial_init_port(ourport, pdev);
|
||||
@ -1867,6 +1871,8 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
|
||||
if (ret < 0)
|
||||
dev_err(&pdev->dev, "failed to add cpufreq notifier\n");
|
||||
|
||||
probe_index++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -117,10 +117,38 @@ struct s3c24xx_uart_port {
|
||||
#define portaddrl(port, reg) \
|
||||
((unsigned long *)(unsigned long)((port)->membase + (reg)))
|
||||
|
||||
#define rd_regb(port, reg) (__raw_readb(portaddr(port, reg)))
|
||||
#define rd_regl(port, reg) (__raw_readl(portaddr(port, reg)))
|
||||
#define rd_regb(port, reg) (readb_relaxed(portaddr(port, reg)))
|
||||
#define rd_regl(port, reg) (readl_relaxed(portaddr(port, reg)))
|
||||
|
||||
#define wr_regb(port, reg, val) __raw_writeb(val, portaddr(port, reg))
|
||||
#define wr_regl(port, reg, val) __raw_writel(val, portaddr(port, reg))
|
||||
#define wr_regb(port, reg, val) writeb_relaxed(val, portaddr(port, reg))
|
||||
#define wr_regl(port, reg, val) writel_relaxed(val, portaddr(port, reg))
|
||||
|
||||
/* Byte-order aware bit setting/clearing functions. */
|
||||
|
||||
static inline void s3c24xx_set_bit(struct uart_port *port, int idx,
|
||||
unsigned int reg)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
|
||||
local_irq_save(flags);
|
||||
val = rd_regl(port, reg);
|
||||
val |= (1 << idx);
|
||||
wr_regl(port, reg, val);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static inline void s3c24xx_clear_bit(struct uart_port *port, int idx,
|
||||
unsigned int reg)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
|
||||
local_irq_save(flags);
|
||||
val = rd_regl(port, reg);
|
||||
val &= ~(1 << idx);
|
||||
wr_regl(port, reg, val);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1317,7 +1317,12 @@ static int tegra_uart_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
u->iotype = UPIO_MEM32;
|
||||
u->irq = platform_get_irq(pdev, 0);
|
||||
ret = platform_get_irq(pdev, 0);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Couldn't get IRQ\n");
|
||||
return ret;
|
||||
}
|
||||
u->irq = ret;
|
||||
u->regshift = 2;
|
||||
ret = uart_add_one_port(&tegra_uart_driver, u);
|
||||
if (ret < 0) {
|
||||
|
@ -887,7 +887,7 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
|
||||
/*
|
||||
* Free and release old regions
|
||||
*/
|
||||
if (old_type != PORT_UNKNOWN)
|
||||
if (old_type != PORT_UNKNOWN && uport->ops->release_port)
|
||||
uport->ops->release_port(uport);
|
||||
|
||||
uport->iobase = new_port;
|
||||
@ -900,7 +900,7 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
|
||||
/*
|
||||
* Claim and map the new regions
|
||||
*/
|
||||
if (uport->type != PORT_UNKNOWN) {
|
||||
if (uport->type != PORT_UNKNOWN && uport->ops->request_port) {
|
||||
retval = uport->ops->request_port(uport);
|
||||
} else {
|
||||
/* Always success - Jean II */
|
||||
@ -1125,7 +1125,7 @@ static int uart_do_autoconfig(struct tty_struct *tty,struct uart_state *state)
|
||||
* If we already have a port type configured,
|
||||
* we must release its resources.
|
||||
*/
|
||||
if (uport->type != PORT_UNKNOWN)
|
||||
if (uport->type != PORT_UNKNOWN && uport->ops->release_port)
|
||||
uport->ops->release_port(uport);
|
||||
|
||||
flags = UART_CONFIG_TYPE;
|
||||
@ -2897,7 +2897,7 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport)
|
||||
/*
|
||||
* Free the port IO and memory resources, if any.
|
||||
*/
|
||||
if (uport->type != PORT_UNKNOWN)
|
||||
if (uport->type != PORT_UNKNOWN && uport->ops->release_port)
|
||||
uport->ops->release_port(uport);
|
||||
kfree(uport->tty_groups);
|
||||
|
||||
|
@ -52,6 +52,9 @@ void mctrl_gpio_set(struct mctrl_gpios *gpios, unsigned int mctrl)
|
||||
int value_array[UART_GPIO_MAX];
|
||||
unsigned int count = 0;
|
||||
|
||||
if (gpios == NULL)
|
||||
return;
|
||||
|
||||
for (i = 0; i < UART_GPIO_MAX; i++)
|
||||
if (gpios->gpio[i] && mctrl_gpios_desc[i].dir_out) {
|
||||
desc_array[count] = gpios->gpio[i];
|
||||
@ -73,6 +76,9 @@ unsigned int mctrl_gpio_get(struct mctrl_gpios *gpios, unsigned int *mctrl)
|
||||
{
|
||||
enum mctrl_gpio_idx i;
|
||||
|
||||
if (gpios == NULL)
|
||||
return *mctrl;
|
||||
|
||||
for (i = 0; i < UART_GPIO_MAX; i++) {
|
||||
if (gpios->gpio[i] && !mctrl_gpios_desc[i].dir_out) {
|
||||
if (gpiod_get_value(gpios->gpio[i]))
|
||||
@ -86,6 +92,27 @@ unsigned int mctrl_gpio_get(struct mctrl_gpios *gpios, unsigned int *mctrl)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mctrl_gpio_get);
|
||||
|
||||
unsigned int
|
||||
mctrl_gpio_get_outputs(struct mctrl_gpios *gpios, unsigned int *mctrl)
|
||||
{
|
||||
enum mctrl_gpio_idx i;
|
||||
|
||||
if (gpios == NULL)
|
||||
return *mctrl;
|
||||
|
||||
for (i = 0; i < UART_GPIO_MAX; i++) {
|
||||
if (gpios->gpio[i] && mctrl_gpios_desc[i].dir_out) {
|
||||
if (gpiod_get_value(gpios->gpio[i]))
|
||||
*mctrl |= mctrl_gpios_desc[i].mctrl;
|
||||
else
|
||||
*mctrl &= ~mctrl_gpios_desc[i].mctrl;
|
||||
}
|
||||
}
|
||||
|
||||
return *mctrl;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mctrl_gpio_get_outputs);
|
||||
|
||||
struct mctrl_gpios *mctrl_gpio_init_noauto(struct device *dev, unsigned int idx)
|
||||
{
|
||||
struct mctrl_gpios *gpios;
|
||||
@ -203,6 +230,9 @@ void mctrl_gpio_free(struct device *dev, struct mctrl_gpios *gpios)
|
||||
{
|
||||
enum mctrl_gpio_idx i;
|
||||
|
||||
if (gpios == NULL)
|
||||
return;
|
||||
|
||||
for (i = 0; i < UART_GPIO_MAX; i++) {
|
||||
if (gpios->irq[i])
|
||||
devm_free_irq(gpios->port->dev, gpios->irq[i], gpios);
|
||||
@ -218,6 +248,9 @@ void mctrl_gpio_enable_ms(struct mctrl_gpios *gpios)
|
||||
{
|
||||
enum mctrl_gpio_idx i;
|
||||
|
||||
if (gpios == NULL)
|
||||
return;
|
||||
|
||||
/* .enable_ms may be called multiple times */
|
||||
if (gpios->mctrl_on)
|
||||
return;
|
||||
@ -240,6 +273,9 @@ void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios)
|
||||
{
|
||||
enum mctrl_gpio_idx i;
|
||||
|
||||
if (gpios == NULL)
|
||||
return;
|
||||
|
||||
if (!gpios->mctrl_on)
|
||||
return;
|
||||
|
||||
|
@ -48,11 +48,18 @@ struct mctrl_gpios;
|
||||
void mctrl_gpio_set(struct mctrl_gpios *gpios, unsigned int mctrl);
|
||||
|
||||
/*
|
||||
* Get state of the modem control output lines from GPIOs.
|
||||
* Get state of the modem control input lines from GPIOs.
|
||||
* The mctrl flags are updated and returned.
|
||||
*/
|
||||
unsigned int mctrl_gpio_get(struct mctrl_gpios *gpios, unsigned int *mctrl);
|
||||
|
||||
/*
|
||||
* Get state of the modem control output lines from GPIOs.
|
||||
* The mctrl flags are updated and returned.
|
||||
*/
|
||||
unsigned int
|
||||
mctrl_gpio_get_outputs(struct mctrl_gpios *gpios, unsigned int *mctrl);
|
||||
|
||||
/*
|
||||
* Returns the associated struct gpio_desc to the modem line gidx
|
||||
*/
|
||||
@ -107,6 +114,12 @@ unsigned int mctrl_gpio_get(struct mctrl_gpios *gpios, unsigned int *mctrl)
|
||||
return *mctrl;
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
mctrl_gpio_get_outputs(struct mctrl_gpios *gpios, unsigned int *mctrl)
|
||||
{
|
||||
return *mctrl;
|
||||
}
|
||||
|
||||
static inline
|
||||
struct gpio_desc *mctrl_gpio_to_gpiod(struct mctrl_gpios *gpios,
|
||||
enum mctrl_gpio_idx gidx)
|
||||
|
@ -57,6 +57,7 @@
|
||||
#include <asm/sh_bios.h>
|
||||
#endif
|
||||
|
||||
#include "serial_mctrl_gpio.h"
|
||||
#include "sh-sci.h"
|
||||
|
||||
/* Offsets into the sci_port->irqs array */
|
||||
@ -111,6 +112,7 @@ struct sci_port {
|
||||
unsigned int error_clear;
|
||||
unsigned int sampling_rate_mask;
|
||||
resource_size_t reg_size;
|
||||
struct mctrl_gpios *gpios;
|
||||
|
||||
/* Break timer */
|
||||
struct timer_list break_timer;
|
||||
@ -139,6 +141,8 @@ struct sci_port {
|
||||
struct timer_list rx_timer;
|
||||
unsigned int rx_timeout;
|
||||
#endif
|
||||
|
||||
bool autorts;
|
||||
};
|
||||
|
||||
#define SCI_NPORTS CONFIG_SERIAL_SH_SCI_NR_UARTS
|
||||
@ -701,7 +705,6 @@ static void sci_poll_put_char(struct uart_port *port, unsigned char c)
|
||||
static void sci_init_pins(struct uart_port *port, unsigned int cflag)
|
||||
{
|
||||
struct sci_port *s = to_sci_port(port);
|
||||
const struct plat_sci_reg *reg = sci_regmap[s->cfg->regtype] + SCSPTR;
|
||||
|
||||
/*
|
||||
* Use port-specific handler if provided.
|
||||
@ -711,21 +714,28 @@ static void sci_init_pins(struct uart_port *port, unsigned int cflag)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* For the generic path SCSPTR is necessary. Bail out if that's
|
||||
* unavailable, too.
|
||||
*/
|
||||
if (!reg->size)
|
||||
return;
|
||||
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
|
||||
u16 ctrl = serial_port_in(port, SCPCR);
|
||||
|
||||
if ((s->cfg->capabilities & SCIx_HAVE_RTSCTS) &&
|
||||
((!(cflag & CRTSCTS)))) {
|
||||
unsigned short status;
|
||||
/* Enable RXD and TXD pin functions */
|
||||
ctrl &= ~(SCPCR_RXDC | SCPCR_TXDC);
|
||||
if (to_sci_port(port)->cfg->capabilities & SCIx_HAVE_RTSCTS) {
|
||||
/* RTS# is output, driven 1 */
|
||||
ctrl |= SCPCR_RTSC;
|
||||
serial_port_out(port, SCPDR,
|
||||
serial_port_in(port, SCPDR) | SCPDR_RTSD);
|
||||
/* Enable CTS# pin function */
|
||||
ctrl &= ~SCPCR_CTSC;
|
||||
}
|
||||
serial_port_out(port, SCPCR, ctrl);
|
||||
} else if (sci_getreg(port, SCSPTR)->size) {
|
||||
u16 status = serial_port_in(port, SCSPTR);
|
||||
|
||||
status = serial_port_in(port, SCSPTR);
|
||||
status &= ~SCSPTR_CTSIO;
|
||||
status |= SCSPTR_RTSIO;
|
||||
serial_port_out(port, SCSPTR, status); /* Set RTS = 1 */
|
||||
/* RTS# is output, driven 1 */
|
||||
status |= SCSPTR_RTSIO | SCSPTR_RTSDT;
|
||||
/* CTS# and SCK are inputs */
|
||||
status &= ~(SCSPTR_CTSIO | SCSPTR_SCKIO);
|
||||
serial_port_out(port, SCSPTR, status);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1803,6 +1813,46 @@ static unsigned int sci_tx_empty(struct uart_port *port)
|
||||
return (status & SCxSR_TEND(port)) && !in_tx_fifo ? TIOCSER_TEMT : 0;
|
||||
}
|
||||
|
||||
static void sci_set_rts(struct uart_port *port, bool state)
|
||||
{
|
||||
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
|
||||
u16 data = serial_port_in(port, SCPDR);
|
||||
|
||||
/* Active low */
|
||||
if (state)
|
||||
data &= ~SCPDR_RTSD;
|
||||
else
|
||||
data |= SCPDR_RTSD;
|
||||
serial_port_out(port, SCPDR, data);
|
||||
|
||||
/* RTS# is output */
|
||||
serial_port_out(port, SCPCR,
|
||||
serial_port_in(port, SCPCR) | SCPCR_RTSC);
|
||||
} else if (sci_getreg(port, SCSPTR)->size) {
|
||||
u16 ctrl = serial_port_in(port, SCSPTR);
|
||||
|
||||
/* Active low */
|
||||
if (state)
|
||||
ctrl &= ~SCSPTR_RTSDT;
|
||||
else
|
||||
ctrl |= SCSPTR_RTSDT;
|
||||
serial_port_out(port, SCSPTR, ctrl);
|
||||
}
|
||||
}
|
||||
|
||||
static bool sci_get_cts(struct uart_port *port)
|
||||
{
|
||||
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
|
||||
/* Active low */
|
||||
return !(serial_port_in(port, SCPDR) & SCPDR_CTSD);
|
||||
} else if (sci_getreg(port, SCSPTR)->size) {
|
||||
/* Active low */
|
||||
return !(serial_port_in(port, SCSPTR) & SCSPTR_CTSDT);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Modem control is a bit of a mixed bag for SCI(F) ports. Generally
|
||||
* CTS/RTS is supported in hardware by at least one port and controlled
|
||||
@ -1817,6 +1867,8 @@ static unsigned int sci_tx_empty(struct uart_port *port)
|
||||
*/
|
||||
static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
{
|
||||
struct sci_port *s = to_sci_port(port);
|
||||
|
||||
if (mctrl & TIOCM_LOOP) {
|
||||
const struct plat_sci_reg *reg;
|
||||
|
||||
@ -1829,25 +1881,72 @@ static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
serial_port_in(port, SCFCR) |
|
||||
SCFCR_LOOP);
|
||||
}
|
||||
|
||||
mctrl_gpio_set(s->gpios, mctrl);
|
||||
|
||||
if (!(s->cfg->capabilities & SCIx_HAVE_RTSCTS))
|
||||
return;
|
||||
|
||||
if (!(mctrl & TIOCM_RTS)) {
|
||||
/* Disable Auto RTS */
|
||||
serial_port_out(port, SCFCR,
|
||||
serial_port_in(port, SCFCR) & ~SCFCR_MCE);
|
||||
|
||||
/* Clear RTS */
|
||||
sci_set_rts(port, 0);
|
||||
} else if (s->autorts) {
|
||||
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
|
||||
/* Enable RTS# pin function */
|
||||
serial_port_out(port, SCPCR,
|
||||
serial_port_in(port, SCPCR) & ~SCPCR_RTSC);
|
||||
}
|
||||
|
||||
/* Enable Auto RTS */
|
||||
serial_port_out(port, SCFCR,
|
||||
serial_port_in(port, SCFCR) | SCFCR_MCE);
|
||||
} else {
|
||||
/* Set RTS */
|
||||
sci_set_rts(port, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int sci_get_mctrl(struct uart_port *port)
|
||||
{
|
||||
struct sci_port *s = to_sci_port(port);
|
||||
struct mctrl_gpios *gpios = s->gpios;
|
||||
unsigned int mctrl = 0;
|
||||
|
||||
mctrl_gpio_get(gpios, &mctrl);
|
||||
|
||||
/*
|
||||
* CTS/RTS is handled in hardware when supported, while nothing
|
||||
* else is wired up. Keep it simple and simply assert DSR/CAR.
|
||||
* else is wired up.
|
||||
*/
|
||||
return TIOCM_DSR | TIOCM_CAR;
|
||||
if (s->autorts) {
|
||||
if (sci_get_cts(port))
|
||||
mctrl |= TIOCM_CTS;
|
||||
} else if (IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(gpios, UART_GPIO_CTS))) {
|
||||
mctrl |= TIOCM_CTS;
|
||||
}
|
||||
if (IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(gpios, UART_GPIO_DSR)))
|
||||
mctrl |= TIOCM_DSR;
|
||||
if (IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(gpios, UART_GPIO_DCD)))
|
||||
mctrl |= TIOCM_CAR;
|
||||
|
||||
return mctrl;
|
||||
}
|
||||
|
||||
static void sci_enable_ms(struct uart_port *port)
|
||||
{
|
||||
mctrl_gpio_enable_ms(to_sci_port(port)->gpios);
|
||||
}
|
||||
|
||||
static void sci_break_ctl(struct uart_port *port, int break_state)
|
||||
{
|
||||
struct sci_port *s = to_sci_port(port);
|
||||
const struct plat_sci_reg *reg = sci_regmap[s->cfg->regtype] + SCSPTR;
|
||||
unsigned short scscr, scsptr;
|
||||
|
||||
/* check wheter the port has SCSPTR */
|
||||
if (!reg->size) {
|
||||
if (!sci_getreg(port, SCSPTR)->size) {
|
||||
/*
|
||||
* Not supported by hardware. Most parts couple break and rx
|
||||
* interrupts together, with break detection always enabled.
|
||||
@ -1873,7 +1972,6 @@ static void sci_break_ctl(struct uart_port *port, int break_state)
|
||||
static int sci_startup(struct uart_port *port)
|
||||
{
|
||||
struct sci_port *s = to_sci_port(port);
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
|
||||
@ -1884,11 +1982,6 @@ static int sci_startup(struct uart_port *port)
|
||||
|
||||
sci_request_dma(port);
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
sci_start_tx(port);
|
||||
sci_start_rx(port);
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1896,12 +1989,19 @@ static void sci_shutdown(struct uart_port *port)
|
||||
{
|
||||
struct sci_port *s = to_sci_port(port);
|
||||
unsigned long flags;
|
||||
u16 scr;
|
||||
|
||||
dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
|
||||
|
||||
s->autorts = false;
|
||||
mctrl_gpio_disable_ms(to_sci_port(port)->gpios);
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
sci_stop_rx(port);
|
||||
sci_stop_tx(port);
|
||||
/* Stop RX and TX, disable related interrupts, keep clock source */
|
||||
scr = serial_port_in(port, SCSCR);
|
||||
serial_port_out(port, SCSCR, scr & (SCSCR_CKE1 | SCSCR_CKE0));
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
|
||||
#ifdef CONFIG_SERIAL_SH_SCI_DMA
|
||||
@ -2056,6 +2156,15 @@ static void sci_reset(struct uart_port *port)
|
||||
reg = sci_getreg(port, SCFCR);
|
||||
if (reg->size)
|
||||
serial_port_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST);
|
||||
|
||||
sci_clear_SCxSR(port,
|
||||
SCxSR_RDxF_CLEAR(port) & SCxSR_ERROR_CLEAR(port) &
|
||||
SCxSR_BREAK_CLEAR(port));
|
||||
if (sci_getreg(port, SCLSR)->size) {
|
||||
status = serial_port_in(port, SCLSR);
|
||||
status &= ~(SCLSR_TO | SCLSR_ORER);
|
||||
serial_port_out(port, SCLSR, status);
|
||||
}
|
||||
}
|
||||
|
||||
static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
@ -2218,15 +2327,18 @@ done:
|
||||
|
||||
sci_init_pins(port, termios->c_cflag);
|
||||
|
||||
port->status &= ~UPSTAT_AUTOCTS;
|
||||
s->autorts = false;
|
||||
reg = sci_getreg(port, SCFCR);
|
||||
if (reg->size) {
|
||||
unsigned short ctrl = serial_port_in(port, SCFCR);
|
||||
|
||||
if (s->cfg->capabilities & SCIx_HAVE_RTSCTS) {
|
||||
if (termios->c_cflag & CRTSCTS)
|
||||
ctrl |= SCFCR_MCE;
|
||||
else
|
||||
ctrl &= ~SCFCR_MCE;
|
||||
if ((port->flags & UPF_HARD_FLOW) &&
|
||||
(termios->c_cflag & CRTSCTS)) {
|
||||
/* There is no CTS interrupt to restart the hardware */
|
||||
port->status |= UPSTAT_AUTOCTS;
|
||||
/* MCE is enabled when RTS is raised */
|
||||
s->autorts = true;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2300,6 +2412,9 @@ done:
|
||||
sci_start_rx(port);
|
||||
|
||||
sci_port_disable(s);
|
||||
|
||||
if (UART_ENABLE_MS(port, termios->c_cflag))
|
||||
sci_enable_ms(port);
|
||||
}
|
||||
|
||||
static void sci_pm(struct uart_port *port, unsigned int state,
|
||||
@ -2425,6 +2540,7 @@ static struct uart_ops sci_uart_ops = {
|
||||
.start_tx = sci_start_tx,
|
||||
.stop_tx = sci_stop_tx,
|
||||
.stop_rx = sci_stop_rx,
|
||||
.enable_ms = sci_enable_ms,
|
||||
.break_ctl = sci_break_ctl,
|
||||
.startup = sci_startup,
|
||||
.shutdown = sci_shutdown,
|
||||
@ -2890,6 +3006,9 @@ sci_parse_dt(struct platform_device *pdev, unsigned int *dev_id)
|
||||
p->regtype = SCI_OF_REGTYPE(match->data);
|
||||
p->scscr = SCSCR_RE | SCSCR_TE;
|
||||
|
||||
if (of_find_property(np, "uart-has-rtscts", NULL))
|
||||
p->capabilities |= SCIx_HAVE_RTSCTS;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
@ -2912,6 +3031,21 @@ static int sci_probe_single(struct platform_device *dev,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
sciport->gpios = mctrl_gpio_init(&sciport->port, 0);
|
||||
if (IS_ERR(sciport->gpios) && PTR_ERR(sciport->gpios) != -ENOSYS)
|
||||
return PTR_ERR(sciport->gpios);
|
||||
|
||||
if (p->capabilities & SCIx_HAVE_RTSCTS) {
|
||||
if (!IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(sciport->gpios,
|
||||
UART_GPIO_CTS)) ||
|
||||
!IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(sciport->gpios,
|
||||
UART_GPIO_RTS))) {
|
||||
dev_err(&dev->dev, "Conflicting RTS/CTS config\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
sciport->port.flags |= UPF_HARD_FLOW;
|
||||
}
|
||||
|
||||
ret = uart_add_one_port(&sci_uart_driver, &sciport->port);
|
||||
if (ret) {
|
||||
sci_cleanup_single(sciport);
|
||||
|
@ -105,13 +105,16 @@ enum {
|
||||
#define SCFCR_LOOP BIT(0) /* Loopback Test */
|
||||
|
||||
/* SCLSR (Line Status Register) on (H)SCIF */
|
||||
#define SCLSR_TO BIT(2) /* Timeout */
|
||||
#define SCLSR_ORER BIT(0) /* Overrun Error */
|
||||
|
||||
/* SCSPTR (Serial Port Register), optional */
|
||||
#define SCSPTR_RTSIO BIT(7) /* Serial Port RTS Pin Input/Output */
|
||||
#define SCSPTR_RTSDT BIT(6) /* Serial Port RTS Pin Data */
|
||||
#define SCSPTR_CTSIO BIT(5) /* Serial Port CTS Pin Input/Output */
|
||||
#define SCSPTR_CTSDT BIT(4) /* Serial Port CTS Pin Data */
|
||||
#define SCSPTR_RTSIO BIT(7) /* Serial Port RTS# Pin Input/Output */
|
||||
#define SCSPTR_RTSDT BIT(6) /* Serial Port RTS# Pin Data */
|
||||
#define SCSPTR_CTSIO BIT(5) /* Serial Port CTS# Pin Input/Output */
|
||||
#define SCSPTR_CTSDT BIT(4) /* Serial Port CTS# Pin Data */
|
||||
#define SCSPTR_SCKIO BIT(3) /* Serial Port Clock Pin Input/Output */
|
||||
#define SCSPTR_SCKDT BIT(2) /* Serial Port Clock Pin Data */
|
||||
#define SCSPTR_SPB2IO BIT(1) /* Serial Port Break Input/Output */
|
||||
#define SCSPTR_SPB2DT BIT(0) /* Serial Port Break Data */
|
||||
|
||||
@ -119,12 +122,18 @@ enum {
|
||||
#define HSCIF_SRE BIT(15) /* Sampling Rate Register Enable */
|
||||
|
||||
/* SCPCR (Serial Port Control Register), SCIFA/SCIFB only */
|
||||
#define SCPCR_RTSC BIT(4) /* Serial Port RTS Pin / Output Pin */
|
||||
#define SCPCR_CTSC BIT(3) /* Serial Port CTS Pin / Input Pin */
|
||||
#define SCPCR_RTSC BIT(4) /* Serial Port RTS# Pin / Output Pin */
|
||||
#define SCPCR_CTSC BIT(3) /* Serial Port CTS# Pin / Input Pin */
|
||||
#define SCPCR_SCKC BIT(2) /* Serial Port SCK Pin / Output Pin */
|
||||
#define SCPCR_RXDC BIT(1) /* Serial Port RXD Pin / Input Pin */
|
||||
#define SCPCR_TXDC BIT(0) /* Serial Port TXD Pin / Output Pin */
|
||||
|
||||
/* SCPDR (Serial Port Data Register), SCIFA/SCIFB only */
|
||||
#define SCPDR_RTSD BIT(4) /* Serial Port RTS Output Pin Data */
|
||||
#define SCPDR_CTSD BIT(3) /* Serial Port CTS Input Pin Data */
|
||||
#define SCPDR_RTSD BIT(4) /* Serial Port RTS# Output Pin Data */
|
||||
#define SCPDR_CTSD BIT(3) /* Serial Port CTS# Input Pin Data */
|
||||
#define SCPDR_SCKD BIT(2) /* Serial Port SCK Output Pin Data */
|
||||
#define SCPDR_RXDD BIT(1) /* Serial Port RXD Input Pin Data */
|
||||
#define SCPDR_TXDD BIT(0) /* Serial Port TXD Output Pin Data */
|
||||
|
||||
/*
|
||||
* BRG Clock Select Register (Some SCIF and HSCIF)
|
||||
|
@ -106,7 +106,7 @@ struct sirfsoc_uart_register {
|
||||
enum sirfsoc_uart_type uart_type;
|
||||
};
|
||||
|
||||
u32 uart_usp_ff_full_mask(struct uart_port *port)
|
||||
static u32 uart_usp_ff_full_mask(struct uart_port *port)
|
||||
{
|
||||
u32 full_bit;
|
||||
|
||||
@ -114,7 +114,7 @@ u32 uart_usp_ff_full_mask(struct uart_port *port)
|
||||
return (1 << full_bit);
|
||||
}
|
||||
|
||||
u32 uart_usp_ff_empty_mask(struct uart_port *port)
|
||||
static u32 uart_usp_ff_empty_mask(struct uart_port *port)
|
||||
{
|
||||
u32 empty_bit;
|
||||
|
||||
|
@ -21,7 +21,6 @@
|
||||
|
||||
#include <linux/hrtimer.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/irq.h>
|
||||
@ -730,22 +729,12 @@ static int vt8500_serial_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vt8500_serial_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct vt8500_port *vt8500_port = platform_get_drvdata(pdev);
|
||||
|
||||
clk_disable_unprepare(vt8500_port->clk);
|
||||
uart_remove_one_port(&vt8500_uart_driver, &vt8500_port->uart);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver vt8500_platform_driver = {
|
||||
.probe = vt8500_serial_probe,
|
||||
.remove = vt8500_serial_remove,
|
||||
.driver = {
|
||||
.name = "vt8500_serial",
|
||||
.of_match_table = wmt_dt_ids,
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
};
|
||||
|
||||
@ -764,19 +753,4 @@ static int __init vt8500_serial_init(void)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit vt8500_serial_exit(void)
|
||||
{
|
||||
#ifdef CONFIG_SERIAL_VT8500_CONSOLE
|
||||
unregister_console(&vt8500_console);
|
||||
#endif
|
||||
platform_driver_unregister(&vt8500_platform_driver);
|
||||
uart_unregister_driver(&vt8500_uart_driver);
|
||||
}
|
||||
|
||||
module_init(vt8500_serial_init);
|
||||
module_exit(vt8500_serial_exit);
|
||||
|
||||
MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>");
|
||||
MODULE_DESCRIPTION("Driver for vt8500 serial device");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
device_initcall(vt8500_serial_init);
|
||||
|
@ -976,6 +976,23 @@ static void cdns_uart_poll_put_char(struct uart_port *port, unsigned char c)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void cdns_uart_pm(struct uart_port *port, unsigned int state,
|
||||
unsigned int oldstate)
|
||||
{
|
||||
struct cdns_uart *cdns_uart = port->private_data;
|
||||
|
||||
switch (state) {
|
||||
case UART_PM_STATE_OFF:
|
||||
clk_disable(cdns_uart->uartclk);
|
||||
clk_disable(cdns_uart->pclk);
|
||||
break;
|
||||
default:
|
||||
clk_enable(cdns_uart->pclk);
|
||||
clk_enable(cdns_uart->uartclk);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static struct uart_ops cdns_uart_ops = {
|
||||
.set_mctrl = cdns_uart_set_mctrl,
|
||||
.get_mctrl = cdns_uart_get_mctrl,
|
||||
@ -987,6 +1004,7 @@ static struct uart_ops cdns_uart_ops = {
|
||||
.set_termios = cdns_uart_set_termios,
|
||||
.startup = cdns_uart_startup,
|
||||
.shutdown = cdns_uart_shutdown,
|
||||
.pm = cdns_uart_pm,
|
||||
.type = cdns_uart_type,
|
||||
.verify_port = cdns_uart_verify_port,
|
||||
.request_port = cdns_uart_request_port,
|
||||
@ -1350,12 +1368,12 @@ static int cdns_uart_probe(struct platform_device *pdev)
|
||||
return PTR_ERR(cdns_uart_data->uartclk);
|
||||
}
|
||||
|
||||
rc = clk_prepare_enable(cdns_uart_data->pclk);
|
||||
rc = clk_prepare(cdns_uart_data->pclk);
|
||||
if (rc) {
|
||||
dev_err(&pdev->dev, "Unable to enable pclk clock.\n");
|
||||
return rc;
|
||||
}
|
||||
rc = clk_prepare_enable(cdns_uart_data->uartclk);
|
||||
rc = clk_prepare(cdns_uart_data->uartclk);
|
||||
if (rc) {
|
||||
dev_err(&pdev->dev, "Unable to enable device clock.\n");
|
||||
goto err_out_clk_dis_pclk;
|
||||
@ -1422,9 +1440,9 @@ err_out_notif_unreg:
|
||||
&cdns_uart_data->clk_rate_change_nb);
|
||||
#endif
|
||||
err_out_clk_disable:
|
||||
clk_disable_unprepare(cdns_uart_data->uartclk);
|
||||
clk_unprepare(cdns_uart_data->uartclk);
|
||||
err_out_clk_dis_pclk:
|
||||
clk_disable_unprepare(cdns_uart_data->pclk);
|
||||
clk_unprepare(cdns_uart_data->pclk);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -1448,8 +1466,8 @@ static int cdns_uart_remove(struct platform_device *pdev)
|
||||
#endif
|
||||
rc = uart_remove_one_port(&cdns_uart_uart_driver, port);
|
||||
port->mapbase = 0;
|
||||
clk_disable_unprepare(cdns_uart_data->uartclk);
|
||||
clk_disable_unprepare(cdns_uart_data->pclk);
|
||||
clk_unprepare(cdns_uart_data->uartclk);
|
||||
clk_unprepare(cdns_uart_data->pclk);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -499,9 +499,8 @@ con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ui is a leftover from using a hashtable, but might be used again
|
||||
Caller must hold the lock */
|
||||
static int con_do_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
|
||||
/* Caller must hold the lock */
|
||||
static int con_do_clear_unimap(struct vc_data *vc)
|
||||
{
|
||||
struct uni_pagedir *p, *q;
|
||||
|
||||
@ -524,11 +523,11 @@ static int con_do_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
|
||||
int con_clear_unimap(struct vc_data *vc)
|
||||
{
|
||||
int ret;
|
||||
console_lock();
|
||||
ret = con_do_clear_unimap(vc, ui);
|
||||
ret = con_do_clear_unimap(vc);
|
||||
console_unlock();
|
||||
return ret;
|
||||
}
|
||||
@ -556,7 +555,7 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
|
||||
int j, k;
|
||||
u16 **p1, *p2, l;
|
||||
|
||||
err1 = con_do_clear_unimap(vc, NULL);
|
||||
err1 = con_do_clear_unimap(vc);
|
||||
if (err1) {
|
||||
console_unlock();
|
||||
return err1;
|
||||
@ -677,7 +676,7 @@ int con_set_default_unimap(struct vc_data *vc)
|
||||
|
||||
/* The default font is always 256 characters */
|
||||
|
||||
err = con_do_clear_unimap(vc, NULL);
|
||||
err = con_do_clear_unimap(vc);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -567,7 +567,7 @@ static void fn_scroll_forw(struct vc_data *vc)
|
||||
|
||||
static void fn_scroll_back(struct vc_data *vc)
|
||||
{
|
||||
scrollback(vc, 0);
|
||||
scrollback(vc);
|
||||
}
|
||||
|
||||
static void fn_show_mem(struct vc_data *vc)
|
||||
@ -1733,16 +1733,10 @@ int vt_do_diacrit(unsigned int cmd, void __user *udp, int perm)
|
||||
return -EINVAL;
|
||||
|
||||
if (ct) {
|
||||
buf = kmalloc(ct * sizeof(struct kbdiacruc),
|
||||
GFP_KERNEL);
|
||||
if (buf == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
if (copy_from_user(buf, a->kbdiacruc,
|
||||
ct * sizeof(struct kbdiacruc))) {
|
||||
kfree(buf);
|
||||
return -EFAULT;
|
||||
}
|
||||
buf = memdup_user(a->kbdiacruc,
|
||||
ct * sizeof(struct kbdiacruc));
|
||||
if (IS_ERR(buf))
|
||||
return PTR_ERR(buf);
|
||||
}
|
||||
spin_lock_irqsave(&kbd_event_lock, flags);
|
||||
if (ct)
|
||||
|
@ -277,13 +277,15 @@ static void notify_update(struct vc_data *vc)
|
||||
* Low-Level Functions
|
||||
*/
|
||||
|
||||
#define IS_FG(vc) ((vc)->vc_num == fg_console)
|
||||
static inline bool con_is_fg(const struct vc_data *vc)
|
||||
{
|
||||
return vc->vc_num == fg_console;
|
||||
}
|
||||
|
||||
#ifdef VT_BUF_VRAM_ONLY
|
||||
#define DO_UPDATE(vc) 0
|
||||
#else
|
||||
#define DO_UPDATE(vc) (CON_IS_VISIBLE(vc) && !console_blanked)
|
||||
#endif
|
||||
static inline bool con_should_update(const struct vc_data *vc)
|
||||
{
|
||||
return con_is_visible(vc) && !console_blanked;
|
||||
}
|
||||
|
||||
static inline unsigned short *screenpos(struct vc_data *vc, int offset, int viewed)
|
||||
{
|
||||
@ -321,7 +323,7 @@ static void scrup(struct vc_data *vc, unsigned int t, unsigned int b, int nr)
|
||||
nr = b - t - 1;
|
||||
if (b > vc->vc_rows || t >= b || nr < 1)
|
||||
return;
|
||||
if (CON_IS_VISIBLE(vc) && vc->vc_sw->con_scroll(vc, t, b, SM_UP, nr))
|
||||
if (con_is_visible(vc) && vc->vc_sw->con_scroll(vc, t, b, SM_UP, nr))
|
||||
return;
|
||||
d = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t);
|
||||
s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * (t + nr));
|
||||
@ -339,7 +341,7 @@ static void scrdown(struct vc_data *vc, unsigned int t, unsigned int b, int nr)
|
||||
nr = b - t - 1;
|
||||
if (b > vc->vc_rows || t >= b || nr < 1)
|
||||
return;
|
||||
if (CON_IS_VISIBLE(vc) && vc->vc_sw->con_scroll(vc, t, b, SM_DOWN, nr))
|
||||
if (con_is_visible(vc) && vc->vc_sw->con_scroll(vc, t, b, SM_DOWN, nr))
|
||||
return;
|
||||
s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t);
|
||||
step = vc->vc_cols * nr;
|
||||
@ -349,7 +351,6 @@ static void scrdown(struct vc_data *vc, unsigned int t, unsigned int b, int nr)
|
||||
|
||||
static void do_update_region(struct vc_data *vc, unsigned long start, int count)
|
||||
{
|
||||
#ifndef VT_BUF_VRAM_ONLY
|
||||
unsigned int xx, yy, offset;
|
||||
u16 *p;
|
||||
|
||||
@ -390,14 +391,13 @@ static void do_update_region(struct vc_data *vc, unsigned long start, int count)
|
||||
start = vc->vc_sw->con_getxy(vc, start, NULL, NULL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void update_region(struct vc_data *vc, unsigned long start, int count)
|
||||
{
|
||||
WARN_CONSOLE_UNLOCKED();
|
||||
|
||||
if (DO_UPDATE(vc)) {
|
||||
if (con_should_update(vc)) {
|
||||
hide_cursor(vc);
|
||||
do_update_region(vc, start, count);
|
||||
set_cursor(vc);
|
||||
@ -413,7 +413,6 @@ static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink,
|
||||
return vc->vc_sw->con_build_attr(vc, _color, _intensity,
|
||||
_blink, _underline, _reverse, _italic);
|
||||
|
||||
#ifndef VT_BUF_VRAM_ONLY
|
||||
/*
|
||||
* ++roman: I completely changed the attribute format for monochrome
|
||||
* mode (!can_do_color). The formerly used MDA (monochrome display
|
||||
@ -448,9 +447,6 @@ static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink,
|
||||
a <<= 1;
|
||||
return a;
|
||||
}
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void update_attr(struct vc_data *vc)
|
||||
@ -470,10 +466,9 @@ void invert_screen(struct vc_data *vc, int offset, int count, int viewed)
|
||||
|
||||
count /= 2;
|
||||
p = screenpos(vc, offset, viewed);
|
||||
if (vc->vc_sw->con_invert_region)
|
||||
if (vc->vc_sw->con_invert_region) {
|
||||
vc->vc_sw->con_invert_region(vc, p, count);
|
||||
#ifndef VT_BUF_VRAM_ONLY
|
||||
else {
|
||||
} else {
|
||||
u16 *q = p;
|
||||
int cnt = count;
|
||||
u16 a;
|
||||
@ -501,8 +496,8 @@ void invert_screen(struct vc_data *vc, int offset, int count, int viewed)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (DO_UPDATE(vc))
|
||||
|
||||
if (con_should_update(vc))
|
||||
do_update_region(vc, (unsigned long) p, count);
|
||||
notify_update(vc);
|
||||
}
|
||||
@ -519,7 +514,7 @@ void complement_pos(struct vc_data *vc, int offset)
|
||||
if (old_offset != -1 && old_offset >= 0 &&
|
||||
old_offset < vc->vc_screenbuf_size) {
|
||||
scr_writew(old, screenpos(vc, old_offset, 1));
|
||||
if (DO_UPDATE(vc))
|
||||
if (con_should_update(vc))
|
||||
vc->vc_sw->con_putc(vc, old, oldy, oldx);
|
||||
notify_update(vc);
|
||||
}
|
||||
@ -534,7 +529,7 @@ void complement_pos(struct vc_data *vc, int offset)
|
||||
old = scr_readw(p);
|
||||
new = old ^ vc->vc_complement_mask;
|
||||
scr_writew(new, p);
|
||||
if (DO_UPDATE(vc)) {
|
||||
if (con_should_update(vc)) {
|
||||
oldx = (offset >> 1) % vc->vc_cols;
|
||||
oldy = (offset >> 1) / vc->vc_cols;
|
||||
vc->vc_sw->con_putc(vc, new, oldy, oldx);
|
||||
@ -550,7 +545,7 @@ static void insert_char(struct vc_data *vc, unsigned int nr)
|
||||
scr_memmovew(p + nr, p, (vc->vc_cols - vc->vc_x - nr) * 2);
|
||||
scr_memsetw(p, vc->vc_video_erase_char, nr * 2);
|
||||
vc->vc_need_wrap = 0;
|
||||
if (DO_UPDATE(vc))
|
||||
if (con_should_update(vc))
|
||||
do_update_region(vc, (unsigned long) p,
|
||||
vc->vc_cols - vc->vc_x);
|
||||
}
|
||||
@ -563,7 +558,7 @@ static void delete_char(struct vc_data *vc, unsigned int nr)
|
||||
scr_memsetw(p + vc->vc_cols - vc->vc_x - nr, vc->vc_video_erase_char,
|
||||
nr * 2);
|
||||
vc->vc_need_wrap = 0;
|
||||
if (DO_UPDATE(vc))
|
||||
if (con_should_update(vc))
|
||||
do_update_region(vc, (unsigned long) p,
|
||||
vc->vc_cols - vc->vc_x);
|
||||
}
|
||||
@ -583,7 +578,7 @@ static void add_softcursor(struct vc_data *vc)
|
||||
if ((type & 0x20) && ((softcursor_original & 0x7000) == (i & 0x7000))) i ^= 0x7000;
|
||||
if ((type & 0x40) && ((i & 0x700) == ((i & 0x7000) >> 4))) i ^= 0x0700;
|
||||
scr_writew(i, (u16 *) vc->vc_pos);
|
||||
if (DO_UPDATE(vc))
|
||||
if (con_should_update(vc))
|
||||
vc->vc_sw->con_putc(vc, i, vc->vc_y, vc->vc_x);
|
||||
}
|
||||
|
||||
@ -591,7 +586,7 @@ static void hide_softcursor(struct vc_data *vc)
|
||||
{
|
||||
if (softcursor_original != -1) {
|
||||
scr_writew(softcursor_original, (u16 *)vc->vc_pos);
|
||||
if (DO_UPDATE(vc))
|
||||
if (con_should_update(vc))
|
||||
vc->vc_sw->con_putc(vc, softcursor_original,
|
||||
vc->vc_y, vc->vc_x);
|
||||
softcursor_original = -1;
|
||||
@ -608,8 +603,7 @@ static void hide_cursor(struct vc_data *vc)
|
||||
|
||||
static void set_cursor(struct vc_data *vc)
|
||||
{
|
||||
if (!IS_FG(vc) || console_blanked ||
|
||||
vc->vc_mode == KD_GRAPHICS)
|
||||
if (!con_is_fg(vc) || console_blanked || vc->vc_mode == KD_GRAPHICS)
|
||||
return;
|
||||
if (vc->vc_deccm) {
|
||||
if (vc == sel_cons)
|
||||
@ -625,7 +619,7 @@ static void set_origin(struct vc_data *vc)
|
||||
{
|
||||
WARN_CONSOLE_UNLOCKED();
|
||||
|
||||
if (!CON_IS_VISIBLE(vc) ||
|
||||
if (!con_is_visible(vc) ||
|
||||
!vc->vc_sw->con_set_origin ||
|
||||
!vc->vc_sw->con_set_origin(vc))
|
||||
vc->vc_origin = (unsigned long)vc->vc_screenbuf;
|
||||
@ -673,12 +667,12 @@ void redraw_screen(struct vc_data *vc, int is_switch)
|
||||
struct vc_data *old_vc = vc_cons[fg_console].d;
|
||||
if (old_vc == vc)
|
||||
return;
|
||||
if (!CON_IS_VISIBLE(vc))
|
||||
if (!con_is_visible(vc))
|
||||
redraw = 1;
|
||||
*vc->vc_display_fg = vc;
|
||||
fg_console = vc->vc_num;
|
||||
hide_cursor(old_vc);
|
||||
if (!CON_IS_VISIBLE(old_vc)) {
|
||||
if (!con_is_visible(old_vc)) {
|
||||
save_screen(old_vc);
|
||||
set_origin(old_vc);
|
||||
}
|
||||
@ -954,7 +948,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
|
||||
tty_do_resize(tty, &ws);
|
||||
}
|
||||
|
||||
if (CON_IS_VISIBLE(vc))
|
||||
if (con_is_visible(vc))
|
||||
update_screen(vc);
|
||||
vt_event_post(VT_EVENT_RESIZE, vc->vc_num, vc->vc_num);
|
||||
return err;
|
||||
@ -1103,11 +1097,9 @@ static void gotoxay(struct vc_data *vc, int new_x, int new_y)
|
||||
gotoxy(vc, new_x, vc->vc_decom ? (vc->vc_top + new_y) : new_y);
|
||||
}
|
||||
|
||||
void scrollback(struct vc_data *vc, int lines)
|
||||
void scrollback(struct vc_data *vc)
|
||||
{
|
||||
if (!lines)
|
||||
lines = vc->vc_rows / 2;
|
||||
scrolldelta(-lines);
|
||||
scrolldelta(-(vc->vc_rows / 2));
|
||||
}
|
||||
|
||||
void scrollfront(struct vc_data *vc, int lines)
|
||||
@ -1186,7 +1178,7 @@ static void csi_J(struct vc_data *vc, int vpar)
|
||||
scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char,
|
||||
vc->vc_screenbuf_size >> 1);
|
||||
set_origin(vc);
|
||||
if (CON_IS_VISIBLE(vc))
|
||||
if (con_is_visible(vc))
|
||||
update_screen(vc);
|
||||
/* fall through */
|
||||
case 2: /* erase whole display */
|
||||
@ -1197,7 +1189,7 @@ static void csi_J(struct vc_data *vc, int vpar)
|
||||
return;
|
||||
}
|
||||
scr_memsetw(start, vc->vc_video_erase_char, 2 * count);
|
||||
if (DO_UPDATE(vc))
|
||||
if (con_should_update(vc))
|
||||
do_update_region(vc, (unsigned long) start, count);
|
||||
vc->vc_need_wrap = 0;
|
||||
}
|
||||
@ -1225,7 +1217,7 @@ static void csi_K(struct vc_data *vc, int vpar)
|
||||
}
|
||||
scr_memsetw(start, vc->vc_video_erase_char, 2 * count);
|
||||
vc->vc_need_wrap = 0;
|
||||
if (DO_UPDATE(vc))
|
||||
if (con_should_update(vc))
|
||||
do_update_region(vc, (unsigned long) start, count);
|
||||
}
|
||||
|
||||
@ -1238,7 +1230,7 @@ static void csi_X(struct vc_data *vc, int vpar) /* erase the following vpar posi
|
||||
count = (vpar > vc->vc_cols - vc->vc_x) ? (vc->vc_cols - vc->vc_x) : vpar;
|
||||
|
||||
scr_memsetw((unsigned short *)vc->vc_pos, vc->vc_video_erase_char, 2 * count);
|
||||
if (DO_UPDATE(vc))
|
||||
if (con_should_update(vc))
|
||||
vc->vc_sw->con_clear(vc, vc->vc_y, vc->vc_x, 1, count);
|
||||
vc->vc_need_wrap = 0;
|
||||
}
|
||||
@ -1255,48 +1247,87 @@ static void default_attr(struct vc_data *vc)
|
||||
|
||||
struct rgb { u8 r; u8 g; u8 b; };
|
||||
|
||||
static struct rgb rgb_from_256(int i)
|
||||
static void rgb_from_256(int i, struct rgb *c)
|
||||
{
|
||||
struct rgb c;
|
||||
if (i < 8) { /* Standard colours. */
|
||||
c.r = i&1 ? 0xaa : 0x00;
|
||||
c.g = i&2 ? 0xaa : 0x00;
|
||||
c.b = i&4 ? 0xaa : 0x00;
|
||||
c->r = i&1 ? 0xaa : 0x00;
|
||||
c->g = i&2 ? 0xaa : 0x00;
|
||||
c->b = i&4 ? 0xaa : 0x00;
|
||||
} else if (i < 16) {
|
||||
c.r = i&1 ? 0xff : 0x55;
|
||||
c.g = i&2 ? 0xff : 0x55;
|
||||
c.b = i&4 ? 0xff : 0x55;
|
||||
c->r = i&1 ? 0xff : 0x55;
|
||||
c->g = i&2 ? 0xff : 0x55;
|
||||
c->b = i&4 ? 0xff : 0x55;
|
||||
} else if (i < 232) { /* 6x6x6 colour cube. */
|
||||
c.r = (i - 16) / 36 * 85 / 2;
|
||||
c.g = (i - 16) / 6 % 6 * 85 / 2;
|
||||
c.b = (i - 16) % 6 * 85 / 2;
|
||||
c->r = (i - 16) / 36 * 85 / 2;
|
||||
c->g = (i - 16) / 6 % 6 * 85 / 2;
|
||||
c->b = (i - 16) % 6 * 85 / 2;
|
||||
} else /* Grayscale ramp. */
|
||||
c.r = c.g = c.b = i * 10 - 2312;
|
||||
return c;
|
||||
c->r = c->g = c->b = i * 10 - 2312;
|
||||
}
|
||||
|
||||
static void rgb_foreground(struct vc_data *vc, struct rgb c)
|
||||
static void rgb_foreground(struct vc_data *vc, const struct rgb *c)
|
||||
{
|
||||
u8 hue, max = c.r;
|
||||
if (c.g > max)
|
||||
max = c.g;
|
||||
if (c.b > max)
|
||||
max = c.b;
|
||||
hue = (c.r > max/2 ? 4 : 0)
|
||||
| (c.g > max/2 ? 2 : 0)
|
||||
| (c.b > max/2 ? 1 : 0);
|
||||
if (hue == 7 && max <= 0x55)
|
||||
hue = 0, vc->vc_intensity = 2;
|
||||
u8 hue = 0, max = max3(c->r, c->g, c->b);
|
||||
|
||||
if (c->r > max / 2)
|
||||
hue |= 4;
|
||||
if (c->g > max / 2)
|
||||
hue |= 2;
|
||||
if (c->b > max / 2)
|
||||
hue |= 1;
|
||||
|
||||
if (hue == 7 && max <= 0x55) {
|
||||
hue = 0;
|
||||
vc->vc_intensity = 2;
|
||||
} else if (max > 0xaa)
|
||||
vc->vc_intensity = 2;
|
||||
else
|
||||
vc->vc_intensity = (max > 0xaa) + 1;
|
||||
vc->vc_intensity = 1;
|
||||
|
||||
vc->vc_color = (vc->vc_color & 0xf0) | hue;
|
||||
}
|
||||
|
||||
static void rgb_background(struct vc_data *vc, struct rgb c)
|
||||
static void rgb_background(struct vc_data *vc, const struct rgb *c)
|
||||
{
|
||||
/* For backgrounds, err on the dark side. */
|
||||
vc->vc_color = (vc->vc_color & 0x0f)
|
||||
| (c.r&0x80) >> 1 | (c.g&0x80) >> 2 | (c.b&0x80) >> 3;
|
||||
| (c->r&0x80) >> 1 | (c->g&0x80) >> 2 | (c->b&0x80) >> 3;
|
||||
}
|
||||
|
||||
/*
|
||||
* ITU T.416 Higher colour modes. They break the usual properties of SGR codes
|
||||
* and thus need to be detected and ignored by hand. Strictly speaking, that
|
||||
* standard also wants : rather than ; as separators, contrary to ECMA-48, but
|
||||
* no one produces such codes and almost no one accepts them.
|
||||
*
|
||||
* Subcommands 3 (CMY) and 4 (CMYK) are so insane there's no point in
|
||||
* supporting them.
|
||||
*/
|
||||
static int vc_t416_color(struct vc_data *vc, int i,
|
||||
void(*set_color)(struct vc_data *vc, const struct rgb *c))
|
||||
{
|
||||
struct rgb c;
|
||||
|
||||
i++;
|
||||
if (i > vc->vc_npar)
|
||||
return i;
|
||||
|
||||
if (vc->vc_par[i] == 5 && i < vc->vc_npar) {
|
||||
/* 256 colours -- ubiquitous */
|
||||
i++;
|
||||
rgb_from_256(vc->vc_par[i], &c);
|
||||
} else if (vc->vc_par[i] == 2 && i <= vc->vc_npar + 3) {
|
||||
/* 24 bit -- extremely rare */
|
||||
c.r = vc->vc_par[i + 1];
|
||||
c.g = vc->vc_par[i + 2];
|
||||
c.b = vc->vc_par[i + 3];
|
||||
i += 3;
|
||||
} else
|
||||
return i;
|
||||
|
||||
set_color(vc, &c);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/* console_lock is held */
|
||||
@ -1306,135 +1337,91 @@ static void csi_m(struct vc_data *vc)
|
||||
|
||||
for (i = 0; i <= vc->vc_npar; i++)
|
||||
switch (vc->vc_par[i]) {
|
||||
case 0: /* all attributes off */
|
||||
default_attr(vc);
|
||||
break;
|
||||
case 1:
|
||||
vc->vc_intensity = 2;
|
||||
break;
|
||||
case 2:
|
||||
vc->vc_intensity = 0;
|
||||
break;
|
||||
case 3:
|
||||
vc->vc_italic = 1;
|
||||
break;
|
||||
case 4:
|
||||
vc->vc_underline = 1;
|
||||
break;
|
||||
case 5:
|
||||
vc->vc_blink = 1;
|
||||
break;
|
||||
case 7:
|
||||
vc->vc_reverse = 1;
|
||||
break;
|
||||
case 10: /* ANSI X3.64-1979 (SCO-ish?)
|
||||
* Select primary font, don't display
|
||||
* control chars if defined, don't set
|
||||
* bit 8 on output.
|
||||
*/
|
||||
vc->vc_translate = set_translate(vc->vc_charset == 0
|
||||
? vc->vc_G0_charset
|
||||
: vc->vc_G1_charset, vc);
|
||||
vc->vc_disp_ctrl = 0;
|
||||
vc->vc_toggle_meta = 0;
|
||||
break;
|
||||
case 11: /* ANSI X3.64-1979 (SCO-ish?)
|
||||
* Select first alternate font, lets
|
||||
* chars < 32 be displayed as ROM chars.
|
||||
*/
|
||||
vc->vc_translate = set_translate(IBMPC_MAP, vc);
|
||||
vc->vc_disp_ctrl = 1;
|
||||
vc->vc_toggle_meta = 0;
|
||||
break;
|
||||
case 12: /* ANSI X3.64-1979 (SCO-ish?)
|
||||
* Select second alternate font, toggle
|
||||
* high bit before displaying as ROM char.
|
||||
*/
|
||||
vc->vc_translate = set_translate(IBMPC_MAP, vc);
|
||||
vc->vc_disp_ctrl = 1;
|
||||
vc->vc_toggle_meta = 1;
|
||||
break;
|
||||
case 21:
|
||||
case 22:
|
||||
vc->vc_intensity = 1;
|
||||
break;
|
||||
case 23:
|
||||
vc->vc_italic = 0;
|
||||
break;
|
||||
case 24:
|
||||
vc->vc_underline = 0;
|
||||
break;
|
||||
case 25:
|
||||
vc->vc_blink = 0;
|
||||
break;
|
||||
case 27:
|
||||
vc->vc_reverse = 0;
|
||||
break;
|
||||
case 38: /* ITU T.416
|
||||
* Higher colour modes.
|
||||
* They break the usual properties of SGR codes
|
||||
* and thus need to be detected and ignored by
|
||||
* hand. Strictly speaking, that standard also
|
||||
* wants : rather than ; as separators, contrary
|
||||
* to ECMA-48, but no one produces such codes
|
||||
* and almost no one accepts them.
|
||||
*/
|
||||
i++;
|
||||
if (i > vc->vc_npar)
|
||||
break;
|
||||
if (vc->vc_par[i] == 5 && /* 256 colours */
|
||||
i < vc->vc_npar) { /* ubiquitous */
|
||||
i++;
|
||||
rgb_foreground(vc,
|
||||
rgb_from_256(vc->vc_par[i]));
|
||||
} else if (vc->vc_par[i] == 2 && /* 24 bit */
|
||||
i <= vc->vc_npar + 3) {/* extremely rare */
|
||||
struct rgb c = {
|
||||
.r = vc->vc_par[i + 1],
|
||||
.g = vc->vc_par[i + 2],
|
||||
.b = vc->vc_par[i + 3],
|
||||
};
|
||||
rgb_foreground(vc, c);
|
||||
i += 3;
|
||||
}
|
||||
/* Subcommands 3 (CMY) and 4 (CMYK) are so insane
|
||||
* there's no point in supporting them.
|
||||
*/
|
||||
break;
|
||||
case 48:
|
||||
i++;
|
||||
if (i > vc->vc_npar)
|
||||
break;
|
||||
if (vc->vc_par[i] == 5 && /* 256 colours */
|
||||
i < vc->vc_npar) {
|
||||
i++;
|
||||
rgb_background(vc,
|
||||
rgb_from_256(vc->vc_par[i]));
|
||||
} else if (vc->vc_par[i] == 2 && /* 24 bit */
|
||||
i <= vc->vc_npar + 3) {
|
||||
struct rgb c = {
|
||||
.r = vc->vc_par[i + 1],
|
||||
.g = vc->vc_par[i + 2],
|
||||
.b = vc->vc_par[i + 3],
|
||||
};
|
||||
rgb_background(vc, c);
|
||||
i += 3;
|
||||
}
|
||||
break;
|
||||
case 39:
|
||||
vc->vc_color = (vc->vc_def_color & 0x0f) | (vc->vc_color & 0xf0);
|
||||
break;
|
||||
case 49:
|
||||
vc->vc_color = (vc->vc_def_color & 0xf0) | (vc->vc_color & 0x0f);
|
||||
break;
|
||||
default:
|
||||
if (vc->vc_par[i] >= 30 && vc->vc_par[i] <= 37)
|
||||
vc->vc_color = color_table[vc->vc_par[i] - 30]
|
||||
| (vc->vc_color & 0xf0);
|
||||
else if (vc->vc_par[i] >= 40 && vc->vc_par[i] <= 47)
|
||||
vc->vc_color = (color_table[vc->vc_par[i] - 40] << 4)
|
||||
| (vc->vc_color & 0x0f);
|
||||
break;
|
||||
case 0: /* all attributes off */
|
||||
default_attr(vc);
|
||||
break;
|
||||
case 1:
|
||||
vc->vc_intensity = 2;
|
||||
break;
|
||||
case 2:
|
||||
vc->vc_intensity = 0;
|
||||
break;
|
||||
case 3:
|
||||
vc->vc_italic = 1;
|
||||
break;
|
||||
case 4:
|
||||
vc->vc_underline = 1;
|
||||
break;
|
||||
case 5:
|
||||
vc->vc_blink = 1;
|
||||
break;
|
||||
case 7:
|
||||
vc->vc_reverse = 1;
|
||||
break;
|
||||
case 10: /* ANSI X3.64-1979 (SCO-ish?)
|
||||
* Select primary font, don't display control chars if
|
||||
* defined, don't set bit 8 on output.
|
||||
*/
|
||||
vc->vc_translate = set_translate(vc->vc_charset == 0
|
||||
? vc->vc_G0_charset
|
||||
: vc->vc_G1_charset, vc);
|
||||
vc->vc_disp_ctrl = 0;
|
||||
vc->vc_toggle_meta = 0;
|
||||
break;
|
||||
case 11: /* ANSI X3.64-1979 (SCO-ish?)
|
||||
* Select first alternate font, lets chars < 32 be
|
||||
* displayed as ROM chars.
|
||||
*/
|
||||
vc->vc_translate = set_translate(IBMPC_MAP, vc);
|
||||
vc->vc_disp_ctrl = 1;
|
||||
vc->vc_toggle_meta = 0;
|
||||
break;
|
||||
case 12: /* ANSI X3.64-1979 (SCO-ish?)
|
||||
* Select second alternate font, toggle high bit
|
||||
* before displaying as ROM char.
|
||||
*/
|
||||
vc->vc_translate = set_translate(IBMPC_MAP, vc);
|
||||
vc->vc_disp_ctrl = 1;
|
||||
vc->vc_toggle_meta = 1;
|
||||
break;
|
||||
case 21:
|
||||
case 22:
|
||||
vc->vc_intensity = 1;
|
||||
break;
|
||||
case 23:
|
||||
vc->vc_italic = 0;
|
||||
break;
|
||||
case 24:
|
||||
vc->vc_underline = 0;
|
||||
break;
|
||||
case 25:
|
||||
vc->vc_blink = 0;
|
||||
break;
|
||||
case 27:
|
||||
vc->vc_reverse = 0;
|
||||
break;
|
||||
case 38:
|
||||
i = vc_t416_color(vc, i, rgb_foreground);
|
||||
break;
|
||||
case 48:
|
||||
i = vc_t416_color(vc, i, rgb_background);
|
||||
break;
|
||||
case 39:
|
||||
vc->vc_color = (vc->vc_def_color & 0x0f) |
|
||||
(vc->vc_color & 0xf0);
|
||||
break;
|
||||
case 49:
|
||||
vc->vc_color = (vc->vc_def_color & 0xf0) |
|
||||
(vc->vc_color & 0x0f);
|
||||
break;
|
||||
default:
|
||||
if (vc->vc_par[i] >= 30 && vc->vc_par[i] <= 37)
|
||||
vc->vc_color = color_table[vc->vc_par[i] - 30]
|
||||
| (vc->vc_color & 0xf0);
|
||||
else if (vc->vc_par[i] >= 40 && vc->vc_par[i] <= 47)
|
||||
vc->vc_color = (color_table[vc->vc_par[i] - 40] << 4)
|
||||
| (vc->vc_color & 0x0f);
|
||||
break;
|
||||
}
|
||||
update_attr(vc);
|
||||
}
|
||||
@ -1496,7 +1483,6 @@ static void set_mode(struct vc_data *vc, int on_off)
|
||||
clr_kbd(vc, decckm);
|
||||
break;
|
||||
case 3: /* 80/132 mode switch unimplemented */
|
||||
vc->vc_deccolm = on_off;
|
||||
#if 0
|
||||
vc_resize(deccolm ? 132 : 80, vc->vc_rows);
|
||||
/* this alone does not suffice; some user mode
|
||||
@ -2178,18 +2164,20 @@ static int is_double_width(uint32_t ucs)
|
||||
return bisearch(ucs, double_width, ARRAY_SIZE(double_width) - 1);
|
||||
}
|
||||
|
||||
static void con_flush(struct vc_data *vc, unsigned long draw_from,
|
||||
unsigned long draw_to, int *draw_x)
|
||||
{
|
||||
if (*draw_x < 0)
|
||||
return;
|
||||
|
||||
vc->vc_sw->con_putcs(vc, (u16 *)draw_from,
|
||||
(u16 *)draw_to - (u16 *)draw_from, vc->vc_y, *draw_x);
|
||||
*draw_x = -1;
|
||||
}
|
||||
|
||||
/* acquires console_lock */
|
||||
static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int count)
|
||||
{
|
||||
#ifdef VT_BUF_VRAM_ONLY
|
||||
#define FLUSH do { } while(0);
|
||||
#else
|
||||
#define FLUSH if (draw_x >= 0) { \
|
||||
vc->vc_sw->con_putcs(vc, (u16 *)draw_from, (u16 *)draw_to - (u16 *)draw_from, vc->vc_y, draw_x); \
|
||||
draw_x = -1; \
|
||||
}
|
||||
#endif
|
||||
|
||||
int c, tc, ok, n = 0, draw_x = -1;
|
||||
unsigned int currcons;
|
||||
unsigned long draw_from = 0, draw_to = 0;
|
||||
@ -2226,7 +2214,7 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
|
||||
charmask = himask ? 0x1ff : 0xff;
|
||||
|
||||
/* undraw cursor first */
|
||||
if (IS_FG(vc))
|
||||
if (con_is_fg(vc))
|
||||
hide_cursor(vc);
|
||||
|
||||
param.vc = vc;
|
||||
@ -2381,12 +2369,13 @@ rescan_last_byte:
|
||||
} else {
|
||||
vc_attr = ((vc->vc_attr) & 0x88) | (((vc->vc_attr) & 0x70) >> 4) | (((vc->vc_attr) & 0x07) << 4);
|
||||
}
|
||||
FLUSH
|
||||
con_flush(vc, draw_from, draw_to, &draw_x);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (vc->vc_need_wrap || vc->vc_decim)
|
||||
FLUSH
|
||||
con_flush(vc, draw_from, draw_to,
|
||||
&draw_x);
|
||||
if (vc->vc_need_wrap) {
|
||||
cr(vc);
|
||||
lf(vc);
|
||||
@ -2397,7 +2386,7 @@ rescan_last_byte:
|
||||
((vc_attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) :
|
||||
(vc_attr << 8) + tc,
|
||||
(u16 *) vc->vc_pos);
|
||||
if (DO_UPDATE(vc) && draw_x < 0) {
|
||||
if (con_should_update(vc) && draw_x < 0) {
|
||||
draw_x = vc->vc_x;
|
||||
draw_from = vc->vc_pos;
|
||||
}
|
||||
@ -2416,9 +2405,8 @@ rescan_last_byte:
|
||||
}
|
||||
notify_write(vc, c);
|
||||
|
||||
if (inverse) {
|
||||
FLUSH
|
||||
}
|
||||
if (inverse)
|
||||
con_flush(vc, draw_from, draw_to, &draw_x);
|
||||
|
||||
if (rescan) {
|
||||
rescan = 0;
|
||||
@ -2429,15 +2417,14 @@ rescan_last_byte:
|
||||
}
|
||||
continue;
|
||||
}
|
||||
FLUSH
|
||||
con_flush(vc, draw_from, draw_to, &draw_x);
|
||||
do_con_trol(tty, vc, orig);
|
||||
}
|
||||
FLUSH
|
||||
con_flush(vc, draw_from, draw_to, &draw_x);
|
||||
console_conditional_schedule();
|
||||
console_unlock();
|
||||
notify_update(vc);
|
||||
return n;
|
||||
#undef FLUSH
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2471,7 +2458,7 @@ static void console_callback(struct work_struct *ignored)
|
||||
if (scrollback_delta) {
|
||||
struct vc_data *vc = vc_cons[fg_console].d;
|
||||
clear_selection();
|
||||
if (vc->vc_mode == KD_TEXT)
|
||||
if (vc->vc_mode == KD_TEXT && vc->vc_sw->con_scrolldelta)
|
||||
vc->vc_sw->con_scrolldelta(vc, scrollback_delta);
|
||||
scrollback_delta = 0;
|
||||
}
|
||||
@ -2583,7 +2570,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
|
||||
goto quit;
|
||||
|
||||
/* undraw cursor first */
|
||||
if (IS_FG(vc))
|
||||
if (con_is_fg(vc))
|
||||
hide_cursor(vc);
|
||||
|
||||
start = (ushort *)vc->vc_pos;
|
||||
@ -2594,7 +2581,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
|
||||
c = *b++;
|
||||
if (c == 10 || c == 13 || c == 8 || vc->vc_need_wrap) {
|
||||
if (cnt > 0) {
|
||||
if (CON_IS_VISIBLE(vc))
|
||||
if (con_is_visible(vc))
|
||||
vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, vc->vc_x);
|
||||
vc->vc_x += cnt;
|
||||
if (vc->vc_need_wrap)
|
||||
@ -2626,7 +2613,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
|
||||
myx++;
|
||||
}
|
||||
if (cnt > 0) {
|
||||
if (CON_IS_VISIBLE(vc))
|
||||
if (con_is_visible(vc))
|
||||
vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, vc->vc_x);
|
||||
vc->vc_x += cnt;
|
||||
if (vc->vc_x == vc->vc_cols) {
|
||||
@ -3173,7 +3160,7 @@ static int do_bind_con_driver(const struct consw *csw, int first, int last,
|
||||
|
||||
j = i;
|
||||
|
||||
if (CON_IS_VISIBLE(vc)) {
|
||||
if (con_is_visible(vc)) {
|
||||
k = i;
|
||||
save_screen(vc);
|
||||
}
|
||||
@ -3981,7 +3968,7 @@ static void set_palette(struct vc_data *vc)
|
||||
{
|
||||
WARN_CONSOLE_UNLOCKED();
|
||||
|
||||
if (vc->vc_mode != KD_GRAPHICS)
|
||||
if (vc->vc_mode != KD_GRAPHICS && vc->vc_sw->con_set_palette)
|
||||
vc->vc_sw->con_set_palette(vc, color_table);
|
||||
}
|
||||
|
||||
|
@ -1006,16 +1006,10 @@ int vt_ioctl(struct tty_struct *tty,
|
||||
break;
|
||||
|
||||
case PIO_UNIMAPCLR:
|
||||
{ struct unimapinit ui;
|
||||
if (!perm)
|
||||
return -EPERM;
|
||||
ret = copy_from_user(&ui, up, sizeof(struct unimapinit));
|
||||
if (ret)
|
||||
ret = -EFAULT;
|
||||
else
|
||||
con_clear_unimap(vc, &ui);
|
||||
con_clear_unimap(vc);
|
||||
break;
|
||||
}
|
||||
|
||||
case PIO_UNIMAP:
|
||||
case GIO_UNIMAP:
|
||||
|
@ -1285,18 +1285,22 @@ int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data)
|
||||
}
|
||||
|
||||
int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
|
||||
u32 dest, int length, size_t *bytes_written)
|
||||
u32 dest, int length)
|
||||
{
|
||||
size_t dummy;
|
||||
|
||||
return sisusb_write_mem_bulk(sisusb, dest, src, length,
|
||||
NULL, 0, bytes_written);
|
||||
NULL, 0, &dummy);
|
||||
}
|
||||
|
||||
#ifdef SISUSBENDIANTEST
|
||||
int sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest,
|
||||
u32 src, int length, size_t *bytes_written)
|
||||
static int sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest,
|
||||
u32 src, int length)
|
||||
{
|
||||
size_t dummy;
|
||||
|
||||
return sisusb_read_mem_bulk(sisusb, src, dest, length,
|
||||
NULL, bytes_written);
|
||||
NULL, &dummy);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@ -1306,16 +1310,14 @@ static void sisusb_testreadwrite(struct sisusb_usb_data *sisusb)
|
||||
{
|
||||
static char srcbuffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
|
||||
char destbuffer[10];
|
||||
size_t dummy;
|
||||
int i, j;
|
||||
|
||||
sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7, &dummy);
|
||||
sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7);
|
||||
|
||||
for (i = 1; i <= 7; i++) {
|
||||
dev_dbg(&sisusb->sisusb_dev->dev,
|
||||
"sisusb: rwtest %d bytes\n", i);
|
||||
sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase,
|
||||
i, &dummy);
|
||||
sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase, i);
|
||||
for (j = 0; j < i; j++) {
|
||||
dev_dbg(&sisusb->sisusb_dev->dev,
|
||||
"rwtest read[%d] = %x\n",
|
||||
@ -2276,7 +2278,6 @@ int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init)
|
||||
const struct font_desc *myfont;
|
||||
u8 *tempbuf;
|
||||
u16 *tempbufb;
|
||||
size_t written;
|
||||
static const char bootstring[] =
|
||||
"SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
|
||||
static const char bootlogo[] = "(o_ //\\ V_/_";
|
||||
@ -2343,18 +2344,15 @@ int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init)
|
||||
*(tempbufb++) = 0x0700 | bootstring[i++];
|
||||
|
||||
ret |= sisusb_copy_memory(sisusb, tempbuf,
|
||||
sisusb->vrambase, 8192, &written);
|
||||
sisusb->vrambase, 8192);
|
||||
|
||||
vfree(tempbuf);
|
||||
|
||||
}
|
||||
|
||||
} else if (sisusb->scrbuf) {
|
||||
|
||||
ret |= sisusb_copy_memory(sisusb, (char *)sisusb->scrbuf,
|
||||
sisusb->vrambase, sisusb->scrbuf_size,
|
||||
&written);
|
||||
|
||||
sisusb->vrambase, sisusb->scrbuf_size);
|
||||
}
|
||||
|
||||
if (sisusb->sisusb_cursor_size_from >= 0 &&
|
||||
|
@ -370,7 +370,6 @@ static void
|
||||
sisusbcon_putc(struct vc_data *c, int ch, int y, int x)
|
||||
{
|
||||
struct sisusb_usb_data *sisusb;
|
||||
ssize_t written;
|
||||
|
||||
sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num);
|
||||
if (!sisusb)
|
||||
@ -384,7 +383,7 @@ sisusbcon_putc(struct vc_data *c, int ch, int y, int x)
|
||||
|
||||
|
||||
sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y),
|
||||
(long)SISUSB_HADDR(x, y), 2, &written);
|
||||
(long)SISUSB_HADDR(x, y), 2);
|
||||
|
||||
mutex_unlock(&sisusb->lock);
|
||||
}
|
||||
@ -395,7 +394,6 @@ sisusbcon_putcs(struct vc_data *c, const unsigned short *s,
|
||||
int count, int y, int x)
|
||||
{
|
||||
struct sisusb_usb_data *sisusb;
|
||||
ssize_t written;
|
||||
u16 *dest;
|
||||
int i;
|
||||
|
||||
@ -420,7 +418,7 @@ sisusbcon_putcs(struct vc_data *c, const unsigned short *s,
|
||||
}
|
||||
|
||||
sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y),
|
||||
(long)SISUSB_HADDR(x, y), count * 2, &written);
|
||||
(long)SISUSB_HADDR(x, y), count * 2);
|
||||
|
||||
mutex_unlock(&sisusb->lock);
|
||||
}
|
||||
@ -431,7 +429,6 @@ sisusbcon_clear(struct vc_data *c, int y, int x, int height, int width)
|
||||
{
|
||||
struct sisusb_usb_data *sisusb;
|
||||
u16 eattr = c->vc_video_erase_char;
|
||||
ssize_t written;
|
||||
int i, length, cols;
|
||||
u16 *dest;
|
||||
|
||||
@ -475,41 +472,7 @@ sisusbcon_clear(struct vc_data *c, int y, int x, int height, int width)
|
||||
|
||||
|
||||
sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(x, y),
|
||||
(long)SISUSB_HADDR(x, y), length, &written);
|
||||
|
||||
mutex_unlock(&sisusb->lock);
|
||||
}
|
||||
|
||||
/* Interface routine */
|
||||
static void
|
||||
sisusbcon_bmove(struct vc_data *c, int sy, int sx,
|
||||
int dy, int dx, int height, int width)
|
||||
{
|
||||
struct sisusb_usb_data *sisusb;
|
||||
ssize_t written;
|
||||
int cols, length;
|
||||
|
||||
if (width <= 0 || height <= 0)
|
||||
return;
|
||||
|
||||
sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num);
|
||||
if (!sisusb)
|
||||
return;
|
||||
|
||||
/* sisusb->lock is down */
|
||||
|
||||
cols = sisusb->sisusb_num_columns;
|
||||
|
||||
if (sisusb_is_inactive(c, sisusb)) {
|
||||
mutex_unlock(&sisusb->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
length = ((height * cols) - dx - (cols - width - dx)) * 2;
|
||||
|
||||
|
||||
sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(dx, dy),
|
||||
(long)SISUSB_HADDR(dx, dy), length, &written);
|
||||
(long)SISUSB_HADDR(x, y), length);
|
||||
|
||||
mutex_unlock(&sisusb->lock);
|
||||
}
|
||||
@ -519,7 +482,6 @@ static int
|
||||
sisusbcon_switch(struct vc_data *c)
|
||||
{
|
||||
struct sisusb_usb_data *sisusb;
|
||||
ssize_t written;
|
||||
int length;
|
||||
|
||||
/* Returnvalue 0 means we have fully restored screen,
|
||||
@ -559,7 +521,7 @@ sisusbcon_switch(struct vc_data *c)
|
||||
|
||||
sisusb_copy_memory(sisusb, (unsigned char *)c->vc_origin,
|
||||
(long)SISUSB_HADDR(0, 0),
|
||||
length, &written);
|
||||
length);
|
||||
|
||||
mutex_unlock(&sisusb->lock);
|
||||
|
||||
@ -600,7 +562,7 @@ sisusbcon_save_screen(struct vc_data *c)
|
||||
}
|
||||
|
||||
/* interface routine */
|
||||
static int
|
||||
static void
|
||||
sisusbcon_set_palette(struct vc_data *c, const unsigned char *table)
|
||||
{
|
||||
struct sisusb_usb_data *sisusb;
|
||||
@ -608,18 +570,18 @@ sisusbcon_set_palette(struct vc_data *c, const unsigned char *table)
|
||||
|
||||
/* Return value not used by vt */
|
||||
|
||||
if (!CON_IS_VISIBLE(c))
|
||||
return -EINVAL;
|
||||
if (!con_is_visible(c))
|
||||
return;
|
||||
|
||||
sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num);
|
||||
if (!sisusb)
|
||||
return -EINVAL;
|
||||
return;
|
||||
|
||||
/* sisusb->lock is down */
|
||||
|
||||
if (sisusb_is_inactive(c, sisusb)) {
|
||||
mutex_unlock(&sisusb->lock);
|
||||
return -EINVAL;
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = j = 0; i < 16; i++) {
|
||||
@ -634,8 +596,6 @@ sisusbcon_set_palette(struct vc_data *c, const unsigned char *table)
|
||||
}
|
||||
|
||||
mutex_unlock(&sisusb->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* interface routine */
|
||||
@ -644,7 +604,6 @@ sisusbcon_blank(struct vc_data *c, int blank, int mode_switch)
|
||||
{
|
||||
struct sisusb_usb_data *sisusb;
|
||||
u8 sr1, cr17, pmreg, cr63;
|
||||
ssize_t written;
|
||||
int ret = 0;
|
||||
|
||||
sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num);
|
||||
@ -672,7 +631,7 @@ sisusbcon_blank(struct vc_data *c, int blank, int mode_switch)
|
||||
(unsigned char *)c->vc_origin,
|
||||
(u32)(sisusb->vrambase +
|
||||
(c->vc_origin - sisusb->scrbuf)),
|
||||
c->vc_screenbuf_size, &written);
|
||||
c->vc_screenbuf_size);
|
||||
sisusb->con_blanked = 1;
|
||||
ret = 1;
|
||||
break;
|
||||
@ -723,24 +682,22 @@ sisusbcon_blank(struct vc_data *c, int blank, int mode_switch)
|
||||
}
|
||||
|
||||
/* interface routine */
|
||||
static int
|
||||
static void
|
||||
sisusbcon_scrolldelta(struct vc_data *c, int lines)
|
||||
{
|
||||
struct sisusb_usb_data *sisusb;
|
||||
int margin = c->vc_size_row * 4;
|
||||
int ul, we, p, st;
|
||||
|
||||
/* The return value does not seem to be used */
|
||||
|
||||
sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num);
|
||||
if (!sisusb)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
/* sisusb->lock is down */
|
||||
|
||||
if (sisusb_is_inactive(c, sisusb)) {
|
||||
mutex_unlock(&sisusb->lock);
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!lines) /* Turn scrollback off */
|
||||
@ -780,8 +737,6 @@ sisusbcon_scrolldelta(struct vc_data *c, int lines)
|
||||
sisusbcon_set_start_address(sisusb, c);
|
||||
|
||||
mutex_unlock(&sisusb->lock);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Interface routine */
|
||||
@ -860,7 +815,6 @@ sisusbcon_scroll_area(struct vc_data *c, struct sisusb_usb_data *sisusb,
|
||||
int cols = sisusb->sisusb_num_columns;
|
||||
int length = ((b - t) * cols) * 2;
|
||||
u16 eattr = c->vc_video_erase_char;
|
||||
ssize_t written;
|
||||
|
||||
/* sisusb->lock is down */
|
||||
|
||||
@ -890,7 +844,7 @@ sisusbcon_scroll_area(struct vc_data *c, struct sisusb_usb_data *sisusb,
|
||||
}
|
||||
|
||||
sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(0, t),
|
||||
(long)SISUSB_HADDR(0, t), length, &written);
|
||||
(long)SISUSB_HADDR(0, t), length);
|
||||
|
||||
mutex_unlock(&sisusb->lock);
|
||||
|
||||
@ -903,7 +857,6 @@ sisusbcon_scroll(struct vc_data *c, int t, int b, int dir, int lines)
|
||||
{
|
||||
struct sisusb_usb_data *sisusb;
|
||||
u16 eattr = c->vc_video_erase_char;
|
||||
ssize_t written;
|
||||
int copyall = 0;
|
||||
unsigned long oldorigin;
|
||||
unsigned int delta = lines * c->vc_size_row;
|
||||
@ -996,18 +949,18 @@ sisusbcon_scroll(struct vc_data *c, int t, int b, int dir, int lines)
|
||||
sisusb_copy_memory(sisusb,
|
||||
(char *)c->vc_origin,
|
||||
(u32)(sisusb->vrambase + originoffset),
|
||||
c->vc_screenbuf_size, &written);
|
||||
c->vc_screenbuf_size);
|
||||
else if (dir == SM_UP)
|
||||
sisusb_copy_memory(sisusb,
|
||||
(char *)c->vc_origin + c->vc_screenbuf_size - delta,
|
||||
(u32)sisusb->vrambase + originoffset +
|
||||
c->vc_screenbuf_size - delta,
|
||||
delta, &written);
|
||||
delta);
|
||||
else
|
||||
sisusb_copy_memory(sisusb,
|
||||
(char *)c->vc_origin,
|
||||
(u32)(sisusb->vrambase + originoffset),
|
||||
delta, &written);
|
||||
delta);
|
||||
|
||||
c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
|
||||
c->vc_visible_origin = c->vc_origin;
|
||||
@ -1273,7 +1226,7 @@ sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot,
|
||||
struct vc_data *vc = vc_cons[i].d;
|
||||
|
||||
if (vc && vc->vc_sw == &sisusb_con) {
|
||||
if (CON_IS_VISIBLE(vc)) {
|
||||
if (con_is_visible(vc)) {
|
||||
vc->vc_sw->con_cursor(vc, CM_DRAW);
|
||||
}
|
||||
vc->vc_font.height = fh;
|
||||
@ -1385,7 +1338,6 @@ static const struct consw sisusb_con = {
|
||||
.con_putcs = sisusbcon_putcs,
|
||||
.con_cursor = sisusbcon_cursor,
|
||||
.con_scroll = sisusbcon_scroll,
|
||||
.con_bmove = sisusbcon_bmove,
|
||||
.con_switch = sisusbcon_switch,
|
||||
.con_blank = sisusbcon_blank,
|
||||
.con_font_set = sisusbcon_font_set,
|
||||
@ -1433,15 +1385,12 @@ static const struct consw sisusb_dummy_con = {
|
||||
.con_putcs = SISUSBCONDUMMY,
|
||||
.con_cursor = SISUSBCONDUMMY,
|
||||
.con_scroll = SISUSBCONDUMMY,
|
||||
.con_bmove = SISUSBCONDUMMY,
|
||||
.con_switch = SISUSBCONDUMMY,
|
||||
.con_blank = SISUSBCONDUMMY,
|
||||
.con_font_set = SISUSBCONDUMMY,
|
||||
.con_font_get = SISUSBCONDUMMY,
|
||||
.con_font_default = SISUSBCONDUMMY,
|
||||
.con_font_copy = SISUSBCONDUMMY,
|
||||
.con_set_palette = SISUSBCONDUMMY,
|
||||
.con_scrolldelta = SISUSBCONDUMMY,
|
||||
};
|
||||
|
||||
int
|
||||
|
@ -828,7 +828,7 @@ void sisusb_delete(struct kref *kref);
|
||||
int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data);
|
||||
int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 * data);
|
||||
int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
|
||||
u32 dest, int length, size_t * bytes_written);
|
||||
u32 dest, int length);
|
||||
int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init);
|
||||
int sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot,
|
||||
u8 * arg, int cmapsz, int ch512, int dorecalc,
|
||||
|
@ -64,14 +64,11 @@ const struct consw dummy_con = {
|
||||
.con_putcs = DUMMY,
|
||||
.con_cursor = DUMMY,
|
||||
.con_scroll = DUMMY,
|
||||
.con_bmove = DUMMY,
|
||||
.con_switch = DUMMY,
|
||||
.con_blank = DUMMY,
|
||||
.con_font_set = DUMMY,
|
||||
.con_font_get = DUMMY,
|
||||
.con_font_default = DUMMY,
|
||||
.con_font_copy = DUMMY,
|
||||
.con_set_palette = DUMMY,
|
||||
.con_scrolldelta = DUMMY,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(dummy_con);
|
||||
|
@ -170,8 +170,7 @@ static void fbcon_bmove(struct vc_data *vc, int sy, int sx, int dy, int dx,
|
||||
int height, int width);
|
||||
static int fbcon_switch(struct vc_data *vc);
|
||||
static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch);
|
||||
static int fbcon_set_palette(struct vc_data *vc, const unsigned char *table);
|
||||
static int fbcon_scrolldelta(struct vc_data *vc, int lines);
|
||||
static void fbcon_set_palette(struct vc_data *vc, const unsigned char *table);
|
||||
|
||||
/*
|
||||
* Internal routines
|
||||
@ -381,7 +380,7 @@ static void fb_flashcursor(struct work_struct *work)
|
||||
if (ops && ops->currcon != -1)
|
||||
vc = vc_cons[ops->currcon].d;
|
||||
|
||||
if (!vc || !CON_IS_VISIBLE(vc) ||
|
||||
if (!vc || !con_is_visible(vc) ||
|
||||
registered_fb[con2fb_map[vc->vc_num]] != info ||
|
||||
vc->vc_deccm != 1) {
|
||||
console_unlock();
|
||||
@ -619,7 +618,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,
|
||||
erase,
|
||||
vc->vc_size_row * logo_lines);
|
||||
|
||||
if (CON_IS_VISIBLE(vc) && vc->vc_mode == KD_TEXT) {
|
||||
if (con_is_visible(vc) && vc->vc_mode == KD_TEXT) {
|
||||
fbcon_clear_margins(vc, 0);
|
||||
update_screen(vc);
|
||||
}
|
||||
@ -1113,7 +1112,7 @@ static void fbcon_init(struct vc_data *vc, int init)
|
||||
*
|
||||
* We need to do it in fbcon_init() to prevent screen corruption.
|
||||
*/
|
||||
if (CON_IS_VISIBLE(vc) && vc->vc_mode == KD_TEXT) {
|
||||
if (con_is_visible(vc) && vc->vc_mode == KD_TEXT) {
|
||||
if (info->fbops->fb_set_par &&
|
||||
!(ops->flags & FBCON_FLAGS_INIT)) {
|
||||
ret = info->fbops->fb_set_par(info);
|
||||
@ -1193,7 +1192,7 @@ static void fbcon_deinit(struct vc_data *vc)
|
||||
if (!ops)
|
||||
goto finished;
|
||||
|
||||
if (CON_IS_VISIBLE(vc))
|
||||
if (con_is_visible(vc))
|
||||
fbcon_del_cursor_timer(info);
|
||||
|
||||
ops->flags &= ~FBCON_FLAGS_INIT;
|
||||
@ -1398,7 +1397,7 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
|
||||
rows /= vc->vc_font.height;
|
||||
vc_resize(vc, cols, rows);
|
||||
|
||||
if (CON_IS_VISIBLE(vc)) {
|
||||
if (con_is_visible(vc)) {
|
||||
update_screen(vc);
|
||||
if (softback_buf)
|
||||
fbcon_update_softback(vc);
|
||||
@ -2146,7 +2145,7 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width,
|
||||
return -EINVAL;
|
||||
|
||||
DPRINTK("resize now %ix%i\n", var.xres, var.yres);
|
||||
if (CON_IS_VISIBLE(vc)) {
|
||||
if (con_is_visible(vc)) {
|
||||
var.activate = FB_ACTIVATE_NOW |
|
||||
FB_ACTIVATE_FORCE;
|
||||
fb_set_var(info, &var);
|
||||
@ -2449,7 +2448,7 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
|
||||
int cnt;
|
||||
char *old_data = NULL;
|
||||
|
||||
if (CON_IS_VISIBLE(vc) && softback_lines)
|
||||
if (con_is_visible(vc) && softback_lines)
|
||||
fbcon_set_origin(vc);
|
||||
|
||||
resize = (w != vc->vc_font.width) || (h != vc->vc_font.height);
|
||||
@ -2530,9 +2529,9 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
|
||||
cols /= w;
|
||||
rows /= h;
|
||||
vc_resize(vc, cols, rows);
|
||||
if (CON_IS_VISIBLE(vc) && softback_buf)
|
||||
if (con_is_visible(vc) && softback_buf)
|
||||
fbcon_update_softback(vc);
|
||||
} else if (CON_IS_VISIBLE(vc)
|
||||
} else if (con_is_visible(vc)
|
||||
&& vc->vc_mode == KD_TEXT) {
|
||||
fbcon_clear_margins(vc, 0);
|
||||
update_screen(vc);
|
||||
@ -2652,17 +2651,17 @@ static struct fb_cmap palette_cmap = {
|
||||
0, 16, palette_red, palette_green, palette_blue, NULL
|
||||
};
|
||||
|
||||
static int fbcon_set_palette(struct vc_data *vc, const unsigned char *table)
|
||||
static void fbcon_set_palette(struct vc_data *vc, const unsigned char *table)
|
||||
{
|
||||
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
|
||||
int i, j, k, depth;
|
||||
u8 val;
|
||||
|
||||
if (fbcon_is_inactive(vc, info))
|
||||
return -EINVAL;
|
||||
return;
|
||||
|
||||
if (!CON_IS_VISIBLE(vc))
|
||||
return 0;
|
||||
if (!con_is_visible(vc))
|
||||
return;
|
||||
|
||||
depth = fb_get_color_depth(&info->var, &info->fix);
|
||||
if (depth > 3) {
|
||||
@ -2684,7 +2683,7 @@ static int fbcon_set_palette(struct vc_data *vc, const unsigned char *table)
|
||||
} else
|
||||
fb_copy_cmap(fb_default_cmap(1 << depth), &palette_cmap);
|
||||
|
||||
return fb_set_cmap(&palette_cmap, info);
|
||||
fb_set_cmap(&palette_cmap, info);
|
||||
}
|
||||
|
||||
static u16 *fbcon_screen_pos(struct vc_data *vc, int offset)
|
||||
@ -2765,7 +2764,7 @@ static void fbcon_invert_region(struct vc_data *vc, u16 * p, int cnt)
|
||||
}
|
||||
}
|
||||
|
||||
static int fbcon_scrolldelta(struct vc_data *vc, int lines)
|
||||
static void fbcon_scrolldelta(struct vc_data *vc, int lines)
|
||||
{
|
||||
struct fb_info *info = registered_fb[con2fb_map[fg_console]];
|
||||
struct fbcon_ops *ops = info->fbcon_par;
|
||||
@ -2774,9 +2773,9 @@ static int fbcon_scrolldelta(struct vc_data *vc, int lines)
|
||||
|
||||
if (softback_top) {
|
||||
if (vc->vc_num != fg_console)
|
||||
return 0;
|
||||
return;
|
||||
if (vc->vc_mode != KD_TEXT || !lines)
|
||||
return 0;
|
||||
return;
|
||||
if (logo_shown >= 0) {
|
||||
struct vc_data *conp2 = vc_cons[logo_shown].d;
|
||||
|
||||
@ -2809,11 +2808,11 @@ static int fbcon_scrolldelta(struct vc_data *vc, int lines)
|
||||
fbcon_cursor(vc, CM_ERASE | CM_SOFTBACK);
|
||||
fbcon_redraw_softback(vc, disp, lines);
|
||||
fbcon_cursor(vc, CM_DRAW | CM_SOFTBACK);
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!scrollback_phys_max)
|
||||
return -ENOSYS;
|
||||
return;
|
||||
|
||||
scrollback_old = scrollback_current;
|
||||
scrollback_current -= lines;
|
||||
@ -2822,10 +2821,10 @@ static int fbcon_scrolldelta(struct vc_data *vc, int lines)
|
||||
else if (scrollback_current > scrollback_max)
|
||||
scrollback_current = scrollback_max;
|
||||
if (scrollback_current == scrollback_old)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
if (fbcon_is_inactive(vc, info))
|
||||
return 0;
|
||||
return;
|
||||
|
||||
fbcon_cursor(vc, CM_ERASE);
|
||||
|
||||
@ -2852,7 +2851,6 @@ static int fbcon_scrolldelta(struct vc_data *vc, int lines)
|
||||
|
||||
if (!scrollback_current)
|
||||
fbcon_cursor(vc, CM_DRAW);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fbcon_set_origin(struct vc_data *vc)
|
||||
@ -2904,7 +2902,7 @@ static void fbcon_modechanged(struct fb_info *info)
|
||||
p = &fb_display[vc->vc_num];
|
||||
set_blitting_type(vc, info);
|
||||
|
||||
if (CON_IS_VISIBLE(vc)) {
|
||||
if (con_is_visible(vc)) {
|
||||
var_to_display(p, &info->var, info);
|
||||
cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
|
||||
rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
|
||||
@ -2943,7 +2941,7 @@ static void fbcon_set_all_vcs(struct fb_info *info)
|
||||
registered_fb[con2fb_map[i]] != info)
|
||||
continue;
|
||||
|
||||
if (CON_IS_VISIBLE(vc)) {
|
||||
if (con_is_visible(vc)) {
|
||||
fg = i;
|
||||
continue;
|
||||
}
|
||||
@ -3182,7 +3180,7 @@ static void fbcon_fb_blanked(struct fb_info *info, int blank)
|
||||
registered_fb[con2fb_map[ops->currcon]] != info)
|
||||
return;
|
||||
|
||||
if (CON_IS_VISIBLE(vc)) {
|
||||
if (con_is_visible(vc)) {
|
||||
if (blank)
|
||||
do_blank_screen(0);
|
||||
else
|
||||
@ -3336,7 +3334,6 @@ static const struct consw fb_con = {
|
||||
.con_putcs = fbcon_putcs,
|
||||
.con_cursor = fbcon_cursor,
|
||||
.con_scroll = fbcon_scroll,
|
||||
.con_bmove = fbcon_bmove,
|
||||
.con_switch = fbcon_switch,
|
||||
.con_blank = fbcon_blank,
|
||||
.con_font_set = fbcon_set_font,
|
||||
|
@ -444,48 +444,11 @@ static void mdacon_clear(struct vc_data *c, int y, int x,
|
||||
}
|
||||
}
|
||||
|
||||
static void mdacon_bmove(struct vc_data *c, int sy, int sx,
|
||||
int dy, int dx, int height, int width)
|
||||
{
|
||||
u16 *src, *dest;
|
||||
|
||||
if (width <= 0 || height <= 0)
|
||||
return;
|
||||
|
||||
if (sx==0 && dx==0 && width==mda_num_columns) {
|
||||
scr_memmovew(MDA_ADDR(0,dy), MDA_ADDR(0,sy), height*width*2);
|
||||
|
||||
} else if (dy < sy || (dy == sy && dx < sx)) {
|
||||
src = MDA_ADDR(sx, sy);
|
||||
dest = MDA_ADDR(dx, dy);
|
||||
|
||||
for (; height > 0; height--) {
|
||||
scr_memmovew(dest, src, width*2);
|
||||
src += mda_num_columns;
|
||||
dest += mda_num_columns;
|
||||
}
|
||||
} else {
|
||||
src = MDA_ADDR(sx, sy+height-1);
|
||||
dest = MDA_ADDR(dx, dy+height-1);
|
||||
|
||||
for (; height > 0; height--) {
|
||||
scr_memmovew(dest, src, width*2);
|
||||
src -= mda_num_columns;
|
||||
dest -= mda_num_columns;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int mdacon_switch(struct vc_data *c)
|
||||
{
|
||||
return 1; /* redrawing needed */
|
||||
}
|
||||
|
||||
static int mdacon_set_palette(struct vc_data *c, const unsigned char *table)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int mdacon_blank(struct vc_data *c, int blank, int mode_switch)
|
||||
{
|
||||
if (mda_type == TYPE_MDA) {
|
||||
@ -505,11 +468,6 @@ static int mdacon_blank(struct vc_data *c, int blank, int mode_switch)
|
||||
}
|
||||
}
|
||||
|
||||
static int mdacon_scrolldelta(struct vc_data *c, int lines)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mdacon_cursor(struct vc_data *c, int mode)
|
||||
{
|
||||
if (mode == CM_ERASE) {
|
||||
@ -574,11 +532,8 @@ static const struct consw mda_con = {
|
||||
.con_putcs = mdacon_putcs,
|
||||
.con_cursor = mdacon_cursor,
|
||||
.con_scroll = mdacon_scroll,
|
||||
.con_bmove = mdacon_bmove,
|
||||
.con_switch = mdacon_switch,
|
||||
.con_blank = mdacon_blank,
|
||||
.con_set_palette = mdacon_set_palette,
|
||||
.con_scrolldelta = mdacon_scrolldelta,
|
||||
.con_build_attr = mdacon_build_attr,
|
||||
.con_invert_region = mdacon_invert_region,
|
||||
};
|
||||
|
@ -574,17 +574,6 @@ static int newport_font_set(struct vc_data *vc, struct console_font *font, unsig
|
||||
return newport_set_font(vc->vc_num, font);
|
||||
}
|
||||
|
||||
static int newport_set_palette(struct vc_data *vc, const unsigned char *table)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int newport_scrolldelta(struct vc_data *vc, int lines)
|
||||
{
|
||||
/* there is (nearly) no off-screen memory, so we can't scroll back */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int newport_scroll(struct vc_data *vc, int t, int b, int dir,
|
||||
int lines)
|
||||
{
|
||||
@ -684,34 +673,6 @@ static int newport_scroll(struct vc_data *vc, int t, int b, int dir,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void newport_bmove(struct vc_data *vc, int sy, int sx, int dy,
|
||||
int dx, int h, int w)
|
||||
{
|
||||
short xs, ys, xe, ye, xoffs, yoffs;
|
||||
|
||||
xs = sx << 3;
|
||||
xe = ((sx + w) << 3) - 1;
|
||||
/*
|
||||
* as bmove is only used to move stuff around in the same line
|
||||
* (h == 1), we don't care about wrap arounds caused by topscan != 0
|
||||
*/
|
||||
ys = ((sy << 4) + topscan) & 0x3ff;
|
||||
ye = (((sy + h) << 4) - 1 + topscan) & 0x3ff;
|
||||
xoffs = (dx - sx) << 3;
|
||||
yoffs = (dy - sy) << 4;
|
||||
if (xoffs > 0) {
|
||||
/* move to the right, exchange starting points */
|
||||
swap(xe, xs);
|
||||
}
|
||||
newport_wait(npregs);
|
||||
npregs->set.drawmode0 = (NPORT_DMODE0_S2S | NPORT_DMODE0_BLOCK |
|
||||
NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX
|
||||
| NPORT_DMODE0_STOPY);
|
||||
npregs->set.xystarti = (xs << 16) | ys;
|
||||
npregs->set.xyendi = (xe << 16) | ye;
|
||||
npregs->go.xymove = (xoffs << 16) | yoffs;
|
||||
}
|
||||
|
||||
static int newport_dummy(struct vc_data *c)
|
||||
{
|
||||
return 0;
|
||||
@ -729,13 +690,10 @@ const struct consw newport_con = {
|
||||
.con_putcs = newport_putcs,
|
||||
.con_cursor = newport_cursor,
|
||||
.con_scroll = newport_scroll,
|
||||
.con_bmove = newport_bmove,
|
||||
.con_switch = newport_switch,
|
||||
.con_blank = newport_blank,
|
||||
.con_font_set = newport_font_set,
|
||||
.con_font_default = newport_font_default,
|
||||
.con_set_palette = newport_set_palette,
|
||||
.con_scrolldelta = newport_scrolldelta,
|
||||
.con_set_origin = DUMMY,
|
||||
.con_save_screen = DUMMY
|
||||
};
|
||||
|
@ -79,11 +79,6 @@ static const char *sticon_startup(void)
|
||||
return "STI console";
|
||||
}
|
||||
|
||||
static int sticon_set_palette(struct vc_data *c, const unsigned char *table)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void sticon_putc(struct vc_data *conp, int c, int ypos, int xpos)
|
||||
{
|
||||
int redraw_cursor = 0;
|
||||
@ -182,22 +177,6 @@ static int sticon_scroll(struct vc_data *conp, int t, int b, int dir, int count)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sticon_bmove(struct vc_data *conp, int sy, int sx,
|
||||
int dy, int dx, int height, int width)
|
||||
{
|
||||
if (!width || !height)
|
||||
return;
|
||||
#if 0
|
||||
if (((sy <= p->cursor_y) && (p->cursor_y < sy+height) &&
|
||||
(sx <= p->cursor_x) && (p->cursor_x < sx+width)) ||
|
||||
((dy <= p->cursor_y) && (p->cursor_y < dy+height) &&
|
||||
(dx <= p->cursor_x) && (p->cursor_x < dx+width)))
|
||||
sticon_cursor(p, CM_ERASE /*|CM_SOFTBACK*/);
|
||||
#endif
|
||||
|
||||
sti_bmove(sticon_sti, sy, sx, dy, dx, height, width);
|
||||
}
|
||||
|
||||
static void sticon_init(struct vc_data *c, int init)
|
||||
{
|
||||
struct sti_struct *sti = sticon_sti;
|
||||
@ -256,11 +235,6 @@ static int sticon_blank(struct vc_data *c, int blank, int mode_switch)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int sticon_scrolldelta(struct vc_data *conp, int lines)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u16 *sticon_screen_pos(struct vc_data *conp, int offset)
|
||||
{
|
||||
int line;
|
||||
@ -355,11 +329,8 @@ static const struct consw sti_con = {
|
||||
.con_putcs = sticon_putcs,
|
||||
.con_cursor = sticon_cursor,
|
||||
.con_scroll = sticon_scroll,
|
||||
.con_bmove = sticon_bmove,
|
||||
.con_switch = sticon_switch,
|
||||
.con_blank = sticon_blank,
|
||||
.con_set_palette = sticon_set_palette,
|
||||
.con_scrolldelta = sticon_scrolldelta,
|
||||
.con_set_origin = sticon_set_origin,
|
||||
.con_save_screen = sticon_save_screen,
|
||||
.con_build_attr = sticon_build_attr,
|
||||
|
@ -80,7 +80,7 @@ static void vgacon_deinit(struct vc_data *c);
|
||||
static void vgacon_cursor(struct vc_data *c, int mode);
|
||||
static int vgacon_switch(struct vc_data *c);
|
||||
static int vgacon_blank(struct vc_data *c, int blank, int mode_switch);
|
||||
static int vgacon_scrolldelta(struct vc_data *c, int lines);
|
||||
static void vgacon_scrolldelta(struct vc_data *c, int lines);
|
||||
static int vgacon_set_origin(struct vc_data *c);
|
||||
static void vgacon_save_screen(struct vc_data *c);
|
||||
static int vgacon_scroll(struct vc_data *c, int t, int b, int dir,
|
||||
@ -248,18 +248,18 @@ static void vgacon_restore_screen(struct vc_data *c)
|
||||
}
|
||||
}
|
||||
|
||||
static int vgacon_scrolldelta(struct vc_data *c, int lines)
|
||||
static void vgacon_scrolldelta(struct vc_data *c, int lines)
|
||||
{
|
||||
int start, end, count, soff;
|
||||
|
||||
if (!lines) {
|
||||
c->vc_visible_origin = c->vc_origin;
|
||||
vga_set_mem_top(c);
|
||||
return 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!vgacon_scrollback)
|
||||
return 1;
|
||||
return;
|
||||
|
||||
if (!vgacon_scrollback_save) {
|
||||
vgacon_cursor(c, CM_ERASE);
|
||||
@ -320,8 +320,6 @@ static int vgacon_scrolldelta(struct vc_data *c, int lines)
|
||||
scr_memcpyw(d, s, diff * c->vc_size_row);
|
||||
} else
|
||||
vgacon_cursor(c, CM_MOVE);
|
||||
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
#define vgacon_scrollback_startup(...) do { } while (0)
|
||||
@ -334,7 +332,7 @@ static void vgacon_restore_screen(struct vc_data *c)
|
||||
vgacon_scrolldelta(c, 0);
|
||||
}
|
||||
|
||||
static int vgacon_scrolldelta(struct vc_data *c, int lines)
|
||||
static void vgacon_scrolldelta(struct vc_data *c, int lines)
|
||||
{
|
||||
if (!lines) /* Turn scrollback off */
|
||||
c->vc_visible_origin = c->vc_origin;
|
||||
@ -362,7 +360,6 @@ static int vgacon_scrolldelta(struct vc_data *c, int lines)
|
||||
c->vc_visible_origin = vga_vram_base + (p + ul) % we;
|
||||
}
|
||||
vga_set_mem_top(c);
|
||||
return 1;
|
||||
}
|
||||
#endif /* CONFIG_VGACON_SOFT_SCROLLBACK */
|
||||
|
||||
@ -592,7 +589,7 @@ static void vgacon_init(struct vc_data *c, int init)
|
||||
static void vgacon_deinit(struct vc_data *c)
|
||||
{
|
||||
/* When closing the active console, reset video origin */
|
||||
if (CON_IS_VISIBLE(c)) {
|
||||
if (con_is_visible(c)) {
|
||||
c->vc_visible_origin = vga_vram_base;
|
||||
vga_set_mem_top(c);
|
||||
}
|
||||
@ -859,16 +856,13 @@ static void vga_set_palette(struct vc_data *vc, const unsigned char *table)
|
||||
}
|
||||
}
|
||||
|
||||
static int vgacon_set_palette(struct vc_data *vc, const unsigned char *table)
|
||||
static void vgacon_set_palette(struct vc_data *vc, const unsigned char *table)
|
||||
{
|
||||
#ifdef CAN_LOAD_PALETTE
|
||||
if (vga_video_type != VIDEO_TYPE_VGAC || vga_palette_blanked
|
||||
|| !CON_IS_VISIBLE(vc))
|
||||
return -EINVAL;
|
||||
|| !con_is_visible(vc))
|
||||
return;
|
||||
vga_set_palette(vc, table);
|
||||
return 0;
|
||||
#else
|
||||
return -EINVAL;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1254,7 +1248,7 @@ static int vgacon_adjust_height(struct vc_data *vc, unsigned fontheight)
|
||||
struct vc_data *c = vc_cons[i].d;
|
||||
|
||||
if (c && c->vc_sw == &vga_con) {
|
||||
if (CON_IS_VISIBLE(c)) {
|
||||
if (con_is_visible(c)) {
|
||||
/* void size to cause regs to be rewritten */
|
||||
cursor_size_lastfrom = 0;
|
||||
cursor_size_lastto = 0;
|
||||
@ -1318,7 +1312,7 @@ static int vgacon_resize(struct vc_data *c, unsigned int width,
|
||||
return success */
|
||||
return (user) ? 0 : -EINVAL;
|
||||
|
||||
if (CON_IS_VISIBLE(c) && !vga_is_gfx) /* who knows */
|
||||
if (con_is_visible(c) && !vga_is_gfx) /* who knows */
|
||||
vgacon_doresize(c, width, height);
|
||||
return 0;
|
||||
}
|
||||
@ -1427,7 +1421,6 @@ const struct consw vga_con = {
|
||||
.con_putcs = DUMMY,
|
||||
.con_cursor = vgacon_cursor,
|
||||
.con_scroll = vgacon_scroll,
|
||||
.con_bmove = DUMMY,
|
||||
.con_switch = vgacon_switch,
|
||||
.con_blank = vgacon_blank,
|
||||
.con_font_set = vgacon_font_set,
|
||||
|
@ -28,6 +28,13 @@ struct tty_struct;
|
||||
#define VT100ID "\033[?1;2c"
|
||||
#define VT102ID "\033[?6c"
|
||||
|
||||
/**
|
||||
* struct consw - callbacks for consoles
|
||||
*
|
||||
* @con_set_palette: sets the palette of the console to @table (optional)
|
||||
* @con_scrolldelta: the contents of the console should be scrolled by @lines.
|
||||
* Invoked by user. (optional)
|
||||
*/
|
||||
struct consw {
|
||||
struct module *owner;
|
||||
const char *(*con_startup)(void);
|
||||
@ -38,7 +45,6 @@ struct consw {
|
||||
void (*con_putcs)(struct vc_data *, const unsigned short *, int, int, int);
|
||||
void (*con_cursor)(struct vc_data *, int);
|
||||
int (*con_scroll)(struct vc_data *, int, int, int, int);
|
||||
void (*con_bmove)(struct vc_data *, int, int, int, int, int, int);
|
||||
int (*con_switch)(struct vc_data *);
|
||||
int (*con_blank)(struct vc_data *, int, int);
|
||||
int (*con_font_set)(struct vc_data *, struct console_font *, unsigned);
|
||||
@ -47,8 +53,9 @@ struct consw {
|
||||
int (*con_font_copy)(struct vc_data *, int);
|
||||
int (*con_resize)(struct vc_data *, unsigned int, unsigned int,
|
||||
unsigned int);
|
||||
int (*con_set_palette)(struct vc_data *, const unsigned char *);
|
||||
int (*con_scrolldelta)(struct vc_data *, int);
|
||||
void (*con_set_palette)(struct vc_data *,
|
||||
const unsigned char *table);
|
||||
void (*con_scrolldelta)(struct vc_data *, int lines);
|
||||
int (*con_set_origin)(struct vc_data *);
|
||||
void (*con_save_screen)(struct vc_data *);
|
||||
u8 (*con_build_attr)(struct vc_data *, u8, u8, u8, u8, u8, u8);
|
||||
|
@ -21,6 +21,38 @@ struct uni_pagedir;
|
||||
|
||||
#define NPAR 16
|
||||
|
||||
/*
|
||||
* Example: vc_data of a console that was scrolled 3 lines down.
|
||||
*
|
||||
* Console buffer
|
||||
* vc_screenbuf ---------> +----------------------+-.
|
||||
* | initializing W | \
|
||||
* | initializing X | |
|
||||
* | initializing Y | > scroll-back area
|
||||
* | initializing Z | |
|
||||
* | | /
|
||||
* vc_visible_origin ---> ^+----------------------+-:
|
||||
* (changes by scroll) || Welcome to linux | \
|
||||
* || | |
|
||||
* vc_rows --->< | login: root | | visible on console
|
||||
* || password: | > (vc_screenbuf_size is
|
||||
* vc_origin -----------> || | | vc_size_row * vc_rows)
|
||||
* (start when no scroll) || Last login: 12:28 | /
|
||||
* v+----------------------+-:
|
||||
* | Have a lot of fun... | \
|
||||
* vc_pos -----------------|--------v | > scroll-front area
|
||||
* | ~ # cat_ | /
|
||||
* vc_scr_end -----------> +----------------------+-:
|
||||
* (vc_origin + | | \ EMPTY, to be filled by
|
||||
* vc_screenbuf_size) | | / vc_video_erase_char
|
||||
* +----------------------+-'
|
||||
* <---- 2 * vc_cols ----->
|
||||
* <---- vc_size_row ----->
|
||||
*
|
||||
* Note that every character in the console buffer is accompanied with an
|
||||
* attribute in the buffer right after the character. This is not depicted
|
||||
* in the figure.
|
||||
*/
|
||||
struct vc_data {
|
||||
struct tty_port port; /* Upper level data */
|
||||
|
||||
@ -74,7 +106,6 @@ struct vc_data {
|
||||
unsigned int vc_decawm : 1; /* Autowrap Mode */
|
||||
unsigned int vc_deccm : 1; /* Cursor Visible */
|
||||
unsigned int vc_decim : 1; /* Insert Mode */
|
||||
unsigned int vc_deccolm : 1; /* 80/132 Column Mode */
|
||||
/* attribute flags */
|
||||
unsigned int vc_intensity : 2; /* 0=half-bright, 1=normal, 2=bold */
|
||||
unsigned int vc_italic:1;
|
||||
@ -136,6 +167,9 @@ extern void vc_SAK(struct work_struct *work);
|
||||
|
||||
#define CUR_DEFAULT CUR_UNDERLINE
|
||||
|
||||
#define CON_IS_VISIBLE(conp) (*conp->vc_display_fg == conp)
|
||||
static inline bool con_is_visible(const struct vc_data *vc)
|
||||
{
|
||||
return *vc->vc_display_fg == vc;
|
||||
}
|
||||
|
||||
#endif /* _LINUX_CONSOLE_STRUCT_H */
|
||||
|
@ -39,14 +39,22 @@ struct hsu_dma_chip {
|
||||
|
||||
#if IS_ENABLED(CONFIG_HSU_DMA)
|
||||
/* Export to the internal users */
|
||||
irqreturn_t hsu_dma_irq(struct hsu_dma_chip *chip, unsigned short nr);
|
||||
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);
|
||||
|
||||
/* Export to the platform drivers */
|
||||
int hsu_dma_probe(struct hsu_dma_chip *chip);
|
||||
int hsu_dma_remove(struct hsu_dma_chip *chip);
|
||||
#else
|
||||
static inline irqreturn_t hsu_dma_irq(struct hsu_dma_chip *chip,
|
||||
unsigned short nr)
|
||||
static inline int hsu_dma_get_status(struct hsu_dma_chip *chip,
|
||||
unsigned short nr, u32 *status)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline irqreturn_t hsu_dma_do_irq(struct hsu_dma_chip *chip,
|
||||
unsigned short nr, u32 status)
|
||||
{
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
@ -111,6 +111,7 @@ struct uart_8250_port {
|
||||
* if no_console_suspend
|
||||
*/
|
||||
unsigned char probe;
|
||||
struct mctrl_gpios *gpios;
|
||||
#define UART_PROBE_RSA (1 << 0)
|
||||
|
||||
/*
|
||||
|
@ -352,9 +352,15 @@ struct earlycon_id {
|
||||
extern const struct earlycon_id __earlycon_table[];
|
||||
extern const struct earlycon_id __earlycon_table_end[];
|
||||
|
||||
#if defined(CONFIG_SERIAL_EARLYCON) && !defined(MODULE)
|
||||
#define EARLYCON_USED_OR_UNUSED __used
|
||||
#else
|
||||
#define EARLYCON_USED_OR_UNUSED __maybe_unused
|
||||
#endif
|
||||
|
||||
#define OF_EARLYCON_DECLARE(_name, compat, fn) \
|
||||
static const struct earlycon_id __UNIQUE_ID(__earlycon_##_name) \
|
||||
__used __section(__earlycon_table) \
|
||||
EARLYCON_USED_OR_UNUSED __section(__earlycon_table) \
|
||||
= { .name = __stringify(_name), \
|
||||
.compatible = compat, \
|
||||
.setup = fn }
|
||||
|
@ -45,7 +45,7 @@ void poke_blanked_console(void);
|
||||
int con_font_op(struct vc_data *vc, struct console_font_op *op);
|
||||
int con_set_cmap(unsigned char __user *cmap);
|
||||
int con_get_cmap(unsigned char __user *cmap);
|
||||
void scrollback(struct vc_data *vc, int lines);
|
||||
void scrollback(struct vc_data *vc);
|
||||
void scrollfront(struct vc_data *vc, int lines);
|
||||
void clear_buffer_attributes(struct vc_data *vc);
|
||||
void update_region(struct vc_data *vc, unsigned long start, int count);
|
||||
@ -59,14 +59,13 @@ int tioclinux(struct tty_struct *tty, unsigned long arg);
|
||||
#ifdef CONFIG_CONSOLE_TRANSLATIONS
|
||||
/* consolemap.c */
|
||||
|
||||
struct unimapinit;
|
||||
struct unipair;
|
||||
|
||||
int con_set_trans_old(unsigned char __user * table);
|
||||
int con_get_trans_old(unsigned char __user * table);
|
||||
int con_set_trans_new(unsigned short __user * table);
|
||||
int con_get_trans_new(unsigned short __user * table);
|
||||
int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui);
|
||||
int con_clear_unimap(struct vc_data *vc);
|
||||
int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list);
|
||||
int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct unipair __user *list);
|
||||
int con_set_default_unimap(struct vc_data *vc);
|
||||
@ -92,7 +91,7 @@ static inline int con_get_trans_new(unsigned short __user *table)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
static inline int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
|
||||
static inline int con_clear_unimap(struct vc_data *vc)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -246,9 +246,6 @@ static int ircomm_tty_get_serial_info(struct ircomm_tty_cb *self,
|
||||
{
|
||||
struct serial_struct info;
|
||||
|
||||
if (!retinfo)
|
||||
return -EFAULT;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.line = self->line;
|
||||
info.flags = self->port.flags;
|
||||
@ -258,11 +255,6 @@ static int ircomm_tty_get_serial_info(struct ircomm_tty_cb *self,
|
||||
|
||||
/* For compatibility */
|
||||
info.type = PORT_16550A;
|
||||
info.port = 0;
|
||||
info.irq = 0;
|
||||
info.xmit_fifo_size = 0;
|
||||
info.hub6 = 0;
|
||||
info.custom_divisor = 0;
|
||||
|
||||
if (copy_to_user(retinfo, &info, sizeof(*retinfo)))
|
||||
return -EFAULT;
|
||||
|
Loading…
Reference in New Issue
Block a user