Skip to content

Commit aba8290

Browse files
RengarajanSSgregkh
authored andcommitted
8250: microchip: pci1xxxx: Add Burst mode reception support in uart driver for writing into FIFO
In PCI1XXXX C0 endpoint, support for Burst mode is added. pci1xxxx_handle_irq checks the burst status and based on that incoming characters are received in DWORDs, RX handling is done in pci1xxxx_rx_burst. While reading the burst status the RX error is checked and the corresponding error statistics are updated. Signed-off-by: Rengarajan S <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent b7fbca3 commit aba8290

File tree

1 file changed

+121
-2
lines changed

1 file changed

+121
-2
lines changed

drivers/tty/serial/8250/8250_pci1xxxx.c

Lines changed: 121 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@
6666
#define SYSLOCK_SLEEP_TIMEOUT 100
6767
#define SYSLOCK_RETRY_CNT 1000
6868

69+
#define UART_RX_BYTE_FIFO 0x00
70+
#define UART_FIFO_CTL 0x02
71+
6972
#define UART_ACTV_REG 0x11
7073
#define UART_BLOCK_SET_ACTIVE BIT(0)
7174

@@ -96,8 +99,23 @@
9699
#define UART_RESET_REG 0x94
97100
#define UART_RESET_D3_RESET_DISABLE BIT(16)
98101

102+
#define UART_BURST_STATUS_REG 0x9C
103+
#define UART_RX_BURST_FIFO 0xA4
104+
99105
#define MAX_PORTS 4
100106
#define PORT_OFFSET 0x100
107+
#define RX_BUF_SIZE 512
108+
#define UART_BYTE_SIZE 1
109+
#define UART_BURST_SIZE 4
110+
111+
#define UART_BST_STAT_RX_COUNT_MASK 0x00FF
112+
#define UART_BST_STAT_IIR_INT_PEND 0x100000
113+
#define UART_LSR_OVERRUN_ERR_CLR 0x43
114+
#define UART_BST_STAT_LSR_RX_MASK 0x9F000000
115+
#define UART_BST_STAT_LSR_RX_ERR_MASK 0x9E000000
116+
#define UART_BST_STAT_LSR_OVERRUN_ERR 0x2000000
117+
#define UART_BST_STAT_LSR_PARITY_ERR 0x4000000
118+
#define UART_BST_STAT_LSR_FRAME_ERR 0x8000000
101119

102120
struct pci1xxxx_8250 {
103121
unsigned int nr;
@@ -249,6 +267,103 @@ static int pci1xxxx_rs485_config(struct uart_port *port,
249267
return 0;
250268
}
251269

270+
static u32 pci1xxxx_read_burst_status(struct uart_port *port)
271+
{
272+
u32 status;
273+
274+
status = readl(port->membase + UART_BURST_STATUS_REG);
275+
if (status & UART_BST_STAT_LSR_RX_ERR_MASK) {
276+
if (status & UART_BST_STAT_LSR_OVERRUN_ERR) {
277+
writeb(UART_LSR_OVERRUN_ERR_CLR,
278+
port->membase + UART_FIFO_CTL);
279+
port->icount.overrun++;
280+
}
281+
282+
if (status & UART_BST_STAT_LSR_FRAME_ERR)
283+
port->icount.frame++;
284+
285+
if (status & UART_BST_STAT_LSR_PARITY_ERR)
286+
port->icount.parity++;
287+
}
288+
return status;
289+
}
290+
291+
static void pci1xxxx_process_read_data(struct uart_port *port,
292+
unsigned char *rx_buff, u32 *buff_index,
293+
u32 *valid_byte_count)
294+
{
295+
u32 valid_burst_count = *valid_byte_count / UART_BURST_SIZE;
296+
u32 *burst_buf;
297+
298+
/*
299+
* Depending on the RX Trigger Level the number of bytes that can be
300+
* stored in RX FIFO at a time varies. Each transaction reads data
301+
* in DWORDs. If there are less than four remaining valid_byte_count
302+
* to read, the data is received one byte at a time.
303+
*/
304+
while (valid_burst_count--) {
305+
if (*buff_index > (RX_BUF_SIZE - UART_BURST_SIZE))
306+
break;
307+
burst_buf = (u32 *)&rx_buff[*buff_index];
308+
*burst_buf = readl(port->membase + UART_RX_BURST_FIFO);
309+
*buff_index += UART_BURST_SIZE;
310+
*valid_byte_count -= UART_BURST_SIZE;
311+
}
312+
313+
while (*valid_byte_count) {
314+
if (*buff_index > RX_BUF_SIZE)
315+
break;
316+
rx_buff[*buff_index] = readb(port->membase +
317+
UART_RX_BYTE_FIFO);
318+
*buff_index += UART_BYTE_SIZE;
319+
*valid_byte_count -= UART_BYTE_SIZE;
320+
}
321+
}
322+
323+
static void pci1xxxx_rx_burst(struct uart_port *port, u32 uart_status)
324+
{
325+
u32 valid_byte_count = uart_status & UART_BST_STAT_RX_COUNT_MASK;
326+
struct tty_port *tty_port = &port->state->port;
327+
unsigned char rx_buff[RX_BUF_SIZE];
328+
u32 buff_index = 0;
329+
u32 copied_len;
330+
331+
if (valid_byte_count != 0 &&
332+
valid_byte_count < RX_BUF_SIZE) {
333+
pci1xxxx_process_read_data(port, rx_buff, &buff_index,
334+
&valid_byte_count);
335+
336+
copied_len = (u32)tty_insert_flip_string(tty_port, rx_buff,
337+
buff_index);
338+
339+
if (copied_len != buff_index)
340+
port->icount.overrun += buff_index - copied_len;
341+
342+
port->icount.rx += buff_index;
343+
tty_flip_buffer_push(tty_port);
344+
}
345+
}
346+
347+
static int pci1xxxx_handle_irq(struct uart_port *port)
348+
{
349+
unsigned long flags;
350+
u32 status;
351+
352+
status = pci1xxxx_read_burst_status(port);
353+
354+
if (status & UART_BST_STAT_IIR_INT_PEND)
355+
return 0;
356+
357+
spin_lock_irqsave(&port->lock, flags);
358+
359+
if (status & UART_BST_STAT_LSR_RX_MASK)
360+
pci1xxxx_rx_burst(port, status);
361+
362+
spin_unlock_irqrestore(&port->lock, flags);
363+
364+
return 1;
365+
}
366+
252367
static bool pci1xxxx_port_suspend(int line)
253368
{
254369
struct uart_8250_port *up = serial8250_get_port(line);
@@ -360,7 +475,7 @@ static int pci1xxxx_resume(struct device *dev)
360475
}
361476

362477
static int pci1xxxx_setup(struct pci_dev *pdev,
363-
struct uart_8250_port *port, int port_idx)
478+
struct uart_8250_port *port, int port_idx, int rev)
364479
{
365480
int ret;
366481

@@ -372,6 +487,10 @@ static int pci1xxxx_setup(struct pci_dev *pdev,
372487
port->port.rs485_config = pci1xxxx_rs485_config;
373488
port->port.rs485_supported = pci1xxxx_rs485_supported;
374489

490+
/* From C0 rev Burst operation is supported */
491+
if (rev >= 0xC0)
492+
port->port.handle_irq = pci1xxxx_handle_irq;
493+
375494
ret = serial8250_pci_setup_port(pdev, port, 0, PORT_OFFSET * port_idx, 0);
376495
if (ret < 0)
377496
return ret;
@@ -491,7 +610,7 @@ static int pci1xxxx_serial_probe(struct pci_dev *pdev,
491610
else
492611
uart.port.irq = pci_irq_vector(pdev, 0);
493612

494-
rc = pci1xxxx_setup(pdev, &uart, port_idx);
613+
rc = pci1xxxx_setup(pdev, &uart, port_idx, priv->dev_rev);
495614
if (rc) {
496615
dev_warn(dev, "Failed to setup port %u\n", i);
497616
continue;

0 commit comments

Comments
 (0)