1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Freescale 16550 UART "driver", Copyright (C) 2011 Paul Gortmaker. |
4 | * Copyright 2020 NXP |
5 | * Copyright 2020 Puresoftware Ltd. |
6 | * |
7 | * This isn't a full driver; it just provides an alternate IRQ |
8 | * handler to deal with an errata and provide ACPI wrapper. |
9 | * Everything else is just using the bog standard 8250 support. |
10 | * |
11 | * We follow code flow of serial8250_default_handle_irq() but add |
12 | * a check for a break and insert a dummy read on the Rx for the |
13 | * immediately following IRQ event. |
14 | * |
15 | * We re-use the already existing "bug handling" lsr_saved_flags |
16 | * field to carry the "what we just did" information from the one |
17 | * IRQ event to the next one. |
18 | */ |
19 | |
20 | #include <linux/acpi.h> |
21 | #include <linux/serial_reg.h> |
22 | #include <linux/serial_8250.h> |
23 | |
24 | #include "8250.h" |
25 | |
26 | int fsl8250_handle_irq(struct uart_port *port) |
27 | { |
28 | unsigned long flags; |
29 | u16 lsr, orig_lsr; |
30 | unsigned int iir; |
31 | struct uart_8250_port *up = up_to_u8250p(up: port); |
32 | |
33 | uart_port_lock_irqsave(up: &up->port, flags: &flags); |
34 | |
35 | iir = port->serial_in(port, UART_IIR); |
36 | if (iir & UART_IIR_NO_INT) { |
37 | uart_port_unlock_irqrestore(up: &up->port, flags); |
38 | return 0; |
39 | } |
40 | |
41 | /* |
42 | * For a single break the hardware reports LSR.BI for each character |
43 | * time. This is described in the MPC8313E chip errata as "General17". |
44 | * A typical break has a duration of 0.3s, with a 115200n8 configuration |
45 | * that (theoretically) corresponds to ~3500 interrupts in these 0.3s. |
46 | * In practise it's less (around 500) because of hardware |
47 | * and software latencies. The workaround recommended by the vendor is |
48 | * to read the RX register (to clear LSR.DR and thus prevent a FIFO |
49 | * aging interrupt). To prevent the irq from retriggering LSR must not be |
50 | * read. (This would clear LSR.BI, hardware would reassert the BI event |
51 | * immediately and interrupt the CPU again. The hardware clears LSR.BI |
52 | * when the next valid char is read.) |
53 | */ |
54 | if (unlikely((iir & UART_IIR_ID) == UART_IIR_RLSI && |
55 | (up->lsr_saved_flags & UART_LSR_BI))) { |
56 | up->lsr_saved_flags &= ~UART_LSR_BI; |
57 | port->serial_in(port, UART_RX); |
58 | uart_port_unlock_irqrestore(up: &up->port, flags); |
59 | return 1; |
60 | } |
61 | |
62 | lsr = orig_lsr = up->port.serial_in(&up->port, UART_LSR); |
63 | |
64 | /* Process incoming characters first */ |
65 | if ((lsr & (UART_LSR_DR | UART_LSR_BI)) && |
66 | (up->ier & (UART_IER_RLSI | UART_IER_RDI))) { |
67 | lsr = serial8250_rx_chars(up, lsr); |
68 | } |
69 | |
70 | /* Stop processing interrupts on input overrun */ |
71 | if ((orig_lsr & UART_LSR_OE) && (up->overrun_backoff_time_ms > 0)) { |
72 | unsigned long delay; |
73 | |
74 | up->ier = port->serial_in(port, UART_IER); |
75 | if (up->ier & (UART_IER_RLSI | UART_IER_RDI)) { |
76 | port->ops->stop_rx(port); |
77 | } else { |
78 | /* Keep restarting the timer until |
79 | * the input overrun subsides. |
80 | */ |
81 | cancel_delayed_work(dwork: &up->overrun_backoff); |
82 | } |
83 | |
84 | delay = msecs_to_jiffies(m: up->overrun_backoff_time_ms); |
85 | schedule_delayed_work(dwork: &up->overrun_backoff, delay); |
86 | } |
87 | |
88 | serial8250_modem_status(up); |
89 | |
90 | if ((lsr & UART_LSR_THRE) && (up->ier & UART_IER_THRI)) |
91 | serial8250_tx_chars(up); |
92 | |
93 | up->lsr_saved_flags |= orig_lsr & UART_LSR_BI; |
94 | |
95 | uart_unlock_and_check_sysrq_irqrestore(port: &up->port, flags); |
96 | |
97 | return 1; |
98 | } |
99 | EXPORT_SYMBOL_GPL(fsl8250_handle_irq); |
100 | |
101 | #ifdef CONFIG_ACPI |
102 | struct fsl8250_data { |
103 | int line; |
104 | }; |
105 | |
106 | static int fsl8250_acpi_probe(struct platform_device *pdev) |
107 | { |
108 | struct fsl8250_data *data; |
109 | struct uart_8250_port port8250; |
110 | struct device *dev = &pdev->dev; |
111 | struct resource *regs; |
112 | |
113 | int ret, irq; |
114 | |
115 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
116 | if (!regs) { |
117 | dev_err(dev, "no registers defined\n" ); |
118 | return -EINVAL; |
119 | } |
120 | |
121 | irq = platform_get_irq(pdev, 0); |
122 | if (irq < 0) |
123 | return irq; |
124 | |
125 | memset(&port8250, 0, sizeof(port8250)); |
126 | |
127 | ret = device_property_read_u32(dev, propname: "clock-frequency" , |
128 | val: &port8250.port.uartclk); |
129 | if (ret) |
130 | return ret; |
131 | |
132 | spin_lock_init(&port8250.port.lock); |
133 | |
134 | port8250.port.mapbase = regs->start; |
135 | port8250.port.irq = irq; |
136 | port8250.port.handle_irq = fsl8250_handle_irq; |
137 | port8250.port.type = PORT_16550A; |
138 | port8250.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF |
139 | | UPF_FIXED_PORT | UPF_IOREMAP |
140 | | UPF_FIXED_TYPE; |
141 | port8250.port.dev = dev; |
142 | port8250.port.mapsize = resource_size(res: regs); |
143 | port8250.port.iotype = UPIO_MEM; |
144 | port8250.port.irqflags = IRQF_SHARED; |
145 | |
146 | port8250.port.membase = devm_ioremap(dev, offset: port8250.port.mapbase, |
147 | size: port8250.port.mapsize); |
148 | if (!port8250.port.membase) |
149 | return -ENOMEM; |
150 | |
151 | data = devm_kzalloc(dev, size: sizeof(*data), GFP_KERNEL); |
152 | if (!data) |
153 | return -ENOMEM; |
154 | |
155 | data->line = serial8250_register_8250_port(&port8250); |
156 | if (data->line < 0) |
157 | return data->line; |
158 | |
159 | platform_set_drvdata(pdev, data); |
160 | return 0; |
161 | } |
162 | |
163 | static void fsl8250_acpi_remove(struct platform_device *pdev) |
164 | { |
165 | struct fsl8250_data *data = platform_get_drvdata(pdev); |
166 | |
167 | serial8250_unregister_port(line: data->line); |
168 | } |
169 | |
170 | static const struct acpi_device_id fsl_8250_acpi_id[] = { |
171 | { "NXP0018" , 0 }, |
172 | { }, |
173 | }; |
174 | MODULE_DEVICE_TABLE(acpi, fsl_8250_acpi_id); |
175 | |
176 | static struct platform_driver fsl8250_platform_driver = { |
177 | .driver = { |
178 | .name = "fsl-16550-uart" , |
179 | .acpi_match_table = ACPI_PTR(fsl_8250_acpi_id), |
180 | }, |
181 | .probe = fsl8250_acpi_probe, |
182 | .remove_new = fsl8250_acpi_remove, |
183 | }; |
184 | |
185 | module_platform_driver(fsl8250_platform_driver); |
186 | #endif |
187 | |
188 | MODULE_LICENSE("GPL" ); |
189 | MODULE_DESCRIPTION("Handling of Freescale specific 8250 variants" ); |
190 | |