* [PATCH v6 1/8] serial: 8250_dw: select port setup through platform data
2026-11-02 19:55 [PATCH v6 0/8] serial: 8250_dw: describe the Allwinner H616 and A523 UART configurations James Hilliard
@ 2026-11-02 19:55 ` James Hilliard
2026-11-02 20:04 ` sashiko-bot
2026-11-03 11:43 ` Andy Shevchenko
2026-11-02 19:55 ` [PATCH v6 2/8] serial: 8250: share the RX trigger conversion helper James Hilliard
` (6 subsequent siblings)
7 siblings, 2 replies; 21+ messages in thread
From: James Hilliard @ 2026-11-02 19:55 UTC (permalink / raw)
To: Andy Shevchenko, Ilpo Järvinen, Greg Kroah-Hartman,
Jiri Slaby, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Chen-Yu Tsai, Jernej Skrabec, Samuel Holland
Cc: linux-kernel, linux-serial, devicetree, linux-arm-kernel,
linux-sunxi, James Hilliard
Select feature discovery and DMA attachment through a platform-data setup
callback. The generic callback probes the optional registers and attaches
DMA when a FIFO size is available. Integrations with a fixed configuration
can supply their own setup before the port is registered. Allow setup to
return an error so integrations can reject invalid configuration before
registration.
Replace skip_autocfg with the Octeon setup selection. Octeon is a 64-bit
platform and continues to skip optional-register probing while retaining
its DMA setup. Select the DMA setup helper directly for this integration.
Keep generic setup for devices without matched platform data as well.
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
---
drivers/tty/serial/8250/8250_dw.c | 41 ++++++++++++++++++++++++++++-----------
1 file changed, 30 insertions(+), 11 deletions(-)
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index 9cbe076463e0..a546cf2de7b6 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -64,6 +64,7 @@ struct dw8250_platform_data {
u8 usr_reg;
u32 cpr_value;
unsigned int quirks;
+ int (*setup)(struct uart_port *p);
};
struct dw8250_data {
@@ -76,7 +77,6 @@ struct dw8250_data {
struct clk *pclk;
struct reset_control *rst;
- unsigned int skip_autocfg:1;
unsigned int uart_16550_compatible:1;
unsigned int in_idle:1;
@@ -596,7 +596,6 @@ static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)
p->serial_out = dw8250_serial_outq;
p->flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE;
p->type = PORT_OCTEON;
- data->skip_autocfg = true;
}
#endif
@@ -631,6 +630,28 @@ static void dw8250_shutdown(struct uart_port *port)
d->no_int_count = 0;
}
+static int dw8250_setup_dma(struct uart_port *p)
+{
+ struct dw8250_data *data = to_dw8250_data(p->private_data);
+ struct uart_8250_port *up = up_to_u8250p(p);
+
+ /* DMA setup requires a FIFO */
+ if (!p->fifosize)
+ return 0;
+
+ data->data.dma.rxconf.src_maxburst = p->fifosize / 4;
+ data->data.dma.txconf.dst_maxburst = p->fifosize / 4;
+ up->dma = &data->data.dma;
+
+ return 0;
+}
+
+static int dw8250_setup(struct uart_port *p)
+{
+ dw8250_setup_port(p);
+ return dw8250_setup_dma(p);
+}
+
static int dw8250_probe(struct platform_device *pdev)
{
struct uart_8250_port uart = {}, *up = &uart;
@@ -765,19 +786,16 @@ static int dw8250_probe(struct platform_device *pdev)
dw8250_setup_dma_filter(p, data);
- if (!data->skip_autocfg)
- dw8250_setup_port(p);
+ if (data->pdata && data->pdata->setup)
+ err = data->pdata->setup(p);
+ else
+ err = dw8250_setup(p);
+ if (err)
+ return err;
/* Use the BUSY-safe sequence for both integer and fractional divisors. */
p->set_divisor = dw8250_set_divisor;
- /* If we have a valid fifosize, try hooking up DMA */
- if (p->fifosize) {
- data->data.dma.rxconf.src_maxburst = p->fifosize / 4;
- data->data.dma.txconf.dst_maxburst = p->fifosize / 4;
- up->dma = &data->data.dma;
- }
-
data->data.uport = serial8250_register_8250_port(up);
if (IS_ERR(data->data.uport))
return PTR_ERR(data->data.uport);
@@ -860,6 +878,7 @@ static const struct dw8250_platform_data dw8250_dw_apb = {
static const struct dw8250_platform_data dw8250_octeon_3860_data = {
.usr_reg = OCTEON_UART_USR,
.quirks = DW_UART_QUIRK_OCTEON,
+ .setup = dw8250_setup_dma,
};
static const struct dw8250_platform_data dw8250_armada_38x_data = {
--
2.53.0
^ permalink raw reply related [flat|nested] 21+ messages in thread* Re: [PATCH v6 1/8] serial: 8250_dw: select port setup through platform data
2026-11-02 19:55 ` [PATCH v6 1/8] serial: 8250_dw: select port setup through platform data James Hilliard
@ 2026-11-02 20:04 ` sashiko-bot
2026-11-03 11:43 ` Andy Shevchenko
1 sibling, 0 replies; 21+ messages in thread
From: sashiko-bot @ 2026-11-02 20:04 UTC (permalink / raw)
To: James Hilliard; +Cc: linux-serial
> Select feature discovery and DMA attachment through a platform-data setup
> callback. The generic callback probes the optional registers and attaches
> DMA when a FIFO size is available. Integrations with a fixed configuration
> can supply their own setup before the port is registered. Allow setup to
> return an error so integrations can reject invalid configuration before
> registration.
>
> Replace skip_autocfg with the Octeon setup selection. Octeon is a 64-bit
> platform and continues to skip optional-register probing while retaining
> its DMA setup. Select the DMA setup helper directly for this integration.
> Keep generic setup for devices without matched platform data as well.
>
> Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
> Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Sashiko has reviewed this patch and found no issues.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261102-submit-h616-uart-fifo-v1-v6-0-25afcb346b0c@gmail.com?part=1
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v6 1/8] serial: 8250_dw: select port setup through platform data
2026-11-02 19:55 ` [PATCH v6 1/8] serial: 8250_dw: select port setup through platform data James Hilliard
2026-11-02 20:04 ` sashiko-bot
@ 2026-11-03 11:43 ` Andy Shevchenko
1 sibling, 0 replies; 21+ messages in thread
From: Andy Shevchenko @ 2026-11-03 11:43 UTC (permalink / raw)
To: James Hilliard
Cc: Ilpo Järvinen, Greg Kroah-Hartman, Jiri Slaby, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai, Jernej Skrabec,
Samuel Holland, linux-kernel, linux-serial, devicetree,
linux-arm-kernel, linux-sunxi
On Mon, Nov 02, 2026 at 12:55:16PM -0700, James Hilliard wrote:
> Select feature discovery and DMA attachment through a platform-data setup
> callback. The generic callback probes the optional registers and attaches
> DMA when a FIFO size is available. Integrations with a fixed configuration
> can supply their own setup before the port is registered. Allow setup to
> return an error so integrations can reject invalid configuration before
> registration.
>
> Replace skip_autocfg with the Octeon setup selection. Octeon is a 64-bit
> platform and continues to skip optional-register probing while retaining
> its DMA setup. Select the DMA setup helper directly for this integration.
> Keep generic setup for devices without matched platform data as well.
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v6 2/8] serial: 8250: share the RX trigger conversion helper
2026-11-02 19:55 [PATCH v6 0/8] serial: 8250_dw: describe the Allwinner H616 and A523 UART configurations James Hilliard
2026-11-02 19:55 ` [PATCH v6 1/8] serial: 8250_dw: select port setup through platform data James Hilliard
@ 2026-11-02 19:55 ` James Hilliard
2026-11-02 20:07 ` sashiko-bot
2026-11-03 11:46 ` Andy Shevchenko
2026-11-02 19:55 ` [PATCH v6 3/8] dt-bindings: serial: snps-dw-apb-uart: add Allwinner H616 James Hilliard
` (5 subsequent siblings)
7 siblings, 2 replies; 21+ messages in thread
From: James Hilliard @ 2026-11-02 19:55 UTC (permalink / raw)
To: Andy Shevchenko, Ilpo Järvinen, Greg Kroah-Hartman,
Jiri Slaby, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Chen-Yu Tsai, Jernej Skrabec, Samuel Holland
Cc: linux-kernel, linux-serial, devicetree, linux-arm-kernel,
linux-sunxi, James Hilliard
Drivers can supply receive-trigger thresholds through the RX trigger
callbacks without adding a legacy port type to uart_config[]. Extract the
threshold search into serial8250_bytes_to_fcr() so those drivers can use
the same conversion as the generic 8250 implementation.
Keep the implementation in 8250_port.c and export it in the SERIAL_8250
namespace. Include the unsupported-table check and preserve the existing
nearest-lower selection and highest-encoding fallback.
Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
---
drivers/tty/serial/8250/8250.h | 2 ++
drivers/tty/serial/8250/8250_port.c | 21 +++++++++++++--------
2 files changed, 15 insertions(+), 8 deletions(-)
diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
index 21ed9c41b751..1600f2e45d76 100644
--- a/drivers/tty/serial/8250/8250.h
+++ b/drivers/tty/serial/8250/8250.h
@@ -73,6 +73,8 @@ struct serial8250_config {
unsigned int flags;
};
+int serial8250_bytes_to_fcr(const unsigned char *rxtrig_bytes, unsigned char bytes);
+
enum uart_port_type {
/* Internal 8250 only */
UART_PORT_AIROHA = 124,
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index 36b2b0a2c05c..4a25badad3c5 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -3015,22 +3015,27 @@ static int fcr_get_rxtrig_bytes(struct uart_8250_port *up)
return bytes ? bytes : -EOPNOTSUPP;
}
-static int bytes_to_fcr_rxtrig(struct uart_8250_port *up, unsigned char bytes)
+int serial8250_bytes_to_fcr(const unsigned char *rxtrig_bytes, unsigned char bytes)
{
- const struct serial8250_config *conf_type = &uart_config[up->port.type];
- int i;
-
- if (!conf_type->rxtrig_bytes[UART_FCR_R_TRIG_BITS(UART_FCR_R_TRIG_00)])
+ if (!rxtrig_bytes[UART_FCR_R_TRIG_BITS(UART_FCR_R_TRIG_00)])
return -EOPNOTSUPP;
- for (i = 1; i < UART_FCR_R_TRIG_MAX_STATE; i++) {
- if (bytes < conf_type->rxtrig_bytes[i])
+ for (unsigned int i = 1; i < UART_FCR_R_TRIG_MAX_STATE; i++) {
+ if (bytes < rxtrig_bytes[i])
/* Use the nearest lower value */
- return (--i) << UART_FCR_R_TRIG_SHIFT;
+ return (i - 1) << UART_FCR_R_TRIG_SHIFT;
}
return UART_FCR_R_TRIG_11;
}
+EXPORT_SYMBOL_NS_GPL(serial8250_bytes_to_fcr, "SERIAL_8250");
+
+static int bytes_to_fcr_rxtrig(struct uart_8250_port *up, unsigned char bytes)
+{
+ const struct serial8250_config *conf_type = &uart_config[up->port.type];
+
+ return serial8250_bytes_to_fcr(conf_type->rxtrig_bytes, bytes);
+}
static int do_get_rxtrig(struct tty_port *port)
{
--
2.53.0
^ permalink raw reply related [flat|nested] 21+ messages in thread* Re: [PATCH v6 2/8] serial: 8250: share the RX trigger conversion helper
2026-11-02 19:55 ` [PATCH v6 2/8] serial: 8250: share the RX trigger conversion helper James Hilliard
@ 2026-11-02 20:07 ` sashiko-bot
2026-11-03 11:46 ` Andy Shevchenko
1 sibling, 0 replies; 21+ messages in thread
From: sashiko-bot @ 2026-11-02 20:07 UTC (permalink / raw)
To: James Hilliard; +Cc: linux-serial
> Drivers can supply receive-trigger thresholds through the RX trigger
> callbacks without adding a legacy port type to uart_config[]. Extract the
> threshold search into serial8250_bytes_to_fcr() so those drivers can use
> the same conversion as the generic 8250 implementation.
>
> Keep the implementation in 8250_port.c and export it in the SERIAL_8250
> namespace. Include the unsupported-table check and preserve the existing
> nearest-lower selection and highest-encoding fallback.
>
> Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
> Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Sashiko has reviewed this patch and found no issues.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261102-submit-h616-uart-fifo-v1-v6-0-25afcb346b0c@gmail.com?part=2
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v6 2/8] serial: 8250: share the RX trigger conversion helper
2026-11-02 19:55 ` [PATCH v6 2/8] serial: 8250: share the RX trigger conversion helper James Hilliard
2026-11-02 20:07 ` sashiko-bot
@ 2026-11-03 11:46 ` Andy Shevchenko
1 sibling, 0 replies; 21+ messages in thread
From: Andy Shevchenko @ 2026-11-03 11:46 UTC (permalink / raw)
To: James Hilliard
Cc: Ilpo Järvinen, Greg Kroah-Hartman, Jiri Slaby, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai, Jernej Skrabec,
Samuel Holland, linux-kernel, linux-serial, devicetree,
linux-arm-kernel, linux-sunxi
On Mon, Nov 02, 2026 at 12:55:17PM -0700, James Hilliard wrote:
> Drivers can supply receive-trigger thresholds through the RX trigger
> callbacks without adding a legacy port type to uart_config[]. Extract the
> threshold search into serial8250_bytes_to_fcr() so those drivers can use
> the same conversion as the generic 8250 implementation.
>
> Keep the implementation in 8250_port.c and export it in the SERIAL_8250
> namespace. Include the unsupported-table check and preserve the existing
> nearest-lower selection and highest-encoding fallback.
...
> -static int bytes_to_fcr_rxtrig(struct uart_8250_port *up, unsigned char bytes)
> +int serial8250_bytes_to_fcr(const unsigned char *rxtrig_bytes, unsigned char bytes)
> {
> - const struct serial8250_config *conf_type = &uart_config[up->port.type];
> - int i;
> -
> - if (!conf_type->rxtrig_bytes[UART_FCR_R_TRIG_BITS(UART_FCR_R_TRIG_00)])
> + if (!rxtrig_bytes[UART_FCR_R_TRIG_BITS(UART_FCR_R_TRIG_00)])
> return -EOPNOTSUPP;
>
> - for (i = 1; i < UART_FCR_R_TRIG_MAX_STATE; i++) {
> - if (bytes < conf_type->rxtrig_bytes[i])
> + for (unsigned int i = 1; i < UART_FCR_R_TRIG_MAX_STATE; i++) {
> + if (bytes < rxtrig_bytes[i])
> /* Use the nearest lower value */
> - return (--i) << UART_FCR_R_TRIG_SHIFT;
> + return (i - 1) << UART_FCR_R_TRIG_SHIFT;
> }
Strictly speaking cosmetics should go into a separate patch (for-loop iterator
locality, (--i) morph).
> return UART_FCR_R_TRIG_11;
> }
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v6 3/8] dt-bindings: serial: snps-dw-apb-uart: add Allwinner H616
2026-11-02 19:55 [PATCH v6 0/8] serial: 8250_dw: describe the Allwinner H616 and A523 UART configurations James Hilliard
2026-11-02 19:55 ` [PATCH v6 1/8] serial: 8250_dw: select port setup through platform data James Hilliard
2026-11-02 19:55 ` [PATCH v6 2/8] serial: 8250: share the RX trigger conversion helper James Hilliard
@ 2026-11-02 19:55 ` James Hilliard
2026-11-02 20:08 ` sashiko-bot
2026-11-02 19:55 ` [PATCH v6 4/8] serial: 8250_dw: configure the Allwinner H616 UART James Hilliard
` (4 subsequent siblings)
7 siblings, 1 reply; 21+ messages in thread
From: James Hilliard @ 2026-11-02 19:55 UTC (permalink / raw)
To: Andy Shevchenko, Ilpo Järvinen, Greg Kroah-Hartman,
Jiri Slaby, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Chen-Yu Tsai, Jernej Skrabec, Samuel Holland
Cc: linux-kernel, linux-serial, devicetree, linux-arm-kernel,
linux-sunxi, James Hilliard, Krzysztof Kozlowski
The H616 UART has 256-byte transmit and receive FIFOs, but its DesignWare
component parameter register does not report the FIFO depth. Its optional
register layout also differs from the generic DesignWare integration.
Add a specific compatible to identify this fixed configuration, retaining
snps,dw-apb-uart as a fallback.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
---
Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
index e2ca126d58ba..fc1289073241 100644
--- a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
+++ b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
@@ -60,6 +60,7 @@ properties:
- const: renesas,rzn1-uart
- items:
- enum:
+ - allwinner,sun50i-h616-uart
- anlogic,dr1v90-uart
- brcm,bcm11351-dw-apb-uart
- brcm,bcm21664-dw-apb-uart
--
2.53.0
^ permalink raw reply related [flat|nested] 21+ messages in thread* [PATCH v6 4/8] serial: 8250_dw: configure the Allwinner H616 UART
2026-11-02 19:55 [PATCH v6 0/8] serial: 8250_dw: describe the Allwinner H616 and A523 UART configurations James Hilliard
` (2 preceding siblings ...)
2026-11-02 19:55 ` [PATCH v6 3/8] dt-bindings: serial: snps-dw-apb-uart: add Allwinner H616 James Hilliard
@ 2026-11-02 19:55 ` James Hilliard
2026-11-02 20:18 ` sashiko-bot
2026-11-03 12:03 ` Andy Shevchenko
2026-11-02 19:55 ` [PATCH v6 5/8] arm64: dts: allwinner: h616: describe the UART integration James Hilliard
` (3 subsequent siblings)
7 siblings, 2 replies; 21+ messages in thread
From: James Hilliard @ 2026-11-02 19:55 UTC (permalink / raw)
To: Andy Shevchenko, Ilpo Järvinen, Greg Kroah-Hartman,
Jiri Slaby, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Chen-Yu Tsai, Jernej Skrabec, Samuel Holland
Cc: linux-kernel, linux-serial, devicetree, linux-arm-kernel,
linux-sunxi, James Hilliard
H616 has 256-byte transmit and receive FIFOs, but its optional DesignWare
component parameter register reads as zero. Generic 16550 probing leaves
the port using the 16-byte FIFO configuration and its trigger-level table.
Keep PORT_16550A and supply H616's fixed FIFO depth through platform data.
The 8250 core derives the transmit load from that depth.
Allwinner encodes receive thresholds relative to the FIFO depth: one byte,
quarter-full, half-full and depth minus two. Construct the RX trigger
threshold array on the fly so other FIFO sizes can reuse the same mapping.
For H616 the thresholds are 1, 64, 128 and 254 bytes, with the normal
half-full FCR setting selecting 128 bytes. Use this array for both RX
trigger callbacks and the shared bytes-to-FCR conversion.
Serialize trigger changes with termios through the port mutex. Hold a
runtime PM reference for the register access and the UART port lock while
updating the FCR shadow and hardware. Changing only the trigger field
preserves the FIFO contents; a runtime resume failure leaves both the
shadow and hardware unchanged.
Advertise automatic flow control so CRTSCTS enables MCR.AFCE, matching the
DesignWare termios path's hardware CTS handling.
Select this configuration through the platform setup callback. H616's
debug-divisor and RS485 control registers overlap offsets used to detect
generic DesignWare features. Use the fixed configuration with BUSY-safe
integer divisor programming and software RS485 handling.
Keep the UART clock enabled during termios changes with SKIP_SET_RATE.
Its clock is a gate on the shared APB2 source rather than an independent
baud-rate generator.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
---
drivers/tty/serial/8250/8250_dw.c | 104 ++++++++++++++++++++++++++++++++++++++
1 file changed, 104 insertions(+)
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index a546cf2de7b6..0b0156464af6 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -9,6 +9,7 @@
* LCR is written whilst busy. If it is, then a busy detect interrupt is
* raised, the LCR needs to be rewritten and the uart status register read.
*/
+#include <linux/array_size.h>
#include <linux/bitfield.h>
#include <linux/bits.h>
#include <linux/cleanup.h>
@@ -19,6 +20,7 @@
#include <linux/io.h>
#include <linux/lockdep.h>
#include <linux/module.h>
+#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
@@ -44,6 +46,11 @@
#define RZN1_UART_xDMACR_8_WORD_BURST (2 << 1)
#define RZN1_UART_xDMACR_BLK_SZ(x) ((x) << 3)
+/* Allwinner FIFO-relative receive thresholds */
+#define SUNXI_UART_RXTRIG_QUARTER_DIV 4
+#define SUNXI_UART_RXTRIG_HALF_DIV 2
+#define SUNXI_UART_RXTRIG_FULL_MARGIN 2
+
/* Quirks */
#define DW_UART_QUIRK_OCTEON BIT(0)
#define DW_UART_QUIRK_ARMADA_38X BIT(1)
@@ -63,6 +70,7 @@
struct dw8250_platform_data {
u8 usr_reg;
u32 cpr_value;
+ unsigned int fifo_size;
unsigned int quirks;
int (*setup)(struct uart_port *p);
};
@@ -81,6 +89,7 @@ struct dw8250_data {
unsigned int in_idle:1;
u8 no_int_count;
+ u8 rxtrig_bytes[UART_FCR_R_TRIG_MAX_STATE];
};
static inline struct dw8250_data *to_dw8250_data(struct dw8250_port_data *data)
@@ -652,6 +661,93 @@ static int dw8250_setup(struct uart_port *p)
return dw8250_setup_dma(p);
}
+/* The trigger is the masked FCR receive trigger field, in register position */
+static unsigned int dw8250_sunxi_rxtrig_bytes(struct uart_port *p, unsigned int trigger)
+{
+ switch (trigger) {
+ case UART_FCR_TRIGGER_1:
+ return 1;
+ case UART_FCR_TRIGGER_4:
+ return p->fifosize / SUNXI_UART_RXTRIG_QUARTER_DIV;
+ case UART_FCR_TRIGGER_8:
+ return p->fifosize / SUNXI_UART_RXTRIG_HALF_DIV;
+ default:
+ return p->fifosize - SUNXI_UART_RXTRIG_FULL_MARGIN;
+ }
+}
+
+static int dw8250_sunxi_get_rxtrig(struct uart_port *p)
+{
+ struct dw8250_data *data = to_dw8250_data(p->private_data);
+ struct uart_8250_port *up = up_to_u8250p(p);
+
+ guard(uart_port_lock_irqsave)(p);
+
+ return data->rxtrig_bytes[UART_FCR_R_TRIG_BITS(up->fcr)];
+}
+
+static int dw8250_sunxi_set_rxtrig(struct uart_port *p, unsigned char bytes)
+{
+ struct dw8250_data *data = to_dw8250_data(p->private_data);
+ struct uart_8250_port *up = up_to_u8250p(p);
+ int fcr, ret;
+
+ fcr = serial8250_bytes_to_fcr(data->rxtrig_bytes, bytes);
+ if (fcr < 0)
+ return fcr;
+
+ guard(mutex)(&p->state->port.mutex);
+
+ PM_RUNTIME_ACQUIRE_IF_ENABLED(p->dev, pm);
+ ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+ if (ret)
+ return ret;
+
+ guard(uart_port_lock_irqsave)(p);
+
+ up->fcr &= ~UART_FCR_TRIGGER_MASK;
+ up->fcr |= fcr;
+ /* Changing the trigger alone preserves the FIFO contents */
+ serial_port_out(p, UART_FCR, up->fcr);
+
+ return 0;
+}
+
+static void dw8250_sunxi_setup_rxtrig(struct uart_port *p)
+{
+ struct dw8250_data *data = to_dw8250_data(p->private_data);
+
+ /* Allwinner RX thresholds differ from the standard 16550A table */
+ for (unsigned int i = 0; i < ARRAY_SIZE(data->rxtrig_bytes); i++) {
+ unsigned int trigger = FIELD_PREP(UART_FCR_TRIGGER_MASK, i);
+
+ data->rxtrig_bytes[i] = dw8250_sunxi_rxtrig_bytes(p, trigger);
+ }
+ p->get_rxtrig = dw8250_sunxi_get_rxtrig;
+ p->set_rxtrig = dw8250_sunxi_set_rxtrig;
+}
+
+static int dw8250_sunxi_setup(struct uart_port *p)
+{
+ struct dw8250_data *data = to_dw8250_data(p->private_data);
+ struct uart_8250_port *up = up_to_u8250p(p);
+
+ p->type = PORT_16550A;
+ p->flags |= UPF_FIXED_TYPE;
+ p->fifosize = data->pdata->fifo_size;
+ up->capabilities = UART_CAP_FIFO | UART_CAP_NOTEMT | UART_CAP_AFE;
+
+ dw8250_sunxi_setup_rxtrig(p);
+
+ /* Use software RS485 with the Allwinner register layout */
+ p->rs485_config = serial8250_em485_config;
+ p->rs485_supported = serial8250_em485_supported;
+ up->rs485_start_tx = serial8250_em485_start_tx;
+ up->rs485_stop_tx = serial8250_em485_stop_tx;
+
+ return 0;
+}
+
static int dw8250_probe(struct platform_device *pdev)
{
struct uart_8250_port uart = {}, *up = &uart;
@@ -875,6 +971,13 @@ static const struct dw8250_platform_data dw8250_dw_apb = {
.usr_reg = DW_UART_USR,
};
+static const struct dw8250_platform_data dw8250_h616_data = {
+ .usr_reg = DW_UART_USR,
+ .fifo_size = 256,
+ .quirks = DW_UART_QUIRK_SKIP_SET_RATE,
+ .setup = dw8250_sunxi_setup,
+};
+
static const struct dw8250_platform_data dw8250_octeon_3860_data = {
.usr_reg = OCTEON_UART_USR,
.quirks = DW_UART_QUIRK_OCTEON,
@@ -926,6 +1029,7 @@ static const struct dw8250_platform_data dw8250_tda54 = {
static const struct of_device_id dw8250_of_match[] = {
{ .compatible = "snps,dw-apb-uart", .data = &dw8250_dw_apb },
+ { .compatible = "allwinner,sun50i-h616-uart", .data = &dw8250_h616_data },
{ .compatible = "cavium,octeon-3860-uart", .data = &dw8250_octeon_3860_data },
{ .compatible = "marvell,armada-38x-uart", .data = &dw8250_armada_38x_data },
{ .compatible = "renesas,rzn1-uart", .data = &dw8250_renesas_rzn1_data },
--
2.53.0
^ permalink raw reply related [flat|nested] 21+ messages in thread* Re: [PATCH v6 4/8] serial: 8250_dw: configure the Allwinner H616 UART
2026-11-02 19:55 ` [PATCH v6 4/8] serial: 8250_dw: configure the Allwinner H616 UART James Hilliard
@ 2026-11-02 20:18 ` sashiko-bot
2026-11-03 12:03 ` Andy Shevchenko
1 sibling, 0 replies; 21+ messages in thread
From: sashiko-bot @ 2026-11-02 20:18 UTC (permalink / raw)
To: James Hilliard; +Cc: linux-serial
> H616 has 256-byte transmit and receive FIFOs, but its optional DesignWare
> component parameter register reads as zero. Generic 16550 probing leaves
> the port using the 16-byte FIFO configuration and its trigger-level table.
>
> Keep PORT_16550A and supply H616's fixed FIFO depth through platform data.
> The 8250 core derives the transmit load from that depth.
>
> Allwinner encodes receive thresholds relative to the FIFO depth: one byte,
> quarter-full, half-full and depth minus two. Construct the RX trigger
> threshold array on the fly so other FIFO sizes can reuse the same mapping.
> For H616 the thresholds are 1, 64, 128 and 254 bytes, with the normal
> half-full FCR setting selecting 128 bytes. Use this array for both RX
> trigger callbacks and the shared bytes-to-FCR conversion.
>
> Serialize trigger changes with termios through the port mutex. Hold a
> [ ... ]
> Keep the UART clock enabled during termios changes with SKIP_SET_RATE.
> Its clock is a gate on the shared APB2 source rather than an independent
> baud-rate generator.
>
> Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Sashiko has reviewed this patch and found no issues.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261102-submit-h616-uart-fifo-v1-v6-0-25afcb346b0c@gmail.com?part=4
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v6 4/8] serial: 8250_dw: configure the Allwinner H616 UART
2026-11-02 19:55 ` [PATCH v6 4/8] serial: 8250_dw: configure the Allwinner H616 UART James Hilliard
2026-11-02 20:18 ` sashiko-bot
@ 2026-11-03 12:03 ` Andy Shevchenko
1 sibling, 0 replies; 21+ messages in thread
From: Andy Shevchenko @ 2026-11-03 12:03 UTC (permalink / raw)
To: James Hilliard
Cc: Ilpo Järvinen, Greg Kroah-Hartman, Jiri Slaby, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai, Jernej Skrabec,
Samuel Holland, linux-kernel, linux-serial, devicetree,
linux-arm-kernel, linux-sunxi
On Mon, Nov 02, 2026 at 12:55:19PM -0700, James Hilliard wrote:
> H616 has 256-byte transmit and receive FIFOs, but its optional DesignWare
> component parameter register reads as zero. Generic 16550 probing leaves
> the port using the 16-byte FIFO configuration and its trigger-level table.
>
> Keep PORT_16550A and supply H616's fixed FIFO depth through platform data.
> The 8250 core derives the transmit load from that depth.
>
> Allwinner encodes receive thresholds relative to the FIFO depth: one byte,
> quarter-full, half-full and depth minus two. Construct the RX trigger
> threshold array on the fly so other FIFO sizes can reuse the same mapping.
> For H616 the thresholds are 1, 64, 128 and 254 bytes, with the normal
> half-full FCR setting selecting 128 bytes. Use this array for both RX
> trigger callbacks and the shared bytes-to-FCR conversion.
>
> Serialize trigger changes with termios through the port mutex. Hold a
> runtime PM reference for the register access and the UART port lock while
> updating the FCR shadow and hardware. Changing only the trigger field
> preserves the FIFO contents; a runtime resume failure leaves both the
> shadow and hardware unchanged.
>
> Advertise automatic flow control so CRTSCTS enables MCR.AFCE, matching the
> DesignWare termios path's hardware CTS handling.
>
> Select this configuration through the platform setup callback. H616's
> debug-divisor and RS485 control registers overlap offsets used to detect
> generic DesignWare features. Use the fixed configuration with BUSY-safe
> integer divisor programming and software RS485 handling.
>
> Keep the UART clock enabled during termios changes with SKIP_SET_RATE.
> Its clock is a gate on the shared APB2 source rather than an independent
> baud-rate generator.
I'm not sure I followed previous discussion, but as far as I get it Ilpo
mentioned the possibility to have that FIFO trigger threshold helper to be
available on 8250_dw level (meaning dwlib). Or was it decided against this?
...
> +static int dw8250_sunxi_set_rxtrig(struct uart_port *p, unsigned char bytes)
> +{
> + struct dw8250_data *data = to_dw8250_data(p->private_data);
> + struct uart_8250_port *up = up_to_u8250p(p);
> + int fcr, ret;
> +
> + fcr = serial8250_bytes_to_fcr(data->rxtrig_bytes, bytes);
> + if (fcr < 0)
> + return fcr;
> +
> + guard(mutex)(&p->state->port.mutex);
> +
> + PM_RUNTIME_ACQUIRE_IF_ENABLED(p->dev, pm);
> + ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
> + if (ret)
> + return ret;
> +
> + guard(uart_port_lock_irqsave)(p);
> + up->fcr &= ~UART_FCR_TRIGGER_MASK;
> + up->fcr |= fcr;
up->fcr = (up->fcr & ~UART_FCR_TRIGGER_MASK) | fcr;
(as is also okay)?
> + /* Changing the trigger alone preserves the FIFO contents */
> + serial_port_out(p, UART_FCR, up->fcr);
> +
> + return 0;
> +}
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v6 5/8] arm64: dts: allwinner: h616: describe the UART integration
2026-11-02 19:55 [PATCH v6 0/8] serial: 8250_dw: describe the Allwinner H616 and A523 UART configurations James Hilliard
` (3 preceding siblings ...)
2026-11-02 19:55 ` [PATCH v6 4/8] serial: 8250_dw: configure the Allwinner H616 UART James Hilliard
@ 2026-11-02 19:55 ` James Hilliard
2026-11-02 20:22 ` sashiko-bot
2026-11-02 19:55 ` [PATCH v6 6/8] dt-bindings: serial: snps-dw-apb-uart: add Allwinner A523 James Hilliard
` (2 subsequent siblings)
7 siblings, 1 reply; 21+ messages in thread
From: James Hilliard @ 2026-11-02 19:55 UTC (permalink / raw)
To: Andy Shevchenko, Ilpo Järvinen, Greg Kroah-Hartman,
Jiri Slaby, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Chen-Yu Tsai, Jernej Skrabec, Samuel Holland
Cc: linux-kernel, linux-serial, devicetree, linux-arm-kernel,
linux-sunxi, James Hilliard
Identify the H616 UART integration on each of the six controllers. The
specific compatible describes the fixed FIFO capacity, register layout
and receive-trigger mapping.
Retain snps,dw-apb-uart as the generic fallback. H618 includes this DTSI
and uses the same UART integration.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
---
arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
index c6b3a3f8359a..b4b2f85726e0 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
@@ -550,7 +550,7 @@ mmc2: mmc@4022000 {
};
uart0: serial@5000000 {
- compatible = "snps,dw-apb-uart";
+ compatible = "allwinner,sun50i-h616-uart", "snps,dw-apb-uart";
reg = <0x05000000 0x400>;
interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
reg-shift = <2>;
@@ -563,7 +563,7 @@ uart0: serial@5000000 {
};
uart1: serial@5000400 {
- compatible = "snps,dw-apb-uart";
+ compatible = "allwinner,sun50i-h616-uart", "snps,dw-apb-uart";
reg = <0x05000400 0x400>;
interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
reg-shift = <2>;
@@ -576,7 +576,7 @@ uart1: serial@5000400 {
};
uart2: serial@5000800 {
- compatible = "snps,dw-apb-uart";
+ compatible = "allwinner,sun50i-h616-uart", "snps,dw-apb-uart";
reg = <0x05000800 0x400>;
interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
reg-shift = <2>;
@@ -589,7 +589,7 @@ uart2: serial@5000800 {
};
uart3: serial@5000c00 {
- compatible = "snps,dw-apb-uart";
+ compatible = "allwinner,sun50i-h616-uart", "snps,dw-apb-uart";
reg = <0x05000c00 0x400>;
interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
reg-shift = <2>;
@@ -602,7 +602,7 @@ uart3: serial@5000c00 {
};
uart4: serial@5001000 {
- compatible = "snps,dw-apb-uart";
+ compatible = "allwinner,sun50i-h616-uart", "snps,dw-apb-uart";
reg = <0x05001000 0x400>;
interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
reg-shift = <2>;
@@ -615,7 +615,7 @@ uart4: serial@5001000 {
};
uart5: serial@5001400 {
- compatible = "snps,dw-apb-uart";
+ compatible = "allwinner,sun50i-h616-uart", "snps,dw-apb-uart";
reg = <0x05001400 0x400>;
interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
reg-shift = <2>;
--
2.53.0
^ permalink raw reply related [flat|nested] 21+ messages in thread* [PATCH v6 6/8] dt-bindings: serial: snps-dw-apb-uart: add Allwinner A523
2026-11-02 19:55 [PATCH v6 0/8] serial: 8250_dw: describe the Allwinner H616 and A523 UART configurations James Hilliard
` (4 preceding siblings ...)
2026-11-02 19:55 ` [PATCH v6 5/8] arm64: dts: allwinner: h616: describe the UART integration James Hilliard
@ 2026-11-02 19:55 ` James Hilliard
2026-11-02 20:26 ` sashiko-bot
2026-11-02 19:55 ` [PATCH v6 7/8] serial: 8250_dw: discover Allwinner A523 FIFO depths through FCC James Hilliard
2026-11-02 19:55 ` [PATCH v6 8/8] arm64: dts: allwinner: a523: describe the UART integration James Hilliard
7 siblings, 1 reply; 21+ messages in thread
From: James Hilliard @ 2026-11-02 19:55 UTC (permalink / raw)
To: Andy Shevchenko, Ilpo Järvinen, Greg Kroah-Hartman,
Jiri Slaby, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Chen-Yu Tsai, Jernej Skrabec, Samuel Holland
Cc: linux-kernel, linux-serial, devicetree, linux-arm-kernel,
linux-sunxi, James Hilliard, Krzysztof Kozlowski
The A523 UART integration has different FIFO depths across its controllers
and reports each controller's depth in the FIFO Clock Control register.
Its receive thresholds are fractions of that depth, and its optional
register layout differs from the generic DesignWare integration.
Add a compatible for this integration, also used by A527 and T527, with
snps,dw-apb-uart as a fallback.
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
---
Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
index fc1289073241..ea6ce99178e3 100644
--- a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
+++ b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
@@ -61,6 +61,7 @@ properties:
- items:
- enum:
- allwinner,sun50i-h616-uart
+ - allwinner,sun55i-a523-uart
- anlogic,dr1v90-uart
- brcm,bcm11351-dw-apb-uart
- brcm,bcm21664-dw-apb-uart
--
2.53.0
^ permalink raw reply related [flat|nested] 21+ messages in thread* [PATCH v6 7/8] serial: 8250_dw: discover Allwinner A523 FIFO depths through FCC
2026-11-02 19:55 [PATCH v6 0/8] serial: 8250_dw: describe the Allwinner H616 and A523 UART configurations James Hilliard
` (5 preceding siblings ...)
2026-11-02 19:55 ` [PATCH v6 6/8] dt-bindings: serial: snps-dw-apb-uart: add Allwinner A523 James Hilliard
@ 2026-11-02 19:55 ` James Hilliard
2026-11-02 20:29 ` sashiko-bot
2026-11-03 12:09 ` Andy Shevchenko
2026-11-02 19:55 ` [PATCH v6 8/8] arm64: dts: allwinner: a523: describe the UART integration James Hilliard
7 siblings, 2 replies; 21+ messages in thread
From: James Hilliard @ 2026-11-02 19:55 UTC (permalink / raw)
To: Andy Shevchenko, Ilpo Järvinen, Greg Kroah-Hartman,
Jiri Slaby, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Chen-Yu Tsai, Jernej Skrabec, Samuel Holland
Cc: linux-kernel, linux-serial, devicetree, linux-arm-kernel,
linux-sunxi, James Hilliard
The A523 UART integration, also used by A527 and T527, has 64-byte FIFOs
on UART0 and 128-byte FIFOs on UART1 through UART7. Each controller reports
its TX/RX FIFO depth in bits 31:8 of the FIFO Clock Control register at
offset 0xf0. The field holds a byte count, not a logarithmic encoding.
Read this field in the sunxi setup callback when platform data does not
provide a fixed FIFO size. A fixed size takes precedence, so H616 retains
its 256-byte configuration without accessing FCC. The probe has already
enabled the clocks and deasserted reset before invoking the callback.
Leave the FIFO clock-control bits untouched.
Validate the depth before generating the RX trigger table or setting the
transmit load. The quarter-full threshold must be positive and the
FIFO-depth-minus-two threshold must fit in the byte-sized table and RX
trigger API. Report an invalid depth and fail probe instead of generating
zero or truncated thresholds. This bound follows the current 8250
table and callback types, not a hardware FIFO-capacity limit; support
for larger thresholds would require widening that interface.
Select this setup for the A523 compatible. Derive the transmit load and
RX threshold table from the discovered depth using the common sunxi
helpers. This handles the different FIFO sizes with one compatible and
one receive-trigger mapping.
Like H616, this integration has Allwinner-specific debug-divisor and
RS485 registers overlapping the generic DesignWare feature probes. Use
the common sunxi PIO setup, BUSY-safe integer divisor programming and
software RS485 handling. Keep the APB clock gate enabled during termios
updates with SKIP_SET_RATE.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
---
drivers/tty/serial/8250/8250_dw.c | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index 0b0156464af6..0ed50d9515e7 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -18,6 +18,7 @@
#include <linux/device.h>
#include <linux/err.h>
#include <linux/io.h>
+#include <linux/limits.h>
#include <linux/lockdep.h>
#include <linux/module.h>
#include <linux/mutex.h>
@@ -51,6 +52,10 @@
#define SUNXI_UART_RXTRIG_HALF_DIV 2
#define SUNXI_UART_RXTRIG_FULL_MARGIN 2
+/* Allwinner FIFO Clock Control register */
+#define SUNXI_UART_FCC 0xf0
+#define SUNXI_UART_FCC_FIFO_DEPTH GENMASK(31, 8)
+
/* Quirks */
#define DW_UART_QUIRK_OCTEON BIT(0)
#define DW_UART_QUIRK_ARMADA_38X BIT(1)
@@ -70,6 +75,7 @@
struct dw8250_platform_data {
u8 usr_reg;
u32 cpr_value;
+ /* Fixed FIFO depth; zero selects discovery during setup */
unsigned int fifo_size;
unsigned int quirks;
int (*setup)(struct uart_port *p);
@@ -735,6 +741,20 @@ static int dw8250_sunxi_setup(struct uart_port *p)
p->type = PORT_16550A;
p->flags |= UPF_FIXED_TYPE;
p->fifosize = data->pdata->fifo_size;
+ if (!p->fifosize) {
+ u32 fcc = dw8250_readl_ext(p, SUNXI_UART_FCC);
+
+ p->fifosize = FIELD_GET(SUNXI_UART_FCC_FIFO_DEPTH, fcc);
+ }
+ /*
+ * The byte-sized 8250 RX trigger interface requires positive,
+ * representable thresholds. Larger thresholds require widening it.
+ */
+ if (p->fifosize < SUNXI_UART_RXTRIG_QUARTER_DIV ||
+ p->fifosize - SUNXI_UART_RXTRIG_FULL_MARGIN > U8_MAX)
+ return dev_err_probe(p->dev, -EINVAL,
+ "invalid FIFO size %u\n", p->fifosize);
+
up->capabilities = UART_CAP_FIFO | UART_CAP_NOTEMT | UART_CAP_AFE;
dw8250_sunxi_setup_rxtrig(p);
@@ -978,6 +998,12 @@ static const struct dw8250_platform_data dw8250_h616_data = {
.setup = dw8250_sunxi_setup,
};
+static const struct dw8250_platform_data dw8250_a523_data = {
+ .usr_reg = DW_UART_USR,
+ .quirks = DW_UART_QUIRK_SKIP_SET_RATE,
+ .setup = dw8250_sunxi_setup,
+};
+
static const struct dw8250_platform_data dw8250_octeon_3860_data = {
.usr_reg = OCTEON_UART_USR,
.quirks = DW_UART_QUIRK_OCTEON,
@@ -1030,6 +1056,7 @@ static const struct dw8250_platform_data dw8250_tda54 = {
static const struct of_device_id dw8250_of_match[] = {
{ .compatible = "snps,dw-apb-uart", .data = &dw8250_dw_apb },
{ .compatible = "allwinner,sun50i-h616-uart", .data = &dw8250_h616_data },
+ { .compatible = "allwinner,sun55i-a523-uart", .data = &dw8250_a523_data },
{ .compatible = "cavium,octeon-3860-uart", .data = &dw8250_octeon_3860_data },
{ .compatible = "marvell,armada-38x-uart", .data = &dw8250_armada_38x_data },
{ .compatible = "renesas,rzn1-uart", .data = &dw8250_renesas_rzn1_data },
--
2.53.0
^ permalink raw reply related [flat|nested] 21+ messages in thread* Re: [PATCH v6 7/8] serial: 8250_dw: discover Allwinner A523 FIFO depths through FCC
2026-11-02 19:55 ` [PATCH v6 7/8] serial: 8250_dw: discover Allwinner A523 FIFO depths through FCC James Hilliard
@ 2026-11-02 20:29 ` sashiko-bot
2026-11-03 12:09 ` Andy Shevchenko
1 sibling, 0 replies; 21+ messages in thread
From: sashiko-bot @ 2026-11-02 20:29 UTC (permalink / raw)
To: James Hilliard; +Cc: linux-serial
> The A523 UART integration, also used by A527 and T527, has 64-byte FIFOs
> on UART0 and 128-byte FIFOs on UART1 through UART7. Each controller reports
> its TX/RX FIFO depth in bits 31:8 of the FIFO Clock Control register at
> offset 0xf0. The field holds a byte count, not a logarithmic encoding.
>
> Read this field in the sunxi setup callback when platform data does not
> provide a fixed FIFO size. A fixed size takes precedence, so H616 retains
> its 256-byte configuration without accessing FCC. The probe has already
> enabled the clocks and deasserted reset before invoking the callback.
> Leave the FIFO clock-control bits untouched.
>
> Validate the depth before generating the RX trigger table or setting the
> transmit load. The quarter-full threshold must be positive and the
> FIFO-depth-minus-two threshold must fit in the byte-sized table and RX
> trigger API. Report an invalid depth and fail probe instead of generating
> [ ... ]
> the common sunxi PIO setup, BUSY-safe integer divisor programming and
> software RS485 handling. Keep the APB clock gate enabled during termios
> updates with SKIP_SET_RATE.
>
> Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Sashiko has reviewed this patch and found no issues.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261102-submit-h616-uart-fifo-v1-v6-0-25afcb346b0c@gmail.com?part=7
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v6 7/8] serial: 8250_dw: discover Allwinner A523 FIFO depths through FCC
2026-11-02 19:55 ` [PATCH v6 7/8] serial: 8250_dw: discover Allwinner A523 FIFO depths through FCC James Hilliard
2026-11-02 20:29 ` sashiko-bot
@ 2026-11-03 12:09 ` Andy Shevchenko
1 sibling, 0 replies; 21+ messages in thread
From: Andy Shevchenko @ 2026-11-03 12:09 UTC (permalink / raw)
To: James Hilliard
Cc: Ilpo Järvinen, Greg Kroah-Hartman, Jiri Slaby, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai, Jernej Skrabec,
Samuel Holland, linux-kernel, linux-serial, devicetree,
linux-arm-kernel, linux-sunxi
On Mon, Nov 02, 2026 at 12:55:22PM -0700, James Hilliard wrote:
> The A523 UART integration, also used by A527 and T527, has 64-byte FIFOs
> on UART0 and 128-byte FIFOs on UART1 through UART7. Each controller reports
> its TX/RX FIFO depth in bits 31:8 of the FIFO Clock Control register at
> offset 0xf0. The field holds a byte count, not a logarithmic encoding.
>
> Read this field in the sunxi setup callback when platform data does not
> provide a fixed FIFO size. A fixed size takes precedence, so H616 retains
> its 256-byte configuration without accessing FCC. The probe has already
> enabled the clocks and deasserted reset before invoking the callback.
> Leave the FIFO clock-control bits untouched.
>
> Validate the depth before generating the RX trigger table or setting the
> transmit load. The quarter-full threshold must be positive and the
> FIFO-depth-minus-two threshold must fit in the byte-sized table and RX
> trigger API. Report an invalid depth and fail probe instead of generating
> zero or truncated thresholds. This bound follows the current 8250
> table and callback types, not a hardware FIFO-capacity limit; support
> for larger thresholds would require widening that interface.
>
> Select this setup for the A523 compatible. Derive the transmit load and
> RX threshold table from the discovered depth using the common sunxi
> helpers. This handles the different FIFO sizes with one compatible and
> one receive-trigger mapping.
>
> Like H616, this integration has Allwinner-specific debug-divisor and
> RS485 registers overlapping the generic DesignWare feature probes. Use
> the common sunxi PIO setup, BUSY-safe integer divisor programming and
> software RS485 handling. Keep the APB clock gate enabled during termios
> updates with SKIP_SET_RATE.
...
> struct dw8250_platform_data {
> u8 usr_reg;
> u32 cpr_value;
> + /* Fixed FIFO depth; zero selects discovery during setup */
But make the code clearer in this sense.
> unsigned int fifo_size;
> unsigned int quirks;
I'm wondering if we can encode the FIFO size (as power-of-2) into quirks,
but this might be harder to follow in the code.
> int (*setup)(struct uart_port *p);
> p->fifosize = data->pdata->fifo_size;
> + if (!p->fifosize) {
> + u32 fcc = dw8250_readl_ext(p, SUNXI_UART_FCC);
> +
> + p->fifosize = FIELD_GET(SUNXI_UART_FCC_FIFO_DEPTH, fcc);
> + }
if (data->pdata->fifo_size) {
p->fifosize = data->pdata->fifo_size;
} else {
u32 fcc = dw8250_readl_ext(p, SUNXI_UART_FCC);
p->fifosize = FIELD_GET(SUNXI_UART_FCC_FIFO_DEPTH, fcc);
}
> + /*
> + * The byte-sized 8250 RX trigger interface requires positive,
> + * representable thresholds. Larger thresholds require widening it.
> + */
> + if (p->fifosize < SUNXI_UART_RXTRIG_QUARTER_DIV ||
> + p->fifosize - SUNXI_UART_RXTRIG_FULL_MARGIN > U8_MAX)
> + return dev_err_probe(p->dev, -EINVAL,
> + "invalid FIFO size %u\n", p->fifosize);
> +
> up->capabilities = UART_CAP_FIFO | UART_CAP_NOTEMT | UART_CAP_AFE;
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v6 8/8] arm64: dts: allwinner: a523: describe the UART integration
2026-11-02 19:55 [PATCH v6 0/8] serial: 8250_dw: describe the Allwinner H616 and A523 UART configurations James Hilliard
` (6 preceding siblings ...)
2026-11-02 19:55 ` [PATCH v6 7/8] serial: 8250_dw: discover Allwinner A523 FIFO depths through FCC James Hilliard
@ 2026-11-02 19:55 ` James Hilliard
2026-11-02 20:33 ` sashiko-bot
7 siblings, 1 reply; 21+ messages in thread
From: James Hilliard @ 2026-11-02 19:55 UTC (permalink / raw)
To: Andy Shevchenko, Ilpo Järvinen, Greg Kroah-Hartman,
Jiri Slaby, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Chen-Yu Tsai, Jernej Skrabec, Samuel Holland
Cc: linux-kernel, linux-serial, devicetree, linux-arm-kernel,
linux-sunxi, James Hilliard
Identify the Allwinner UART integration on all eight CPUX controllers.
The specific compatible selects FIFO-depth discovery through FCC and the
Allwinner receive-trigger mapping. Each controller supplies its own depth,
so the same compatible covers the different FIFO capacities.
Retain snps,dw-apb-uart as a fallback. The common SoC description supplies
these UART nodes to the A527 and T527 boards as well.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
---
arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi b/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi
index 85ef492ffeae..23340b9f58cb 100644
--- a/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi
@@ -390,7 +390,7 @@ wdt: watchdog@2050000 {
};
uart0: serial@2500000 {
- compatible = "snps,dw-apb-uart";
+ compatible = "allwinner,sun55i-a523-uart", "snps,dw-apb-uart";
reg = <0x02500000 0x400>;
interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
reg-shift = <2>;
@@ -403,7 +403,7 @@ uart0: serial@2500000 {
};
uart1: serial@2500400 {
- compatible = "snps,dw-apb-uart";
+ compatible = "allwinner,sun55i-a523-uart", "snps,dw-apb-uart";
reg = <0x02500400 0x400>;
interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
reg-shift = <2>;
@@ -416,7 +416,7 @@ uart1: serial@2500400 {
};
uart2: serial@2500800 {
- compatible = "snps,dw-apb-uart";
+ compatible = "allwinner,sun55i-a523-uart", "snps,dw-apb-uart";
reg = <0x02500800 0x400>;
interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
reg-shift = <2>;
@@ -429,7 +429,7 @@ uart2: serial@2500800 {
};
uart3: serial@2500c00 {
- compatible = "snps,dw-apb-uart";
+ compatible = "allwinner,sun55i-a523-uart", "snps,dw-apb-uart";
reg = <0x02500c00 0x400>;
interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
reg-shift = <2>;
@@ -442,7 +442,7 @@ uart3: serial@2500c00 {
};
uart4: serial@2501000 {
- compatible = "snps,dw-apb-uart";
+ compatible = "allwinner,sun55i-a523-uart", "snps,dw-apb-uart";
reg = <0x02501000 0x400>;
interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
reg-shift = <2>;
@@ -455,7 +455,7 @@ uart4: serial@2501000 {
};
uart5: serial@2501400 {
- compatible = "snps,dw-apb-uart";
+ compatible = "allwinner,sun55i-a523-uart", "snps,dw-apb-uart";
reg = <0x02501400 0x400>;
interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
reg-shift = <2>;
@@ -468,7 +468,7 @@ uart5: serial@2501400 {
};
uart6: serial@2501800 {
- compatible = "snps,dw-apb-uart";
+ compatible = "allwinner,sun55i-a523-uart", "snps,dw-apb-uart";
reg = <0x02501800 0x400>;
interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
reg-shift = <2>;
@@ -481,7 +481,7 @@ uart6: serial@2501800 {
};
uart7: serial@2501c00 {
- compatible = "snps,dw-apb-uart";
+ compatible = "allwinner,sun55i-a523-uart", "snps,dw-apb-uart";
reg = <0x02501c00 0x400>;
interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
reg-shift = <2>;
--
2.53.0
^ permalink raw reply related [flat|nested] 21+ messages in thread