From: "Ji-Ze Hong (Peter Hong)" <hpeter@gmail.com>
To: johan@kernel.org
Cc: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org,
linux-kernel@vger.kernel.org,
"Ji-Ze Hong (Peter Hong)" <hpeter+linux_kernel@gmail.com>
Subject: [PATCH V1 1/4] usb: serial: f81534: add high baud rate support
Date: Thu, 16 Nov 2017 15:46:06 +0800 [thread overview]
Message-ID: <1510818369-10323-1-git-send-email-hpeter+linux_kernel@gmail.com> (raw)
The F81532/534 had 4 clocksource 1.846/18.46/14.77/24MHz and baud rates can
be up to 1.5Mbits with 24MHz.
F81532/534 Clock register (offset +08h)
Bit0: UART Enable (always on)
Bit2-1: Clock source selector
00: 1.846MHz.
01: 18.46MHz.
10: 24MHz.
11: 14.77MHz.
Signed-off-by: Ji-Ze Hong (Peter Hong) <hpeter+linux_kernel@gmail.com>
---
drivers/usb/serial/f81534.c | 84 ++++++++++++++++++++++++++++++++++++---------
1 file changed, 68 insertions(+), 16 deletions(-)
diff --git a/drivers/usb/serial/f81534.c b/drivers/usb/serial/f81534.c
index cb8214860192..76c676ef5f0d 100644
--- a/drivers/usb/serial/f81534.c
+++ b/drivers/usb/serial/f81534.c
@@ -45,6 +45,7 @@
#define F81534_MODEM_CONTROL_REG (0x04 + F81534_UART_BASE_ADDRESS)
#define F81534_LINE_STATUS_REG (0x05 + F81534_UART_BASE_ADDRESS)
#define F81534_MODEM_STATUS_REG (0x06 + F81534_UART_BASE_ADDRESS)
+#define F81534_CLOCK_REG (0x08 + F81534_UART_BASE_ADDRESS)
#define F81534_CONFIG1_REG (0x09 + F81534_UART_BASE_ADDRESS)
#define F81534_DEF_CONF_ADDRESS_START 0x3000
@@ -61,7 +62,7 @@
/* Default URB timeout for USB operations */
#define F81534_USB_MAX_RETRY 10
-#define F81534_USB_TIMEOUT 1000
+#define F81534_USB_TIMEOUT 2000
#define F81534_SET_GET_REGISTER 0xA0
#define F81534_NUM_PORT 4
@@ -100,7 +101,6 @@
#define F81534_CMD_READ 0x03
#define F81534_DEFAULT_BAUD_RATE 9600
-#define F81534_MAX_BAUDRATE 115200
#define F81534_PORT_CONF_DISABLE_PORT BIT(3)
#define F81534_PORT_CONF_NOT_EXIST_PORT BIT(7)
@@ -110,6 +110,22 @@
#define F81534_1X_RXTRIGGER 0xc3
#define F81534_8X_RXTRIGGER 0xcf
+/*
+ * F81532/534 Clock registers (offset +08h)
+ *
+ * Bit0: UART Enable (always on)
+ * Bit2-1: Clock source selector
+ * 00: 1.846MHz.
+ * 01: 18.46MHz.
+ * 10: 24MHz.
+ * 11: 14.77MHz.
+ */
+
+#define F81534_CLK_1_846_MHZ BIT(0)
+#define F81534_CLK_18_46_MHZ (BIT(0) | BIT(1))
+#define F81534_CLK_24_MHZ (BIT(0) | BIT(2))
+#define F81534_CLK_14_77_MHZ (BIT(0) | BIT(1) | BIT(2))
+
static const struct usb_device_id f81534_id_table[] = {
{ USB_DEVICE(FINTEK_VENDOR_ID_1, FINTEK_DEVICE_ID) },
{ USB_DEVICE(FINTEK_VENDOR_ID_2, FINTEK_DEVICE_ID) },
@@ -133,6 +149,7 @@ struct f81534_port_private {
struct usb_serial_port *port;
unsigned long tx_empty;
spinlock_t msr_lock;
+ u32 baud_base;
u8 shadow_mcr;
u8 shadow_lcr;
u8 shadow_msr;
@@ -464,13 +481,51 @@ static u32 f81534_calc_baud_divisor(u32 baudrate, u32 clockrate)
return DIV_ROUND_CLOSEST(clockrate, baudrate);
}
-static int f81534_set_port_config(struct usb_serial_port *port, u32 baudrate,
- u8 lcr)
+static int f81534_set_port_config(struct usb_serial_port *port,
+ struct tty_struct *tty, u32 baudrate, u32 old_baudrate, u8 lcr)
{
struct f81534_port_private *port_priv = usb_get_serial_port_data(port);
u32 divisor;
int status;
+ int idx;
u8 value;
+ static u32 const baudrate_table[] = {115200, 921600, 1152000,
+ 1500000};
+ static u8 const clock_table[] = {F81534_CLK_1_846_MHZ,
+ F81534_CLK_14_77_MHZ, F81534_CLK_18_46_MHZ,
+ F81534_CLK_24_MHZ};
+
+ do {
+ for (idx = 0; idx < ARRAY_SIZE(baudrate_table); ++idx) {
+ if (baudrate <= baudrate_table[idx] &&
+ baudrate_table[idx] % baudrate == 0)
+ break;
+ }
+
+ /* Found acceptable baud rate */
+ if (idx != ARRAY_SIZE(baudrate_table))
+ break;
+
+ if (baudrate == old_baudrate &&
+ old_baudrate != F81534_DEFAULT_BAUD_RATE)
+ old_baudrate = F81534_DEFAULT_BAUD_RATE;
+
+ dev_warn(&port->dev,
+ "baudrate: %d not supported, change to: %d\n",
+ baudrate, old_baudrate);
+
+ baudrate = old_baudrate;
+ tty_encode_baud_rate(tty, baudrate, baudrate);
+
+ } while (1);
+
+ port_priv->baud_base = baudrate_table[idx];
+ status = f81534_set_port_register(port, F81534_CLOCK_REG,
+ clock_table[idx]);
+ if (status) {
+ dev_err(&port->dev, "CLOCK_REG setting failed\n");
+ return status;
+ }
if (baudrate <= 1200)
value = F81534_1X_RXTRIGGER; /* 128 FIFO & TL: 1x */
@@ -486,7 +541,7 @@ static int f81534_set_port_config(struct usb_serial_port *port, u32 baudrate,
if (baudrate <= 1200)
value = UART_FCR_TRIGGER_1 | UART_FCR_ENABLE_FIFO; /* TL: 1 */
else
- value = UART_FCR_R_TRIG_11 | UART_FCR_ENABLE_FIFO; /* TL: 14 */
+ value = UART_FCR_TRIGGER_8 | UART_FCR_ENABLE_FIFO; /* TL: 8 */
status = f81534_set_port_register(port, F81534_FIFO_CONTROL_REG,
value);
@@ -495,7 +550,7 @@ static int f81534_set_port_config(struct usb_serial_port *port, u32 baudrate,
return status;
}
- divisor = f81534_calc_baud_divisor(baudrate, F81534_MAX_BAUDRATE);
+ divisor = f81534_calc_baud_divisor(baudrate, baudrate_table[idx]);
mutex_lock(&port_priv->lcr_mutex);
@@ -745,6 +800,7 @@ static void f81534_set_termios(struct tty_struct *tty,
u8 new_lcr = 0;
int status;
u32 baud;
+ u32 old_baud;
if (C_BAUD(tty) == B0)
f81534_update_mctrl(port, 0, TIOCM_DTR | TIOCM_RTS);
@@ -784,18 +840,14 @@ static void f81534_set_termios(struct tty_struct *tty,
if (!baud)
return;
- if (baud > F81534_MAX_BAUDRATE) {
- if (old_termios)
- baud = tty_termios_baud_rate(old_termios);
- else
- baud = F81534_DEFAULT_BAUD_RATE;
-
- tty_encode_baud_rate(tty, baud, baud);
- }
+ if (old_termios)
+ old_baud = tty_termios_baud_rate(old_termios);
+ else
+ old_baud = F81534_DEFAULT_BAUD_RATE;
dev_dbg(&port->dev, "%s: baud: %d\n", __func__, baud);
- status = f81534_set_port_config(port, baud, new_lcr);
+ status = f81534_set_port_config(port, tty, baud, old_baud, new_lcr);
if (status < 0) {
dev_err(&port->dev, "%s: set port config failed: %d\n",
__func__, status);
@@ -951,7 +1003,7 @@ static int f81534_get_serial_info(struct usb_serial_port *port,
tmp.type = PORT_16550A;
tmp.port = port->port_number;
tmp.line = port->minor;
- tmp.baud_base = F81534_MAX_BAUDRATE;
+ tmp.baud_base = port_priv->baud_base;
if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
return -EFAULT;
--
2.7.4
next reply other threads:[~2017-11-16 7:46 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-11-16 7:46 Ji-Ze Hong (Peter Hong) [this message]
2017-11-16 7:46 ` [PATCH V1 2/4] usb: serial: f81534: add auto RTS direction support Ji-Ze Hong (Peter Hong)
2017-12-18 15:18 ` Johan Hovold
2017-11-16 7:46 ` [PATCH V1 3/4] usb: serial: f81534: add output pin control Ji-Ze Hong (Peter Hong)
2017-12-18 16:06 ` Johan Hovold
2017-12-21 9:49 ` Ji-Ze Hong (Peter Hong)
2017-12-27 10:30 ` Johan Hovold
2018-01-02 3:24 ` Ji-Ze Hong (Peter Hong)
2018-01-02 9:27 ` Johan Hovold
2017-11-16 7:46 ` [PATCH V1 4/4] usb: serial: f81534: add H/W disable port support Ji-Ze Hong (Peter Hong)
2017-12-18 16:15 ` Johan Hovold
2017-12-18 15:14 ` [PATCH V1 1/4] usb: serial: f81534: add high baud rate support Johan Hovold
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1510818369-10323-1-git-send-email-hpeter+linux_kernel@gmail.com \
--to=hpeter@gmail.com \
--cc=gregkh@linuxfoundation.org \
--cc=hpeter+linux_kernel@gmail.com \
--cc=johan@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.