hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/tty/serial/sccnxp.c
....@@ -7,11 +7,8 @@
77 * Based on sc26xx.c, by Thomas Bogendörfer (tsbogend@alpha.franken.de)
88 */
99
10
-#if defined(CONFIG_SERIAL_SCCNXP_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
11
-#define SUPPORT_SYSRQ
12
-#endif
13
-
1410 #include <linux/clk.h>
11
+#include <linux/delay.h>
1512 #include <linux/err.h>
1613 #include <linux/module.h>
1714 #include <linux/mod_devicetable.h>
....@@ -47,7 +44,6 @@
4744 # define MR2_STOP1 (7 << 0)
4845 # define MR2_STOP2 (0xf << 0)
4946 #define SCCNXP_SR_REG (0x01)
50
-#define SCCNXP_CSR_REG SCCNXP_SR_REG
5147 # define SR_RXRDY (1 << 0)
5248 # define SR_FULL (1 << 1)
5349 # define SR_TXRDY (1 << 2)
....@@ -56,6 +52,8 @@
5652 # define SR_PE (1 << 5)
5753 # define SR_FE (1 << 6)
5854 # define SR_BRK (1 << 7)
55
+#define SCCNXP_CSR_REG (SCCNXP_SR_REG)
56
+# define CSR_TIMER_MODE (0x0d)
5957 #define SCCNXP_CR_REG (0x02)
6058 # define CR_RX_ENABLE (1 << 0)
6159 # define CR_RX_DISABLE (1 << 1)
....@@ -82,9 +80,12 @@
8280 # define IMR_RXRDY (1 << 1)
8381 # define ISR_TXRDY(x) (1 << ((x * 4) + 0))
8482 # define ISR_RXRDY(x) (1 << ((x * 4) + 1))
83
+#define SCCNXP_CTPU_REG (0x06)
84
+#define SCCNXP_CTPL_REG (0x07)
8585 #define SCCNXP_IPR_REG (0x0d)
8686 #define SCCNXP_OPCR_REG SCCNXP_IPR_REG
8787 #define SCCNXP_SOP_REG (0x0e)
88
+#define SCCNXP_START_COUNTER_REG SCCNXP_SOP_REG
8889 #define SCCNXP_ROP_REG (0x0f)
8990
9091 /* Route helpers */
....@@ -103,6 +104,8 @@
103104 unsigned long freq_max;
104105 unsigned int flags;
105106 unsigned int fifosize;
107
+ /* Time between read/write cycles */
108
+ unsigned int trwd;
106109 };
107110
108111 struct sccnxp_port {
....@@ -137,6 +140,7 @@
137140 .freq_max = 4000000,
138141 .flags = SCCNXP_HAVE_IO,
139142 .fifosize = 3,
143
+ .trwd = 200,
140144 };
141145
142146 static const struct sccnxp_chip sc2691 = {
....@@ -147,6 +151,7 @@
147151 .freq_max = 4000000,
148152 .flags = 0,
149153 .fifosize = 3,
154
+ .trwd = 150,
150155 };
151156
152157 static const struct sccnxp_chip sc2692 = {
....@@ -157,6 +162,7 @@
157162 .freq_max = 4000000,
158163 .flags = SCCNXP_HAVE_IO,
159164 .fifosize = 3,
165
+ .trwd = 30,
160166 };
161167
162168 static const struct sccnxp_chip sc2891 = {
....@@ -167,6 +173,7 @@
167173 .freq_max = 8000000,
168174 .flags = SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0,
169175 .fifosize = 16,
176
+ .trwd = 27,
170177 };
171178
172179 static const struct sccnxp_chip sc2892 = {
....@@ -177,6 +184,7 @@
177184 .freq_max = 8000000,
178185 .flags = SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0,
179186 .fifosize = 16,
187
+ .trwd = 17,
180188 };
181189
182190 static const struct sccnxp_chip sc28202 = {
....@@ -187,6 +195,7 @@
187195 .freq_max = 50000000,
188196 .flags = SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0,
189197 .fifosize = 256,
198
+ .trwd = 10,
190199 };
191200
192201 static const struct sccnxp_chip sc68681 = {
....@@ -197,6 +206,7 @@
197206 .freq_max = 4000000,
198207 .flags = SCCNXP_HAVE_IO,
199208 .fifosize = 3,
209
+ .trwd = 200,
200210 };
201211
202212 static const struct sccnxp_chip sc68692 = {
....@@ -207,24 +217,36 @@
207217 .freq_max = 4000000,
208218 .flags = SCCNXP_HAVE_IO,
209219 .fifosize = 3,
220
+ .trwd = 200,
210221 };
211222
212
-static inline u8 sccnxp_read(struct uart_port *port, u8 reg)
223
+static u8 sccnxp_read(struct uart_port *port, u8 reg)
213224 {
214
- return readb(port->membase + (reg << port->regshift));
225
+ struct sccnxp_port *s = dev_get_drvdata(port->dev);
226
+ u8 ret;
227
+
228
+ ret = readb(port->membase + (reg << port->regshift));
229
+
230
+ ndelay(s->chip->trwd);
231
+
232
+ return ret;
215233 }
216234
217
-static inline void sccnxp_write(struct uart_port *port, u8 reg, u8 v)
235
+static void sccnxp_write(struct uart_port *port, u8 reg, u8 v)
218236 {
237
+ struct sccnxp_port *s = dev_get_drvdata(port->dev);
238
+
219239 writeb(v, port->membase + (reg << port->regshift));
240
+
241
+ ndelay(s->chip->trwd);
220242 }
221243
222
-static inline u8 sccnxp_port_read(struct uart_port *port, u8 reg)
244
+static u8 sccnxp_port_read(struct uart_port *port, u8 reg)
223245 {
224246 return sccnxp_read(port, (port->line << 3) + reg);
225247 }
226248
227
-static inline void sccnxp_port_write(struct uart_port *port, u8 reg, u8 v)
249
+static void sccnxp_port_write(struct uart_port *port, u8 reg, u8 v)
228250 {
229251 sccnxp_write(port, (port->line << 3) + reg, v);
230252 }
....@@ -233,7 +255,7 @@
233255 {
234256 int err = abs(a - b);
235257
236
- if ((*besterr < 0) || (*besterr > err)) {
258
+ if (*besterr > err) {
237259 *besterr = err;
238260 return 0;
239261 }
....@@ -281,9 +303,21 @@
281303 static int sccnxp_set_baud(struct uart_port *port, int baud)
282304 {
283305 struct sccnxp_port *s = dev_get_drvdata(port->dev);
284
- int div_std, tmp_baud, bestbaud = baud, besterr = -1;
306
+ int div_std, tmp_baud, bestbaud = INT_MAX, besterr = INT_MAX;
285307 struct sccnxp_chip *chip = s->chip;
286308 u8 i, acr = 0, csr = 0, mr0 = 0;
309
+
310
+ /* Find divisor to load to the timer preset registers */
311
+ div_std = DIV_ROUND_CLOSEST(port->uartclk, 2 * 16 * baud);
312
+ if ((div_std >= 2) && (div_std <= 0xffff)) {
313
+ bestbaud = DIV_ROUND_CLOSEST(port->uartclk, 2 * 16 * div_std);
314
+ sccnxp_update_best_err(baud, bestbaud, &besterr);
315
+ csr = CSR_TIMER_MODE;
316
+ sccnxp_port_write(port, SCCNXP_CTPU_REG, div_std >> 8);
317
+ sccnxp_port_write(port, SCCNXP_CTPL_REG, div_std);
318
+ /* Issue start timer/counter command */
319
+ sccnxp_port_read(port, SCCNXP_START_COUNTER_REG);
320
+ }
287321
288322 /* Find best baud from table */
289323 for (i = 0; baud_std[i].baud && besterr; i++) {
....@@ -923,7 +957,6 @@
923957 if (!s->poll) {
924958 s->irq = platform_get_irq(pdev, 0);
925959 if (s->irq < 0) {
926
- dev_err(&pdev->dev, "Missing irq resource data\n");
927960 ret = -ENXIO;
928961 goto err_out;
929962 }
....@@ -963,6 +996,7 @@
963996 s->port[i].regshift = s->pdata.reg_shift;
964997 s->port[i].uartclk = uartclk;
965998 s->port[i].ops = &sccnxp_ops;
999
+ s->port[i].has_sysrq = IS_ENABLED(CONFIG_SERIAL_SCCNXP_CONSOLE);
9661000 uart_add_one_port(&s->uart, &s->port[i]);
9671001 /* Set direction to input */
9681002 if (s->chip->flags & SCCNXP_HAVE_IO)