* [PATCH 0/2] Airoha UART support @ 2025-01-05 13:11 Benjamin Larsson 2025-01-05 13:11 ` [PATCH 1/2] dt-bindings: serial: 8250: Add Airoha compatibles Benjamin Larsson 2025-01-05 13:11 ` [PATCH 2/2] serial: Airoha SoC UART and HSUART support Benjamin Larsson 0 siblings, 2 replies; 19+ messages in thread From: Benjamin Larsson @ 2025-01-05 13:11 UTC (permalink / raw) To: linux-serial, devicetree; +Cc: ansuelsmth, lorenzo, Benjamin Larsson The Airoha familty of SoCs have a UART hardware that is 16550-compatible with the exception of the baud rate settings. This patch implements code for calculating the baud rate for the Airoha UART and HSUART. Benjamin Larsson (2): dt-bindings: serial: 8250: Add Airoha compatibles serial: Airoha SoC UART and HSUART support devicetree/bindings/serial/8250.yaml | 2 + drivers/tty/serial/8250/8250_airoha.c | 85 +++++++++++++++++++ drivers/tty/serial/8250/8250_of.c | 2 + drivers/tty/serial/8250/8250_port.c | 26 ++++++ drivers/tty/serial/8250/Kconfig | 10 +++ drivers/tty/serial/8250/Makefile | 1 + include/linux/serial_8250.h | 1 + include/uapi/linux/serial_core.h | 6 ++ include/uapi/linux/serial_reg.h | 9 ++ 9 files changed, 142 insertions(+) create mode 100644 drivers/tty/serial/8250/8250_airoha.c Signed-off-by: Benjamin Larsson <benjamin.larsson@genexis.eu> -- 2.34.1 ^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH 1/2] dt-bindings: serial: 8250: Add Airoha compatibles 2025-01-05 13:11 [PATCH 0/2] Airoha UART support Benjamin Larsson @ 2025-01-05 13:11 ` Benjamin Larsson 2025-01-06 7:16 ` Krzysztof Kozlowski 2025-01-05 13:11 ` [PATCH 2/2] serial: Airoha SoC UART and HSUART support Benjamin Larsson 1 sibling, 1 reply; 19+ messages in thread From: Benjamin Larsson @ 2025-01-05 13:11 UTC (permalink / raw) To: linux-serial, devicetree; +Cc: ansuelsmth, lorenzo, Benjamin Larsson The Airoha SoC family have a mostly 16550-compatible UART hardware with the exception of custom baud rate settings register. Specifying one of the following compatibles will enable routines for calculating the baud rate. For the regular UART use: compatible = "airoha,airoha-uart"; For the high speed HSUART use: compatible = "airoha,airoha-hsuart"; Signed-off-by: Benjamin Larsson <benjamin.larsson@genexis.eu> --- Documentation/devicetree/bindings/serial/8250.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/serial/8250.yaml b/Documentation/devicetree/bindings/serial/8250.yaml index 692aa05500fd..2fbb972e5460 100644 --- a/Documentation/devicetree/bindings/serial/8250.yaml +++ b/Documentation/devicetree/bindings/serial/8250.yaml @@ -63,6 +63,8 @@ properties: - const: mrvl,pxa-uart - const: nuvoton,wpcm450-uart - const: nuvoton,npcm750-uart + - const: airoha,airoha-uart + - const: airoha,airoha-hsuart - const: nvidia,tegra20-uart - const: nxp,lpc3220-uart - items: -- 2.34.1 ^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH 1/2] dt-bindings: serial: 8250: Add Airoha compatibles 2025-01-05 13:11 ` [PATCH 1/2] dt-bindings: serial: 8250: Add Airoha compatibles Benjamin Larsson @ 2025-01-06 7:16 ` Krzysztof Kozlowski 0 siblings, 0 replies; 19+ messages in thread From: Krzysztof Kozlowski @ 2025-01-06 7:16 UTC (permalink / raw) To: Benjamin Larsson; +Cc: linux-serial, devicetree, ansuelsmth, lorenzo On Sun, Jan 05, 2025 at 02:11:46PM +0100, Benjamin Larsson wrote: > The Airoha SoC family have a mostly 16550-compatible UART > hardware with the exception of custom baud rate settings > register. Specifying one of the following compatibles > will enable routines for calculating the baud rate. > > For the regular UART use: > compatible = "airoha,airoha-uart"; > > For the high speed HSUART use: > compatible = "airoha,airoha-hsuart"; Drop the compatibles explanation, obvious. Rather say: "... a mostly 16550-compatible UART and High-Speed UART hardware ..." or whatever HS is shortcut of. > > Signed-off-by: Benjamin Larsson <benjamin.larsson@genexis.eu> > --- > Documentation/devicetree/bindings/serial/8250.yaml | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/Documentation/devicetree/bindings/serial/8250.yaml b/Documentation/devicetree/bindings/serial/8250.yaml > index 692aa05500fd..2fbb972e5460 100644 > --- a/Documentation/devicetree/bindings/serial/8250.yaml > +++ b/Documentation/devicetree/bindings/serial/8250.yaml > @@ -63,6 +63,8 @@ properties: > - const: mrvl,pxa-uart > - const: nuvoton,wpcm450-uart > - const: nuvoton,npcm750-uart > + - const: airoha,airoha-uart > + - const: airoha,airoha-hsuart Devices are not compatible? Best regards, Krzysztof ^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH 2/2] serial: Airoha SoC UART and HSUART support 2025-01-05 13:11 [PATCH 0/2] Airoha UART support Benjamin Larsson 2025-01-05 13:11 ` [PATCH 1/2] dt-bindings: serial: 8250: Add Airoha compatibles Benjamin Larsson @ 2025-01-05 13:11 ` Benjamin Larsson 2025-01-05 15:59 ` Greg KH 2025-01-06 7:19 ` Krzysztof Kozlowski 1 sibling, 2 replies; 19+ messages in thread From: Benjamin Larsson @ 2025-01-05 13:11 UTC (permalink / raw) To: linux-serial, devicetree; +Cc: ansuelsmth, lorenzo, Benjamin Larsson Support for Airoha AN7581 SoC UART and HSUART baud rate calculation routine. Signed-off-by: Benjamin Larsson <benjamin.larsson@genexis.eu> --- drivers/tty/serial/8250/8250_airoha.c | 85 +++++++++++++++++++++++++++ drivers/tty/serial/8250/8250_of.c | 2 + drivers/tty/serial/8250/8250_port.c | 26 ++++++++ drivers/tty/serial/8250/Kconfig | 10 ++++ drivers/tty/serial/8250/Makefile | 1 + include/linux/serial_8250.h | 1 + include/uapi/linux/serial_core.h | 6 ++ include/uapi/linux/serial_reg.h | 9 +++ 8 files changed, 140 insertions(+) create mode 100644 drivers/tty/serial/8250/8250_airoha.c diff --git a/drivers/tty/serial/8250/8250_airoha.c b/drivers/tty/serial/8250/8250_airoha.c new file mode 100644 index 000000000000..c57789dcc174 --- /dev/null +++ b/drivers/tty/serial/8250/8250_airoha.c @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/* + * Airoha UART driver. + * + * Copyright (c) 2025 Genexis Sweden AB + * Author: Benjamin Larsson <benjamin.larsson@genexis.eu> + */ + +#include <linux/clk.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/of_irq.h> +#include <linux/of_platform.h> +#include <linux/pinctrl/consumer.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/serial_8250.h> +#include <linux/serial_reg.h> +#include <linux/console.h> +#include <linux/dma-mapping.h> +#include <linux/tty.h> +#include <linux/tty_flip.h> + +#include "8250.h" + +/* The Airoha UART is 16550-compatible except for the baud rate calculation. + * + * crystal_clock = 20 MHz + * xindiv_clock = crystal_clock / clock_div + * (x/y) = XYD, 32 bit register with 16 bits of x and then 16 bits of y + * clock_div = XINCLK_DIVCNT (default set to 10 (0x4)), + * - 3 bit register [ 1, 2, 4, 8, 10, 12, 16, 20 ] + * + * baud_rate = ((xindiv_clock) * (x/y)) / ([BRDH,BRDL] * 16) + * + * XYD_y seems to need to be larger then XYD_x for proper waveform generation. + * Setting [BRDH,BRDL] to [0,1] and XYD_y to 65000 give even values + * for usual baud rates. + * + * Selecting divider needs to fulfill + * 1.8432 MHz <= xindiv_clk <= APB clock / 2 + * The clocks are unknown but a divider of value 1 did not result in a valid + * waveform. + * + */ + +#define CLOCK_DIV_TAB_ELEMS 3 +#define XYD_Y 65000 +#define XINDIV_CLOCK 20000000 +#define UART_BRDL_20M 0x01 +#define UART_BRDH_20M 0x00 +static int clock_div_tab[] = { 10, 4, 2}; +static int clock_div_reg[] = { 4, 2, 1}; + +int airoha8250_set_baud_rate(struct uart_port *port, + unsigned int baud, unsigned int hs) +{ + struct uart_8250_port *up = up_to_u8250p(port); + unsigned int xyd_x, nom, denom; + + int i; + /* set DLAB to access the baud rate divider registers (BRDH, BRDL) */ + serial_port_out(port, UART_LCR, up->lcr | UART_LCR_DLAB); + /* set baud rate calculation defaults */ + /* set BRDIV ([BRDH,BRDL]) to 1 */ + serial_port_out(port, UART_BRDL, UART_BRDL_20M); + serial_port_out(port, UART_BRDH, UART_BRDH_20M); + /* calculate XYD_x and XINCLKDR register + * for the HSUART xyd_x needs to be scale by a factor of 2 + */ + for (i = 0 ; i < CLOCK_DIV_TAB_ELEMS ; i++) { + denom = (XINDIV_CLOCK/40) / clock_div_tab[i]; + nom = (baud * (XYD_Y/40)); + xyd_x = ((nom/denom) << 4) >> hs; + if (xyd_x < XYD_Y) + break; + } + serial_port_out(port, UART_XINCLKDR, clock_div_reg[i]); + serial_port_out(port, UART_XYD, (xyd_x<<16) | XYD_Y); + /* unset DLAB */ + serial_port_out(port, UART_LCR, up->lcr); + return 0; +} +EXPORT_SYMBOL_GPL(airoha8250_set_baud_rate); diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c index 64aed7efc569..5315bc1bc06d 100644 --- a/drivers/tty/serial/8250/8250_of.c +++ b/drivers/tty/serial/8250/8250_of.c @@ -341,6 +341,8 @@ static const struct of_device_id of_platform_serial_table[] = { { .compatible = "ti,da830-uart", .data = (void *)PORT_DA830, }, { .compatible = "nuvoton,wpcm450-uart", .data = (void *)PORT_NPCM, }, { .compatible = "nuvoton,npcm750-uart", .data = (void *)PORT_NPCM, }, + { .compatible = "airoha,airoha-uart", .data = (void *)PORT_AIROHA, }, + { .compatible = "airoha,airoha-hsuart", .data = (void *)PORT_AIROHA_HS, }, { /* end of list */ }, }; MODULE_DEVICE_TABLE(of, of_platform_serial_table); diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 1ea52fce9bf1..00163a3d35cd 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -319,6 +319,22 @@ static const struct serial8250_config uart_config[] = { .rxtrig_bytes = {1, 8, 16, 30}, .flags = UART_CAP_FIFO | UART_CAP_AFE, }, + [PORT_AIROHA] = { + .name = "Airoha UART", + .fifo_size = 8, + .tx_loadsz = 1, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 | UART_FCR_CLEAR_RCVR, + .rxtrig_bytes = {1, 4}, + .flags = UART_CAP_FIFO, + }, + [PORT_AIROHA_HS] = { + .name = "Airoha HSUART", + .fifo_size = 128, + .tx_loadsz = 128, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 | UART_FCR_CLEAR_RCVR, + .rxtrig_bytes = {1, 4}, + .flags = UART_CAP_FIFO, + }, }; /* Uart divisor latch read */ @@ -2847,6 +2863,16 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, serial8250_set_divisor(port, baud, quot, frac); + + /* + * Airoha SoCs have custom registers for baud rate settings + */ +#ifdef CONFIG_SERIAL_8250_AIROHA + if (port->type == PORT_AIROHA) + airoha8250_set_baud_rate(port, baud, 0); + if (port->type == PORT_AIROHA_HS) + airoha8250_set_baud_rate(port, baud, 1); +#endif /* * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR * is written without DLAB set, this mode will be disabled. diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index 55d26d16df9b..97fe6ea9393d 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -356,6 +356,16 @@ config SERIAL_8250_ACORN system, say Y to this option. The driver can handle 1, 2, or 3 port cards. If unsure, say N. +config SERIAL_8250_AIROHA + tristate "Airoha UART support" + depends on (ARCH_AIROHA || COMPILE_TEST) && OF && SERIAL_8250 + help + Selecting this option enables an Airoha SoC specific baud rate + calculation routine on an otherwise 16550 compatible UART hardware. + + If you have an Airoha based board and want to use the serial port, + say Y to this option. If unsure, say N. + config SERIAL_8250_BCM2835AUX tristate "BCM2835 auxiliar mini UART support" depends on ARCH_BCM2835 || COMPILE_TEST diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile index 1516de629b61..b7f07d5c4cca 100644 --- a/drivers/tty/serial/8250/Makefile +++ b/drivers/tty/serial/8250/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o +obj-$(CONFIG_SERIAL_8250_AIROHA) += 8250_airoha.o obj-$(CONFIG_SERIAL_8250_ASPEED_VUART) += 8250_aspeed_vuart.o obj-$(CONFIG_SERIAL_8250_BCM2835AUX) += 8250_bcm2835aux.o obj-$(CONFIG_SERIAL_8250_BCM7271) += 8250_bcm7271.o diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h index e0717c8393d7..33e7e1922149 100644 --- a/include/linux/serial_8250.h +++ b/include/linux/serial_8250.h @@ -195,6 +195,7 @@ void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl); void serial8250_do_set_divisor(struct uart_port *port, unsigned int baud, unsigned int quot); int fsl8250_handle_irq(struct uart_port *port); +int airoha8250_set_baud_rate(struct uart_port *port, unsigned int baud, unsigned int hs); int serial8250_handle_irq(struct uart_port *port, unsigned int iir); u16 serial8250_rx_chars(struct uart_8250_port *up, u16 lsr); void serial8250_read_char(struct uart_8250_port *up, u16 lsr); diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h index 9c007a106330..c71fb338accb 100644 --- a/include/uapi/linux/serial_core.h +++ b/include/uapi/linux/serial_core.h @@ -231,6 +231,12 @@ /* Sunplus UART */ #define PORT_SUNPLUS 123 +/* Airoha UART */ +#define PORT_AIROHA 124 + +/* Airoha HSUART */ +#define PORT_AIROHA_HS 125 + /* Generic type identifier for ports which type is not important to userspace. */ #define PORT_GENERIC (-1) diff --git a/include/uapi/linux/serial_reg.h b/include/uapi/linux/serial_reg.h index 9c987b04e2d0..72a71e171602 100644 --- a/include/uapi/linux/serial_reg.h +++ b/include/uapi/linux/serial_reg.h @@ -383,5 +383,14 @@ #define UART_ALTR_EN_TXFIFO_LW 0x01 /* Enable the TX FIFO Low Watermark */ #define UART_ALTR_TX_LOW 0x41 /* Tx FIFO Low Watermark */ +/* + * These are definitions for the Airoha UART + * Normalized because of 32 bit registers. + */ +#define UART_BRDL 0 +#define UART_BRDH 1 +#define UART_XINCLKDR 10 +#define UART_XYD 11 + #endif /* _LINUX_SERIAL_REG_H */ -- 2.34.1 ^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH 2/2] serial: Airoha SoC UART and HSUART support 2025-01-05 13:11 ` [PATCH 2/2] serial: Airoha SoC UART and HSUART support Benjamin Larsson @ 2025-01-05 15:59 ` Greg KH 2025-01-05 20:44 ` Benjamin Larsson 2025-01-06 7:19 ` Krzysztof Kozlowski 1 sibling, 1 reply; 19+ messages in thread From: Greg KH @ 2025-01-05 15:59 UTC (permalink / raw) To: Benjamin Larsson; +Cc: linux-serial, devicetree, ansuelsmth, lorenzo On Sun, Jan 05, 2025 at 02:11:47PM +0100, Benjamin Larsson wrote: > Support for Airoha AN7581 SoC UART and HSUART baud rate > calculation routine. > > Signed-off-by: Benjamin Larsson <benjamin.larsson@genexis.eu> > --- > drivers/tty/serial/8250/8250_airoha.c | 85 +++++++++++++++++++++++++++ > drivers/tty/serial/8250/8250_of.c | 2 + > drivers/tty/serial/8250/8250_port.c | 26 ++++++++ > drivers/tty/serial/8250/Kconfig | 10 ++++ > drivers/tty/serial/8250/Makefile | 1 + > include/linux/serial_8250.h | 1 + > include/uapi/linux/serial_core.h | 6 ++ > include/uapi/linux/serial_reg.h | 9 +++ > 8 files changed, 140 insertions(+) > create mode 100644 drivers/tty/serial/8250/8250_airoha.c > > diff --git a/drivers/tty/serial/8250/8250_airoha.c b/drivers/tty/serial/8250/8250_airoha.c > new file mode 100644 > index 000000000000..c57789dcc174 > --- /dev/null > +++ b/drivers/tty/serial/8250/8250_airoha.c > @@ -0,0 +1,85 @@ > +// SPDX-License-Identifier: GPL-2.0+ Do you really mean "+" here? Sorry, I have to ask. > + > +/* > + * Airoha UART driver. > + * > + * Copyright (c) 2025 Genexis Sweden AB > + * Author: Benjamin Larsson <benjamin.larsson@genexis.eu> > + */ > + > +#include <linux/clk.h> > +#include <linux/io.h> > +#include <linux/module.h> > +#include <linux/of_irq.h> > +#include <linux/of_platform.h> > +#include <linux/pinctrl/consumer.h> > +#include <linux/platform_device.h> > +#include <linux/pm_runtime.h> > +#include <linux/serial_8250.h> > +#include <linux/serial_reg.h> > +#include <linux/console.h> > +#include <linux/dma-mapping.h> > +#include <linux/tty.h> > +#include <linux/tty_flip.h> > + > +#include "8250.h" > + > +/* The Airoha UART is 16550-compatible except for the baud rate calculation. > + * > + * crystal_clock = 20 MHz > + * xindiv_clock = crystal_clock / clock_div > + * (x/y) = XYD, 32 bit register with 16 bits of x and then 16 bits of y > + * clock_div = XINCLK_DIVCNT (default set to 10 (0x4)), > + * - 3 bit register [ 1, 2, 4, 8, 10, 12, 16, 20 ] > + * > + * baud_rate = ((xindiv_clock) * (x/y)) / ([BRDH,BRDL] * 16) > + * > + * XYD_y seems to need to be larger then XYD_x for proper waveform generation. > + * Setting [BRDH,BRDL] to [0,1] and XYD_y to 65000 give even values > + * for usual baud rates. > + * > + * Selecting divider needs to fulfill > + * 1.8432 MHz <= xindiv_clk <= APB clock / 2 > + * The clocks are unknown but a divider of value 1 did not result in a valid > + * waveform. > + * > + */ > + > +#define CLOCK_DIV_TAB_ELEMS 3 > +#define XYD_Y 65000 > +#define XINDIV_CLOCK 20000000 > +#define UART_BRDL_20M 0x01 > +#define UART_BRDH_20M 0x00 > +static int clock_div_tab[] = { 10, 4, 2}; > +static int clock_div_reg[] = { 4, 2, 1}; > + > +int airoha8250_set_baud_rate(struct uart_port *port, > + unsigned int baud, unsigned int hs) What is "hs"? > +{ > + struct uart_8250_port *up = up_to_u8250p(port); > + unsigned int xyd_x, nom, denom; > + > + int i; > + /* set DLAB to access the baud rate divider registers (BRDH, BRDL) */ Didn't checkpatch complain about this? You don't need a blank line before the "int i;", but rather after it. > + serial_port_out(port, UART_LCR, up->lcr | UART_LCR_DLAB); > + /* set baud rate calculation defaults */ > + /* set BRDIV ([BRDH,BRDL]) to 1 */ > + serial_port_out(port, UART_BRDL, UART_BRDL_20M); > + serial_port_out(port, UART_BRDH, UART_BRDH_20M); > + /* calculate XYD_x and XINCLKDR register > + * for the HSUART xyd_x needs to be scale by a factor of 2 > + */ > + for (i = 0 ; i < CLOCK_DIV_TAB_ELEMS ; i++) { > + denom = (XINDIV_CLOCK/40) / clock_div_tab[i]; > + nom = (baud * (XYD_Y/40)); > + xyd_x = ((nom/denom) << 4) >> hs; > + if (xyd_x < XYD_Y) > + break; > + } > + serial_port_out(port, UART_XINCLKDR, clock_div_reg[i]); > + serial_port_out(port, UART_XYD, (xyd_x<<16) | XYD_Y); > + /* unset DLAB */ > + serial_port_out(port, UART_LCR, up->lcr); > + return 0; > +} > +EXPORT_SYMBOL_GPL(airoha8250_set_baud_rate); > diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c > index 64aed7efc569..5315bc1bc06d 100644 > --- a/drivers/tty/serial/8250/8250_of.c > +++ b/drivers/tty/serial/8250/8250_of.c > @@ -341,6 +341,8 @@ static const struct of_device_id of_platform_serial_table[] = { > { .compatible = "ti,da830-uart", .data = (void *)PORT_DA830, }, > { .compatible = "nuvoton,wpcm450-uart", .data = (void *)PORT_NPCM, }, > { .compatible = "nuvoton,npcm750-uart", .data = (void *)PORT_NPCM, }, > + { .compatible = "airoha,airoha-uart", .data = (void *)PORT_AIROHA, }, > + { .compatible = "airoha,airoha-hsuart", .data = (void *)PORT_AIROHA_HS, }, > { /* end of list */ }, > }; > MODULE_DEVICE_TABLE(of, of_platform_serial_table); > diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c > index 1ea52fce9bf1..00163a3d35cd 100644 > --- a/drivers/tty/serial/8250/8250_port.c > +++ b/drivers/tty/serial/8250/8250_port.c > @@ -319,6 +319,22 @@ static const struct serial8250_config uart_config[] = { > .rxtrig_bytes = {1, 8, 16, 30}, > .flags = UART_CAP_FIFO | UART_CAP_AFE, > }, > + [PORT_AIROHA] = { > + .name = "Airoha UART", > + .fifo_size = 8, > + .tx_loadsz = 1, > + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 | UART_FCR_CLEAR_RCVR, > + .rxtrig_bytes = {1, 4}, > + .flags = UART_CAP_FIFO, > + }, > + [PORT_AIROHA_HS] = { > + .name = "Airoha HSUART", > + .fifo_size = 128, > + .tx_loadsz = 128, > + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 | UART_FCR_CLEAR_RCVR, > + .rxtrig_bytes = {1, 4}, > + .flags = UART_CAP_FIFO, > + }, > }; > > /* Uart divisor latch read */ > @@ -2847,6 +2863,16 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, > > serial8250_set_divisor(port, baud, quot, frac); > > + > + /* > + * Airoha SoCs have custom registers for baud rate settings > + */ > +#ifdef CONFIG_SERIAL_8250_AIROHA Please don't put #ifdef in .c files, are you sure this is needed this way? Why not do it the other way around like other uart types do it? > + if (port->type == PORT_AIROHA) > + airoha8250_set_baud_rate(port, baud, 0); > + if (port->type == PORT_AIROHA_HS) > + airoha8250_set_baud_rate(port, baud, 1); > +#endif > /* > * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR > * is written without DLAB set, this mode will be disabled. > diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig > index 55d26d16df9b..97fe6ea9393d 100644 > --- a/drivers/tty/serial/8250/Kconfig > +++ b/drivers/tty/serial/8250/Kconfig > @@ -356,6 +356,16 @@ config SERIAL_8250_ACORN > system, say Y to this option. The driver can handle 1, 2, or 3 port > cards. If unsure, say N. > > +config SERIAL_8250_AIROHA > + tristate "Airoha UART support" > + depends on (ARCH_AIROHA || COMPILE_TEST) && OF && SERIAL_8250 > + help > + Selecting this option enables an Airoha SoC specific baud rate > + calculation routine on an otherwise 16550 compatible UART hardware. > + > + If you have an Airoha based board and want to use the serial port, > + say Y to this option. If unsure, say N. module name? > + > config SERIAL_8250_BCM2835AUX > tristate "BCM2835 auxiliar mini UART support" > depends on ARCH_BCM2835 || COMPILE_TEST > diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile > index 1516de629b61..b7f07d5c4cca 100644 > --- a/drivers/tty/serial/8250/Makefile > +++ b/drivers/tty/serial/8250/Makefile > @@ -20,6 +20,7 @@ obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o > > obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o > obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o > +obj-$(CONFIG_SERIAL_8250_AIROHA) += 8250_airoha.o > obj-$(CONFIG_SERIAL_8250_ASPEED_VUART) += 8250_aspeed_vuart.o > obj-$(CONFIG_SERIAL_8250_BCM2835AUX) += 8250_bcm2835aux.o > obj-$(CONFIG_SERIAL_8250_BCM7271) += 8250_bcm7271.o > diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h > index e0717c8393d7..33e7e1922149 100644 > --- a/include/linux/serial_8250.h > +++ b/include/linux/serial_8250.h > @@ -195,6 +195,7 @@ void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl); > void serial8250_do_set_divisor(struct uart_port *port, unsigned int baud, > unsigned int quot); > int fsl8250_handle_irq(struct uart_port *port); > +int airoha8250_set_baud_rate(struct uart_port *port, unsigned int baud, unsigned int hs); Why is this here? > int serial8250_handle_irq(struct uart_port *port, unsigned int iir); > u16 serial8250_rx_chars(struct uart_8250_port *up, u16 lsr); > void serial8250_read_char(struct uart_8250_port *up, u16 lsr); > diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h > index 9c007a106330..c71fb338accb 100644 > --- a/include/uapi/linux/serial_core.h > +++ b/include/uapi/linux/serial_core.h > @@ -231,6 +231,12 @@ > /* Sunplus UART */ > #define PORT_SUNPLUS 123 > > +/* Airoha UART */ > +#define PORT_AIROHA 124 > + > +/* Airoha HSUART */ > +#define PORT_AIROHA_HS 125 Do you REALLY need these port definitions in userspace? If so, what is going to use them there? > + > /* Generic type identifier for ports which type is not important to userspace. */ > #define PORT_GENERIC (-1) > > diff --git a/include/uapi/linux/serial_reg.h b/include/uapi/linux/serial_reg.h > index 9c987b04e2d0..72a71e171602 100644 > --- a/include/uapi/linux/serial_reg.h > +++ b/include/uapi/linux/serial_reg.h > @@ -383,5 +383,14 @@ > #define UART_ALTR_EN_TXFIFO_LW 0x01 /* Enable the TX FIFO Low Watermark */ > #define UART_ALTR_TX_LOW 0x41 /* Tx FIFO Low Watermark */ > > +/* > + * These are definitions for the Airoha UART > + * Normalized because of 32 bit registers. > + */ > +#define UART_BRDL 0 > +#define UART_BRDH 1 > +#define UART_XINCLKDR 10 > +#define UART_XYD 11 Why does the define not have your uart type in it? And what is userspace going to do with these values? Why do they need to be in this file? thanks, greg k-h ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 2/2] serial: Airoha SoC UART and HSUART support 2025-01-05 15:59 ` Greg KH @ 2025-01-05 20:44 ` Benjamin Larsson 2025-01-06 8:09 ` Greg KH 0 siblings, 1 reply; 19+ messages in thread From: Benjamin Larsson @ 2025-01-05 20:44 UTC (permalink / raw) To: Greg KH; +Cc: linux-serial, devicetree, ansuelsmth, lorenzo Hi. On 05/01/2025 16:59, Greg KH wrote: > > On Sun, Jan 05, 2025 at 02:11:47PM +0100, Benjamin Larsson wrote: >> Support for Airoha AN7581 SoC UART and HSUART baud rate >> calculation routine. >> >> Signed-off-by: Benjamin Larsson <benjamin.larsson@genexis.eu> >> --- >> drivers/tty/serial/8250/8250_airoha.c | 85 +++++++++++++++++++++++++++ >> drivers/tty/serial/8250/8250_of.c | 2 + >> drivers/tty/serial/8250/8250_port.c | 26 ++++++++ >> drivers/tty/serial/8250/Kconfig | 10 ++++ >> drivers/tty/serial/8250/Makefile | 1 + >> include/linux/serial_8250.h | 1 + >> include/uapi/linux/serial_core.h | 6 ++ >> include/uapi/linux/serial_reg.h | 9 +++ >> 8 files changed, 140 insertions(+) >> create mode 100644 drivers/tty/serial/8250/8250_airoha.c >> >> diff --git a/drivers/tty/serial/8250/8250_airoha.c b/drivers/tty/serial/8250/8250_airoha.c >> new file mode 100644 >> index 000000000000..c57789dcc174 >> --- /dev/null >> +++ b/drivers/tty/serial/8250/8250_airoha.c >> @@ -0,0 +1,85 @@ >> +// SPDX-License-Identifier: GPL-2.0+ > > Do you really mean "+" here? Sorry, I have to ask. > I just try to follow the style of 8250_port.c. Whatever is fine by me. >> + >> +/* >> + * Airoha UART driver. >> + * >> + * Copyright (c) 2025 Genexis Sweden AB >> + * Author: Benjamin Larsson <benjamin.larsson@genexis.eu> >> + */ >> + >> +#include <linux/clk.h> >> +#include <linux/io.h> >> +#include <linux/module.h> >> +#include <linux/of_irq.h> >> +#include <linux/of_platform.h> >> +#include <linux/pinctrl/consumer.h> >> +#include <linux/platform_device.h> >> +#include <linux/pm_runtime.h> >> +#include <linux/serial_8250.h> >> +#include <linux/serial_reg.h> >> +#include <linux/console.h> >> +#include <linux/dma-mapping.h> >> +#include <linux/tty.h> >> +#include <linux/tty_flip.h> >> + >> +#include "8250.h" >> + >> +/* The Airoha UART is 16550-compatible except for the baud rate calculation. >> + * >> + * crystal_clock = 20 MHz >> + * xindiv_clock = crystal_clock / clock_div >> + * (x/y) = XYD, 32 bit register with 16 bits of x and then 16 bits of y >> + * clock_div = XINCLK_DIVCNT (default set to 10 (0x4)), >> + * - 3 bit register [ 1, 2, 4, 8, 10, 12, 16, 20 ] >> + * >> + * baud_rate = ((xindiv_clock) * (x/y)) / ([BRDH,BRDL] * 16) >> + * >> + * XYD_y seems to need to be larger then XYD_x for proper waveform generation. >> + * Setting [BRDH,BRDL] to [0,1] and XYD_y to 65000 give even values >> + * for usual baud rates. >> + * >> + * Selecting divider needs to fulfill >> + * 1.8432 MHz <= xindiv_clk <= APB clock / 2 >> + * The clocks are unknown but a divider of value 1 did not result in a valid >> + * waveform. >> + * >> + */ >> + >> +#define CLOCK_DIV_TAB_ELEMS 3 >> +#define XYD_Y 65000 >> +#define XINDIV_CLOCK 20000000 >> +#define UART_BRDL_20M 0x01 >> +#define UART_BRDH_20M 0x00 >> +static int clock_div_tab[] = { 10, 4, 2}; >> +static int clock_div_reg[] = { 4, 2, 1}; >> + >> +int airoha8250_set_baud_rate(struct uart_port *port, >> + unsigned int baud, unsigned int hs) > > What is "hs"? I will address this in v2 by documenting the function. > >> +{ >> + struct uart_8250_port *up = up_to_u8250p(port); >> + unsigned int xyd_x, nom, denom; >> + >> + int i; >> + /* set DLAB to access the baud rate divider registers (BRDH, BRDL) */ > > > Didn't checkpatch complain about this? You don't need a blank line > before the "int i;", but rather after it. ./scripts/checkpatch.pl outgoing/0002-serial-Airoha-SoC-UART-and-HSUART-support.patch WARNING: added, moved or deleted file(s), does MAINTAINERS need updating? #23: new file mode 100644 total: 0 errors, 1 warnings, 187 lines checked I missed the blank line and will address in v2. > >> + serial_port_out(port, UART_LCR, up->lcr | UART_LCR_DLAB); >> + /* set baud rate calculation defaults */ >> + /* set BRDIV ([BRDH,BRDL]) to 1 */ >> + serial_port_out(port, UART_BRDL, UART_BRDL_20M); >> + serial_port_out(port, UART_BRDH, UART_BRDH_20M); >> + /* calculate XYD_x and XINCLKDR register >> + * for the HSUART xyd_x needs to be scale by a factor of 2 >> + */ >> + for (i = 0 ; i < CLOCK_DIV_TAB_ELEMS ; i++) { >> + denom = (XINDIV_CLOCK/40) / clock_div_tab[i]; >> + nom = (baud * (XYD_Y/40)); >> + xyd_x = ((nom/denom) << 4) >> hs; >> + if (xyd_x < XYD_Y) >> + break; >> + } >> + serial_port_out(port, UART_XINCLKDR, clock_div_reg[i]); >> + serial_port_out(port, UART_XYD, (xyd_x<<16) | XYD_Y); >> + /* unset DLAB */ >> + serial_port_out(port, UART_LCR, up->lcr); >> + return 0; >> +} >> +EXPORT_SYMBOL_GPL(airoha8250_set_baud_rate); >> diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c >> index 64aed7efc569..5315bc1bc06d 100644 >> --- a/drivers/tty/serial/8250/8250_of.c >> +++ b/drivers/tty/serial/8250/8250_of.c >> @@ -341,6 +341,8 @@ static const struct of_device_id of_platform_serial_table[] = { >> { .compatible = "ti,da830-uart", .data = (void *)PORT_DA830, }, >> { .compatible = "nuvoton,wpcm450-uart", .data = (void *)PORT_NPCM, }, >> { .compatible = "nuvoton,npcm750-uart", .data = (void *)PORT_NPCM, }, >> + { .compatible = "airoha,airoha-uart", .data = (void *)PORT_AIROHA, }, >> + { .compatible = "airoha,airoha-hsuart", .data = (void *)PORT_AIROHA_HS, }, >> { /* end of list */ }, >> }; >> MODULE_DEVICE_TABLE(of, of_platform_serial_table); >> diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c >> index 1ea52fce9bf1..00163a3d35cd 100644 >> --- a/drivers/tty/serial/8250/8250_port.c >> +++ b/drivers/tty/serial/8250/8250_port.c >> @@ -319,6 +319,22 @@ static const struct serial8250_config uart_config[] = { >> .rxtrig_bytes = {1, 8, 16, 30}, >> .flags = UART_CAP_FIFO | UART_CAP_AFE, >> }, >> + [PORT_AIROHA] = { >> + .name = "Airoha UART", >> + .fifo_size = 8, >> + .tx_loadsz = 1, >> + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 | UART_FCR_CLEAR_RCVR, >> + .rxtrig_bytes = {1, 4}, >> + .flags = UART_CAP_FIFO, >> + }, >> + [PORT_AIROHA_HS] = { >> + .name = "Airoha HSUART", >> + .fifo_size = 128, >> + .tx_loadsz = 128, >> + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 | UART_FCR_CLEAR_RCVR, >> + .rxtrig_bytes = {1, 4}, >> + .flags = UART_CAP_FIFO, >> + }, >> }; >> >> /* Uart divisor latch read */ >> @@ -2847,6 +2863,16 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, >> >> serial8250_set_divisor(port, baud, quot, frac); >> >> + >> + /* >> + * Airoha SoCs have custom registers for baud rate settings >> + */ >> +#ifdef CONFIG_SERIAL_8250_AIROHA > > Please don't put #ifdef in .c files, are you sure this is needed this > way? Why not do it the other way around like other uart types do it? There are other instances of ifdef in the code (#ifdef CONFIG_SERIAL_8250_RSA). Thus I used ifdefs. Should I use IS_REACHABLE or IS_ENABLED instead? > >> + if (port->type == PORT_AIROHA) >> + airoha8250_set_baud_rate(port, baud, 0); >> + if (port->type == PORT_AIROHA_HS) >> + airoha8250_set_baud_rate(port, baud, 1); >> +#endif >> /* >> * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR >> * is written without DLAB set, this mode will be disabled. >> diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig >> index 55d26d16df9b..97fe6ea9393d 100644 >> --- a/drivers/tty/serial/8250/Kconfig >> +++ b/drivers/tty/serial/8250/Kconfig >> @@ -356,6 +356,16 @@ config SERIAL_8250_ACORN >> system, say Y to this option. The driver can handle 1, 2, or 3 port >> cards. If unsure, say N. >> >> +config SERIAL_8250_AIROHA >> + tristate "Airoha UART support" >> + depends on (ARCH_AIROHA || COMPILE_TEST) && OF && SERIAL_8250 >> + help >> + Selecting this option enables an Airoha SoC specific baud rate >> + calculation routine on an otherwise 16550 compatible UART hardware. >> + >> + If you have an Airoha based board and want to use the serial port, >> + say Y to this option. If unsure, say N. > > module name? I will add that this is part of the 8250 driver in v2. > > >> + >> config SERIAL_8250_BCM2835AUX >> tristate "BCM2835 auxiliar mini UART support" >> depends on ARCH_BCM2835 || COMPILE_TEST >> diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile >> index 1516de629b61..b7f07d5c4cca 100644 >> --- a/drivers/tty/serial/8250/Makefile >> +++ b/drivers/tty/serial/8250/Makefile >> @@ -20,6 +20,7 @@ obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o >> >> obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o >> obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o >> +obj-$(CONFIG_SERIAL_8250_AIROHA) += 8250_airoha.o >> obj-$(CONFIG_SERIAL_8250_ASPEED_VUART) += 8250_aspeed_vuart.o >> obj-$(CONFIG_SERIAL_8250_BCM2835AUX) += 8250_bcm2835aux.o >> obj-$(CONFIG_SERIAL_8250_BCM7271) += 8250_bcm7271.o >> diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h >> index e0717c8393d7..33e7e1922149 100644 >> --- a/include/linux/serial_8250.h >> +++ b/include/linux/serial_8250.h >> @@ -195,6 +195,7 @@ void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl); >> void serial8250_do_set_divisor(struct uart_port *port, unsigned int baud, >> unsigned int quot); >> int fsl8250_handle_irq(struct uart_port *port); >> +int airoha8250_set_baud_rate(struct uart_port *port, unsigned int baud, unsigned int hs); > > Why is this here? I use the same place as fsl8250_handle_irq() uses. Should I place it somewhere else ? > >> int serial8250_handle_irq(struct uart_port *port, unsigned int iir); >> u16 serial8250_rx_chars(struct uart_8250_port *up, u16 lsr); >> void serial8250_read_char(struct uart_8250_port *up, u16 lsr); >> diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h >> index 9c007a106330..c71fb338accb 100644 >> --- a/include/uapi/linux/serial_core.h >> +++ b/include/uapi/linux/serial_core.h >> @@ -231,6 +231,12 @@ >> /* Sunplus UART */ >> #define PORT_SUNPLUS 123 >> >> +/* Airoha UART */ >> +#define PORT_AIROHA 124 >> + >> +/* Airoha HSUART */ >> +#define PORT_AIROHA_HS 125 > > Do you REALLY need these port definitions in userspace? If so, what is > going to use them there? > Testing another PORT define gives this result: grep -ri PORT_MTK_BTIF * drivers/tty/serial/8250/8250_of.c: .data = (void *)PORT_MTK_BTIF, }, drivers/tty/serial/8250/8250_port.c: [PORT_MTK_BTIF] = { include/uapi/linux/serial_core.h:#define PORT_MTK_BTIF 117 Per my understanding this is how the current code is designed to work. > >> + >> /* Generic type identifier for ports which type is not important to userspace. */ >> #define PORT_GENERIC (-1) >> >> diff --git a/include/uapi/linux/serial_reg.h b/include/uapi/linux/serial_reg.h >> index 9c987b04e2d0..72a71e171602 100644 >> --- a/include/uapi/linux/serial_reg.h >> +++ b/include/uapi/linux/serial_reg.h >> @@ -383,5 +383,14 @@ >> #define UART_ALTR_EN_TXFIFO_LW 0x01 /* Enable the TX FIFO Low Watermark */ >> #define UART_ALTR_TX_LOW 0x41 /* Tx FIFO Low Watermark */ >> >> +/* >> + * These are definitions for the Airoha UART >> + * Normalized because of 32 bit registers. >> + */ >> +#define UART_BRDL 0 >> +#define UART_BRDH 1 >> +#define UART_XINCLKDR 10 >> +#define UART_XYD 11 > > Why does the define not have your uart type in it? I will address this in v2. > And what is > userspace going to do with these values? Why do they need to be in this > file? Per my understanding I am following the intended design. > > thanks, > > greg k-h MvH Benjamin Larsson ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 2/2] serial: Airoha SoC UART and HSUART support 2025-01-05 20:44 ` Benjamin Larsson @ 2025-01-06 8:09 ` Greg KH 2025-01-06 12:35 ` Benjamin Larsson 0 siblings, 1 reply; 19+ messages in thread From: Greg KH @ 2025-01-06 8:09 UTC (permalink / raw) To: Benjamin Larsson; +Cc: linux-serial, devicetree, ansuelsmth, lorenzo On Sun, Jan 05, 2025 at 09:44:52PM +0100, Benjamin Larsson wrote: > Hi. > > On 05/01/2025 16:59, Greg KH wrote: > > > > On Sun, Jan 05, 2025 at 02:11:47PM +0100, Benjamin Larsson wrote: > > > Support for Airoha AN7581 SoC UART and HSUART baud rate > > > calculation routine. > > > > > > Signed-off-by: Benjamin Larsson <benjamin.larsson@genexis.eu> > > > --- > > > drivers/tty/serial/8250/8250_airoha.c | 85 +++++++++++++++++++++++++++ > > > drivers/tty/serial/8250/8250_of.c | 2 + > > > drivers/tty/serial/8250/8250_port.c | 26 ++++++++ > > > drivers/tty/serial/8250/Kconfig | 10 ++++ > > > drivers/tty/serial/8250/Makefile | 1 + > > > include/linux/serial_8250.h | 1 + > > > include/uapi/linux/serial_core.h | 6 ++ > > > include/uapi/linux/serial_reg.h | 9 +++ > > > 8 files changed, 140 insertions(+) > > > create mode 100644 drivers/tty/serial/8250/8250_airoha.c > > > > > > diff --git a/drivers/tty/serial/8250/8250_airoha.c b/drivers/tty/serial/8250/8250_airoha.c > > > new file mode 100644 > > > index 000000000000..c57789dcc174 > > > --- /dev/null > > > +++ b/drivers/tty/serial/8250/8250_airoha.c > > > @@ -0,0 +1,85 @@ > > > +// SPDX-License-Identifier: GPL-2.0+ > > > > Do you really mean "+" here? Sorry, I have to ask. > > > > I just try to follow the style of 8250_port.c. Whatever is fine by me. That's your call, please talk about it with your company lawyers. > > > /* Uart divisor latch read */ > > > @@ -2847,6 +2863,16 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, > > > > > > serial8250_set_divisor(port, baud, quot, frac); > > > > > > + > > > + /* > > > + * Airoha SoCs have custom registers for baud rate settings > > > + */ > > > +#ifdef CONFIG_SERIAL_8250_AIROHA > > > > Please don't put #ifdef in .c files, are you sure this is needed this > > way? Why not do it the other way around like other uart types do it? > > There are other instances of ifdef in the code (#ifdef > CONFIG_SERIAL_8250_RSA). Thus I used ifdefs. Don't follow bad practices of others please. > Should I use IS_REACHABLE or IS_ENABLED instead? Neither, put it in a .h file properly instead. > > > --- a/include/linux/serial_8250.h > > > +++ b/include/linux/serial_8250.h > > > @@ -195,6 +195,7 @@ void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl); > > > void serial8250_do_set_divisor(struct uart_port *port, unsigned int baud, > > > unsigned int quot); > > > int fsl8250_handle_irq(struct uart_port *port); > > > +int airoha8250_set_baud_rate(struct uart_port *port, unsigned int baud, unsigned int hs); > > > > Why is this here? > > I use the same place as fsl8250_handle_irq() uses. Should I place it > somewhere else ? Yes please, put it in your own .h file which you will need anyway. > > > int serial8250_handle_irq(struct uart_port *port, unsigned int iir); > > > u16 serial8250_rx_chars(struct uart_8250_port *up, u16 lsr); > > > void serial8250_read_char(struct uart_8250_port *up, u16 lsr); > > > diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h > > > index 9c007a106330..c71fb338accb 100644 > > > --- a/include/uapi/linux/serial_core.h > > > +++ b/include/uapi/linux/serial_core.h > > > @@ -231,6 +231,12 @@ > > > /* Sunplus UART */ > > > #define PORT_SUNPLUS 123 > > > > > > +/* Airoha UART */ > > > +#define PORT_AIROHA 124 > > > + > > > +/* Airoha HSUART */ > > > +#define PORT_AIROHA_HS 125 > > > > Do you REALLY need these port definitions in userspace? If so, what is > > going to use them there? > > > > Testing another PORT define gives this result: > > grep -ri PORT_MTK_BTIF * > > drivers/tty/serial/8250/8250_of.c: .data = (void *)PORT_MTK_BTIF, }, > drivers/tty/serial/8250/8250_port.c: [PORT_MTK_BTIF] = { > include/uapi/linux/serial_core.h:#define PORT_MTK_BTIF 117 > > Per my understanding this is how the current code is designed to work. That's a very old pattern, I'm asking you if you need this new number in userspace, which is what you are doing here. I'd prefer not to add new values here as they are a pain to manage and we can never change them if added. > > > + > > > /* Generic type identifier for ports which type is not important to userspace. */ > > > #define PORT_GENERIC (-1) > > > > > > diff --git a/include/uapi/linux/serial_reg.h b/include/uapi/linux/serial_reg.h > > > index 9c987b04e2d0..72a71e171602 100644 > > > --- a/include/uapi/linux/serial_reg.h > > > +++ b/include/uapi/linux/serial_reg.h > > > @@ -383,5 +383,14 @@ > > > #define UART_ALTR_EN_TXFIFO_LW 0x01 /* Enable the TX FIFO Low Watermark */ > > > #define UART_ALTR_TX_LOW 0x41 /* Tx FIFO Low Watermark */ > > > > > > +/* > > > + * These are definitions for the Airoha UART > > > + * Normalized because of 32 bit registers. > > > + */ > > > +#define UART_BRDL 0 > > > +#define UART_BRDH 1 > > > +#define UART_XINCLKDR 10 > > > +#define UART_XYD 11 > > > > Why does the define not have your uart type in it? > > I will address this in v2. > > > And what is > > userspace going to do with these values? Why do they need to be in this > > file? > > Per my understanding I am following the intended design. What design? Again what needs this in userspace to require it in this .h file? Why not just put them in your own private .h file as they are only used by your module and nothing else, right? thanks, greg k-h ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 2/2] serial: Airoha SoC UART and HSUART support 2025-01-06 8:09 ` Greg KH @ 2025-01-06 12:35 ` Benjamin Larsson 2025-01-07 10:44 ` Greg KH 0 siblings, 1 reply; 19+ messages in thread From: Benjamin Larsson @ 2025-01-06 12:35 UTC (permalink / raw) To: Greg KH; +Cc: linux-serial, devicetree, ansuelsmth, lorenzo Hi. >>>> diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h >>>> index 9c007a106330..c71fb338accb 100644 >>>> --- a/include/uapi/linux/serial_core.h >>>> +++ b/include/uapi/linux/serial_core.h >>>> @@ -231,6 +231,12 @@ >>>> /* Sunplus UART */ >>>> #define PORT_SUNPLUS 123 >>>> >>>> +/* Airoha UART */ >>>> +#define PORT_AIROHA 124 >>>> + >>>> +/* Airoha HSUART */ >>>> +#define PORT_AIROHA_HS 125 >>> >>> Do you REALLY need these port definitions in userspace? If so, what is >>> going to use them there? >>> >> >> Testing another PORT define gives this result: >> >> grep -ri PORT_MTK_BTIF * >> >> drivers/tty/serial/8250/8250_of.c: .data = (void *)PORT_MTK_BTIF, }, >> drivers/tty/serial/8250/8250_port.c: [PORT_MTK_BTIF] = { >> include/uapi/linux/serial_core.h:#define PORT_MTK_BTIF 117 >> >> Per my understanding this is how the current code is designed to work. > > That's a very old pattern, I'm asking you if you need this new number in > userspace, which is what you are doing here. I'd prefer not to add new > values here as they are a pain to manage and we can never change them if > added. > I dont need it in userspace. I need it in serial8250_config uart_config[] that uses this header. I need to pass something from 8250_of.c so that 8250_port.c can pick up that an airoha uart is selected via dts. Any solution that is acceptable is fine by me. I just reused the current implemented method in 8250_of.c. MvH Benjamin Larsson ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 2/2] serial: Airoha SoC UART and HSUART support 2025-01-06 12:35 ` Benjamin Larsson @ 2025-01-07 10:44 ` Greg KH 0 siblings, 0 replies; 19+ messages in thread From: Greg KH @ 2025-01-07 10:44 UTC (permalink / raw) To: Benjamin Larsson; +Cc: linux-serial, devicetree, ansuelsmth, lorenzo On Mon, Jan 06, 2025 at 01:35:10PM +0100, Benjamin Larsson wrote: > Hi. > > > > > > diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h > > > > > index 9c007a106330..c71fb338accb 100644 > > > > > --- a/include/uapi/linux/serial_core.h > > > > > +++ b/include/uapi/linux/serial_core.h > > > > > @@ -231,6 +231,12 @@ > > > > > /* Sunplus UART */ > > > > > #define PORT_SUNPLUS 123 > > > > > > > > > > +/* Airoha UART */ > > > > > +#define PORT_AIROHA 124 > > > > > + > > > > > +/* Airoha HSUART */ > > > > > +#define PORT_AIROHA_HS 125 > > > > > > > > Do you REALLY need these port definitions in userspace? If so, what is > > > > going to use them there? > > > > > > > > > > Testing another PORT define gives this result: > > > > > > grep -ri PORT_MTK_BTIF * > > > > > > drivers/tty/serial/8250/8250_of.c: .data = (void *)PORT_MTK_BTIF, }, > > > drivers/tty/serial/8250/8250_port.c: [PORT_MTK_BTIF] = { > > > include/uapi/linux/serial_core.h:#define PORT_MTK_BTIF 117 > > > > > > Per my understanding this is how the current code is designed to work. > > > > That's a very old pattern, I'm asking you if you need this new number in > > userspace, which is what you are doing here. I'd prefer not to add new > > values here as they are a pain to manage and we can never change them if > > added. > > > > I dont need it in userspace. I need it in serial8250_config uart_config[] > that uses this header. Then use something internal to the kernel please, and not exported to userspace where it must never change for the next 50+ years :( thanks, greg k-h ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 2/2] serial: Airoha SoC UART and HSUART support 2025-01-05 13:11 ` [PATCH 2/2] serial: Airoha SoC UART and HSUART support Benjamin Larsson 2025-01-05 15:59 ` Greg KH @ 2025-01-06 7:19 ` Krzysztof Kozlowski 2025-01-06 15:58 ` Benjamin Larsson 1 sibling, 1 reply; 19+ messages in thread From: Krzysztof Kozlowski @ 2025-01-06 7:19 UTC (permalink / raw) To: Benjamin Larsson; +Cc: linux-serial, devicetree, ansuelsmth, lorenzo On Sun, Jan 05, 2025 at 02:11:47PM +0100, Benjamin Larsson wrote: > Support for Airoha AN7581 SoC UART and HSUART baud rate > calculation routine. > > Signed-off-by: Benjamin Larsson <benjamin.larsson@genexis.eu> > --- > drivers/tty/serial/8250/8250_airoha.c | 85 +++++++++++++++++++++++++++ > drivers/tty/serial/8250/8250_of.c | 2 + > drivers/tty/serial/8250/8250_port.c | 26 ++++++++ > drivers/tty/serial/8250/Kconfig | 10 ++++ > drivers/tty/serial/8250/Makefile | 1 + > include/linux/serial_8250.h | 1 + > include/uapi/linux/serial_core.h | 6 ++ > include/uapi/linux/serial_reg.h | 9 +++ > 8 files changed, 140 insertions(+) > create mode 100644 drivers/tty/serial/8250/8250_airoha.c > > diff --git a/drivers/tty/serial/8250/8250_airoha.c b/drivers/tty/serial/8250/8250_airoha.c > new file mode 100644 > index 000000000000..c57789dcc174 > --- /dev/null > +++ b/drivers/tty/serial/8250/8250_airoha.c > @@ -0,0 +1,85 @@ > +// SPDX-License-Identifier: GPL-2.0+ > + > +/* > + * Airoha UART driver. > + * > + * Copyright (c) 2025 Genexis Sweden AB > + * Author: Benjamin Larsson <benjamin.larsson@genexis.eu> > + */ > + > +#include <linux/clk.h> Where is it used? > +#include <linux/io.h> > +#include <linux/module.h> > +#include <linux/of_irq.h> Where is it used? > +#include <linux/of_platform.h> Where is it used? > +#include <linux/pinctrl/consumer.h> I have impression that none of these are used. You include some huge amount of unused headers. > +#include <linux/platform_device.h> ??? > +#include <linux/pm_runtime.h> I really cannot find it. > +#include <linux/serial_8250.h> > +#include <linux/serial_reg.h> > +#include <linux/console.h> > +#include <linux/dma-mapping.h> Where do you use DMA? > +#include <linux/tty.h> > +#include <linux/tty_flip.h> Any of these? > + > +#include "8250.h" > + > +/* The Airoha UART is 16550-compatible except for the baud rate calculation. > + * > + * crystal_clock = 20 MHz > + * xindiv_clock = crystal_clock / clock_div > + * (x/y) = XYD, 32 bit register with 16 bits of x and then 16 bits of y > + * clock_div = XINCLK_DIVCNT (default set to 10 (0x4)), > + * - 3 bit register [ 1, 2, 4, 8, 10, 12, 16, 20 ] > + * > + * baud_rate = ((xindiv_clock) * (x/y)) / ([BRDH,BRDL] * 16) > + * > + * XYD_y seems to need to be larger then XYD_x for proper waveform generation. > + * Setting [BRDH,BRDL] to [0,1] and XYD_y to 65000 give even values > + * for usual baud rates. > + * > + * Selecting divider needs to fulfill > + * 1.8432 MHz <= xindiv_clk <= APB clock / 2 > + * The clocks are unknown but a divider of value 1 did not result in a valid > + * waveform. > + * > + */ > + > +#define CLOCK_DIV_TAB_ELEMS 3 No, use ARRAY_SIZE in your code. > +#define XYD_Y 65000 > +#define XINDIV_CLOCK 20000000 And what if input clock has different rate? > +#define UART_BRDL_20M 0x01 > +#define UART_BRDH_20M 0x00 Blank line > +static int clock_div_tab[] = { 10, 4, 2}; > +static int clock_div_reg[] = { 4, 2, 1}; Why not const? Best regards, Krzysztof ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 2/2] serial: Airoha SoC UART and HSUART support 2025-01-06 7:19 ` Krzysztof Kozlowski @ 2025-01-06 15:58 ` Benjamin Larsson 0 siblings, 0 replies; 19+ messages in thread From: Benjamin Larsson @ 2025-01-06 15:58 UTC (permalink / raw) To: Krzysztof Kozlowski; +Cc: linux-serial, devicetree, ansuelsmth, lorenzo Hi. On 06/01/2025 08:19, Krzysztof Kozlowski wrote: > On Sun, Jan 05, 2025 at 02:11:47PM +0100, Benjamin Larsson wrote: >> Support for Airoha AN7581 SoC UART and HSUART baud rate >> calculation routine. >> >> Signed-off-by: Benjamin Larsson <benjamin.larsson@genexis.eu> >> --- >> drivers/tty/serial/8250/8250_airoha.c | 85 +++++++++++++++++++++++++++ >> drivers/tty/serial/8250/8250_of.c | 2 + >> drivers/tty/serial/8250/8250_port.c | 26 ++++++++ >> drivers/tty/serial/8250/Kconfig | 10 ++++ >> drivers/tty/serial/8250/Makefile | 1 + >> include/linux/serial_8250.h | 1 + >> include/uapi/linux/serial_core.h | 6 ++ >> include/uapi/linux/serial_reg.h | 9 +++ >> 8 files changed, 140 insertions(+) >> create mode 100644 drivers/tty/serial/8250/8250_airoha.c >> >> diff --git a/drivers/tty/serial/8250/8250_airoha.c b/drivers/tty/serial/8250/8250_airoha.c >> new file mode 100644 >> index 000000000000..c57789dcc174 >> --- /dev/null >> +++ b/drivers/tty/serial/8250/8250_airoha.c >> @@ -0,0 +1,85 @@ >> +// SPDX-License-Identifier: GPL-2.0+ >> + >> +/* >> + * Airoha UART driver. >> + * >> + * Copyright (c) 2025 Genexis Sweden AB >> + * Author: Benjamin Larsson <benjamin.larsson@genexis.eu> >> + */ >> + >> +#include <linux/clk.h> > > Where is it used? > >> +#include <linux/io.h> >> +#include <linux/module.h> >> +#include <linux/of_irq.h> > > Where is it used? > >> +#include <linux/of_platform.h> > > Where is it used? > >> +#include <linux/pinctrl/consumer.h> > > I have impression that none of these are used. You include some huge > amount of unused headers. > >> +#include <linux/platform_device.h> > > ??? > >> +#include <linux/pm_runtime.h> > > I really cannot find it. > >> +#include <linux/serial_8250.h> >> +#include <linux/serial_reg.h> >> +#include <linux/console.h> >> +#include <linux/dma-mapping.h> > > Where do you use DMA? > >> +#include <linux/tty.h> >> +#include <linux/tty_flip.h> > > Any of these? My bad forgot to remove most of them, they/some where needed in the initial development. Will address in v2. > >> + >> +#include "8250.h" >> + >> +/* The Airoha UART is 16550-compatible except for the baud rate calculation. >> + * >> + * crystal_clock = 20 MHz >> + * xindiv_clock = crystal_clock / clock_div >> + * (x/y) = XYD, 32 bit register with 16 bits of x and then 16 bits of y >> + * clock_div = XINCLK_DIVCNT (default set to 10 (0x4)), >> + * - 3 bit register [ 1, 2, 4, 8, 10, 12, 16, 20 ] >> + * >> + * baud_rate = ((xindiv_clock) * (x/y)) / ([BRDH,BRDL] * 16) >> + * >> + * XYD_y seems to need to be larger then XYD_x for proper waveform generation. >> + * Setting [BRDH,BRDL] to [0,1] and XYD_y to 65000 give even values >> + * for usual baud rates. >> + * >> + * Selecting divider needs to fulfill >> + * 1.8432 MHz <= xindiv_clk <= APB clock / 2 >> + * The clocks are unknown but a divider of value 1 did not result in a valid >> + * waveform. >> + * >> + */ >> + >> +#define CLOCK_DIV_TAB_ELEMS 3 > > No, use ARRAY_SIZE in your code. Will address in v2. > >> +#define XYD_Y 65000 >> +#define XINDIV_CLOCK 20000000 > > And what if input clock has different rate? On this family of SoCs the clock is fixed. I will add a note about that in v2. > >> +#define UART_BRDL_20M 0x01 >> +#define UART_BRDH_20M 0x00 > > Blank line Will address in v2. > >> +static int clock_div_tab[] = { 10, 4, 2}; >> +static int clock_div_reg[] = { 4, 2, 1}; > > Why not const? Will address in v2. > > Best regards, > Krzysztof > MvH Benjamin Larsson ^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v2 0/2] Airoha UART support @ 2025-01-11 13:22 Benjamin Larsson 2025-01-11 13:22 ` [PATCH 2/2] serial: Airoha SoC UART and HSUART support Benjamin Larsson 0 siblings, 1 reply; 19+ messages in thread From: Benjamin Larsson @ 2025-01-11 13:22 UTC (permalink / raw) To: linux-serial, devicetree Cc: ansuelsmth, lorenzo, krzk, gregkh, Benjamin Larsson The Airoha familty of SoCs have a UART hardware that is 16550-compatible with the exception of the baud rate settings. This patch implements code for calculating the baud rate for the Airoha UART and HSUART. Signed-off-by: Benjamin Larsson <benjamin.larsson@genexis.eu> --- Changes in v2: - Removed ifdef use in .c files - Removed uart port defines from user-space headers - Reworded commit message - Added code documentation Benjamin Larsson (2): dt-bindings: serial: 8250: Add Airoha compatibles serial: Airoha SoC UART and HSUART support .../devicetree/bindings/serial/8250.yaml | 2 + drivers/tty/serial/8250/8250.h | 16 ++++ drivers/tty/serial/8250/8250_airoha.c | 83 +++++++++++++++++++ drivers/tty/serial/8250/8250_of.c | 2 + drivers/tty/serial/8250/8250_port.c | 27 ++++++ drivers/tty/serial/8250/Kconfig | 10 +++ drivers/tty/serial/8250/Makefile | 1 + 7 files changed, 141 insertions(+) create mode 100644 drivers/tty/serial/8250/8250_airoha.c -- 2.34.1 ^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH 2/2] serial: Airoha SoC UART and HSUART support 2025-01-11 13:22 [PATCH v2 0/2] Airoha UART support Benjamin Larsson @ 2025-01-11 13:22 ` Benjamin Larsson 2025-01-12 10:54 ` kernel test robot 2025-01-12 13:04 ` kernel test robot 0 siblings, 2 replies; 19+ messages in thread From: Benjamin Larsson @ 2025-01-11 13:22 UTC (permalink / raw) To: linux-serial, devicetree Cc: ansuelsmth, lorenzo, krzk, gregkh, Benjamin Larsson Support for Airoha AN7581 SoC UART and HSUART baud rate calculation routine. Signed-off-by: Benjamin Larsson <benjamin.larsson@genexis.eu> --- drivers/tty/serial/8250/8250.h | 15 +++++ drivers/tty/serial/8250/8250_airoha.c | 82 +++++++++++++++++++++++++++ drivers/tty/serial/8250/8250_of.c | 2 + drivers/tty/serial/8250/8250_port.c | 27 +++++++++ drivers/tty/serial/8250/Kconfig | 10 ++++ drivers/tty/serial/8250/Makefile | 1 + 6 files changed, 137 insertions(+) create mode 100644 drivers/tty/serial/8250/8250_airoha.c diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index e5310c65cf52..dd762289fa25 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -314,6 +314,21 @@ static inline int serial8250_in_MCR(struct uart_8250_port *up) return mctrl; } +/* uart_config[] table port type defines */ +/* Airoha UART */ +#define PORT_AIROHA 124 + +/* Airoha HSUART */ +#define PORT_AIROHA_HS 125 + +#ifdef CONFIG_SERIAL_8250_AIROHA +void airoha8250_set_baud_rate(struct uart_port *port, + unsigned int baud, unsigned int hs); +#else +static inline void airoha8250_set_baud_rate(struct uart_port *port, + unsigned int baud, unsigned int hs) { } +#endif + #ifdef CONFIG_SERIAL_8250_PNP int serial8250_pnp_init(void); void serial8250_pnp_exit(void); diff --git a/drivers/tty/serial/8250/8250_airoha.c b/drivers/tty/serial/8250/8250_airoha.c new file mode 100644 index 000000000000..d9d679e2188e --- /dev/null +++ b/drivers/tty/serial/8250/8250_airoha.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/* + * Airoha UART baud rate calculation function + * + * Copyright (c) 2025 Genexis Sweden AB + * Author: Benjamin Larsson <benjamin.larsson@genexis.eu> + */ + +#include "8250.h" + +/* The Airoha UART is 16550-compatible except for the baud rate calculation. + * + * crystal_clock = 20 MHz (fixed frequency) + * xindiv_clock = crystal_clock / clock_div + * (x/y) = XYD, 32 bit register with 16 bits of x and then 16 bits of y + * clock_div = XINCLK_DIVCNT (default set to 10 (0x4)), + * - 3 bit register [ 1, 2, 4, 8, 10, 12, 16, 20 ] + * + * baud_rate = ((xindiv_clock) * (x/y)) / ([BRDH,BRDL] * 16) + * + * XYD_y seems to need to be larger then XYD_x for proper waveform generation. + * Setting [BRDH,BRDL] to [0,1] and XYD_y to 65000 give even values + * for usual baud rates. + * + * Selecting divider needs to fulfill + * 1.8432 MHz <= xindiv_clk <= APB clock / 2 + * The clocks are unknown but a divider of value 1 did not result in a valid + * waveform. + * + */ + +/* Custom Airoha UART registers */ +#define UART_AIROHA_BRDL 0 +#define UART_AIROHA_BRDH 1 +#define UART_AIROHA_XINCLKDR 10 +#define UART_AIROHA_XYD 11 + +#define XYD_Y 65000 +#define XINDIV_CLOCK 20000000 +#define UART_BRDL_20M 0x01 +#define UART_BRDH_20M 0x00 + +static const int clock_div_tab[] = { 10, 4, 2}; +static const int clock_div_reg[] = { 4, 2, 1}; + +/** + * airoha8250_set_baud_rate() baud rate calculation routine + * @port: uart port + * @baud: requested uart baud rate + * @hs: uart type selector, 0 for regular uart and 1 for high-speed uart + * + */ + +void airoha8250_set_baud_rate(struct uart_port *port, + unsigned int baud, unsigned int hs) +{ + struct uart_8250_port *up = up_to_u8250p(port); + unsigned int xyd_x, nom, denom; + int i; + + /* set DLAB to access the baud rate divider registers (BRDH, BRDL) */ + serial_port_out(port, UART_LCR, up->lcr | UART_LCR_DLAB); + /* set baud rate calculation defaults */ + /* set BRDIV ([BRDH,BRDL]) to 1 */ + serial_port_out(port, UART_AIROHA_BRDL, UART_BRDL_20M); + serial_port_out(port, UART_AIROHA_BRDH, UART_BRDH_20M); + /* calculate XYD_x and XINCLKDR register + * for the HSUART xyd_x needs to be scale by a factor of 2 + */ + for (i = 0 ; i < ARRAY_SIZE(clock_div_tab) ; i++) { + denom = (XINDIV_CLOCK/40) / clock_div_tab[i]; + nom = (baud * (XYD_Y/40)); + xyd_x = ((nom/denom) << 4) >> hs; + if (xyd_x < XYD_Y) + break; + } + serial_port_out(port, UART_AIROHA_XINCLKDR, clock_div_reg[i]); + serial_port_out(port, UART_AIROHA_XYD, (xyd_x<<16) | XYD_Y); + /* unset DLAB */ + serial_port_out(port, UART_LCR, up->lcr); +} diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c index 64aed7efc569..5315bc1bc06d 100644 --- a/drivers/tty/serial/8250/8250_of.c +++ b/drivers/tty/serial/8250/8250_of.c @@ -341,6 +341,8 @@ static const struct of_device_id of_platform_serial_table[] = { { .compatible = "ti,da830-uart", .data = (void *)PORT_DA830, }, { .compatible = "nuvoton,wpcm450-uart", .data = (void *)PORT_NPCM, }, { .compatible = "nuvoton,npcm750-uart", .data = (void *)PORT_NPCM, }, + { .compatible = "airoha,airoha-uart", .data = (void *)PORT_AIROHA, }, + { .compatible = "airoha,airoha-hsuart", .data = (void *)PORT_AIROHA_HS, }, { /* end of list */ }, }; MODULE_DEVICE_TABLE(of, of_platform_serial_table); diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 1ea52fce9bf1..3cf7f46538f3 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -319,6 +319,24 @@ static const struct serial8250_config uart_config[] = { .rxtrig_bytes = {1, 8, 16, 30}, .flags = UART_CAP_FIFO | UART_CAP_AFE, }, + /* From here on after additional uart config port defines are placed in 8250.h + */ + [PORT_AIROHA] = { + .name = "Airoha UART", + .fifo_size = 8, + .tx_loadsz = 1, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 | UART_FCR_CLEAR_RCVR, + .rxtrig_bytes = {1, 4}, + .flags = UART_CAP_FIFO, + }, + [PORT_AIROHA_HS] = { + .name = "Airoha HSUART", + .fifo_size = 128, + .tx_loadsz = 128, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 | UART_FCR_CLEAR_RCVR, + .rxtrig_bytes = {1, 4}, + .flags = UART_CAP_FIFO, + }, }; /* Uart divisor latch read */ @@ -2847,6 +2865,15 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, serial8250_set_divisor(port, baud, quot, frac); + + /* + * Airoha SoCs have custom registers for baud rate settings + */ + if (port->type == PORT_AIROHA) + airoha8250_set_baud_rate(port, baud, 0); + if (port->type == PORT_AIROHA_HS) + airoha8250_set_baud_rate(port, baud, 1); + /* * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR * is written without DLAB set, this mode will be disabled. diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index 55d26d16df9b..97fe6ea9393d 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -356,6 +356,16 @@ config SERIAL_8250_ACORN system, say Y to this option. The driver can handle 1, 2, or 3 port cards. If unsure, say N. +config SERIAL_8250_AIROHA + tristate "Airoha UART support" + depends on (ARCH_AIROHA || COMPILE_TEST) && OF && SERIAL_8250 + help + Selecting this option enables an Airoha SoC specific baud rate + calculation routine on an otherwise 16550 compatible UART hardware. + + If you have an Airoha based board and want to use the serial port, + say Y to this option. If unsure, say N. + config SERIAL_8250_BCM2835AUX tristate "BCM2835 auxiliar mini UART support" depends on ARCH_BCM2835 || COMPILE_TEST diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile index 1516de629b61..b7f07d5c4cca 100644 --- a/drivers/tty/serial/8250/Makefile +++ b/drivers/tty/serial/8250/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o +obj-$(CONFIG_SERIAL_8250_AIROHA) += 8250_airoha.o obj-$(CONFIG_SERIAL_8250_ASPEED_VUART) += 8250_aspeed_vuart.o obj-$(CONFIG_SERIAL_8250_BCM2835AUX) += 8250_bcm2835aux.o obj-$(CONFIG_SERIAL_8250_BCM7271) += 8250_bcm7271.o -- 2.34.1 ^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH 2/2] serial: Airoha SoC UART and HSUART support 2025-01-11 13:22 ` [PATCH 2/2] serial: Airoha SoC UART and HSUART support Benjamin Larsson @ 2025-01-12 10:54 ` kernel test robot 2025-01-12 13:04 ` kernel test robot 1 sibling, 0 replies; 19+ messages in thread From: kernel test robot @ 2025-01-12 10:54 UTC (permalink / raw) To: Benjamin Larsson, linux-serial, devicetree Cc: oe-kbuild-all, ansuelsmth, lorenzo, krzk, gregkh, Benjamin Larsson Hi Benjamin, kernel test robot noticed the following build errors: [auto build test ERROR on tty/tty-testing] [also build test ERROR on tty/tty-next tty/tty-linus linus/master v6.13-rc6 next-20250110] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Benjamin-Larsson/dt-bindings-serial-8250-Add-Airoha-compatibles/20250111-212544 base: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git tty-testing patch link: https://lore.kernel.org/r/20250111132250.3642694-3-benjamin.larsson%40genexis.eu patch subject: [PATCH 2/2] serial: Airoha SoC UART and HSUART support config: sh-allmodconfig (https://download.01.org/0day-ci/archive/20250112/202501121822.HT0uHM1g-lkp@intel.com/config) compiler: sh4-linux-gcc (GCC) 14.2.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250112/202501121822.HT0uHM1g-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202501121822.HT0uHM1g-lkp@intel.com/ All errors (new ones prefixed by >>): >> drivers/tty/serial/8250/8250_airoha.c:55:6: error: redefinition of 'airoha8250_set_baud_rate' 55 | void airoha8250_set_baud_rate(struct uart_port *port, | ^~~~~~~~~~~~~~~~~~~~~~~~ In file included from drivers/tty/serial/8250/8250_airoha.c:10: drivers/tty/serial/8250/8250.h:328:20: note: previous definition of 'airoha8250_set_baud_rate' with type 'void(struct uart_port *, unsigned int, unsigned int)' 328 | static inline void airoha8250_set_baud_rate(struct uart_port *port, | ^~~~~~~~~~~~~~~~~~~~~~~~ vim +/airoha8250_set_baud_rate +55 drivers/tty/serial/8250/8250_airoha.c 46 47 /** 48 * airoha8250_set_baud_rate() baud rate calculation routine 49 * @port: uart port 50 * @baud: requested uart baud rate 51 * @hs: uart type selector, 0 for regular uart and 1 for high-speed uart 52 * 53 */ 54 > 55 void airoha8250_set_baud_rate(struct uart_port *port, -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 2/2] serial: Airoha SoC UART and HSUART support 2025-01-11 13:22 ` [PATCH 2/2] serial: Airoha SoC UART and HSUART support Benjamin Larsson 2025-01-12 10:54 ` kernel test robot @ 2025-01-12 13:04 ` kernel test robot 1 sibling, 0 replies; 19+ messages in thread From: kernel test robot @ 2025-01-12 13:04 UTC (permalink / raw) To: Benjamin Larsson, linux-serial, devicetree Cc: oe-kbuild-all, ansuelsmth, lorenzo, krzk, gregkh, Benjamin Larsson Hi Benjamin, kernel test robot noticed the following build warnings: [auto build test WARNING on tty/tty-testing] [also build test WARNING on tty/tty-next tty/tty-linus linus/master v6.13-rc6 next-20250110] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Benjamin-Larsson/dt-bindings-serial-8250-Add-Airoha-compatibles/20250111-212544 base: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git tty-testing patch link: https://lore.kernel.org/r/20250111132250.3642694-3-benjamin.larsson%40genexis.eu patch subject: [PATCH 2/2] serial: Airoha SoC UART and HSUART support config: sh-allyesconfig (https://download.01.org/0day-ci/archive/20250112/202501122042.DwBZgyJe-lkp@intel.com/config) compiler: sh4-linux-gcc (GCC) 14.2.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250112/202501122042.DwBZgyJe-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202501122042.DwBZgyJe-lkp@intel.com/ All warnings (new ones prefixed by >>): >> drivers/tty/serial/8250/8250_airoha.c:48: warning: This comment starts with '/**', but isn't a kernel-doc comment. Refer Documentation/doc-guide/kernel-doc.rst * airoha8250_set_baud_rate() baud rate calculation routine vim +48 drivers/tty/serial/8250/8250_airoha.c 46 47 /** > 48 * airoha8250_set_baud_rate() baud rate calculation routine 49 * @port: uart port 50 * @baud: requested uart baud rate 51 * @hs: uart type selector, 0 for regular uart and 1 for high-speed uart 52 * 53 */ 54 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki ^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v3 0/2] Airoha UART support @ 2025-01-19 13:01 Benjamin Larsson 2025-01-19 13:01 ` [PATCH 2/2] serial: Airoha SoC UART and HSUART support Benjamin Larsson 0 siblings, 1 reply; 19+ messages in thread From: Benjamin Larsson @ 2025-01-19 13:01 UTC (permalink / raw) To: linux-serial, devicetree Cc: ansuelsmth, lorenzo, krzk+dt, gregkh, linux-kernel, Benjamin Larsson The Airoha familty of SoCs have a UART hardware that is 16550-compatible with the exception of the baud rate settings. This patch implements code for calculating the baud rate for the Airoha UART and HSUART. Signed-off-by: Benjamin Larsson <benjamin.larsson@genexis.eu> --- Changes in v3: - Reworded commit message - Restructured comment text - Fixed kernel-doc warning - Fixed kernel test robot build error and build warning Changes in v2: - Removed ifdef use in .c files - Removed uart port defines from user-space headers - Reworded commit message - Added code documentation Benjamin Larsson (2): dt-bindings: serial: 8250: Add Airoha compatibles serial: Airoha SoC UART and HSUART support .../devicetree/bindings/serial/8250.yaml | 2 + drivers/tty/serial/8250/8250.h | 15 ++++ drivers/tty/serial/8250/8250_airoha.c | 83 +++++++++++++++++++ drivers/tty/serial/8250/8250_of.c | 2 + drivers/tty/serial/8250/8250_port.c | 27 ++++++ drivers/tty/serial/8250/Kconfig | 10 +++ drivers/tty/serial/8250/Makefile | 1 + 7 files changed, 140 insertions(+) create mode 100644 drivers/tty/serial/8250/8250_airoha.c -- 2.34.1 ^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH 2/2] serial: Airoha SoC UART and HSUART support 2025-01-19 13:01 [PATCH v3 0/2] Airoha UART support Benjamin Larsson @ 2025-01-19 13:01 ` Benjamin Larsson 0 siblings, 0 replies; 19+ messages in thread From: Benjamin Larsson @ 2025-01-19 13:01 UTC (permalink / raw) To: linux-serial, devicetree Cc: ansuelsmth, lorenzo, krzk+dt, gregkh, linux-kernel, Benjamin Larsson Support for Airoha AN7581 SoC UART and HSUART baud rate calculation routine. Signed-off-by: Benjamin Larsson <benjamin.larsson@genexis.eu> --- drivers/tty/serial/8250/8250.h | 15 +++++ drivers/tty/serial/8250/8250_airoha.c | 81 +++++++++++++++++++++++++++ drivers/tty/serial/8250/8250_of.c | 2 + drivers/tty/serial/8250/8250_port.c | 26 +++++++++ drivers/tty/serial/8250/Kconfig | 10 ++++ drivers/tty/serial/8250/Makefile | 1 + 6 files changed, 135 insertions(+) create mode 100644 drivers/tty/serial/8250/8250_airoha.c diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index e5310c65cf52..dd762289fa25 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -314,6 +314,21 @@ static inline int serial8250_in_MCR(struct uart_8250_port *up) return mctrl; } +/* uart_config[] table port type defines */ +/* Airoha UART */ +#define PORT_AIROHA 124 + +/* Airoha HSUART */ +#define PORT_AIROHA_HS 125 + +#ifdef CONFIG_SERIAL_8250_AIROHA +void airoha8250_set_baud_rate(struct uart_port *port, + unsigned int baud, unsigned int hs); +#else +static inline void airoha8250_set_baud_rate(struct uart_port *port, + unsigned int baud, unsigned int hs) { } +#endif + #ifdef CONFIG_SERIAL_8250_PNP int serial8250_pnp_init(void); void serial8250_pnp_exit(void); diff --git a/drivers/tty/serial/8250/8250_airoha.c b/drivers/tty/serial/8250/8250_airoha.c new file mode 100644 index 000000000000..51e675605741 --- /dev/null +++ b/drivers/tty/serial/8250/8250_airoha.c @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/* + * Airoha UART baud rate calculation function + * + * Copyright (c) 2025 Genexis Sweden AB + * Author: Benjamin Larsson <benjamin.larsson@genexis.eu> + */ + +#include "8250.h" + +/* The Airoha UART is 16550-compatible except for the baud rate calculation. */ + +/* Airoha UART registers */ +#define UART_AIROHA_BRDL 0 +#define UART_AIROHA_BRDH 1 +#define UART_AIROHA_XINCLKDR 10 +#define UART_AIROHA_XYD 11 + +#define XYD_Y 65000 +#define XINDIV_CLOCK 20000000 +#define UART_BRDL_20M 0x01 +#define UART_BRDH_20M 0x00 + +static const int clock_div_tab[] = { 10, 4, 2}; +static const int clock_div_reg[] = { 4, 2, 1}; + +/** + * airoha8250_set_baud_rate() - baud rate calculation routine + * @port: uart port + * @baud: requested uart baud rate + * @hs: uart type selector, 0 for regular uart and 1 for high-speed uart + * + * crystal_clock = 20 MHz (fixed frequency) + * xindiv_clock = crystal_clock / clock_div + * (x/y) = XYD, 32 bit register with 16 bits of x and then 16 bits of y + * clock_div = XINCLK_DIVCNT (default set to 10 (0x4)), + * - 3 bit register [ 1, 2, 4, 8, 10, 12, 16, 20 ] + * + * baud_rate = ((xindiv_clock) * (x/y)) / ([BRDH,BRDL] * 16) + * + * Selecting divider needs to fulfill + * 1.8432 MHz <= xindiv_clk <= APB clock / 2 + * The clocks are unknown but a divider of value 1 did not result in a valid + * waveform. + * + * XYD_y seems to need to be larger then XYD_x for proper waveform generation. + * Setting [BRDH,BRDL] to [0,1] and XYD_y to 65000 gives even values + * for usual baud rates. + */ + +void airoha8250_set_baud_rate(struct uart_port *port, + unsigned int baud, unsigned int hs) +{ + struct uart_8250_port *up = up_to_u8250p(port); + unsigned int xyd_x, nom, denom; + int i; + + /* set DLAB to access the baud rate divider registers (BRDH, BRDL) */ + serial_port_out(port, UART_LCR, up->lcr | UART_LCR_DLAB); + /* set baud rate calculation defaults */ + /* set BRDIV ([BRDH,BRDL]) to 1 */ + serial_port_out(port, UART_AIROHA_BRDL, UART_BRDL_20M); + serial_port_out(port, UART_AIROHA_BRDH, UART_BRDH_20M); + /* calculate XYD_x and XINCLKDR register by searching + * through a table of crystal_clock divisors + * + * for the HSUART xyd_x needs to be scaled by a factor of 2 + */ + for (i = 0 ; i < ARRAY_SIZE(clock_div_tab) ; i++) { + denom = (XINDIV_CLOCK/40) / clock_div_tab[i]; + nom = baud * (XYD_Y/40); + xyd_x = ((nom/denom) << 4) >> hs; + if (xyd_x < XYD_Y) + break; + } + serial_port_out(port, UART_AIROHA_XINCLKDR, clock_div_reg[i]); + serial_port_out(port, UART_AIROHA_XYD, (xyd_x<<16) | XYD_Y); + /* unset DLAB */ + serial_port_out(port, UART_LCR, up->lcr); +} diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c index 64aed7efc569..5315bc1bc06d 100644 --- a/drivers/tty/serial/8250/8250_of.c +++ b/drivers/tty/serial/8250/8250_of.c @@ -341,6 +341,8 @@ static const struct of_device_id of_platform_serial_table[] = { { .compatible = "ti,da830-uart", .data = (void *)PORT_DA830, }, { .compatible = "nuvoton,wpcm450-uart", .data = (void *)PORT_NPCM, }, { .compatible = "nuvoton,npcm750-uart", .data = (void *)PORT_NPCM, }, + { .compatible = "airoha,airoha-uart", .data = (void *)PORT_AIROHA, }, + { .compatible = "airoha,airoha-hsuart", .data = (void *)PORT_AIROHA_HS, }, { /* end of list */ }, }; MODULE_DEVICE_TABLE(of, of_platform_serial_table); diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 1ea52fce9bf1..040659de35a2 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -319,6 +319,24 @@ static const struct serial8250_config uart_config[] = { .rxtrig_bytes = {1, 8, 16, 30}, .flags = UART_CAP_FIFO | UART_CAP_AFE, }, + /* From here on after additional uart config port defines are placed in 8250.h + */ + [PORT_AIROHA] = { + .name = "Airoha UART", + .fifo_size = 8, + .tx_loadsz = 1, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 | UART_FCR_CLEAR_RCVR, + .rxtrig_bytes = {1, 4}, + .flags = UART_CAP_FIFO, + }, + [PORT_AIROHA_HS] = { + .name = "Airoha HSUART", + .fifo_size = 128, + .tx_loadsz = 128, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 | UART_FCR_CLEAR_RCVR, + .rxtrig_bytes = {1, 4}, + .flags = UART_CAP_FIFO, + }, }; /* Uart divisor latch read */ @@ -2847,6 +2865,14 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, serial8250_set_divisor(port, baud, quot, frac); + /* + * Airoha SoCs have custom registers for baud rate settings + */ + if (port->type == PORT_AIROHA) + airoha8250_set_baud_rate(port, baud, 0); + if (port->type == PORT_AIROHA_HS) + airoha8250_set_baud_rate(port, baud, 1); + /* * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR * is written without DLAB set, this mode will be disabled. diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index 55d26d16df9b..97fe6ea9393d 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -356,6 +356,16 @@ config SERIAL_8250_ACORN system, say Y to this option. The driver can handle 1, 2, or 3 port cards. If unsure, say N. +config SERIAL_8250_AIROHA + tristate "Airoha UART support" + depends on (ARCH_AIROHA || COMPILE_TEST) && OF && SERIAL_8250 + help + Selecting this option enables an Airoha SoC specific baud rate + calculation routine on an otherwise 16550 compatible UART hardware. + + If you have an Airoha based board and want to use the serial port, + say Y to this option. If unsure, say N. + config SERIAL_8250_BCM2835AUX tristate "BCM2835 auxiliar mini UART support" depends on ARCH_BCM2835 || COMPILE_TEST diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile index 1516de629b61..b7f07d5c4cca 100644 --- a/drivers/tty/serial/8250/Makefile +++ b/drivers/tty/serial/8250/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o +obj-$(CONFIG_SERIAL_8250_AIROHA) += 8250_airoha.o obj-$(CONFIG_SERIAL_8250_ASPEED_VUART) += 8250_aspeed_vuart.o obj-$(CONFIG_SERIAL_8250_BCM2835AUX) += 8250_bcm2835aux.o obj-$(CONFIG_SERIAL_8250_BCM7271) += 8250_bcm7271.o -- 2.34.1 ^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v4 0/2] Airoha UART support @ 2025-02-09 21:02 Benjamin Larsson 2025-02-09 21:02 ` [PATCH 2/2] serial: Airoha SoC UART and HSUART support Benjamin Larsson 0 siblings, 1 reply; 19+ messages in thread From: Benjamin Larsson @ 2025-02-09 21:02 UTC (permalink / raw) To: linux-serial, devicetree; +Cc: ansuelsmth, lorenzo, gregkh, Benjamin Larsson The Airoha familty of SoCs have a UART hardware that is 16550-compatible with the exception of the baud rate settings. This patch implements code for calculating the baud rate for the Airoha UART and HSUART. Signed-off-by: Benjamin Larsson <benjamin.larsson@genexis.eu> --- Changes in v4: - Removed COMPILE_TEST from Kconfig - Removed Kconfig option to build as module Changes in v3: - Reworded commit message - Restructured comment text - Fixed kernel-doc warning - Fixed kernel test robot build error and build warning Changes in v2: - Removed ifdef use in .c files - Removed uart port defines from user-space headers - Reworded commit message - Added code documentation Benjamin Larsson (2): dt-bindings: serial: 8250: Add Airoha compatibles serial: Airoha SoC UART and HSUART support .../devicetree/bindings/serial/8250.yaml | 2 + drivers/tty/serial/8250/8250.h | 15 ++++ drivers/tty/serial/8250/8250_airoha.c | 83 +++++++++++++++++++ drivers/tty/serial/8250/8250_of.c | 2 + drivers/tty/serial/8250/8250_port.c | 27 ++++++ drivers/tty/serial/8250/Kconfig | 10 +++ drivers/tty/serial/8250/Makefile | 1 + 7 files changed, 140 insertions(+) create mode 100644 drivers/tty/serial/8250/8250_airoha.c -- 2.34.1 ^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH 2/2] serial: Airoha SoC UART and HSUART support 2025-02-09 21:02 [PATCH v4 0/2] Airoha UART support Benjamin Larsson @ 2025-02-09 21:02 ` Benjamin Larsson 2025-03-22 21:42 ` Andy Shevchenko 0 siblings, 1 reply; 19+ messages in thread From: Benjamin Larsson @ 2025-02-09 21:02 UTC (permalink / raw) To: linux-serial, devicetree; +Cc: ansuelsmth, lorenzo, gregkh, Benjamin Larsson Support for Airoha AN7581 SoC UART and HSUART baud rate calculation routine. Signed-off-by: Benjamin Larsson <benjamin.larsson@genexis.eu> --- drivers/tty/serial/8250/8250.h | 15 +++++ drivers/tty/serial/8250/8250_airoha.c | 81 +++++++++++++++++++++++++++ drivers/tty/serial/8250/8250_of.c | 2 + drivers/tty/serial/8250/8250_port.c | 26 +++++++++ drivers/tty/serial/8250/Kconfig | 10 ++++ drivers/tty/serial/8250/Makefile | 1 + 6 files changed, 135 insertions(+) create mode 100644 drivers/tty/serial/8250/8250_airoha.c diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index e5310c65cf52..dd762289fa25 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -314,6 +314,21 @@ static inline int serial8250_in_MCR(struct uart_8250_port *up) return mctrl; } +/* uart_config[] table port type defines */ +/* Airoha UART */ +#define PORT_AIROHA 124 + +/* Airoha HSUART */ +#define PORT_AIROHA_HS 125 + +#ifdef CONFIG_SERIAL_8250_AIROHA +void airoha8250_set_baud_rate(struct uart_port *port, + unsigned int baud, unsigned int hs); +#else +static inline void airoha8250_set_baud_rate(struct uart_port *port, + unsigned int baud, unsigned int hs) { } +#endif + #ifdef CONFIG_SERIAL_8250_PNP int serial8250_pnp_init(void); void serial8250_pnp_exit(void); diff --git a/drivers/tty/serial/8250/8250_airoha.c b/drivers/tty/serial/8250/8250_airoha.c new file mode 100644 index 000000000000..51e675605741 --- /dev/null +++ b/drivers/tty/serial/8250/8250_airoha.c @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/* + * Airoha UART baud rate calculation function + * + * Copyright (c) 2025 Genexis Sweden AB + * Author: Benjamin Larsson <benjamin.larsson@genexis.eu> + */ + +#include "8250.h" + +/* The Airoha UART is 16550-compatible except for the baud rate calculation. */ + +/* Airoha UART registers */ +#define UART_AIROHA_BRDL 0 +#define UART_AIROHA_BRDH 1 +#define UART_AIROHA_XINCLKDR 10 +#define UART_AIROHA_XYD 11 + +#define XYD_Y 65000 +#define XINDIV_CLOCK 20000000 +#define UART_BRDL_20M 0x01 +#define UART_BRDH_20M 0x00 + +static const int clock_div_tab[] = { 10, 4, 2}; +static const int clock_div_reg[] = { 4, 2, 1}; + +/** + * airoha8250_set_baud_rate() - baud rate calculation routine + * @port: uart port + * @baud: requested uart baud rate + * @hs: uart type selector, 0 for regular uart and 1 for high-speed uart + * + * crystal_clock = 20 MHz (fixed frequency) + * xindiv_clock = crystal_clock / clock_div + * (x/y) = XYD, 32 bit register with 16 bits of x and then 16 bits of y + * clock_div = XINCLK_DIVCNT (default set to 10 (0x4)), + * - 3 bit register [ 1, 2, 4, 8, 10, 12, 16, 20 ] + * + * baud_rate = ((xindiv_clock) * (x/y)) / ([BRDH,BRDL] * 16) + * + * Selecting divider needs to fulfill + * 1.8432 MHz <= xindiv_clk <= APB clock / 2 + * The clocks are unknown but a divider of value 1 did not result in a valid + * waveform. + * + * XYD_y seems to need to be larger then XYD_x for proper waveform generation. + * Setting [BRDH,BRDL] to [0,1] and XYD_y to 65000 gives even values + * for usual baud rates. + */ + +void airoha8250_set_baud_rate(struct uart_port *port, + unsigned int baud, unsigned int hs) +{ + struct uart_8250_port *up = up_to_u8250p(port); + unsigned int xyd_x, nom, denom; + int i; + + /* set DLAB to access the baud rate divider registers (BRDH, BRDL) */ + serial_port_out(port, UART_LCR, up->lcr | UART_LCR_DLAB); + /* set baud rate calculation defaults */ + /* set BRDIV ([BRDH,BRDL]) to 1 */ + serial_port_out(port, UART_AIROHA_BRDL, UART_BRDL_20M); + serial_port_out(port, UART_AIROHA_BRDH, UART_BRDH_20M); + /* calculate XYD_x and XINCLKDR register by searching + * through a table of crystal_clock divisors + * + * for the HSUART xyd_x needs to be scaled by a factor of 2 + */ + for (i = 0 ; i < ARRAY_SIZE(clock_div_tab) ; i++) { + denom = (XINDIV_CLOCK/40) / clock_div_tab[i]; + nom = baud * (XYD_Y/40); + xyd_x = ((nom/denom) << 4) >> hs; + if (xyd_x < XYD_Y) + break; + } + serial_port_out(port, UART_AIROHA_XINCLKDR, clock_div_reg[i]); + serial_port_out(port, UART_AIROHA_XYD, (xyd_x<<16) | XYD_Y); + /* unset DLAB */ + serial_port_out(port, UART_LCR, up->lcr); +} diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c index 64aed7efc569..5315bc1bc06d 100644 --- a/drivers/tty/serial/8250/8250_of.c +++ b/drivers/tty/serial/8250/8250_of.c @@ -341,6 +341,8 @@ static const struct of_device_id of_platform_serial_table[] = { { .compatible = "ti,da830-uart", .data = (void *)PORT_DA830, }, { .compatible = "nuvoton,wpcm450-uart", .data = (void *)PORT_NPCM, }, { .compatible = "nuvoton,npcm750-uart", .data = (void *)PORT_NPCM, }, + { .compatible = "airoha,airoha-uart", .data = (void *)PORT_AIROHA, }, + { .compatible = "airoha,airoha-hsuart", .data = (void *)PORT_AIROHA_HS, }, { /* end of list */ }, }; MODULE_DEVICE_TABLE(of, of_platform_serial_table); diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 1ea52fce9bf1..040659de35a2 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -319,6 +319,24 @@ static const struct serial8250_config uart_config[] = { .rxtrig_bytes = {1, 8, 16, 30}, .flags = UART_CAP_FIFO | UART_CAP_AFE, }, + /* From here on after additional uart config port defines are placed in 8250.h + */ + [PORT_AIROHA] = { + .name = "Airoha UART", + .fifo_size = 8, + .tx_loadsz = 1, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 | UART_FCR_CLEAR_RCVR, + .rxtrig_bytes = {1, 4}, + .flags = UART_CAP_FIFO, + }, + [PORT_AIROHA_HS] = { + .name = "Airoha HSUART", + .fifo_size = 128, + .tx_loadsz = 128, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 | UART_FCR_CLEAR_RCVR, + .rxtrig_bytes = {1, 4}, + .flags = UART_CAP_FIFO, + }, }; /* Uart divisor latch read */ @@ -2847,6 +2865,14 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, serial8250_set_divisor(port, baud, quot, frac); + /* + * Airoha SoCs have custom registers for baud rate settings + */ + if (port->type == PORT_AIROHA) + airoha8250_set_baud_rate(port, baud, 0); + if (port->type == PORT_AIROHA_HS) + airoha8250_set_baud_rate(port, baud, 1); + /* * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR * is written without DLAB set, this mode will be disabled. diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index 55d26d16df9b..9cf16d392aca 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -356,6 +356,16 @@ config SERIAL_8250_ACORN system, say Y to this option. The driver can handle 1, 2, or 3 port cards. If unsure, say N. +config SERIAL_8250_AIROHA + bool "Airoha UART support" + depends on ARCH_AIROHA && OF && SERIAL_8250 + help + Selecting this option enables an Airoha SoC specific baud rate + calculation routine on an otherwise 16550 compatible UART hardware. + + If you have an Airoha based board and want to use the serial port, + say Y to this option. If unsure, say N. + config SERIAL_8250_BCM2835AUX tristate "BCM2835 auxiliar mini UART support" depends on ARCH_BCM2835 || COMPILE_TEST diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile index 1516de629b61..b7f07d5c4cca 100644 --- a/drivers/tty/serial/8250/Makefile +++ b/drivers/tty/serial/8250/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o +obj-$(CONFIG_SERIAL_8250_AIROHA) += 8250_airoha.o obj-$(CONFIG_SERIAL_8250_ASPEED_VUART) += 8250_aspeed_vuart.o obj-$(CONFIG_SERIAL_8250_BCM2835AUX) += 8250_bcm2835aux.o obj-$(CONFIG_SERIAL_8250_BCM7271) += 8250_bcm7271.o -- 2.34.1 ^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH 2/2] serial: Airoha SoC UART and HSUART support 2025-02-09 21:02 ` [PATCH 2/2] serial: Airoha SoC UART and HSUART support Benjamin Larsson @ 2025-03-22 21:42 ` Andy Shevchenko 2025-03-25 14:19 ` Benjamin Larsson 0 siblings, 1 reply; 19+ messages in thread From: Andy Shevchenko @ 2025-03-22 21:42 UTC (permalink / raw) To: Benjamin Larsson; +Cc: linux-serial, devicetree, ansuelsmth, lorenzo, gregkh Sun, Feb 09, 2025 at 10:02:41PM +0100, Benjamin Larsson kirjoitti: > Support for Airoha AN7581 SoC UART and HSUART baud rate > calculation routine. ... > drivers/tty/serial/8250/8250_port.c | 26 +++++++++ > + /* > + * Airoha SoCs have custom registers for baud rate settings > + */ > + if (port->type == PORT_AIROHA) > + airoha8250_set_baud_rate(port, baud, 0); > + if (port->type == PORT_AIROHA_HS) > + airoha8250_set_baud_rate(port, baud, 1); Why is this here? Please, make it stay in your module. ... > +config SERIAL_8250_AIROHA > + bool "Airoha UART support" Why bool? > + depends on ARCH_AIROHA && OF && SERIAL_8250 What is the purpose of the OF dependency? -- With Best Regards, Andy Shevchenko ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 2/2] serial: Airoha SoC UART and HSUART support 2025-03-22 21:42 ` Andy Shevchenko @ 2025-03-25 14:19 ` Benjamin Larsson 2025-03-25 14:23 ` Andy Shevchenko 0 siblings, 1 reply; 19+ messages in thread From: Benjamin Larsson @ 2025-03-25 14:19 UTC (permalink / raw) To: Andy Shevchenko; +Cc: linux-serial, devicetree, ansuelsmth, lorenzo, gregkh Hi. On 2025-03-22 22:42, Andy Shevchenko wrote: > [You don't often get email from andy.shevchenko@gmail.com. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ] > > Sun, Feb 09, 2025 at 10:02:41PM +0100, Benjamin Larsson kirjoitti: >> Support for Airoha AN7581 SoC UART and HSUART baud rate >> calculation routine. > ... > >> drivers/tty/serial/8250/8250_port.c | 26 +++++++++ >> + /* >> + * Airoha SoCs have custom registers for baud rate settings >> + */ >> + if (port->type == PORT_AIROHA) >> + airoha8250_set_baud_rate(port, baud, 0); >> + if (port->type == PORT_AIROHA_HS) >> + airoha8250_set_baud_rate(port, baud, 1); > Why is this here? Please, make it stay in your module. I dont add an extra module I extend the already existing one. > ... > >> +config SERIAL_8250_AIROHA >> + bool "Airoha UART support" > Why bool? Because it is just an extension of an existing module. > >> + depends on ARCH_AIROHA && OF && SERIAL_8250 > What is the purpose of the OF dependency? I thought it was needed for dts support. I'll remove it. > > -- > With Best Regards, > Andy Shevchenko > > MvH Benajmin Larsson ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 2/2] serial: Airoha SoC UART and HSUART support 2025-03-25 14:19 ` Benjamin Larsson @ 2025-03-25 14:23 ` Andy Shevchenko 0 siblings, 0 replies; 19+ messages in thread From: Andy Shevchenko @ 2025-03-25 14:23 UTC (permalink / raw) To: Benjamin Larsson; +Cc: linux-serial, devicetree, ansuelsmth, lorenzo, gregkh On Tue, Mar 25, 2025 at 4:19 PM Benjamin Larsson <benjamin.larsson@genexis.eu> wrote: > On 2025-03-22 22:42, Andy Shevchenko wrote: > > Sun, Feb 09, 2025 at 10:02:41PM +0100, Benjamin Larsson kirjoitti: ... > >> drivers/tty/serial/8250/8250_port.c | 26 +++++++++ > >> + /* > >> + * Airoha SoCs have custom registers for baud rate settings > >> + */ > >> + if (port->type == PORT_AIROHA) > >> + airoha8250_set_baud_rate(port, baud, 0); > >> + if (port->type == PORT_AIROHA_HS) > >> + airoha8250_set_baud_rate(port, baud, 1); > > Why is this here? Please, make it stay in your module. > > I dont add an extra module I extend the already existing one. We are trying hard to get rid of custom quirks in 8250_pci.c. That's how a few 8250_*.c appeared during the past several years. Please, follow the same approach. ... > >> +config SERIAL_8250_AIROHA > >> + bool "Airoha UART support" > > Why bool? > > Because it is just an extension of an existing module. Please, make a new real module instead. > >> + depends on ARCH_AIROHA && OF && SERIAL_8250 > > What is the purpose of the OF dependency? > > I thought it was needed for dts support. I'll remove it. It's a runtime dependency and not a compile time, right? So, there is no impediment to compile test on the configurations that have CONFIG_OF=n. -- With Best Regards, Andy Shevchenko ^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2025-03-25 14:23 UTC | newest] Thread overview: 19+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-01-05 13:11 [PATCH 0/2] Airoha UART support Benjamin Larsson 2025-01-05 13:11 ` [PATCH 1/2] dt-bindings: serial: 8250: Add Airoha compatibles Benjamin Larsson 2025-01-06 7:16 ` Krzysztof Kozlowski 2025-01-05 13:11 ` [PATCH 2/2] serial: Airoha SoC UART and HSUART support Benjamin Larsson 2025-01-05 15:59 ` Greg KH 2025-01-05 20:44 ` Benjamin Larsson 2025-01-06 8:09 ` Greg KH 2025-01-06 12:35 ` Benjamin Larsson 2025-01-07 10:44 ` Greg KH 2025-01-06 7:19 ` Krzysztof Kozlowski 2025-01-06 15:58 ` Benjamin Larsson -- strict thread matches above, loose matches on Subject: below -- 2025-01-11 13:22 [PATCH v2 0/2] Airoha UART support Benjamin Larsson 2025-01-11 13:22 ` [PATCH 2/2] serial: Airoha SoC UART and HSUART support Benjamin Larsson 2025-01-12 10:54 ` kernel test robot 2025-01-12 13:04 ` kernel test robot 2025-01-19 13:01 [PATCH v3 0/2] Airoha UART support Benjamin Larsson 2025-01-19 13:01 ` [PATCH 2/2] serial: Airoha SoC UART and HSUART support Benjamin Larsson 2025-02-09 21:02 [PATCH v4 0/2] Airoha UART support Benjamin Larsson 2025-02-09 21:02 ` [PATCH 2/2] serial: Airoha SoC UART and HSUART support Benjamin Larsson 2025-03-22 21:42 ` Andy Shevchenko 2025-03-25 14:19 ` Benjamin Larsson 2025-03-25 14:23 ` Andy Shevchenko
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox