Commit 356a0319 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'tty-6.12-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" set of tty/serial driver updates for 6.12-rc1.

  Nothing major in here, just nice forward progress in the slow cleanup
  of the serial apis, and lots of other driver updates and fixes.

  Included in here are:

   - serial api updates from Jiri to make things more uniform and sane

   - 8250_platform driver cleanups

   - samsung serial driver fixes and updates

   - qcom-geni serial driver fixes from Johan for the bizarre UART
     engine that that chip seems to have. Hopefully it's in a better
     state now, but hardware designers still seem to come up with more
     ways to make broken UARTS 40+ years after this all should have
     finished.

   - sc16is7xx driver updates

   - omap 8250 driver updates

   - 8250_bcm2835aux driver updates

   - a few new serial driver bindings added

   - other serial minor driver updates

  All of these have been in linux-next for a long time with no reported
  problems"

* tag 'tty-6.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (65 commits)
  tty: serial: samsung: Fix serial rx on Apple A7-A9
  tty: serial: samsung: Fix A7-A11 serial earlycon SError
  tty: serial: samsung: Use bit manipulation macros for APPLE_S5L_*
  tty: rp2: Fix reset with non forgiving PCIe host bridges
  serial: 8250_aspeed_vuart: Enable module autoloading
  serial: qcom-geni: fix polled console corruption
  serial: qcom-geni: disable interrupts during console writes
  serial: qcom-geni: fix console corruption
  serial: qcom-geni: introduce qcom_geni_serial_poll_bitfield()
  serial: qcom-geni: fix arg types for qcom_geni_serial_poll_bit()
  soc: qcom: geni-se: add GP_LENGTH/IRQ_EN_SET/IRQ_EN_CLEAR registers
  serial: qcom-geni: fix false console tx restart
  serial: qcom-geni: fix fifo polling timeout
  tty: hvc: convert comma to semicolon
  mxser: convert comma to semicolon
  serial: 8250_bcm2835aux: Fix clock imbalance in PM resume
  serial: sc16is7xx: convert bitmask definitions to use BIT() macro
  serial: sc16is7xx: fix copy-paste errors in EFR_SWFLOWx_BIT constants
  serial: sc16is7xx: remove SC16IS7XX_MSR_DELTA_MASK
  serial: xilinx_uartps: Make cdns_rs485_supported static
  ...
parents 4965ddb1 5ed771f1
...@@ -76,6 +76,7 @@ properties: ...@@ -76,6 +76,7 @@ properties:
clock-frequency: true clock-frequency: true
current-speed: true current-speed: true
overrun-throttle-ms: true overrun-throttle-ms: true
wakeup-source: true
required: required:
- compatible - compatible
......
...@@ -23,13 +23,20 @@ properties: ...@@ -23,13 +23,20 @@ properties:
- const: atmel,at91sam9260-dbgu - const: atmel,at91sam9260-dbgu
- const: atmel,at91sam9260-usart - const: atmel,at91sam9260-usart
- items: - items:
- const: microchip,sam9x60-usart - enum:
- microchip,sam9x60-usart
- microchip,sam9x7-usart
- const: atmel,at91sam9260-usart - const: atmel,at91sam9260-usart
- items: - items:
- const: microchip,sam9x60-dbgu - const: microchip,sam9x60-dbgu
- const: microchip,sam9x60-usart - const: microchip,sam9x60-usart
- const: atmel,at91sam9260-dbgu - const: atmel,at91sam9260-dbgu
- const: atmel,at91sam9260-usart - const: atmel,at91sam9260-usart
- items:
- const: microchip,sam9x7-dbgu
- const: atmel,at91sam9260-dbgu
- const: microchip,sam9x7-usart
- const: atmel,at91sam9260-usart
reg: reg:
maxItems: 1 maxItems: 1
......
...@@ -36,6 +36,7 @@ properties: ...@@ -36,6 +36,7 @@ properties:
- mediatek,mt7622-uart - mediatek,mt7622-uart
- mediatek,mt7623-uart - mediatek,mt7623-uart
- mediatek,mt7629-uart - mediatek,mt7629-uart
- mediatek,mt7981-uart
- mediatek,mt7986-uart - mediatek,mt7986-uart
- mediatek,mt7988-uart - mediatek,mt7988-uart
- mediatek,mt8127-uart - mediatek,mt8127-uart
......
...@@ -46,6 +46,7 @@ properties: ...@@ -46,6 +46,7 @@ properties:
- items: - items:
- enum: - enum:
- renesas,scif-r8a774a1 # RZ/G2M - renesas,scif-r8a774a1 # RZ/G2M
- renesas,scif-r8a774a3 # RZ/G2M v3.0
- renesas,scif-r8a774b1 # RZ/G2N - renesas,scif-r8a774b1 # RZ/G2N
- renesas,scif-r8a774c0 # RZ/G2E - renesas,scif-r8a774c0 # RZ/G2E
- renesas,scif-r8a774e1 # RZ/G2H - renesas,scif-r8a774e1 # RZ/G2H
......
...@@ -56,14 +56,8 @@ properties: ...@@ -56,14 +56,8 @@ properties:
maxItems: 5 maxItems: 5
clock-names: clock-names:
description: N = 0 is allowed for SoCs without internal baud clock mux.
minItems: 2 minItems: 2
items: maxItems: 5
- const: uart
- pattern: '^clk_uart_baud[0-3]$'
- pattern: '^clk_uart_baud[0-3]$'
- pattern: '^clk_uart_baud[0-3]$'
- pattern: '^clk_uart_baud[0-3]$'
dmas: dmas:
items: items:
...@@ -103,18 +97,45 @@ allOf: ...@@ -103,18 +97,45 @@ allOf:
compatible: compatible:
contains: contains:
enum: enum:
- samsung,s5pv210-uart - samsung,s3c6400-uart
then: then:
properties: properties:
clocks: clocks:
minItems: 2 minItems: 3
maxItems: 3 maxItems: 3
clock-names:
items:
- const: uart
- const: clk_uart_baud2
- const: clk_uart_baud3
else:
properties:
clock-names: clock-names:
minItems: 2 minItems: 2
items: items:
- const: uart - const: uart
- pattern: '^clk_uart_baud[0-1]$' - const: clk_uart_baud0
- pattern: '^clk_uart_baud[0-1]$' - const: clk_uart_baud1
- const: clk_uart_baud2
- const: clk_uart_baud3
- if:
properties:
compatible:
contains:
enum:
- samsung,s5pv210-uart
then:
properties:
clocks:
minItems: 3
maxItems: 3
clock-names:
minItems: 3
maxItems: 3
- if: - if:
properties: properties:
...@@ -129,10 +150,9 @@ allOf: ...@@ -129,10 +150,9 @@ allOf:
properties: properties:
clocks: clocks:
maxItems: 2 maxItems: 2
clock-names: clock-names:
items: maxItems: 2
- const: uart
- const: clk_uart_baud0
- if: - if:
properties: properties:
...@@ -146,6 +166,12 @@ allOf: ...@@ -146,6 +166,12 @@ allOf:
properties: properties:
reg-io-width: false reg-io-width: false
clocks:
maxItems: 2
clock-names:
maxItems: 2
unevaluatedProperties: false unevaluatedProperties: false
examples: examples:
...@@ -163,3 +189,19 @@ examples: ...@@ -163,3 +189,19 @@ examples:
<&clocks SCLK_UART>; <&clocks SCLK_UART>;
samsung,uart-fifosize = <16>; samsung,uart-fifosize = <16>;
}; };
- |
#include <dt-bindings/clock/google,gs101.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
serial_0: serial@10a00000 {
compatible = "google,gs101-uart";
reg = <0x10a00000 0xc0>;
clocks = <&cmu_peric0 CLK_GOUT_PERIC0_PERIC0_TOP1_PCLK_0>,
<&cmu_peric0 CLK_GOUT_PERIC0_PERIC0_TOP1_IPCLK_0>;
clock-names = "uart", "clk_uart_baud0";
interrupts = <GIC_SPI 634 IRQ_TYPE_LEVEL_HIGH 0>;
pinctrl-0 = <&uart0_bus>;
pinctrl-names = "default";
samsung,uart-fifosize = <256>;
};
...@@ -94,6 +94,39 @@ pwm@10048000 { ...@@ -94,6 +94,39 @@ pwm@10048000 {
#pwm-cells = <2>; #pwm-cells = <2>;
}; };
serial@11002000 {
compatible = "mediatek,mt7981-uart", "mediatek,mt6577-uart";
reg = <0 0x11002000 0 0x100>;
interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "uart", "wakeup";
clocks = <&infracfg CLK_INFRA_UART0_SEL>,
<&infracfg CLK_INFRA_UART0_CK>;
clock-names = "baud", "bus";
status = "disabled";
};
serial@11003000 {
compatible = "mediatek,mt7981-uart", "mediatek,mt6577-uart";
reg = <0 0x11003000 0 0x100>;
interrupts = <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "uart", "wakeup";
clocks = <&infracfg CLK_INFRA_UART1_SEL>,
<&infracfg CLK_INFRA_UART1_CK>;
clock-names = "baud", "bus";
status = "disabled";
};
serial@11004000 {
compatible = "mediatek,mt7981-uart", "mediatek,mt6577-uart";
reg = <0 0x11004000 0 0x100>;
interrupts = <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "uart", "wakeup";
clocks = <&infracfg CLK_INFRA_UART2_SEL>,
<&infracfg CLK_INFRA_UART2_CK>;
clock-names = "baud", "bus";
status = "disabled";
};
i2c@11007000 { i2c@11007000 {
compatible = "mediatek,mt7981-i2c"; compatible = "mediatek,mt7981-i2c";
reg = <0 0x11007000 0 0x1000>, reg = <0 0x11007000 0 0x1000>,
......
...@@ -37,8 +37,6 @@ ...@@ -37,8 +37,6 @@
#include <linux/semaphore.h> #include <linux/semaphore.h>
#include <linux/refcount.h> #include <linux/refcount.h>
#define SIXPACK_VERSION "Revision: 0.3.0"
/* sixpack priority commands */ /* sixpack priority commands */
#define SIXP_SEOF 0x40 /* start and end of a 6pack frame */ #define SIXP_SEOF 0x40 /* start and end of a 6pack frame */
#define SIXP_TX_URUN 0x48 /* transmit overrun */ #define SIXP_TX_URUN 0x48 /* transmit overrun */
...@@ -88,22 +86,18 @@ struct sixpack { ...@@ -88,22 +86,18 @@ struct sixpack {
struct net_device *dev; /* easy for intr handling */ struct net_device *dev; /* easy for intr handling */
/* These are pointers to the malloc()ed frame buffers. */ /* These are pointers to the malloc()ed frame buffers. */
unsigned char *rbuff; /* receiver buffer */
int rcount; /* received chars counter */ int rcount; /* received chars counter */
unsigned char *xbuff; /* transmitter buffer */ unsigned char *xbuff; /* transmitter buffer */
unsigned char *xhead; /* next byte to XMIT */ unsigned char *xhead; /* next byte to XMIT */
int xleft; /* bytes left in XMIT queue */ int xleft; /* bytes left in XMIT queue */
unsigned char raw_buf[4]; u8 raw_buf[4];
unsigned char cooked_buf[400]; u8 cooked_buf[400];
unsigned int rx_count; unsigned int rx_count;
unsigned int rx_count_cooked; unsigned int rx_count_cooked;
spinlock_t rxlock; spinlock_t rxlock;
int mtu; /* Our mtu (to spot changes!) */
int buffsize; /* Max buffers sizes */
unsigned long flags; /* Flag values/ mode etc */ unsigned long flags; /* Flag values/ mode etc */
unsigned char mode; /* 6pack mode */ unsigned char mode; /* 6pack mode */
...@@ -113,8 +107,8 @@ struct sixpack { ...@@ -113,8 +107,8 @@ struct sixpack {
unsigned char slottime; unsigned char slottime;
unsigned char duplex; unsigned char duplex;
unsigned char led_state; unsigned char led_state;
unsigned char status; u8 status;
unsigned char status1; u8 status1;
unsigned char status2; unsigned char status2;
unsigned char tx_enable; unsigned char tx_enable;
unsigned char tnc_state; unsigned char tnc_state;
...@@ -128,7 +122,7 @@ struct sixpack { ...@@ -128,7 +122,7 @@ struct sixpack {
#define AX25_6PACK_HEADER_LEN 0 #define AX25_6PACK_HEADER_LEN 0
static void sixpack_decode(struct sixpack *, const unsigned char[], int); static void sixpack_decode(struct sixpack *, const u8 *, size_t);
static int encode_sixpack(unsigned char *, unsigned char *, int, unsigned char); static int encode_sixpack(unsigned char *, unsigned char *, int, unsigned char);
/* /*
...@@ -167,7 +161,7 @@ static void sp_encaps(struct sixpack *sp, unsigned char *icp, int len) ...@@ -167,7 +161,7 @@ static void sp_encaps(struct sixpack *sp, unsigned char *icp, int len)
unsigned char *msg, *p = icp; unsigned char *msg, *p = icp;
int actual, count; int actual, count;
if (len > sp->mtu) { /* sp->mtu = AX25_MTU = max. PACLEN = 256 */ if (len > AX25_MTU + 73) {
msg = "oversized transmit packet!"; msg = "oversized transmit packet!";
goto out_drop; goto out_drop;
} }
...@@ -333,7 +327,7 @@ static void sp_bump(struct sixpack *sp, char cmd) ...@@ -333,7 +327,7 @@ static void sp_bump(struct sixpack *sp, char cmd)
{ {
struct sk_buff *skb; struct sk_buff *skb;
int count; int count;
unsigned char *ptr; u8 *ptr;
count = sp->rcount + 1; count = sp->rcount + 1;
...@@ -431,7 +425,7 @@ static void sixpack_receive_buf(struct tty_struct *tty, const u8 *cp, ...@@ -431,7 +425,7 @@ static void sixpack_receive_buf(struct tty_struct *tty, const u8 *cp,
const u8 *fp, size_t count) const u8 *fp, size_t count)
{ {
struct sixpack *sp; struct sixpack *sp;
int count1; size_t count1;
if (!count) if (!count)
return; return;
...@@ -544,7 +538,7 @@ static inline int tnc_init(struct sixpack *sp) ...@@ -544,7 +538,7 @@ static inline int tnc_init(struct sixpack *sp)
*/ */
static int sixpack_open(struct tty_struct *tty) static int sixpack_open(struct tty_struct *tty)
{ {
char *rbuff = NULL, *xbuff = NULL; char *xbuff = NULL;
struct net_device *dev; struct net_device *dev;
struct sixpack *sp; struct sixpack *sp;
unsigned long len; unsigned long len;
...@@ -574,10 +568,8 @@ static int sixpack_open(struct tty_struct *tty) ...@@ -574,10 +568,8 @@ static int sixpack_open(struct tty_struct *tty)
len = dev->mtu * 2; len = dev->mtu * 2;
rbuff = kmalloc(len + 4, GFP_KERNEL);
xbuff = kmalloc(len + 4, GFP_KERNEL); xbuff = kmalloc(len + 4, GFP_KERNEL);
if (xbuff == NULL) {
if (rbuff == NULL || xbuff == NULL) {
err = -ENOBUFS; err = -ENOBUFS;
goto out_free; goto out_free;
} }
...@@ -586,11 +578,8 @@ static int sixpack_open(struct tty_struct *tty) ...@@ -586,11 +578,8 @@ static int sixpack_open(struct tty_struct *tty)
sp->tty = tty; sp->tty = tty;
sp->rbuff = rbuff;
sp->xbuff = xbuff; sp->xbuff = xbuff;
sp->mtu = AX25_MTU + 73;
sp->buffsize = len;
sp->rcount = 0; sp->rcount = 0;
sp->rx_count = 0; sp->rx_count = 0;
sp->rx_count_cooked = 0; sp->rx_count_cooked = 0;
...@@ -631,7 +620,6 @@ static int sixpack_open(struct tty_struct *tty) ...@@ -631,7 +620,6 @@ static int sixpack_open(struct tty_struct *tty)
out_free: out_free:
kfree(xbuff); kfree(xbuff);
kfree(rbuff);
free_netdev(dev); free_netdev(dev);
...@@ -676,7 +664,6 @@ static void sixpack_close(struct tty_struct *tty) ...@@ -676,7 +664,6 @@ static void sixpack_close(struct tty_struct *tty)
del_timer_sync(&sp->resync_t); del_timer_sync(&sp->resync_t);
/* Free all 6pack frame buffers after unreg. */ /* Free all 6pack frame buffers after unreg. */
kfree(sp->rbuff);
kfree(sp->xbuff); kfree(sp->xbuff);
free_netdev(sp->dev); free_netdev(sp->dev);
...@@ -756,21 +743,14 @@ static struct tty_ldisc_ops sp_ldisc = { ...@@ -756,21 +743,14 @@ static struct tty_ldisc_ops sp_ldisc = {
/* Initialize 6pack control device -- register 6pack line discipline */ /* Initialize 6pack control device -- register 6pack line discipline */
static const char msg_banner[] __initconst = KERN_INFO \
"AX.25: 6pack driver, " SIXPACK_VERSION "\n";
static const char msg_regfail[] __initconst = KERN_ERR \
"6pack: can't register line discipline (err = %d)\n";
static int __init sixpack_init_driver(void) static int __init sixpack_init_driver(void)
{ {
int status; int status;
printk(msg_banner);
/* Register the provided line protocol discipline */ /* Register the provided line protocol discipline */
status = tty_register_ldisc(&sp_ldisc); status = tty_register_ldisc(&sp_ldisc);
if (status) if (status)
printk(msg_regfail, status); pr_err("6pack: can't register line discipline (err = %d)\n", status);
return status; return status;
} }
...@@ -820,9 +800,9 @@ static int encode_sixpack(unsigned char *tx_buf, unsigned char *tx_buf_raw, ...@@ -820,9 +800,9 @@ static int encode_sixpack(unsigned char *tx_buf, unsigned char *tx_buf_raw,
/* decode 4 sixpack-encoded bytes into 3 data bytes */ /* decode 4 sixpack-encoded bytes into 3 data bytes */
static void decode_data(struct sixpack *sp, unsigned char inbyte) static void decode_data(struct sixpack *sp, u8 inbyte)
{ {
unsigned char *buf; u8 *buf;
if (sp->rx_count != 3) { if (sp->rx_count != 3) {
sp->raw_buf[sp->rx_count++] = inbyte; sp->raw_buf[sp->rx_count++] = inbyte;
...@@ -848,9 +828,9 @@ static void decode_data(struct sixpack *sp, unsigned char inbyte) ...@@ -848,9 +828,9 @@ static void decode_data(struct sixpack *sp, unsigned char inbyte)
/* identify and execute a 6pack priority command byte */ /* identify and execute a 6pack priority command byte */
static void decode_prio_command(struct sixpack *sp, unsigned char cmd) static void decode_prio_command(struct sixpack *sp, u8 cmd)
{ {
int actual; ssize_t actual;
if ((cmd & SIXP_PRIO_DATA_MASK) != 0) { /* idle ? */ if ((cmd & SIXP_PRIO_DATA_MASK) != 0) { /* idle ? */
...@@ -898,9 +878,9 @@ static void decode_prio_command(struct sixpack *sp, unsigned char cmd) ...@@ -898,9 +878,9 @@ static void decode_prio_command(struct sixpack *sp, unsigned char cmd)
/* identify and execute a standard 6pack command byte */ /* identify and execute a standard 6pack command byte */
static void decode_std_command(struct sixpack *sp, unsigned char cmd) static void decode_std_command(struct sixpack *sp, u8 cmd)
{ {
unsigned char checksum = 0, rest = 0; u8 checksum = 0, rest = 0;
short i; short i;
switch (cmd & SIXP_CMD_MASK) { /* normal command */ switch (cmd & SIXP_CMD_MASK) { /* normal command */
...@@ -948,10 +928,10 @@ static void decode_std_command(struct sixpack *sp, unsigned char cmd) ...@@ -948,10 +928,10 @@ static void decode_std_command(struct sixpack *sp, unsigned char cmd)
/* decode a 6pack packet */ /* decode a 6pack packet */
static void static void
sixpack_decode(struct sixpack *sp, const unsigned char *pre_rbuff, int count) sixpack_decode(struct sixpack *sp, const u8 *pre_rbuff, size_t count)
{ {
unsigned char inbyte; size_t count1;
int count1; u8 inbyte;
for (count1 = 0; count1 < count; count1++) { for (count1 = 0; count1 < count; count1++) {
inbyte = pre_rbuff[count1]; inbyte = pre_rbuff[count1];
......
...@@ -64,18 +64,18 @@ struct mctp_serial { ...@@ -64,18 +64,18 @@ struct mctp_serial {
u16 txfcs, rxfcs, rxfcs_rcvd; u16 txfcs, rxfcs, rxfcs_rcvd;
unsigned int txlen, rxlen; unsigned int txlen, rxlen;
unsigned int txpos, rxpos; unsigned int txpos, rxpos;
unsigned char txbuf[BUFSIZE], u8 txbuf[BUFSIZE],
rxbuf[BUFSIZE]; rxbuf[BUFSIZE];
}; };
static bool needs_escape(unsigned char c) static bool needs_escape(u8 c)
{ {
return c == BYTE_ESC || c == BYTE_FRAME; return c == BYTE_ESC || c == BYTE_FRAME;
} }
static int next_chunk_len(struct mctp_serial *dev) static unsigned int next_chunk_len(struct mctp_serial *dev)
{ {
int i; unsigned int i;
/* either we have no bytes to send ... */ /* either we have no bytes to send ... */
if (dev->txpos == dev->txlen) if (dev->txpos == dev->txlen)
...@@ -99,7 +99,7 @@ static int next_chunk_len(struct mctp_serial *dev) ...@@ -99,7 +99,7 @@ static int next_chunk_len(struct mctp_serial *dev)
return i; return i;
} }
static int write_chunk(struct mctp_serial *dev, unsigned char *buf, int len) static ssize_t write_chunk(struct mctp_serial *dev, u8 *buf, size_t len)
{ {
return dev->tty->ops->write(dev->tty, buf, len); return dev->tty->ops->write(dev->tty, buf, len);
} }
...@@ -108,9 +108,10 @@ static void mctp_serial_tx_work(struct work_struct *work) ...@@ -108,9 +108,10 @@ static void mctp_serial_tx_work(struct work_struct *work)
{ {
struct mctp_serial *dev = container_of(work, struct mctp_serial, struct mctp_serial *dev = container_of(work, struct mctp_serial,
tx_work); tx_work);
unsigned char c, buf[3];
unsigned long flags; unsigned long flags;
int len, txlen; ssize_t txlen;
unsigned int len;
u8 c, buf[3];
spin_lock_irqsave(&dev->lock, flags); spin_lock_irqsave(&dev->lock, flags);
...@@ -293,7 +294,7 @@ static void mctp_serial_rx(struct mctp_serial *dev) ...@@ -293,7 +294,7 @@ static void mctp_serial_rx(struct mctp_serial *dev)
dev->netdev->stats.rx_bytes += dev->rxlen; dev->netdev->stats.rx_bytes += dev->rxlen;
} }
static void mctp_serial_push_header(struct mctp_serial *dev, unsigned char c) static void mctp_serial_push_header(struct mctp_serial *dev, u8 c)
{ {
switch (dev->rxpos) { switch (dev->rxpos) {
case 0: case 0:
...@@ -323,7 +324,7 @@ static void mctp_serial_push_header(struct mctp_serial *dev, unsigned char c) ...@@ -323,7 +324,7 @@ static void mctp_serial_push_header(struct mctp_serial *dev, unsigned char c)
} }
} }
static void mctp_serial_push_trailer(struct mctp_serial *dev, unsigned char c) static void mctp_serial_push_trailer(struct mctp_serial *dev, u8 c)
{ {
switch (dev->rxpos) { switch (dev->rxpos) {
case 0: case 0:
...@@ -347,7 +348,7 @@ static void mctp_serial_push_trailer(struct mctp_serial *dev, unsigned char c) ...@@ -347,7 +348,7 @@ static void mctp_serial_push_trailer(struct mctp_serial *dev, unsigned char c)
} }
} }
static void mctp_serial_push(struct mctp_serial *dev, unsigned char c) static void mctp_serial_push(struct mctp_serial *dev, u8 c)
{ {
switch (dev->rxstate) { switch (dev->rxstate) {
case STATE_IDLE: case STATE_IDLE:
...@@ -394,7 +395,7 @@ static void mctp_serial_tty_receive_buf(struct tty_struct *tty, const u8 *c, ...@@ -394,7 +395,7 @@ static void mctp_serial_tty_receive_buf(struct tty_struct *tty, const u8 *c,
const u8 *f, size_t len) const u8 *f, size_t len)
{ {
struct mctp_serial *dev = tty->disc_data; struct mctp_serial *dev = tty->disc_data;
int i; size_t i;
if (!netif_running(dev->netdev)) if (!netif_running(dev->netdev))
return; return;
......
...@@ -303,7 +303,7 @@ int hvsilib_write_mctrl(struct hvsi_priv *pv, int dtr) ...@@ -303,7 +303,7 @@ int hvsilib_write_mctrl(struct hvsi_priv *pv, int dtr)
pr_devel("HVSI@%x: %s DTR...\n", pv->termno, pr_devel("HVSI@%x: %s DTR...\n", pv->termno,
dtr ? "Setting" : "Clearing"); dtr ? "Setting" : "Clearing");
ctrl.hdr.type = VS_CONTROL_PACKET_HEADER, ctrl.hdr.type = VS_CONTROL_PACKET_HEADER;
ctrl.hdr.len = sizeof(struct hvsi_control); ctrl.hdr.len = sizeof(struct hvsi_control);
ctrl.verb = cpu_to_be16(VSV_SET_MODEM_CTL); ctrl.verb = cpu_to_be16(VSV_SET_MODEM_CTL);
ctrl.mask = cpu_to_be32(HVSI_TSDTR); ctrl.mask = cpu_to_be32(HVSI_TSDTR);
......
...@@ -208,9 +208,6 @@ static const struct { ...@@ -208,9 +208,6 @@ static const struct {
}; };
#define UART_INFO_NUM ARRAY_SIZE(Gpci_uart_info) #define UART_INFO_NUM ARRAY_SIZE(Gpci_uart_info)
/* driver_data correspond to the lines in the structure above
see also ISA probe function before you change something */
static const struct pci_device_id mxser_pcibrds[] = { static const struct pci_device_id mxser_pcibrds[] = {
{ PCI_DEVICE_DATA(MOXA, C168, 8) }, { PCI_DEVICE_DATA(MOXA, C168, 8) },
{ PCI_DEVICE_DATA(MOXA, C104, 4) }, { PCI_DEVICE_DATA(MOXA, C104, 4) },
...@@ -986,7 +983,7 @@ static int mxser_get_serial_info(struct tty_struct *tty, ...@@ -986,7 +983,7 @@ static int mxser_get_serial_info(struct tty_struct *tty,
ss->baud_base = MXSER_BAUD_BASE; ss->baud_base = MXSER_BAUD_BASE;
ss->close_delay = close_delay; ss->close_delay = close_delay;
ss->closing_wait = closing_wait; ss->closing_wait = closing_wait;
ss->custom_divisor = MXSER_CUSTOM_DIVISOR, ss->custom_divisor = MXSER_CUSTOM_DIVISOR;
mutex_unlock(&port->mutex); mutex_unlock(&port->mutex);
return 0; return 0;
} }
...@@ -1773,8 +1770,6 @@ static void mxser_initbrd(struct mxser_board *brd, bool high_baud) ...@@ -1773,8 +1770,6 @@ static void mxser_initbrd(struct mxser_board *brd, bool high_baud)
mxser_process_txrx_fifo(info); mxser_process_txrx_fifo(info);
info->port.close_delay = 5 * HZ / 10;
info->port.closing_wait = 30 * HZ;
spin_lock_init(&info->slock); spin_lock_init(&info->slock);
/* before set INT ISR, disable all int */ /* before set INT ISR, disable all int */
......
...@@ -529,7 +529,7 @@ static int of_serdev_register_devices(struct serdev_controller *ctrl) ...@@ -529,7 +529,7 @@ static int of_serdev_register_devices(struct serdev_controller *ctrl)
bool found = false; bool found = false;
for_each_available_child_of_node(ctrl->dev.of_node, node) { for_each_available_child_of_node(ctrl->dev.of_node, node) {
if (!of_get_property(node, "compatible", NULL)) if (!of_property_present(node, "compatible"))
continue; continue;
dev_dbg(&ctrl->dev, "adding child %pOF\n", node); dev_dbg(&ctrl->dev, "adding child %pOF\n", node);
......
...@@ -561,6 +561,7 @@ static const struct of_device_id aspeed_vuart_table[] = { ...@@ -561,6 +561,7 @@ static const struct of_device_id aspeed_vuart_table[] = {
{ .compatible = "aspeed,ast2500-vuart" }, { .compatible = "aspeed,ast2500-vuart" },
{ }, { },
}; };
MODULE_DEVICE_TABLE(of, aspeed_vuart_table);
static struct platform_driver aspeed_vuart_driver = { static struct platform_driver aspeed_vuart_driver = {
.driver = { .driver = {
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
*/ */
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/console.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
...@@ -213,11 +214,57 @@ static const struct acpi_device_id bcm2835aux_serial_acpi_match[] = { ...@@ -213,11 +214,57 @@ static const struct acpi_device_id bcm2835aux_serial_acpi_match[] = {
}; };
MODULE_DEVICE_TABLE(acpi, bcm2835aux_serial_acpi_match); MODULE_DEVICE_TABLE(acpi, bcm2835aux_serial_acpi_match);
static bool bcm2835aux_can_disable_clock(struct device *dev)
{
struct bcm2835aux_data *data = dev_get_drvdata(dev);
struct uart_8250_port *up = serial8250_get_port(data->line);
if (device_may_wakeup(dev))
return false;
if (uart_console(&up->port) && !console_suspend_enabled)
return false;
return true;
}
static int bcm2835aux_suspend(struct device *dev)
{
struct bcm2835aux_data *data = dev_get_drvdata(dev);
serial8250_suspend_port(data->line);
if (!bcm2835aux_can_disable_clock(dev))
return 0;
clk_disable_unprepare(data->clk);
return 0;
}
static int bcm2835aux_resume(struct device *dev)
{
struct bcm2835aux_data *data = dev_get_drvdata(dev);
int ret;
if (bcm2835aux_can_disable_clock(dev)) {
ret = clk_prepare_enable(data->clk);
if (ret)
return ret;
}
serial8250_resume_port(data->line);
return 0;
}
static DEFINE_SIMPLE_DEV_PM_OPS(bcm2835aux_dev_pm_ops, bcm2835aux_suspend, bcm2835aux_resume);
static struct platform_driver bcm2835aux_serial_driver = { static struct platform_driver bcm2835aux_serial_driver = {
.driver = { .driver = {
.name = "bcm2835-aux-uart", .name = "bcm2835-aux-uart",
.of_match_table = bcm2835aux_serial_match, .of_match_table = bcm2835aux_serial_match,
.acpi_match_table = bcm2835aux_serial_acpi_match, .acpi_match_table = bcm2835aux_serial_acpi_match,
.pm = pm_ptr(&bcm2835aux_dev_pm_ops),
}, },
.probe = bcm2835aux_serial_probe, .probe = bcm2835aux_serial_probe,
.remove_new = bcm2835aux_serial_remove, .remove_new = bcm2835aux_serial_remove,
......
...@@ -89,7 +89,9 @@ int serial8250_tx_dma(struct uart_8250_port *p) ...@@ -89,7 +89,9 @@ int serial8250_tx_dma(struct uart_8250_port *p)
struct tty_port *tport = &p->port.state->port; struct tty_port *tport = &p->port.state->port;
struct dma_async_tx_descriptor *desc; struct dma_async_tx_descriptor *desc;
struct uart_port *up = &p->port; struct uart_port *up = &p->port;
struct scatterlist sg; struct scatterlist *sg;
struct scatterlist sgl[2];
int i;
int ret; int ret;
if (dma->tx_running) { if (dma->tx_running) {
...@@ -110,18 +112,17 @@ int serial8250_tx_dma(struct uart_8250_port *p) ...@@ -110,18 +112,17 @@ int serial8250_tx_dma(struct uart_8250_port *p)
serial8250_do_prepare_tx_dma(p); serial8250_do_prepare_tx_dma(p);
sg_init_table(&sg, 1); sg_init_table(sgl, ARRAY_SIZE(sgl));
/* kfifo can do more than one sg, we don't (quite yet) */
ret = kfifo_dma_out_prepare_mapped(&tport->xmit_fifo, &sg, 1, ret = kfifo_dma_out_prepare_mapped(&tport->xmit_fifo, sgl, ARRAY_SIZE(sgl),
UART_XMIT_SIZE, dma->tx_addr); UART_XMIT_SIZE, dma->tx_addr);
/* we already checked empty fifo above, so there should be something */ dma->tx_size = 0;
if (WARN_ON_ONCE(ret != 1))
return 0;
dma->tx_size = sg_dma_len(&sg); for_each_sg(sgl, sg, ret, i)
dma->tx_size += sg_dma_len(sg);
desc = dmaengine_prep_slave_sg(dma->txchan, &sg, 1, desc = dmaengine_prep_slave_sg(dma->txchan, sgl, ret,
DMA_MEM_TO_DEV, DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK); DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc) { if (!desc) {
......
...@@ -89,7 +89,7 @@ static void dw8250_set_divisor(struct uart_port *p, unsigned int baud, ...@@ -89,7 +89,7 @@ static void dw8250_set_divisor(struct uart_port *p, unsigned int baud,
unsigned int quot, unsigned int quot_frac) unsigned int quot, unsigned int quot_frac)
{ {
dw8250_writel_ext(p, DW_UART_DLF, quot_frac); dw8250_writel_ext(p, DW_UART_DLF, quot_frac);
serial8250_do_set_divisor(p, baud, quot, quot_frac); serial8250_do_set_divisor(p, baud, quot);
} }
void dw8250_do_set_termios(struct uart_port *p, struct ktermios *termios, void dw8250_do_set_termios(struct uart_port *p, struct ktermios *termios,
......
...@@ -171,6 +171,17 @@ OF_EARLYCON_DECLARE(ns16550a, "ns16550a", early_serial8250_setup); ...@@ -171,6 +171,17 @@ OF_EARLYCON_DECLARE(ns16550a, "ns16550a", early_serial8250_setup);
OF_EARLYCON_DECLARE(uart, "nvidia,tegra20-uart", early_serial8250_setup); OF_EARLYCON_DECLARE(uart, "nvidia,tegra20-uart", early_serial8250_setup);
OF_EARLYCON_DECLARE(uart, "snps,dw-apb-uart", early_serial8250_setup); OF_EARLYCON_DECLARE(uart, "snps,dw-apb-uart", early_serial8250_setup);
static int __init early_serial8250_rs2_setup(struct earlycon_device *device,
const char *options)
{
device->port.regshift = 2;
return early_serial8250_setup(device, options);
}
OF_EARLYCON_DECLARE(uart, "intel,xscale-uart", early_serial8250_rs2_setup);
OF_EARLYCON_DECLARE(uart, "mrvl,mmp-uart", early_serial8250_rs2_setup);
OF_EARLYCON_DECLARE(uart, "mrvl,pxa-uart", early_serial8250_rs2_setup);
#ifdef CONFIG_SERIAL_8250_OMAP #ifdef CONFIG_SERIAL_8250_OMAP
static int __init early_omap8250_setup(struct earlycon_device *device, static int __init early_omap8250_setup(struct earlycon_device *device,
......
...@@ -500,7 +500,7 @@ static unsigned int xr17v35x_get_divisor(struct uart_port *p, unsigned int baud, ...@@ -500,7 +500,7 @@ static unsigned int xr17v35x_get_divisor(struct uart_port *p, unsigned int baud,
static void xr17v35x_set_divisor(struct uart_port *p, unsigned int baud, static void xr17v35x_set_divisor(struct uart_port *p, unsigned int baud,
unsigned int quot, unsigned int quot_frac) unsigned int quot, unsigned int quot_frac)
{ {
serial8250_do_set_divisor(p, baud, quot, quot_frac); serial8250_do_set_divisor(p, baud, quot);
/* Preserve bits not related to baudrate; DLD[7:4]. */ /* Preserve bits not related to baudrate; DLD[7:4]. */
quot_frac |= serial_port_in(p, 0x2) & 0xf0; quot_frac |= serial_port_in(p, 0x2) & 0xf0;
......
...@@ -137,7 +137,6 @@ struct omap8250_priv { ...@@ -137,7 +137,6 @@ struct omap8250_priv {
atomic_t active; atomic_t active;
bool is_suspending; bool is_suspending;
int wakeirq; int wakeirq;
int wakeups_enabled;
u32 latency; u32 latency;
u32 calc_latency; u32 calc_latency;
struct pm_qos_request pm_qos_request; struct pm_qos_request pm_qos_request;
...@@ -1523,7 +1522,10 @@ static int omap8250_probe(struct platform_device *pdev) ...@@ -1523,7 +1522,10 @@ static int omap8250_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, priv); platform_set_drvdata(pdev, priv);
device_init_wakeup(&pdev->dev, true); device_set_wakeup_capable(&pdev->dev, true);
if (of_property_read_bool(np, "wakeup-source"))
device_set_wakeup_enable(&pdev->dev, true);
pm_runtime_enable(&pdev->dev); pm_runtime_enable(&pdev->dev);
pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_use_autosuspend(&pdev->dev);
...@@ -1581,7 +1583,7 @@ static int omap8250_probe(struct platform_device *pdev) ...@@ -1581,7 +1583,7 @@ static int omap8250_probe(struct platform_device *pdev)
ret = devm_request_irq(&pdev->dev, up.port.irq, omap8250_irq, 0, ret = devm_request_irq(&pdev->dev, up.port.irq, omap8250_irq, 0,
dev_name(&pdev->dev), priv); dev_name(&pdev->dev), priv);
if (ret < 0) if (ret < 0)
return ret; goto err;
priv->wakeirq = irq_of_parse_and_map(np, 1); priv->wakeirq = irq_of_parse_and_map(np, 1);
...@@ -1622,7 +1624,7 @@ static void omap8250_remove(struct platform_device *pdev) ...@@ -1622,7 +1624,7 @@ static void omap8250_remove(struct platform_device *pdev)
flush_work(&priv->qos_work); flush_work(&priv->qos_work);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
cpu_latency_qos_remove_request(&priv->pm_qos_request); cpu_latency_qos_remove_request(&priv->pm_qos_request);
device_init_wakeup(&pdev->dev, false); device_set_wakeup_capable(&pdev->dev, false);
} }
static int omap8250_prepare(struct device *dev) static int omap8250_prepare(struct device *dev)
......
...@@ -1277,7 +1277,7 @@ static void pci_oxsemi_tornado_set_divisor(struct uart_port *port, ...@@ -1277,7 +1277,7 @@ static void pci_oxsemi_tornado_set_divisor(struct uart_port *port,
serial_icr_write(up, UART_TCR, tcr); serial_icr_write(up, UART_TCR, tcr);
serial_icr_write(up, UART_CPR, cpr); serial_icr_write(up, UART_CPR, cpr);
serial_icr_write(up, UART_CKS, cpr2); serial_icr_write(up, UART_CKS, cpr2);
serial8250_do_set_divisor(port, baud, quot, 0); serial8250_do_set_divisor(port, baud, quot);
} }
/* /*
......
...@@ -2,11 +2,15 @@ ...@@ -2,11 +2,15 @@
/* /*
* Universal/legacy platform driver for 8250/16550-type serial ports * Universal/legacy platform driver for 8250/16550-type serial ports
* *
* Supports: ISA-compatible 8250/16550 ports * Supports:
* ISA-compatible 8250/16550 ports
* ACPI 8250/16550 ports
* PNP 8250/16550 ports * PNP 8250/16550 ports
* "serial8250" platform devices * "serial8250" platform devices
*/ */
#include <linux/acpi.h>
#include <linux/array_size.h> #include <linux/array_size.h>
#include <linux/io.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/once.h> #include <linux/once.h>
...@@ -22,9 +26,9 @@ ...@@ -22,9 +26,9 @@
/* /*
* Configuration: * Configuration:
* share_irqs Whether we pass IRQF_SHARED to request_irq(). * share_irqs: Whether we pass IRQF_SHARED to request_irq().
* This option is unsafe when used on edge-triggered interrupts. * This option is unsafe when used on edge-triggered interrupts.
* skip_txen_test Force skip of txen test at init time. * skip_txen_test: Force skip of txen test at init time.
*/ */
unsigned int share_irqs = SERIAL8250_SHARE_IRQS; unsigned int share_irqs = SERIAL8250_SHARE_IRQS;
unsigned int skip_txen_test; unsigned int skip_txen_test;
...@@ -61,9 +65,9 @@ static void __init __serial8250_isa_init_ports(void) ...@@ -61,9 +65,9 @@ static void __init __serial8250_isa_init_ports(void)
nr_uarts = UART_NR; nr_uarts = UART_NR;
/* /*
* Set up initial isa ports based on nr_uart module param, or else * Set up initial ISA ports based on nr_uart module param, or else
* default to CONFIG_SERIAL_8250_RUNTIME_UARTS. Note that we do not * default to CONFIG_SERIAL_8250_RUNTIME_UARTS. Note that we do not
* need to increase nr_uarts when setting up the initial isa ports. * need to increase nr_uarts when setting up the initial ISA ports.
*/ */
for (i = 0; i < nr_uarts; i++) for (i = 0; i < nr_uarts; i++)
serial8250_setup_port(i); serial8250_setup_port(i);
...@@ -101,13 +105,63 @@ void __init serial8250_isa_init_ports(void) ...@@ -101,13 +105,63 @@ void __init serial8250_isa_init_ports(void)
} }
/* /*
* Register a set of serial devices attached to a platform device. The * Generic 16550A platform devices
* list is terminated with a zero flags entry, which means we expect
* all entries to have at least UPF_BOOT_AUTOCONF set.
*/ */
static int serial8250_probe(struct platform_device *dev) static int serial8250_probe_acpi(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct uart_8250_port uart = { };
struct resource *regs;
unsigned char iotype;
int ret, line;
regs = platform_get_mem_or_io(pdev, 0);
if (!regs)
return dev_err_probe(dev, -EINVAL, "no registers defined\n");
switch (resource_type(regs)) {
case IORESOURCE_IO:
uart.port.iobase = regs->start;
iotype = UPIO_PORT;
break;
case IORESOURCE_MEM:
uart.port.mapbase = regs->start;
uart.port.mapsize = resource_size(regs);
uart.port.flags = UPF_IOREMAP;
iotype = UPIO_MEM;
break;
default:
return -EINVAL;
}
/* default clock frequency */
uart.port.uartclk = 1843200;
uart.port.type = PORT_16550A;
uart.port.dev = &pdev->dev;
uart.port.flags |= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
ret = uart_read_and_validate_port_properties(&uart.port);
/* no interrupt -> fall back to polling */
if (ret == -ENXIO)
ret = 0;
if (ret)
return ret;
/*
* The previous call may not set iotype correctly when reg-io-width
* property is absent and it doesn't support IO port resource.
*/
uart.port.iotype = iotype;
line = serial8250_register_8250_port(&uart);
if (line < 0)
return line;
return 0;
}
static int serial8250_probe_platform(struct platform_device *dev, struct plat_serial8250_port *p)
{ {
struct plat_serial8250_port *p = dev_get_platdata(&dev->dev);
struct uart_8250_port uart; struct uart_8250_port uart;
int ret, i, irqflag = 0; int ret, i, irqflag = 0;
...@@ -155,6 +209,31 @@ static int serial8250_probe(struct platform_device *dev) ...@@ -155,6 +209,31 @@ static int serial8250_probe(struct platform_device *dev)
return 0; return 0;
} }
/*
* Register a set of serial devices attached to a platform device.
* The list is terminated with a zero flags entry, which means we expect
* all entries to have at least UPF_BOOT_AUTOCONF set.
*/
static int serial8250_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct plat_serial8250_port *p;
p = dev_get_platdata(dev);
if (p)
return serial8250_probe_platform(pdev, p);
/*
* Probe platform UART devices defined using standard hardware
* discovery mechanism like ACPI or DT. Support only ACPI based
* serial device for now.
*/
if (has_acpi_companion(dev))
return serial8250_probe_acpi(pdev);
return 0;
}
/* /*
* Remove serial ports registered against a platform device. * Remove serial ports registered against a platform device.
*/ */
...@@ -198,6 +277,12 @@ static int serial8250_resume(struct platform_device *dev) ...@@ -198,6 +277,12 @@ static int serial8250_resume(struct platform_device *dev)
return 0; return 0;
} }
static const struct acpi_device_id acpi_platform_serial_table[] = {
{ "RSCV0003" }, /* RISC-V Generic 16550A UART */
{ }
};
MODULE_DEVICE_TABLE(acpi, acpi_platform_serial_table);
static struct platform_driver serial8250_isa_driver = { static struct platform_driver serial8250_isa_driver = {
.probe = serial8250_probe, .probe = serial8250_probe,
.remove_new = serial8250_remove, .remove_new = serial8250_remove,
...@@ -205,12 +290,13 @@ static struct platform_driver serial8250_isa_driver = { ...@@ -205,12 +290,13 @@ static struct platform_driver serial8250_isa_driver = {
.resume = serial8250_resume, .resume = serial8250_resume,
.driver = { .driver = {
.name = "serial8250", .name = "serial8250",
.acpi_match_table = acpi_platform_serial_table,
}, },
}; };
/* /*
* This "device" covers _all_ ISA 8250-compatible serial devices listed * This "device" covers _all_ ISA 8250-compatible serial devices listed
* in the table in include/asm/serial.h * in the table in include/asm/serial.h.
*/ */
struct platform_device *serial8250_isa_devs; struct platform_device *serial8250_isa_devs;
...@@ -239,8 +325,7 @@ static int __init serial8250_init(void) ...@@ -239,8 +325,7 @@ static int __init serial8250_init(void)
if (ret) if (ret)
goto unreg_uart_drv; goto unreg_uart_drv;
serial8250_isa_devs = platform_device_alloc("serial8250", serial8250_isa_devs = platform_device_alloc("serial8250", PLAT8250_DEV_LEGACY);
PLAT8250_DEV_LEGACY);
if (!serial8250_isa_devs) { if (!serial8250_isa_devs) {
ret = -ENOMEM; ret = -ENOMEM;
goto unreg_pnp; goto unreg_pnp;
...@@ -279,7 +364,7 @@ static void __exit serial8250_exit(void) ...@@ -279,7 +364,7 @@ static void __exit serial8250_exit(void)
/* /*
* This tells serial8250_unregister_port() not to re-register * This tells serial8250_unregister_port() not to re-register
* the ports (thereby making serial8250_isa_driver permanently * the ports (thereby making serial8250_isa_driver permanently
* in use.) * in use).
*/ */
serial8250_isa_devs = NULL; serial8250_isa_devs = NULL;
...@@ -312,12 +397,13 @@ MODULE_ALIAS_CHARDEV_MAJOR(TTY_MAJOR); ...@@ -312,12 +397,13 @@ MODULE_ALIAS_CHARDEV_MAJOR(TTY_MAJOR);
#ifdef CONFIG_SERIAL_8250_DEPRECATED_OPTIONS #ifdef CONFIG_SERIAL_8250_DEPRECATED_OPTIONS
#ifndef MODULE #ifndef MODULE
/* This module was renamed to 8250_core in 3.7. Keep the old "8250" name /*
* working as well for the module options so we don't break people. We * This module was renamed to 8250_core in 3.7. Keep the old "8250" name
* working as well for the module options so we don't break people. We
* need to keep the names identical and the convenient macros will happily * need to keep the names identical and the convenient macros will happily
* refuse to let us do that by failing the build with redefinition errors * refuse to let us do that by failing the build with redefinition errors
* of global variables. So we stick them inside a dummy function to avoid * of global variables. So we stick them inside a dummy function to avoid
* those conflicts. The options still get parsed, and the redefined * those conflicts. The options still get parsed, and the redefined
* MODULE_PARAM_PREFIX lets us keep the "8250." syntax alive. * MODULE_PARAM_PREFIX lets us keep the "8250." syntax alive.
* *
* This is hacky. I'm sorry. * This is hacky. I'm sorry.
......
...@@ -2609,7 +2609,7 @@ static unsigned char serial8250_compute_lcr(struct uart_8250_port *up, ...@@ -2609,7 +2609,7 @@ static unsigned char serial8250_compute_lcr(struct uart_8250_port *up,
} }
void serial8250_do_set_divisor(struct uart_port *port, unsigned int baud, void serial8250_do_set_divisor(struct uart_port *port, unsigned int baud,
unsigned int quot, unsigned int quot_frac) unsigned int quot)
{ {
struct uart_8250_port *up = up_to_u8250p(port); struct uart_8250_port *up = up_to_u8250p(port);
...@@ -2641,7 +2641,7 @@ static void serial8250_set_divisor(struct uart_port *port, unsigned int baud, ...@@ -2641,7 +2641,7 @@ static void serial8250_set_divisor(struct uart_port *port, unsigned int baud,
if (port->set_divisor) if (port->set_divisor)
port->set_divisor(port, baud, quot, quot_frac); port->set_divisor(port, baud, quot, quot_frac);
else else
serial8250_do_set_divisor(port, baud, quot, quot_frac); serial8250_do_set_divisor(port, baud, quot);
} }
static unsigned int serial8250_get_baud_rate(struct uart_port *port, static unsigned int serial8250_get_baud_rate(struct uart_port *port,
......
...@@ -165,22 +165,6 @@ static struct platform_driver serial_pxa_driver = { ...@@ -165,22 +165,6 @@ static struct platform_driver serial_pxa_driver = {
module_platform_driver(serial_pxa_driver); module_platform_driver(serial_pxa_driver);
#ifdef CONFIG_SERIAL_8250_CONSOLE
static int __init early_serial_pxa_setup(struct earlycon_device *device,
const char *options)
{
struct uart_port *port = &device->port;
if (!(device->port.membase || device->port.iobase))
return -ENODEV;
port->regshift = 2;
return early_serial8250_setup(device, NULL);
}
OF_EARLYCON_DECLARE(early_pxa, "mrvl,pxa-uart", early_serial_pxa_setup);
OF_EARLYCON_DECLARE(mmp, "mrvl,mmp-uart", early_serial_pxa_setup);
#endif
MODULE_AUTHOR("Sergei Ianovich"); MODULE_AUTHOR("Sergei Ianovich");
MODULE_DESCRIPTION("driver for PXA on-board UARTS"); MODULE_DESCRIPTION("driver for PXA on-board UARTS");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
......
...@@ -124,13 +124,14 @@ struct qcom_geni_serial_port { ...@@ -124,13 +124,14 @@ struct qcom_geni_serial_port {
dma_addr_t tx_dma_addr; dma_addr_t tx_dma_addr;
dma_addr_t rx_dma_addr; dma_addr_t rx_dma_addr;
bool setup; bool setup;
unsigned int baud; unsigned long poll_timeout_us;
unsigned long clk_rate; unsigned long clk_rate;
void *rx_buf; void *rx_buf;
u32 loopback; u32 loopback;
bool brk; bool brk;
unsigned int tx_remaining; unsigned int tx_remaining;
unsigned int tx_queued;
int wakeup_irq; int wakeup_irq;
bool rx_tx_swap; bool rx_tx_swap;
bool cts_rts_swap; bool cts_rts_swap;
...@@ -144,6 +145,9 @@ static const struct uart_ops qcom_geni_uart_pops; ...@@ -144,6 +145,9 @@ static const struct uart_ops qcom_geni_uart_pops;
static struct uart_driver qcom_geni_console_driver; static struct uart_driver qcom_geni_console_driver;
static struct uart_driver qcom_geni_uart_driver; static struct uart_driver qcom_geni_uart_driver;
static void __qcom_geni_serial_cancel_tx_cmd(struct uart_port *uport);
static void qcom_geni_serial_cancel_tx_cmd(struct uart_port *uport);
static inline struct qcom_geni_serial_port *to_dev_port(struct uart_port *uport) static inline struct qcom_geni_serial_port *to_dev_port(struct uart_port *uport)
{ {
return container_of(uport, struct qcom_geni_serial_port, uport); return container_of(uport, struct qcom_geni_serial_port, uport);
...@@ -265,27 +269,18 @@ static bool qcom_geni_serial_secondary_active(struct uart_port *uport) ...@@ -265,27 +269,18 @@ static bool qcom_geni_serial_secondary_active(struct uart_port *uport)
return readl(uport->membase + SE_GENI_STATUS) & S_GENI_CMD_ACTIVE; return readl(uport->membase + SE_GENI_STATUS) & S_GENI_CMD_ACTIVE;
} }
static bool qcom_geni_serial_poll_bit(struct uart_port *uport, static bool qcom_geni_serial_poll_bitfield(struct uart_port *uport,
int offset, int field, bool set) unsigned int offset, u32 field, u32 val)
{ {
u32 reg; u32 reg;
struct qcom_geni_serial_port *port; struct qcom_geni_serial_port *port;
unsigned int baud;
unsigned int fifo_bits;
unsigned long timeout_us = 20000; unsigned long timeout_us = 20000;
struct qcom_geni_private_data *private_data = uport->private_data; struct qcom_geni_private_data *private_data = uport->private_data;
if (private_data->drv) { if (private_data->drv) {
port = to_dev_port(uport); port = to_dev_port(uport);
baud = port->baud; if (port->poll_timeout_us)
if (!baud) timeout_us = port->poll_timeout_us;
baud = 115200;
fifo_bits = port->tx_fifo_depth * port->tx_fifo_width;
/*
* Total polling iterations based on FIFO worth of bytes to be
* sent at current baud. Add a little fluff to the wait.
*/
timeout_us = ((fifo_bits * USEC_PER_SEC) / baud) + 500;
} }
/* /*
...@@ -295,7 +290,7 @@ static bool qcom_geni_serial_poll_bit(struct uart_port *uport, ...@@ -295,7 +290,7 @@ static bool qcom_geni_serial_poll_bit(struct uart_port *uport,
timeout_us = DIV_ROUND_UP(timeout_us, 10) * 10; timeout_us = DIV_ROUND_UP(timeout_us, 10) * 10;
while (timeout_us) { while (timeout_us) {
reg = readl(uport->membase + offset); reg = readl(uport->membase + offset);
if ((bool)(reg & field) == set) if ((reg & field) == val)
return true; return true;
udelay(10); udelay(10);
timeout_us -= 10; timeout_us -= 10;
...@@ -303,6 +298,12 @@ static bool qcom_geni_serial_poll_bit(struct uart_port *uport, ...@@ -303,6 +298,12 @@ static bool qcom_geni_serial_poll_bit(struct uart_port *uport,
return false; return false;
} }
static bool qcom_geni_serial_poll_bit(struct uart_port *uport,
unsigned int offset, u32 field, bool set)
{
return qcom_geni_serial_poll_bitfield(uport, offset, field, set ? field : 0);
}
static void qcom_geni_serial_setup_tx(struct uart_port *uport, u32 xmit_size) static void qcom_geni_serial_setup_tx(struct uart_port *uport, u32 xmit_size)
{ {
u32 m_cmd; u32 m_cmd;
...@@ -315,18 +316,16 @@ static void qcom_geni_serial_setup_tx(struct uart_port *uport, u32 xmit_size) ...@@ -315,18 +316,16 @@ static void qcom_geni_serial_setup_tx(struct uart_port *uport, u32 xmit_size)
static void qcom_geni_serial_poll_tx_done(struct uart_port *uport) static void qcom_geni_serial_poll_tx_done(struct uart_port *uport)
{ {
int done; int done;
u32 irq_clear = M_CMD_DONE_EN;
done = qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS, done = qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
M_CMD_DONE_EN, true); M_CMD_DONE_EN, true);
if (!done) { if (!done) {
writel(M_GENI_CMD_ABORT, uport->membase + writel(M_GENI_CMD_ABORT, uport->membase +
SE_GENI_M_CMD_CTRL_REG); SE_GENI_M_CMD_CTRL_REG);
irq_clear |= M_CMD_ABORT_EN;
qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS, qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
M_CMD_ABORT_EN, true); M_CMD_ABORT_EN, true);
writel(M_CMD_ABORT_EN, uport->membase + SE_GENI_M_IRQ_CLEAR);
} }
writel(irq_clear, uport->membase + SE_GENI_M_IRQ_CLEAR);
} }
static void qcom_geni_serial_abort_rx(struct uart_port *uport) static void qcom_geni_serial_abort_rx(struct uart_port *uport)
...@@ -386,17 +385,27 @@ static int qcom_geni_serial_get_char(struct uart_port *uport) ...@@ -386,17 +385,27 @@ static int qcom_geni_serial_get_char(struct uart_port *uport)
static void qcom_geni_serial_poll_put_char(struct uart_port *uport, static void qcom_geni_serial_poll_put_char(struct uart_port *uport,
unsigned char c) unsigned char c)
{ {
writel(DEF_TX_WM, uport->membase + SE_GENI_TX_WATERMARK_REG); if (qcom_geni_serial_main_active(uport)) {
qcom_geni_serial_poll_tx_done(uport);
__qcom_geni_serial_cancel_tx_cmd(uport);
}
writel(M_CMD_DONE_EN, uport->membase + SE_GENI_M_IRQ_CLEAR);
qcom_geni_serial_setup_tx(uport, 1); qcom_geni_serial_setup_tx(uport, 1);
WARN_ON(!qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
M_TX_FIFO_WATERMARK_EN, true));
writel(c, uport->membase + SE_GENI_TX_FIFOn); writel(c, uport->membase + SE_GENI_TX_FIFOn);
writel(M_TX_FIFO_WATERMARK_EN, uport->membase + SE_GENI_M_IRQ_CLEAR);
qcom_geni_serial_poll_tx_done(uport); qcom_geni_serial_poll_tx_done(uport);
} }
#endif #endif
#ifdef CONFIG_SERIAL_QCOM_GENI_CONSOLE #ifdef CONFIG_SERIAL_QCOM_GENI_CONSOLE
static void qcom_geni_serial_drain_fifo(struct uart_port *uport)
{
struct qcom_geni_serial_port *port = to_dev_port(uport);
qcom_geni_serial_poll_bitfield(uport, SE_GENI_M_GP_LENGTH, GP_LENGTH,
port->tx_queued);
}
static void qcom_geni_serial_wr_char(struct uart_port *uport, unsigned char ch) static void qcom_geni_serial_wr_char(struct uart_port *uport, unsigned char ch)
{ {
struct qcom_geni_private_data *private_data = uport->private_data; struct qcom_geni_private_data *private_data = uport->private_data;
...@@ -431,6 +440,7 @@ __qcom_geni_serial_console_write(struct uart_port *uport, const char *s, ...@@ -431,6 +440,7 @@ __qcom_geni_serial_console_write(struct uart_port *uport, const char *s,
} }
writel(DEF_TX_WM, uport->membase + SE_GENI_TX_WATERMARK_REG); writel(DEF_TX_WM, uport->membase + SE_GENI_TX_WATERMARK_REG);
writel(M_CMD_DONE_EN, uport->membase + SE_GENI_M_IRQ_CLEAR);
qcom_geni_serial_setup_tx(uport, bytes_to_send); qcom_geni_serial_setup_tx(uport, bytes_to_send);
for (i = 0; i < count; ) { for (i = 0; i < count; ) {
size_t chars_to_write = 0; size_t chars_to_write = 0;
...@@ -469,10 +479,9 @@ static void qcom_geni_serial_console_write(struct console *co, const char *s, ...@@ -469,10 +479,9 @@ static void qcom_geni_serial_console_write(struct console *co, const char *s,
{ {
struct uart_port *uport; struct uart_port *uport;
struct qcom_geni_serial_port *port; struct qcom_geni_serial_port *port;
u32 m_irq_en, s_irq_en;
bool locked = true; bool locked = true;
unsigned long flags; unsigned long flags;
u32 geni_status;
u32 irq_en;
WARN_ON(co->index < 0 || co->index >= GENI_UART_CONS_PORTS); WARN_ON(co->index < 0 || co->index >= GENI_UART_CONS_PORTS);
...@@ -486,40 +495,28 @@ static void qcom_geni_serial_console_write(struct console *co, const char *s, ...@@ -486,40 +495,28 @@ static void qcom_geni_serial_console_write(struct console *co, const char *s,
else else
uart_port_lock_irqsave(uport, &flags); uart_port_lock_irqsave(uport, &flags);
geni_status = readl(uport->membase + SE_GENI_STATUS); m_irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN);
s_irq_en = readl(uport->membase + SE_GENI_S_IRQ_EN);
if (!locked) { writel(0, uport->membase + SE_GENI_M_IRQ_EN);
/* writel(0, uport->membase + SE_GENI_S_IRQ_EN);
* We can only get here if an oops is in progress then we were
* unable to get the lock. This means we can't safely access if (qcom_geni_serial_main_active(uport)) {
* our state variables like tx_remaining. About the best we /* Wait for completion or drain FIFO */
* can do is wait for the FIFO to be empty before we start our if (!locked || port->tx_remaining == 0)
* transfer, so we'll do that. qcom_geni_serial_poll_tx_done(uport);
*/ else
qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS, qcom_geni_serial_drain_fifo(uport);
M_TX_FIFO_NOT_EMPTY_EN, false);
} else if ((geni_status & M_GENI_CMD_ACTIVE) && !port->tx_remaining) { qcom_geni_serial_cancel_tx_cmd(uport);
/*
* It seems we can't interrupt existing transfers if all data
* has been sent, in which case we need to look for done first.
*/
qcom_geni_serial_poll_tx_done(uport);
if (!kfifo_is_empty(&uport->state->port.xmit_fifo)) {
irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN);
writel(irq_en | M_TX_FIFO_WATERMARK_EN,
uport->membase + SE_GENI_M_IRQ_EN);
}
} }
__qcom_geni_serial_console_write(uport, s, count); __qcom_geni_serial_console_write(uport, s, count);
writel(m_irq_en, uport->membase + SE_GENI_M_IRQ_EN);
writel(s_irq_en, uport->membase + SE_GENI_S_IRQ_EN);
if (locked) { if (locked)
if (port->tx_remaining)
qcom_geni_serial_setup_tx(uport, port->tx_remaining);
uart_port_unlock_irqrestore(uport, flags); uart_port_unlock_irqrestore(uport, flags);
}
} }
static void handle_rx_console(struct uart_port *uport, u32 bytes, bool drop) static void handle_rx_console(struct uart_port *uport, u32 bytes, bool drop)
...@@ -682,13 +679,10 @@ static void qcom_geni_serial_stop_tx_fifo(struct uart_port *uport) ...@@ -682,13 +679,10 @@ static void qcom_geni_serial_stop_tx_fifo(struct uart_port *uport)
writel(irq_en, uport->membase + SE_GENI_M_IRQ_EN); writel(irq_en, uport->membase + SE_GENI_M_IRQ_EN);
} }
static void qcom_geni_serial_cancel_tx_cmd(struct uart_port *uport) static void __qcom_geni_serial_cancel_tx_cmd(struct uart_port *uport)
{ {
struct qcom_geni_serial_port *port = to_dev_port(uport); struct qcom_geni_serial_port *port = to_dev_port(uport);
if (!qcom_geni_serial_main_active(uport))
return;
geni_se_cancel_m_cmd(&port->se); geni_se_cancel_m_cmd(&port->se);
if (!qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS, if (!qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
M_CMD_CANCEL_EN, true)) { M_CMD_CANCEL_EN, true)) {
...@@ -698,8 +692,19 @@ static void qcom_geni_serial_cancel_tx_cmd(struct uart_port *uport) ...@@ -698,8 +692,19 @@ static void qcom_geni_serial_cancel_tx_cmd(struct uart_port *uport)
writel(M_CMD_ABORT_EN, uport->membase + SE_GENI_M_IRQ_CLEAR); writel(M_CMD_ABORT_EN, uport->membase + SE_GENI_M_IRQ_CLEAR);
} }
writel(M_CMD_CANCEL_EN, uport->membase + SE_GENI_M_IRQ_CLEAR); writel(M_CMD_CANCEL_EN, uport->membase + SE_GENI_M_IRQ_CLEAR);
}
static void qcom_geni_serial_cancel_tx_cmd(struct uart_port *uport)
{
struct qcom_geni_serial_port *port = to_dev_port(uport);
if (!qcom_geni_serial_main_active(uport))
return;
__qcom_geni_serial_cancel_tx_cmd(uport);
port->tx_remaining = 0; port->tx_remaining = 0;
port->tx_queued = 0;
} }
static void qcom_geni_serial_handle_rx_fifo(struct uart_port *uport, bool drop) static void qcom_geni_serial_handle_rx_fifo(struct uart_port *uport, bool drop)
...@@ -923,9 +928,10 @@ static void qcom_geni_serial_handle_tx_fifo(struct uart_port *uport, ...@@ -923,9 +928,10 @@ static void qcom_geni_serial_handle_tx_fifo(struct uart_port *uport,
if (!chunk) if (!chunk)
goto out_write_wakeup; goto out_write_wakeup;
if (!port->tx_remaining) { if (!active) {
qcom_geni_serial_setup_tx(uport, pending); qcom_geni_serial_setup_tx(uport, pending);
port->tx_remaining = pending; port->tx_remaining = pending;
port->tx_queued = 0;
irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN); irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN);
if (!(irq_en & M_TX_FIFO_WATERMARK_EN)) if (!(irq_en & M_TX_FIFO_WATERMARK_EN))
...@@ -934,6 +940,7 @@ static void qcom_geni_serial_handle_tx_fifo(struct uart_port *uport, ...@@ -934,6 +940,7 @@ static void qcom_geni_serial_handle_tx_fifo(struct uart_port *uport,
} }
qcom_geni_serial_send_chunk_fifo(uport, chunk); qcom_geni_serial_send_chunk_fifo(uport, chunk);
port->tx_queued += chunk;
/* /*
* The tx fifo watermark is level triggered and latched. Though we had * The tx fifo watermark is level triggered and latched. Though we had
...@@ -1244,11 +1251,11 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport, ...@@ -1244,11 +1251,11 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport,
unsigned long clk_rate; unsigned long clk_rate;
u32 ver, sampling_rate; u32 ver, sampling_rate;
unsigned int avg_bw_core; unsigned int avg_bw_core;
unsigned long timeout;
qcom_geni_serial_stop_rx(uport); qcom_geni_serial_stop_rx(uport);
/* baud rate */ /* baud rate */
baud = uart_get_baud_rate(uport, termios, old, 300, 4000000); baud = uart_get_baud_rate(uport, termios, old, 300, 4000000);
port->baud = baud;
sampling_rate = UART_OVERSAMPLING; sampling_rate = UART_OVERSAMPLING;
/* Sampling rate is halved for IP versions >= 2.5 */ /* Sampling rate is halved for IP versions >= 2.5 */
...@@ -1326,9 +1333,21 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport, ...@@ -1326,9 +1333,21 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport,
else else
tx_trans_cfg |= UART_CTS_MASK; tx_trans_cfg |= UART_CTS_MASK;
if (baud) if (baud) {
uart_update_timeout(uport, termios->c_cflag, baud); uart_update_timeout(uport, termios->c_cflag, baud);
/*
* Make sure that qcom_geni_serial_poll_bitfield() waits for
* the FIFO, two-word intermediate transfer register and shift
* register to clear.
*
* Note that uart_fifo_timeout() also adds a 20 ms margin.
*/
timeout = jiffies_to_usecs(uart_fifo_timeout(uport));
timeout += 3 * timeout / port->tx_fifo_depth;
WRITE_ONCE(port->poll_timeout_us, timeout);
}
if (!uart_console(uport)) if (!uart_console(uport))
writel(port->loopback, writel(port->loopback,
uport->membase + SE_UART_LOOPBACK_CFG); uport->membase + SE_UART_LOOPBACK_CFG);
......
...@@ -577,8 +577,8 @@ static void rp2_reset_asic(struct rp2_card *card, unsigned int asic_id) ...@@ -577,8 +577,8 @@ static void rp2_reset_asic(struct rp2_card *card, unsigned int asic_id)
u32 clk_cfg; u32 clk_cfg;
writew(1, base + RP2_GLOBAL_CMD); writew(1, base + RP2_GLOBAL_CMD);
readw(base + RP2_GLOBAL_CMD);
msleep(100); msleep(100);
readw(base + RP2_GLOBAL_CMD);
writel(0, base + RP2_CLK_PRESCALER); writel(0, base + RP2_CLK_PRESCALER);
/* TDM clock configuration */ /* TDM clock configuration */
......
...@@ -550,6 +550,7 @@ static void s3c24xx_serial_stop_rx(struct uart_port *port) ...@@ -550,6 +550,7 @@ static void s3c24xx_serial_stop_rx(struct uart_port *port)
case TYPE_APPLE_S5L: case TYPE_APPLE_S5L:
s3c24xx_clear_bit(port, APPLE_S5L_UCON_RXTHRESH_ENA, S3C2410_UCON); s3c24xx_clear_bit(port, APPLE_S5L_UCON_RXTHRESH_ENA, S3C2410_UCON);
s3c24xx_clear_bit(port, APPLE_S5L_UCON_RXTO_ENA, S3C2410_UCON); s3c24xx_clear_bit(port, APPLE_S5L_UCON_RXTO_ENA, S3C2410_UCON);
s3c24xx_clear_bit(port, APPLE_S5L_UCON_RXTO_LEGACY_ENA, S3C2410_UCON);
break; break;
default: default:
disable_irq_nosync(ourport->rx_irq); disable_irq_nosync(ourport->rx_irq);
...@@ -707,9 +708,8 @@ static void enable_rx_pio(struct s3c24xx_uart_port *ourport) ...@@ -707,9 +708,8 @@ static void enable_rx_pio(struct s3c24xx_uart_port *ourport)
static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport); static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport);
static irqreturn_t s3c24xx_serial_rx_chars_dma(void *dev_id) static irqreturn_t s3c24xx_serial_rx_chars_dma(struct s3c24xx_uart_port *ourport)
{ {
struct s3c24xx_uart_port *ourport = dev_id;
struct uart_port *port = &ourport->port; struct uart_port *port = &ourport->port;
struct s3c24xx_uart_dma *dma = ourport->dma; struct s3c24xx_uart_dma *dma = ourport->dma;
struct tty_struct *tty = tty_port_tty_get(&ourport->port.state->port); struct tty_struct *tty = tty_port_tty_get(&ourport->port.state->port);
...@@ -843,9 +843,8 @@ static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport) ...@@ -843,9 +843,8 @@ static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport)
tty_flip_buffer_push(&port->state->port); tty_flip_buffer_push(&port->state->port);
} }
static irqreturn_t s3c24xx_serial_rx_chars_pio(void *dev_id) static irqreturn_t s3c24xx_serial_rx_chars_pio(struct s3c24xx_uart_port *ourport)
{ {
struct s3c24xx_uart_port *ourport = dev_id;
struct uart_port *port = &ourport->port; struct uart_port *port = &ourport->port;
uart_port_lock(port); uart_port_lock(port);
...@@ -855,13 +854,11 @@ static irqreturn_t s3c24xx_serial_rx_chars_pio(void *dev_id) ...@@ -855,13 +854,11 @@ static irqreturn_t s3c24xx_serial_rx_chars_pio(void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static irqreturn_t s3c24xx_serial_rx_irq(int irq, void *dev_id) static irqreturn_t s3c24xx_serial_rx_irq(struct s3c24xx_uart_port *ourport)
{ {
struct s3c24xx_uart_port *ourport = dev_id;
if (ourport->dma && ourport->dma->rx_chan) if (ourport->dma && ourport->dma->rx_chan)
return s3c24xx_serial_rx_chars_dma(dev_id); return s3c24xx_serial_rx_chars_dma(ourport);
return s3c24xx_serial_rx_chars_pio(dev_id); return s3c24xx_serial_rx_chars_pio(ourport);
} }
static void s3c24xx_serial_tx_chars(struct s3c24xx_uart_port *ourport) static void s3c24xx_serial_tx_chars(struct s3c24xx_uart_port *ourport)
...@@ -928,9 +925,8 @@ static void s3c24xx_serial_tx_chars(struct s3c24xx_uart_port *ourport) ...@@ -928,9 +925,8 @@ static void s3c24xx_serial_tx_chars(struct s3c24xx_uart_port *ourport)
s3c24xx_serial_stop_tx(port); s3c24xx_serial_stop_tx(port);
} }
static irqreturn_t s3c24xx_serial_tx_irq(int irq, void *id) static irqreturn_t s3c24xx_serial_tx_irq(struct s3c24xx_uart_port *ourport)
{ {
struct s3c24xx_uart_port *ourport = id;
struct uart_port *port = &ourport->port; struct uart_port *port = &ourport->port;
uart_port_lock(port); uart_port_lock(port);
...@@ -944,17 +940,17 @@ static irqreturn_t s3c24xx_serial_tx_irq(int irq, void *id) ...@@ -944,17 +940,17 @@ static irqreturn_t s3c24xx_serial_tx_irq(int irq, void *id)
/* interrupt handler for s3c64xx and later SoC's.*/ /* interrupt handler for s3c64xx and later SoC's.*/
static irqreturn_t s3c64xx_serial_handle_irq(int irq, void *id) static irqreturn_t s3c64xx_serial_handle_irq(int irq, void *id)
{ {
const struct s3c24xx_uart_port *ourport = id; struct s3c24xx_uart_port *ourport = id;
const struct uart_port *port = &ourport->port; const struct uart_port *port = &ourport->port;
u32 pend = rd_regl(port, S3C64XX_UINTP); u32 pend = rd_regl(port, S3C64XX_UINTP);
irqreturn_t ret = IRQ_HANDLED; irqreturn_t ret = IRQ_HANDLED;
if (pend & S3C64XX_UINTM_RXD_MSK) { if (pend & S3C64XX_UINTM_RXD_MSK) {
ret = s3c24xx_serial_rx_irq(irq, id); ret = s3c24xx_serial_rx_irq(ourport);
wr_regl(port, S3C64XX_UINTP, S3C64XX_UINTM_RXD_MSK); wr_regl(port, S3C64XX_UINTP, S3C64XX_UINTM_RXD_MSK);
} }
if (pend & S3C64XX_UINTM_TXD_MSK) { if (pend & S3C64XX_UINTM_TXD_MSK) {
ret = s3c24xx_serial_tx_irq(irq, id); ret = s3c24xx_serial_tx_irq(ourport);
wr_regl(port, S3C64XX_UINTP, S3C64XX_UINTM_TXD_MSK); wr_regl(port, S3C64XX_UINTP, S3C64XX_UINTM_TXD_MSK);
} }
return ret; return ret;
...@@ -963,19 +959,21 @@ static irqreturn_t s3c64xx_serial_handle_irq(int irq, void *id) ...@@ -963,19 +959,21 @@ static irqreturn_t s3c64xx_serial_handle_irq(int irq, void *id)
/* interrupt handler for Apple SoC's.*/ /* interrupt handler for Apple SoC's.*/
static irqreturn_t apple_serial_handle_irq(int irq, void *id) static irqreturn_t apple_serial_handle_irq(int irq, void *id)
{ {
const struct s3c24xx_uart_port *ourport = id; struct s3c24xx_uart_port *ourport = id;
const struct uart_port *port = &ourport->port; const struct uart_port *port = &ourport->port;
u32 pend = rd_regl(port, S3C2410_UTRSTAT); u32 pend = rd_regl(port, S3C2410_UTRSTAT);
irqreturn_t ret = IRQ_NONE; irqreturn_t ret = IRQ_NONE;
if (pend & (APPLE_S5L_UTRSTAT_RXTHRESH | APPLE_S5L_UTRSTAT_RXTO)) { if (pend & (APPLE_S5L_UTRSTAT_RXTHRESH | APPLE_S5L_UTRSTAT_RXTO |
APPLE_S5L_UTRSTAT_RXTO_LEGACY)) {
wr_regl(port, S3C2410_UTRSTAT, wr_regl(port, S3C2410_UTRSTAT,
APPLE_S5L_UTRSTAT_RXTHRESH | APPLE_S5L_UTRSTAT_RXTO); APPLE_S5L_UTRSTAT_RXTHRESH | APPLE_S5L_UTRSTAT_RXTO |
ret = s3c24xx_serial_rx_irq(irq, id); APPLE_S5L_UTRSTAT_RXTO_LEGACY);
ret = s3c24xx_serial_rx_irq(ourport);
} }
if (pend & APPLE_S5L_UTRSTAT_TXTHRESH) { if (pend & APPLE_S5L_UTRSTAT_TXTHRESH) {
wr_regl(port, S3C2410_UTRSTAT, APPLE_S5L_UTRSTAT_TXTHRESH); wr_regl(port, S3C2410_UTRSTAT, APPLE_S5L_UTRSTAT_TXTHRESH);
ret = s3c24xx_serial_tx_irq(irq, id); ret = s3c24xx_serial_tx_irq(ourport);
} }
return ret; return ret;
...@@ -1195,7 +1193,8 @@ static void apple_s5l_serial_shutdown(struct uart_port *port) ...@@ -1195,7 +1193,8 @@ static void apple_s5l_serial_shutdown(struct uart_port *port)
ucon = rd_regl(port, S3C2410_UCON); ucon = rd_regl(port, S3C2410_UCON);
ucon &= ~(APPLE_S5L_UCON_TXTHRESH_ENA_MSK | ucon &= ~(APPLE_S5L_UCON_TXTHRESH_ENA_MSK |
APPLE_S5L_UCON_RXTHRESH_ENA_MSK | APPLE_S5L_UCON_RXTHRESH_ENA_MSK |
APPLE_S5L_UCON_RXTO_ENA_MSK); APPLE_S5L_UCON_RXTO_ENA_MSK |
APPLE_S5L_UCON_RXTO_LEGACY_ENA_MSK);
wr_regl(port, S3C2410_UCON, ucon); wr_regl(port, S3C2410_UCON, ucon);
wr_regl(port, S3C2410_UTRSTAT, APPLE_S5L_UTRSTAT_ALL_FLAGS); wr_regl(port, S3C2410_UTRSTAT, APPLE_S5L_UTRSTAT_ALL_FLAGS);
...@@ -1292,6 +1291,7 @@ static int apple_s5l_serial_startup(struct uart_port *port) ...@@ -1292,6 +1291,7 @@ static int apple_s5l_serial_startup(struct uart_port *port)
/* Enable Rx Interrupt */ /* Enable Rx Interrupt */
s3c24xx_set_bit(port, APPLE_S5L_UCON_RXTHRESH_ENA, S3C2410_UCON); s3c24xx_set_bit(port, APPLE_S5L_UCON_RXTHRESH_ENA, S3C2410_UCON);
s3c24xx_set_bit(port, APPLE_S5L_UCON_RXTO_ENA, S3C2410_UCON); s3c24xx_set_bit(port, APPLE_S5L_UCON_RXTO_ENA, S3C2410_UCON);
s3c24xx_set_bit(port, APPLE_S5L_UCON_RXTO_LEGACY_ENA, S3C2410_UCON);
return ret; return ret;
} }
...@@ -2148,13 +2148,15 @@ static int s3c24xx_serial_resume_noirq(struct device *dev) ...@@ -2148,13 +2148,15 @@ static int s3c24xx_serial_resume_noirq(struct device *dev)
ucon &= ~(APPLE_S5L_UCON_TXTHRESH_ENA_MSK | ucon &= ~(APPLE_S5L_UCON_TXTHRESH_ENA_MSK |
APPLE_S5L_UCON_RXTHRESH_ENA_MSK | APPLE_S5L_UCON_RXTHRESH_ENA_MSK |
APPLE_S5L_UCON_RXTO_ENA_MSK); APPLE_S5L_UCON_RXTO_ENA_MSK |
APPLE_S5L_UCON_RXTO_LEGACY_ENA_MSK);
if (ourport->tx_enabled) if (ourport->tx_enabled)
ucon |= APPLE_S5L_UCON_TXTHRESH_ENA_MSK; ucon |= APPLE_S5L_UCON_TXTHRESH_ENA_MSK;
if (ourport->rx_enabled) if (ourport->rx_enabled)
ucon |= APPLE_S5L_UCON_RXTHRESH_ENA_MSK | ucon |= APPLE_S5L_UCON_RXTHRESH_ENA_MSK |
APPLE_S5L_UCON_RXTO_ENA_MSK; APPLE_S5L_UCON_RXTO_ENA_MSK |
APPLE_S5L_UCON_RXTO_LEGACY_ENA_MSK;
wr_regl(port, S3C2410_UCON, ucon); wr_regl(port, S3C2410_UCON, ucon);
...@@ -2541,7 +2543,7 @@ static const struct s3c24xx_serial_drv_data s5l_serial_drv_data = { ...@@ -2541,7 +2543,7 @@ static const struct s3c24xx_serial_drv_data s5l_serial_drv_data = {
.name = "Apple S5L UART", .name = "Apple S5L UART",
.type = TYPE_APPLE_S5L, .type = TYPE_APPLE_S5L,
.port_type = PORT_8250, .port_type = PORT_8250,
.iotype = UPIO_MEM, .iotype = UPIO_MEM32,
.fifosize = 16, .fifosize = 16,
.rx_fifomask = S3C2410_UFSTAT_RXMASK, .rx_fifomask = S3C2410_UFSTAT_RXMASK,
.rx_fifoshift = S3C2410_UFSTAT_RXSHIFT, .rx_fifoshift = S3C2410_UFSTAT_RXSHIFT,
...@@ -2827,6 +2829,9 @@ OF_EARLYCON_DECLARE(gs101, "google,gs101-uart", gs101_early_console_setup); ...@@ -2827,6 +2829,9 @@ OF_EARLYCON_DECLARE(gs101, "google,gs101-uart", gs101_early_console_setup);
static int __init apple_s5l_early_console_setup(struct earlycon_device *device, static int __init apple_s5l_early_console_setup(struct earlycon_device *device,
const char *opt) const char *opt)
{ {
/* Apple A7-A11 requires MMIO32 register accesses. */
device->port.iotype = UPIO_MEM32;
/* Close enough to S3C2410 for earlycon... */ /* Close enough to S3C2410 for earlycon... */
device->port.private_data = &s3c2410_early_console_data; device->port.private_data = &s3c2410_early_console_data;
......
This diff is collapsed.
...@@ -407,14 +407,16 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state) ...@@ -407,14 +407,16 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state)
/* /*
* Turn off DTR and RTS early. * Turn off DTR and RTS early.
*/ */
if (uport && uart_console(uport) && tty) { if (uport) {
uport->cons->cflag = tty->termios.c_cflag; if (uart_console(uport) && tty) {
uport->cons->ispeed = tty->termios.c_ispeed; uport->cons->cflag = tty->termios.c_cflag;
uport->cons->ospeed = tty->termios.c_ospeed; uport->cons->ispeed = tty->termios.c_ispeed;
} uport->cons->ospeed = tty->termios.c_ospeed;
}
if (!tty || C_HUPCL(tty)) if (!tty || C_HUPCL(tty))
uart_port_dtr_rts(uport, false); uart_port_dtr_rts(uport, false);
}
uart_port_shutdown(port); uart_port_shutdown(port);
} }
...@@ -1102,21 +1104,19 @@ static int uart_tiocmget(struct tty_struct *tty) ...@@ -1102,21 +1104,19 @@ static int uart_tiocmget(struct tty_struct *tty)
struct uart_state *state = tty->driver_data; struct uart_state *state = tty->driver_data;
struct tty_port *port = &state->port; struct tty_port *port = &state->port;
struct uart_port *uport; struct uart_port *uport;
int result = -EIO; int result;
guard(mutex)(&port->mutex);
mutex_lock(&port->mutex);
uport = uart_port_check(state); uport = uart_port_check(state);
if (!uport) if (!uport || tty_io_error(tty))
goto out; return -EIO;
uart_port_lock_irq(uport);
result = uport->mctrl;
result |= uport->ops->get_mctrl(uport);
uart_port_unlock_irq(uport);
if (!tty_io_error(tty)) {
uart_port_lock_irq(uport);
result = uport->mctrl;
result |= uport->ops->get_mctrl(uport);
uart_port_unlock_irq(uport);
}
out:
mutex_unlock(&port->mutex);
return result; return result;
} }
...@@ -1126,20 +1126,16 @@ uart_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) ...@@ -1126,20 +1126,16 @@ uart_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear)
struct uart_state *state = tty->driver_data; struct uart_state *state = tty->driver_data;
struct tty_port *port = &state->port; struct tty_port *port = &state->port;
struct uart_port *uport; struct uart_port *uport;
int ret = -EIO;
mutex_lock(&port->mutex); guard(mutex)(&port->mutex);
uport = uart_port_check(state); uport = uart_port_check(state);
if (!uport) if (!uport || tty_io_error(tty))
goto out; return -EIO;
if (!tty_io_error(tty)) { uart_update_mctrl(uport, set, clear);
uart_update_mctrl(uport, set, clear);
ret = 0; return 0;
}
out:
mutex_unlock(&port->mutex);
return ret;
} }
static int uart_break_ctl(struct tty_struct *tty, int break_state) static int uart_break_ctl(struct tty_struct *tty, int break_state)
...@@ -1147,19 +1143,17 @@ static int uart_break_ctl(struct tty_struct *tty, int break_state) ...@@ -1147,19 +1143,17 @@ static int uart_break_ctl(struct tty_struct *tty, int break_state)
struct uart_state *state = tty->driver_data; struct uart_state *state = tty->driver_data;
struct tty_port *port = &state->port; struct tty_port *port = &state->port;
struct uart_port *uport; struct uart_port *uport;
int ret = -EIO;
mutex_lock(&port->mutex); guard(mutex)(&port->mutex);
uport = uart_port_check(state); uport = uart_port_check(state);
if (!uport) if (!uport)
goto out; return -EIO;
if (uport->type != PORT_UNKNOWN && uport->ops->break_ctl) if (uport->type != PORT_UNKNOWN && uport->ops->break_ctl)
uport->ops->break_ctl(uport, break_state); uport->ops->break_ctl(uport, break_state);
ret = 0;
out: return 0;
mutex_unlock(&port->mutex);
return ret;
} }
static int uart_do_autoconfig(struct tty_struct *tty, struct uart_state *state) static int uart_do_autoconfig(struct tty_struct *tty, struct uart_state *state)
...@@ -1176,17 +1170,14 @@ static int uart_do_autoconfig(struct tty_struct *tty, struct uart_state *state) ...@@ -1176,17 +1170,14 @@ static int uart_do_autoconfig(struct tty_struct *tty, struct uart_state *state)
* changing, and hence any extra opens of the port while * changing, and hence any extra opens of the port while
* we're auto-configuring. * we're auto-configuring.
*/ */
if (mutex_lock_interruptible(&port->mutex)) scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &port->mutex) {
return -ERESTARTSYS; uport = uart_port_check(state);
if (!uport)
return -EIO;
uport = uart_port_check(state); if (tty_port_users(port) != 1)
if (!uport) { return -EBUSY;
ret = -EIO;
goto out;
}
ret = -EBUSY;
if (tty_port_users(port) == 1) {
uart_shutdown(tty, state); uart_shutdown(tty, state);
/* /*
...@@ -1207,14 +1198,15 @@ static int uart_do_autoconfig(struct tty_struct *tty, struct uart_state *state) ...@@ -1207,14 +1198,15 @@ static int uart_do_autoconfig(struct tty_struct *tty, struct uart_state *state)
uport->ops->config_port(uport, flags); uport->ops->config_port(uport, flags);
ret = uart_startup(tty, state, true); ret = uart_startup(tty, state, true);
if (ret == 0) if (ret < 0)
tty_port_set_initialized(port, true); return ret;
if (ret > 0) if (ret > 0)
ret = 0; return 0;
tty_port_set_initialized(port, true);
} }
out:
mutex_unlock(&port->mutex); return 0;
return ret;
} }
static void uart_enable_ms(struct uart_port *uport) static void uart_enable_ms(struct uart_port *uport)
...@@ -1709,10 +1701,11 @@ static void uart_set_termios(struct tty_struct *tty, ...@@ -1709,10 +1701,11 @@ static void uart_set_termios(struct tty_struct *tty,
unsigned int iflag_mask = IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK; unsigned int iflag_mask = IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK;
bool sw_changed = false; bool sw_changed = false;
mutex_lock(&state->port.mutex); guard(mutex)(&state->port.mutex);
uport = uart_port_check(state); uport = uart_port_check(state);
if (!uport) if (!uport)
goto out; return;
/* /*
* Drivers doing software flow control also need to know * Drivers doing software flow control also need to know
...@@ -1735,9 +1728,8 @@ static void uart_set_termios(struct tty_struct *tty, ...@@ -1735,9 +1728,8 @@ static void uart_set_termios(struct tty_struct *tty,
tty->termios.c_ospeed == old_termios->c_ospeed && tty->termios.c_ospeed == old_termios->c_ospeed &&
tty->termios.c_ispeed == old_termios->c_ispeed && tty->termios.c_ispeed == old_termios->c_ispeed &&
((tty->termios.c_iflag ^ old_termios->c_iflag) & iflag_mask) == 0 && ((tty->termios.c_iflag ^ old_termios->c_iflag) & iflag_mask) == 0 &&
!sw_changed) { !sw_changed)
goto out; return;
}
uart_change_line_settings(tty, state, old_termios); uart_change_line_settings(tty, state, old_termios);
/* reload cflag from termios; port driver may have overridden flags */ /* reload cflag from termios; port driver may have overridden flags */
...@@ -1754,8 +1746,6 @@ static void uart_set_termios(struct tty_struct *tty, ...@@ -1754,8 +1746,6 @@ static void uart_set_termios(struct tty_struct *tty,
mask |= TIOCM_RTS; mask |= TIOCM_RTS;
uart_set_mctrl(uport, mask); uart_set_mctrl(uport, mask);
} }
out:
mutex_unlock(&state->port.mutex);
} }
/* /*
...@@ -2049,10 +2039,11 @@ static void uart_line_info(struct seq_file *m, struct uart_driver *drv, int i) ...@@ -2049,10 +2039,11 @@ static void uart_line_info(struct seq_file *m, struct uart_driver *drv, int i)
unsigned int status; unsigned int status;
int mmio; int mmio;
mutex_lock(&port->mutex); guard(mutex)(&port->mutex);
uport = uart_port_check(state); uport = uart_port_check(state);
if (!uport) if (!uport)
goto out; return;
mmio = uport->iotype >= UPIO_MEM; mmio = uport->iotype >= UPIO_MEM;
seq_printf(m, "%d: uart:%s %s%08llX irq:%d", seq_printf(m, "%d: uart:%s %s%08llX irq:%d",
...@@ -2064,7 +2055,7 @@ static void uart_line_info(struct seq_file *m, struct uart_driver *drv, int i) ...@@ -2064,7 +2055,7 @@ static void uart_line_info(struct seq_file *m, struct uart_driver *drv, int i)
if (uport->type == PORT_UNKNOWN) { if (uport->type == PORT_UNKNOWN) {
seq_putc(m, '\n'); seq_putc(m, '\n');
goto out; return;
} }
if (capable(CAP_SYS_ADMIN)) { if (capable(CAP_SYS_ADMIN)) {
...@@ -2115,8 +2106,6 @@ static void uart_line_info(struct seq_file *m, struct uart_driver *drv, int i) ...@@ -2115,8 +2106,6 @@ static void uart_line_info(struct seq_file *m, struct uart_driver *drv, int i)
seq_putc(m, '\n'); seq_putc(m, '\n');
#undef STATBIT #undef STATBIT
#undef INFOBIT #undef INFOBIT
out:
mutex_unlock(&port->mutex);
} }
static int uart_proc_show(struct seq_file *m, void *v) static int uart_proc_show(struct seq_file *m, void *v)
...@@ -2393,13 +2382,12 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport) ...@@ -2393,13 +2382,12 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)
struct device *tty_dev; struct device *tty_dev;
struct uart_match match = {uport, drv}; struct uart_match match = {uport, drv};
mutex_lock(&port->mutex); guard(mutex)(&port->mutex);
tty_dev = device_find_child(&uport->port_dev->dev, &match, serial_match_port); tty_dev = device_find_child(&uport->port_dev->dev, &match, serial_match_port);
if (tty_dev && device_may_wakeup(tty_dev)) { if (tty_dev && device_may_wakeup(tty_dev)) {
enable_irq_wake(uport->irq); enable_irq_wake(uport->irq);
put_device(tty_dev); put_device(tty_dev);
mutex_unlock(&port->mutex);
return 0; return 0;
} }
put_device(tty_dev); put_device(tty_dev);
...@@ -2417,7 +2405,7 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport) ...@@ -2417,7 +2405,7 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)
uart_port_unlock_irq(uport); uart_port_unlock_irq(uport);
} }
device_set_awake_path(uport->dev); device_set_awake_path(uport->dev);
goto unlock; return 0;
} }
uport->suspended = 1; uport->suspended = 1;
...@@ -2460,8 +2448,6 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport) ...@@ -2460,8 +2448,6 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)
console_stop(uport->cons); console_stop(uport->cons);
uart_change_pm(state, UART_PM_STATE_OFF); uart_change_pm(state, UART_PM_STATE_OFF);
unlock:
mutex_unlock(&port->mutex);
return 0; return 0;
} }
...@@ -2475,14 +2461,13 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) ...@@ -2475,14 +2461,13 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
struct uart_match match = {uport, drv}; struct uart_match match = {uport, drv};
struct ktermios termios; struct ktermios termios;
mutex_lock(&port->mutex); guard(mutex)(&port->mutex);
tty_dev = device_find_child(&uport->port_dev->dev, &match, serial_match_port); tty_dev = device_find_child(&uport->port_dev->dev, &match, serial_match_port);
if (!uport->suspended && device_may_wakeup(tty_dev)) { if (!uport->suspended && device_may_wakeup(tty_dev)) {
if (irqd_is_wakeup_set(irq_get_irq_data((uport->irq)))) if (irqd_is_wakeup_set(irq_get_irq_data((uport->irq))))
disable_irq_wake(uport->irq); disable_irq_wake(uport->irq);
put_device(tty_dev); put_device(tty_dev);
mutex_unlock(&port->mutex);
return 0; return 0;
} }
put_device(tty_dev); put_device(tty_dev);
...@@ -2555,8 +2540,6 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) ...@@ -2555,8 +2540,6 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
tty_port_set_suspended(port, false); tty_port_set_suspended(port, false);
} }
mutex_unlock(&port->mutex);
return 0; return 0;
} }
EXPORT_SYMBOL(uart_resume_port); EXPORT_SYMBOL(uart_resume_port);
...@@ -2696,14 +2679,13 @@ static int uart_poll_init(struct tty_driver *driver, int line, char *options) ...@@ -2696,14 +2679,13 @@ static int uart_poll_init(struct tty_driver *driver, int line, char *options)
int ret = 0; int ret = 0;
tport = &state->port; tport = &state->port;
mutex_lock(&tport->mutex);
guard(mutex)(&tport->mutex);
port = uart_port_check(state); port = uart_port_check(state);
if (!port || port->type == PORT_UNKNOWN || if (!port || port->type == PORT_UNKNOWN ||
!(port->ops->poll_get_char && port->ops->poll_put_char)) { !(port->ops->poll_get_char && port->ops->poll_put_char))
ret = -1; return -1;
goto out;
}
pm_state = state->pm_state; pm_state = state->pm_state;
uart_change_pm(state, UART_PM_STATE_ON); uart_change_pm(state, UART_PM_STATE_ON);
...@@ -2723,10 +2705,10 @@ static int uart_poll_init(struct tty_driver *driver, int line, char *options) ...@@ -2723,10 +2705,10 @@ static int uart_poll_init(struct tty_driver *driver, int line, char *options)
ret = uart_set_options(port, NULL, baud, parity, bits, flow); ret = uart_set_options(port, NULL, baud, parity, bits, flow);
console_list_unlock(); console_list_unlock();
} }
out:
if (ret) if (ret)
uart_change_pm(state, pm_state); uart_change_pm(state, pm_state);
mutex_unlock(&tport->mutex);
return ret; return ret;
} }
......
...@@ -808,7 +808,6 @@ static void asc_serial_remove(struct platform_device *pdev) ...@@ -808,7 +808,6 @@ static void asc_serial_remove(struct platform_device *pdev)
uart_remove_one_port(&asc_uart_driver, port); uart_remove_one_port(&asc_uart_driver, port);
} }
#ifdef CONFIG_PM_SLEEP
static int asc_serial_suspend(struct device *dev) static int asc_serial_suspend(struct device *dev)
{ {
struct uart_port *port = dev_get_drvdata(dev); struct uart_port *port = dev_get_drvdata(dev);
...@@ -823,8 +822,6 @@ static int asc_serial_resume(struct device *dev) ...@@ -823,8 +822,6 @@ static int asc_serial_resume(struct device *dev)
return uart_resume_port(&asc_uart_driver, port); return uart_resume_port(&asc_uart_driver, port);
} }
#endif /* CONFIG_PM_SLEEP */
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
#ifdef CONFIG_SERIAL_ST_ASC_CONSOLE #ifdef CONFIG_SERIAL_ST_ASC_CONSOLE
...@@ -932,16 +929,15 @@ static struct uart_driver asc_uart_driver = { ...@@ -932,16 +929,15 @@ static struct uart_driver asc_uart_driver = {
.cons = ASC_SERIAL_CONSOLE, .cons = ASC_SERIAL_CONSOLE,
}; };
static const struct dev_pm_ops asc_serial_pm_ops = { static DEFINE_SIMPLE_DEV_PM_OPS(asc_serial_pm_ops, asc_serial_suspend,
SET_SYSTEM_SLEEP_PM_OPS(asc_serial_suspend, asc_serial_resume) asc_serial_resume);
};
static struct platform_driver asc_serial_driver = { static struct platform_driver asc_serial_driver = {
.probe = asc_serial_probe, .probe = asc_serial_probe,
.remove_new = asc_serial_remove, .remove_new = asc_serial_remove,
.driver = { .driver = {
.name = DRIVER_NAME, .name = DRIVER_NAME,
.pm = &asc_serial_pm_ops, .pm = pm_sleep_ptr(&asc_serial_pm_ops),
.of_match_table = of_match_ptr(asc_match), .of_match_table = of_match_ptr(asc_match),
}, },
}; };
......
...@@ -219,7 +219,7 @@ struct cdns_platform_data { ...@@ -219,7 +219,7 @@ struct cdns_platform_data {
u32 quirks; u32 quirks;
}; };
struct serial_rs485 cdns_rs485_supported = { static struct serial_rs485 cdns_rs485_supported = {
.flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND | .flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND |
SER_RS485_RTS_AFTER_SEND, SER_RS485_RTS_AFTER_SEND,
.delay_rts_before_send = 1, .delay_rts_before_send = 1,
......
...@@ -350,22 +350,19 @@ int tty_dev_name_to_number(const char *name, dev_t *number) ...@@ -350,22 +350,19 @@ int tty_dev_name_to_number(const char *name, dev_t *number)
return ret; return ret;
prefix_length = str - name; prefix_length = str - name;
mutex_lock(&tty_mutex);
guard(mutex)(&tty_mutex);
list_for_each_entry(p, &tty_drivers, tty_drivers) list_for_each_entry(p, &tty_drivers, tty_drivers)
if (prefix_length == strlen(p->name) && strncmp(name, if (prefix_length == strlen(p->name) && strncmp(name,
p->name, prefix_length) == 0) { p->name, prefix_length) == 0) {
if (index < p->num) { if (index < p->num) {
*number = MKDEV(p->major, p->minor_start + index); *number = MKDEV(p->major, p->minor_start + index);
goto out; return 0;
} }
} }
/* if here then driver wasn't found */ return -ENODEV;
ret = -ENODEV;
out:
mutex_unlock(&tty_mutex);
return ret;
} }
EXPORT_SYMBOL_GPL(tty_dev_name_to_number); EXPORT_SYMBOL_GPL(tty_dev_name_to_number);
......
...@@ -110,7 +110,6 @@ struct dbc_port { ...@@ -110,7 +110,6 @@ struct dbc_port {
struct tasklet_struct push; struct tasklet_struct push;
struct list_head write_pool; struct list_head write_pool;
struct kfifo write_fifo;
bool registered; bool registered;
}; };
......
...@@ -24,19 +24,6 @@ static inline struct dbc_port *dbc_to_port(struct xhci_dbc *dbc) ...@@ -24,19 +24,6 @@ static inline struct dbc_port *dbc_to_port(struct xhci_dbc *dbc)
return dbc->priv; return dbc->priv;
} }
static unsigned int
dbc_send_packet(struct dbc_port *port, char *packet, unsigned int size)
{
unsigned int len;
len = kfifo_len(&port->write_fifo);
if (len < size)
size = len;
if (size != 0)
size = kfifo_out(&port->write_fifo, packet, size);
return size;
}
static int dbc_start_tx(struct dbc_port *port) static int dbc_start_tx(struct dbc_port *port)
__releases(&port->port_lock) __releases(&port->port_lock)
__acquires(&port->port_lock) __acquires(&port->port_lock)
...@@ -49,7 +36,7 @@ static int dbc_start_tx(struct dbc_port *port) ...@@ -49,7 +36,7 @@ static int dbc_start_tx(struct dbc_port *port)
while (!list_empty(pool)) { while (!list_empty(pool)) {
req = list_entry(pool->next, struct dbc_request, list_pool); req = list_entry(pool->next, struct dbc_request, list_pool);
len = dbc_send_packet(port, req->buf, DBC_MAX_PACKET); len = kfifo_out(&port->port.xmit_fifo, req->buf, DBC_MAX_PACKET);
if (len == 0) if (len == 0)
break; break;
do_tty_wake = true; do_tty_wake = true;
...@@ -216,7 +203,7 @@ static ssize_t dbc_tty_write(struct tty_struct *tty, const u8 *buf, ...@@ -216,7 +203,7 @@ static ssize_t dbc_tty_write(struct tty_struct *tty, const u8 *buf,
spin_lock_irqsave(&port->port_lock, flags); spin_lock_irqsave(&port->port_lock, flags);
if (count) if (count)
count = kfifo_in(&port->write_fifo, buf, count); count = kfifo_in(&port->port.xmit_fifo, buf, count);
dbc_start_tx(port); dbc_start_tx(port);
spin_unlock_irqrestore(&port->port_lock, flags); spin_unlock_irqrestore(&port->port_lock, flags);
...@@ -230,7 +217,7 @@ static int dbc_tty_put_char(struct tty_struct *tty, u8 ch) ...@@ -230,7 +217,7 @@ static int dbc_tty_put_char(struct tty_struct *tty, u8 ch)
int status; int status;
spin_lock_irqsave(&port->port_lock, flags); spin_lock_irqsave(&port->port_lock, flags);
status = kfifo_put(&port->write_fifo, ch); status = kfifo_put(&port->port.xmit_fifo, ch);
spin_unlock_irqrestore(&port->port_lock, flags); spin_unlock_irqrestore(&port->port_lock, flags);
return status; return status;
...@@ -253,7 +240,7 @@ static unsigned int dbc_tty_write_room(struct tty_struct *tty) ...@@ -253,7 +240,7 @@ static unsigned int dbc_tty_write_room(struct tty_struct *tty)
unsigned int room; unsigned int room;
spin_lock_irqsave(&port->port_lock, flags); spin_lock_irqsave(&port->port_lock, flags);
room = kfifo_avail(&port->write_fifo); room = kfifo_avail(&port->port.xmit_fifo);
spin_unlock_irqrestore(&port->port_lock, flags); spin_unlock_irqrestore(&port->port_lock, flags);
return room; return room;
...@@ -266,7 +253,7 @@ static unsigned int dbc_tty_chars_in_buffer(struct tty_struct *tty) ...@@ -266,7 +253,7 @@ static unsigned int dbc_tty_chars_in_buffer(struct tty_struct *tty)
unsigned int chars; unsigned int chars;
spin_lock_irqsave(&port->port_lock, flags); spin_lock_irqsave(&port->port_lock, flags);
chars = kfifo_len(&port->write_fifo); chars = kfifo_len(&port->port.xmit_fifo);
spin_unlock_irqrestore(&port->port_lock, flags); spin_unlock_irqrestore(&port->port_lock, flags);
return chars; return chars;
...@@ -424,7 +411,8 @@ static int xhci_dbc_tty_register_device(struct xhci_dbc *dbc) ...@@ -424,7 +411,8 @@ static int xhci_dbc_tty_register_device(struct xhci_dbc *dbc)
goto err_idr; goto err_idr;
} }
ret = kfifo_alloc(&port->write_fifo, DBC_WRITE_BUF_SIZE, GFP_KERNEL); ret = kfifo_alloc(&port->port.xmit_fifo, DBC_WRITE_BUF_SIZE,
GFP_KERNEL);
if (ret) if (ret)
goto err_exit_port; goto err_exit_port;
...@@ -453,7 +441,7 @@ static int xhci_dbc_tty_register_device(struct xhci_dbc *dbc) ...@@ -453,7 +441,7 @@ static int xhci_dbc_tty_register_device(struct xhci_dbc *dbc)
xhci_dbc_free_requests(&port->read_pool); xhci_dbc_free_requests(&port->read_pool);
xhci_dbc_free_requests(&port->write_pool); xhci_dbc_free_requests(&port->write_pool);
err_free_fifo: err_free_fifo:
kfifo_free(&port->write_fifo); kfifo_free(&port->port.xmit_fifo);
err_exit_port: err_exit_port:
idr_remove(&dbc_tty_minors, port->minor); idr_remove(&dbc_tty_minors, port->minor);
err_idr: err_idr:
...@@ -478,7 +466,7 @@ static void xhci_dbc_tty_unregister_device(struct xhci_dbc *dbc) ...@@ -478,7 +466,7 @@ static void xhci_dbc_tty_unregister_device(struct xhci_dbc *dbc)
idr_remove(&dbc_tty_minors, port->minor); idr_remove(&dbc_tty_minors, port->minor);
mutex_unlock(&dbc_tty_minors_lock); mutex_unlock(&dbc_tty_minors_lock);
kfifo_free(&port->write_fifo); kfifo_free(&port->port.xmit_fifo);
xhci_dbc_free_requests(&port->read_pool); xhci_dbc_free_requests(&port->read_pool);
xhci_dbc_free_requests(&port->read_queue); xhci_dbc_free_requests(&port->read_queue);
xhci_dbc_free_requests(&port->write_pool); xhci_dbc_free_requests(&port->write_pool);
......
...@@ -193,7 +193,7 @@ void serial8250_do_pm(struct uart_port *port, unsigned int state, ...@@ -193,7 +193,7 @@ void serial8250_do_pm(struct uart_port *port, unsigned int state,
unsigned int oldstate); unsigned int oldstate);
void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl); void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl);
void serial8250_do_set_divisor(struct uart_port *port, unsigned int baud, void serial8250_do_set_divisor(struct uart_port *port, unsigned int baud,
unsigned int quot, unsigned int quot_frac); unsigned int quot);
int fsl8250_handle_irq(struct uart_port *port); int fsl8250_handle_irq(struct uart_port *port);
int serial8250_handle_irq(struct uart_port *port, unsigned int iir); int serial8250_handle_irq(struct uart_port *port, unsigned int iir);
u16 serial8250_rx_chars(struct uart_8250_port *up, u16 lsr); u16 serial8250_rx_chars(struct uart_8250_port *up, u16 lsr);
......
...@@ -246,24 +246,28 @@ ...@@ -246,24 +246,28 @@
S5PV210_UFCON_TXTRIG4 | \ S5PV210_UFCON_TXTRIG4 | \
S5PV210_UFCON_RXTRIG4) S5PV210_UFCON_RXTRIG4)
#define APPLE_S5L_UCON_RXTO_ENA 9 #define APPLE_S5L_UCON_RXTO_ENA 9
#define APPLE_S5L_UCON_RXTHRESH_ENA 12 #define APPLE_S5L_UCON_RXTO_LEGACY_ENA 11
#define APPLE_S5L_UCON_TXTHRESH_ENA 13 #define APPLE_S5L_UCON_RXTHRESH_ENA 12
#define APPLE_S5L_UCON_RXTO_ENA_MSK (1 << APPLE_S5L_UCON_RXTO_ENA) #define APPLE_S5L_UCON_TXTHRESH_ENA 13
#define APPLE_S5L_UCON_RXTHRESH_ENA_MSK (1 << APPLE_S5L_UCON_RXTHRESH_ENA) #define APPLE_S5L_UCON_RXTO_ENA_MSK BIT(APPLE_S5L_UCON_RXTO_ENA)
#define APPLE_S5L_UCON_TXTHRESH_ENA_MSK (1 << APPLE_S5L_UCON_TXTHRESH_ENA) #define APPLE_S5L_UCON_RXTO_LEGACY_ENA_MSK BIT(APPLE_S5L_UCON_RXTO_LEGACY_ENA)
#define APPLE_S5L_UCON_RXTHRESH_ENA_MSK BIT(APPLE_S5L_UCON_RXTHRESH_ENA)
#define APPLE_S5L_UCON_TXTHRESH_ENA_MSK BIT(APPLE_S5L_UCON_TXTHRESH_ENA)
#define APPLE_S5L_UCON_DEFAULT (S3C2410_UCON_TXIRQMODE | \ #define APPLE_S5L_UCON_DEFAULT (S3C2410_UCON_TXIRQMODE | \
S3C2410_UCON_RXIRQMODE | \ S3C2410_UCON_RXIRQMODE | \
S3C2410_UCON_RXFIFO_TOI) S3C2410_UCON_RXFIFO_TOI)
#define APPLE_S5L_UCON_MASK (APPLE_S5L_UCON_RXTO_ENA_MSK | \ #define APPLE_S5L_UCON_MASK (APPLE_S5L_UCON_RXTO_ENA_MSK | \
APPLE_S5L_UCON_RXTO_LEGACY_ENA_MSK | \
APPLE_S5L_UCON_RXTHRESH_ENA_MSK | \ APPLE_S5L_UCON_RXTHRESH_ENA_MSK | \
APPLE_S5L_UCON_TXTHRESH_ENA_MSK) APPLE_S5L_UCON_TXTHRESH_ENA_MSK)
#define APPLE_S5L_UTRSTAT_RXTHRESH (1<<4) #define APPLE_S5L_UTRSTAT_RXTO_LEGACY BIT(3)
#define APPLE_S5L_UTRSTAT_TXTHRESH (1<<5) #define APPLE_S5L_UTRSTAT_RXTHRESH BIT(4)
#define APPLE_S5L_UTRSTAT_RXTO (1<<9) #define APPLE_S5L_UTRSTAT_TXTHRESH BIT(5)
#define APPLE_S5L_UTRSTAT_ALL_FLAGS (0x3f0) #define APPLE_S5L_UTRSTAT_RXTO BIT(9)
#define APPLE_S5L_UTRSTAT_ALL_FLAGS GENMASK(9, 3)
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
......
...@@ -88,11 +88,15 @@ struct geni_se { ...@@ -88,11 +88,15 @@ struct geni_se {
#define SE_GENI_M_IRQ_STATUS 0x610 #define SE_GENI_M_IRQ_STATUS 0x610
#define SE_GENI_M_IRQ_EN 0x614 #define SE_GENI_M_IRQ_EN 0x614
#define SE_GENI_M_IRQ_CLEAR 0x618 #define SE_GENI_M_IRQ_CLEAR 0x618
#define SE_GENI_M_IRQ_EN_SET 0x61c
#define SE_GENI_M_IRQ_EN_CLEAR 0x620
#define SE_GENI_S_CMD0 0x630 #define SE_GENI_S_CMD0 0x630
#define SE_GENI_S_CMD_CTRL_REG 0x634 #define SE_GENI_S_CMD_CTRL_REG 0x634
#define SE_GENI_S_IRQ_STATUS 0x640 #define SE_GENI_S_IRQ_STATUS 0x640
#define SE_GENI_S_IRQ_EN 0x644 #define SE_GENI_S_IRQ_EN 0x644
#define SE_GENI_S_IRQ_CLEAR 0x648 #define SE_GENI_S_IRQ_CLEAR 0x648
#define SE_GENI_S_IRQ_EN_SET 0x64c
#define SE_GENI_S_IRQ_EN_CLEAR 0x650
#define SE_GENI_TX_FIFOn 0x700 #define SE_GENI_TX_FIFOn 0x700
#define SE_GENI_RX_FIFOn 0x780 #define SE_GENI_RX_FIFOn 0x780
#define SE_GENI_TX_FIFO_STATUS 0x800 #define SE_GENI_TX_FIFO_STATUS 0x800
...@@ -101,6 +105,8 @@ struct geni_se { ...@@ -101,6 +105,8 @@ struct geni_se {
#define SE_GENI_RX_WATERMARK_REG 0x810 #define SE_GENI_RX_WATERMARK_REG 0x810
#define SE_GENI_RX_RFR_WATERMARK_REG 0x814 #define SE_GENI_RX_RFR_WATERMARK_REG 0x814
#define SE_GENI_IOS 0x908 #define SE_GENI_IOS 0x908
#define SE_GENI_M_GP_LENGTH 0x910
#define SE_GENI_S_GP_LENGTH 0x914
#define SE_DMA_TX_IRQ_STAT 0xc40 #define SE_DMA_TX_IRQ_STAT 0xc40
#define SE_DMA_TX_IRQ_CLR 0xc44 #define SE_DMA_TX_IRQ_CLR 0xc44
#define SE_DMA_TX_FSM_RST 0xc58 #define SE_DMA_TX_FSM_RST 0xc58
...@@ -234,6 +240,9 @@ struct geni_se { ...@@ -234,6 +240,9 @@ struct geni_se {
#define IO2_DATA_IN BIT(1) #define IO2_DATA_IN BIT(1)
#define RX_DATA_IN BIT(0) #define RX_DATA_IN BIT(0)
/* SE_GENI_M_GP_LENGTH and SE_GENI_S_GP_LENGTH fields */
#define GP_LENGTH GENMASK(31, 0)
/* SE_DMA_TX_IRQ_STAT Register fields */ /* SE_DMA_TX_IRQ_STAT Register fields */
#define TX_DMA_DONE BIT(0) #define TX_DMA_DONE BIT(0)
#define TX_EOT BIT(1) #define TX_EOT BIT(1)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment