From ea08eeccae9297f7aabd2ef7f0c2517ac4549acc Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Tue, 20 Feb 2024 01:18:26 +0000
Subject: [PATCH] write in 30M
---
kernel/drivers/tty/serial/sccnxp.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++-------------
1 files changed, 47 insertions(+), 13 deletions(-)
diff --git a/kernel/drivers/tty/serial/sccnxp.c b/kernel/drivers/tty/serial/sccnxp.c
index 339befd..10cc16a 100644
--- a/kernel/drivers/tty/serial/sccnxp.c
+++ b/kernel/drivers/tty/serial/sccnxp.c
@@ -7,11 +7,8 @@
* Based on sc26xx.c, by Thomas Bogendörfer (tsbogend@alpha.franken.de)
*/
-#if defined(CONFIG_SERIAL_SCCNXP_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
#include <linux/clk.h>
+#include <linux/delay.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
@@ -47,7 +44,6 @@
# define MR2_STOP1 (7 << 0)
# define MR2_STOP2 (0xf << 0)
#define SCCNXP_SR_REG (0x01)
-#define SCCNXP_CSR_REG SCCNXP_SR_REG
# define SR_RXRDY (1 << 0)
# define SR_FULL (1 << 1)
# define SR_TXRDY (1 << 2)
@@ -56,6 +52,8 @@
# define SR_PE (1 << 5)
# define SR_FE (1 << 6)
# define SR_BRK (1 << 7)
+#define SCCNXP_CSR_REG (SCCNXP_SR_REG)
+# define CSR_TIMER_MODE (0x0d)
#define SCCNXP_CR_REG (0x02)
# define CR_RX_ENABLE (1 << 0)
# define CR_RX_DISABLE (1 << 1)
@@ -82,9 +80,12 @@
# define IMR_RXRDY (1 << 1)
# define ISR_TXRDY(x) (1 << ((x * 4) + 0))
# define ISR_RXRDY(x) (1 << ((x * 4) + 1))
+#define SCCNXP_CTPU_REG (0x06)
+#define SCCNXP_CTPL_REG (0x07)
#define SCCNXP_IPR_REG (0x0d)
#define SCCNXP_OPCR_REG SCCNXP_IPR_REG
#define SCCNXP_SOP_REG (0x0e)
+#define SCCNXP_START_COUNTER_REG SCCNXP_SOP_REG
#define SCCNXP_ROP_REG (0x0f)
/* Route helpers */
@@ -103,6 +104,8 @@
unsigned long freq_max;
unsigned int flags;
unsigned int fifosize;
+ /* Time between read/write cycles */
+ unsigned int trwd;
};
struct sccnxp_port {
@@ -137,6 +140,7 @@
.freq_max = 4000000,
.flags = SCCNXP_HAVE_IO,
.fifosize = 3,
+ .trwd = 200,
};
static const struct sccnxp_chip sc2691 = {
@@ -147,6 +151,7 @@
.freq_max = 4000000,
.flags = 0,
.fifosize = 3,
+ .trwd = 150,
};
static const struct sccnxp_chip sc2692 = {
@@ -157,6 +162,7 @@
.freq_max = 4000000,
.flags = SCCNXP_HAVE_IO,
.fifosize = 3,
+ .trwd = 30,
};
static const struct sccnxp_chip sc2891 = {
@@ -167,6 +173,7 @@
.freq_max = 8000000,
.flags = SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0,
.fifosize = 16,
+ .trwd = 27,
};
static const struct sccnxp_chip sc2892 = {
@@ -177,6 +184,7 @@
.freq_max = 8000000,
.flags = SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0,
.fifosize = 16,
+ .trwd = 17,
};
static const struct sccnxp_chip sc28202 = {
@@ -187,6 +195,7 @@
.freq_max = 50000000,
.flags = SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0,
.fifosize = 256,
+ .trwd = 10,
};
static const struct sccnxp_chip sc68681 = {
@@ -197,6 +206,7 @@
.freq_max = 4000000,
.flags = SCCNXP_HAVE_IO,
.fifosize = 3,
+ .trwd = 200,
};
static const struct sccnxp_chip sc68692 = {
@@ -207,24 +217,36 @@
.freq_max = 4000000,
.flags = SCCNXP_HAVE_IO,
.fifosize = 3,
+ .trwd = 200,
};
-static inline u8 sccnxp_read(struct uart_port *port, u8 reg)
+static u8 sccnxp_read(struct uart_port *port, u8 reg)
{
- return readb(port->membase + (reg << port->regshift));
+ struct sccnxp_port *s = dev_get_drvdata(port->dev);
+ u8 ret;
+
+ ret = readb(port->membase + (reg << port->regshift));
+
+ ndelay(s->chip->trwd);
+
+ return ret;
}
-static inline void sccnxp_write(struct uart_port *port, u8 reg, u8 v)
+static void sccnxp_write(struct uart_port *port, u8 reg, u8 v)
{
+ struct sccnxp_port *s = dev_get_drvdata(port->dev);
+
writeb(v, port->membase + (reg << port->regshift));
+
+ ndelay(s->chip->trwd);
}
-static inline u8 sccnxp_port_read(struct uart_port *port, u8 reg)
+static u8 sccnxp_port_read(struct uart_port *port, u8 reg)
{
return sccnxp_read(port, (port->line << 3) + reg);
}
-static inline void sccnxp_port_write(struct uart_port *port, u8 reg, u8 v)
+static void sccnxp_port_write(struct uart_port *port, u8 reg, u8 v)
{
sccnxp_write(port, (port->line << 3) + reg, v);
}
@@ -233,7 +255,7 @@
{
int err = abs(a - b);
- if ((*besterr < 0) || (*besterr > err)) {
+ if (*besterr > err) {
*besterr = err;
return 0;
}
@@ -281,9 +303,21 @@
static int sccnxp_set_baud(struct uart_port *port, int baud)
{
struct sccnxp_port *s = dev_get_drvdata(port->dev);
- int div_std, tmp_baud, bestbaud = baud, besterr = -1;
+ int div_std, tmp_baud, bestbaud = INT_MAX, besterr = INT_MAX;
struct sccnxp_chip *chip = s->chip;
u8 i, acr = 0, csr = 0, mr0 = 0;
+
+ /* Find divisor to load to the timer preset registers */
+ div_std = DIV_ROUND_CLOSEST(port->uartclk, 2 * 16 * baud);
+ if ((div_std >= 2) && (div_std <= 0xffff)) {
+ bestbaud = DIV_ROUND_CLOSEST(port->uartclk, 2 * 16 * div_std);
+ sccnxp_update_best_err(baud, bestbaud, &besterr);
+ csr = CSR_TIMER_MODE;
+ sccnxp_port_write(port, SCCNXP_CTPU_REG, div_std >> 8);
+ sccnxp_port_write(port, SCCNXP_CTPL_REG, div_std);
+ /* Issue start timer/counter command */
+ sccnxp_port_read(port, SCCNXP_START_COUNTER_REG);
+ }
/* Find best baud from table */
for (i = 0; baud_std[i].baud && besterr; i++) {
@@ -923,7 +957,6 @@
if (!s->poll) {
s->irq = platform_get_irq(pdev, 0);
if (s->irq < 0) {
- dev_err(&pdev->dev, "Missing irq resource data\n");
ret = -ENXIO;
goto err_out;
}
@@ -963,6 +996,7 @@
s->port[i].regshift = s->pdata.reg_shift;
s->port[i].uartclk = uartclk;
s->port[i].ops = &sccnxp_ops;
+ s->port[i].has_sysrq = IS_ENABLED(CONFIG_SERIAL_SCCNXP_CONSOLE);
uart_add_one_port(&s->uart, &s->port[i]);
/* Set direction to input */
if (s->chip->flags & SCCNXP_HAVE_IO)
--
Gitblit v1.6.2