AR934x chips also got the 'old' qca,ar9330-uart in addition to the
'new' ns16550a compatible one. Add support for UART1 clock selector as
well as device-tree bindings in ar934x.dtsi to make use of that uart.
Diff'ing the drivers showed that the only difference is that AR934x
requires setting UART1_CS_TX_READY_ORIDE and UART1_CS_RX_READY_ORIDE
registers which seems to be unneeded on AR933x (probably because it's
already set by the bootloader which on AR934x typically uses the
NS16550-compatible UART and hence doesn't touch those registers).
Without those registers set, the UART will not function without
hardware flow-control being enabled (which is not an option as
RTS/CTS pins may not be assigned).

Reported-by: Piotr Dymacz <pep...@gmail.com>
Signed-off-by: Daniel Golle <dan...@makrotopia.org>
---
 target/linux/ath79/dts/ar934x.dtsi            |  17 +++
 ...S-ath79-export-UART1-reference-clock.patch |  52 +++++++
 ...40-tty-serial-ar933x-uart-add-ar934x.patch | 128 ++++++++++++++++++
 3 files changed, 197 insertions(+)
 create mode 100644 
target/linux/ath79/patches-4.19/0039-MIPS-ath79-export-UART1-reference-clock.patch
 create mode 100644 
target/linux/ath79/patches-4.19/0040-tty-serial-ar933x-uart-add-ar934x.patch

diff --git a/target/linux/ath79/dts/ar934x.dtsi 
b/target/linux/ath79/dts/ar934x.dtsi
index 8cd0b4e086..d90d823884 100644
--- a/target/linux/ath79/dts/ar934x.dtsi
+++ b/target/linux/ath79/dts/ar934x.dtsi
@@ -133,8 +133,25 @@
 
                                #reset-cells = <1>;
                        };
+
+                       hs_uart: uart@18500000 {
+                               compatible = "qca,ar9341-uart";
+                               reg = <0x18500000 0x14>;
+
+                               interrupts = <6>;
+                               interrupt-parent = <&miscintc>;
+
+                               clocks = <&pll ATH79_CLK_UART1>;
+                               clock-names = "uart";
+
+                               resets = <&rst 17>;
+                               reset-names = "uart";
+
+                               status = "disabled";
+                       };
                };
 
+
                nand: nand@1b000200 {
                        compatible = "qca,ar934x-nand";
                        reg = <0x1b000200 0xb8>;
diff --git 
a/target/linux/ath79/patches-4.19/0039-MIPS-ath79-export-UART1-reference-clock.patch
 
b/target/linux/ath79/patches-4.19/0039-MIPS-ath79-export-UART1-reference-clock.patch
new file mode 100644
index 0000000000..8656fafe0e
--- /dev/null
+++ 
b/target/linux/ath79/patches-4.19/0039-MIPS-ath79-export-UART1-reference-clock.patch
@@ -0,0 +1,52 @@
+--- a/arch/mips/ath79/clock.c
++++ b/arch/mips/ath79/clock.c
+@@ -42,6 +42,7 @@ static const char * const clk_names[ATH7
+       [ATH79_CLK_AHB] = "ahb",
+       [ATH79_CLK_REF] = "ref",
+       [ATH79_CLK_MDIO] = "mdio",
++      [ATH79_CLK_UART1] = "uart1",
+ };
+ 
+ static const char * __init ath79_clk_name(int type)
+@@ -346,6 +347,9 @@ static void __init ar934x_clocks_init(vo
+       if (clk_ctrl & AR934X_PLL_SWITCH_CLOCK_CONTROL_MDIO_CLK_SEL)
+               ath79_set_clk(ATH79_CLK_MDIO, 100 * 1000 * 1000);
+ 
++      if (clk_ctrl & AR934X_PLL_SWITCH_CLOCK_CONTROL_UART1_CLK_SEL)
++              ath79_set_clk(ATH79_CLK_UART1, 100 * 1000 * 1000);
++
+       iounmap(dpll_base);
+ }
+ 
+@@ -651,6 +655,9 @@ static void __init ath79_clocks_init_dt(
+       if (!clks[ATH79_CLK_MDIO])
+               clks[ATH79_CLK_MDIO] = clks[ATH79_CLK_REF];
+ 
++      if (!clks[ATH79_CLK_UART1])
++              clks[ATH79_CLK_UART1] = clks[ATH79_CLK_REF];
++
+       if (of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data)) {
+               pr_err("%pOF: could not register clk provider\n", np);
+               goto err_iounmap;
+--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
++++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
+@@ -351,6 +351,7 @@
+ #define AR934X_PLL_CPU_DDR_CLK_CTRL_AHBCLK_FROM_DDRPLL        BIT(24)
+ 
+ #define AR934X_PLL_SWITCH_CLOCK_CONTROL_MDIO_CLK_SEL  BIT(6)
++#define AR934X_PLL_SWITCH_CLOCK_CONTROL_UART1_CLK_SEL BIT(7)
+ 
+ #define QCA953X_PLL_CPU_CONFIG_REG            0x00
+ #define QCA953X_PLL_DDR_CONFIG_REG            0x04
+--- a/include/dt-bindings/clock/ath79-clk.h
++++ b/include/dt-bindings/clock/ath79-clk.h
+@@ -15,7 +15,8 @@
+ #define ATH79_CLK_AHB         2
+ #define ATH79_CLK_REF         3
+ #define ATH79_CLK_MDIO                4
++#define ATH79_CLK_UART1               5
+ 
+-#define ATH79_CLK_END         5
++#define ATH79_CLK_END         6
+ 
+ #endif /* __DT_BINDINGS_ATH79_CLK_H */
diff --git 
a/target/linux/ath79/patches-4.19/0040-tty-serial-ar933x-uart-add-ar934x.patch 
b/target/linux/ath79/patches-4.19/0040-tty-serial-ar933x-uart-add-ar934x.patch
new file mode 100644
index 0000000000..f8f0ffbea1
--- /dev/null
+++ 
b/target/linux/ath79/patches-4.19/0040-tty-serial-ar933x-uart-add-ar934x.patch
@@ -0,0 +1,128 @@
+Index: linux-4.19.98/drivers/tty/serial/ar933x_uart.c
+===================================================================
+--- linux-4.19.98.orig/drivers/tty/serial/ar933x_uart.c
++++ linux-4.19.98/drivers/tty/serial/ar933x_uart.c
+@@ -39,6 +39,9 @@
+ 
+ #define AR933X_DUMMY_STATUS_RD        0x01
+ 
++#define UART_IS_AR9330 0
++#define UART_IS_AR9341 1
++
+ static struct uart_driver ar933x_uart_driver;
+ 
+ struct ar933x_uart_port {
+@@ -46,6 +49,7 @@ struct ar933x_uart_port {
+       unsigned int            ier;    /* shadow Interrupt Enable Register */
+       unsigned int            min_baud;
+       unsigned int            max_baud;
++      unsigned int            subtype;
+       struct clk              *clk;
+ };
+ 
+@@ -286,6 +290,15 @@ static void ar933x_uart_set_termios(stru
+       ar933x_uart_rmw_set(up, AR933X_UART_CS_REG,
+                           AR933X_UART_CS_HOST_INT_EN);
+ 
++      if (up->subtype == UART_IS_AR9341) {
++              /* enable TX ready overide */
++              ar933x_uart_rmw_set(up, AR933X_UART_CS_REG,
++                      AR933X_UART_CS_TX_READY_ORIDE);
++              /* enable RX ready overide */
++              ar933x_uart_rmw_set(up, AR933X_UART_CS_REG,
++                      AR933X_UART_CS_RX_READY_ORIDE);
++      }
++
+       /* reenable the UART */
+       ar933x_uart_rmw(up, AR933X_UART_CS_REG,
+                       AR933X_UART_CS_IF_MODE_M << AR933X_UART_CS_IF_MODE_S,
+@@ -418,6 +431,12 @@ static int ar933x_uart_startup(struct ua
+       ar933x_uart_rmw_set(up, AR933X_UART_CS_REG,
+                           AR933X_UART_CS_HOST_INT_EN);
+ 
++      if (up->subtype == UART_IS_AR9341) {
++              /* enable TX ready overide */
++              ar933x_uart_rmw_set(up, AR933X_UART_CS_REG,
++                              AR933X_UART_CS_TX_READY_ORIDE);
++      }
++
+       /* Enable RX interrupts */
+       up->ier = AR933X_UART_INT_RX_VALID;
+       ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier);
+@@ -445,7 +464,11 @@ static void ar933x_uart_shutdown(struct
+ 
+ static const char *ar933x_uart_type(struct uart_port *port)
+ {
+-      return (port->type == PORT_AR933X) ? "AR933X UART" : NULL;
++      struct ar933x_uart_port *up =
++              container_of(port, struct ar933x_uart_port, port);
++
++      return (port->type == PORT_AR933X) ?
++              ((up->subtype == UART_IS_AR9341) ? "AR934X high-speed UART" : 
"AR933X UART") : NULL;
+ }
+ 
+ static void ar933x_uart_release_port(struct uart_port *port)
+@@ -610,6 +633,15 @@ static struct uart_driver ar933x_uart_dr
+       .cons           = NULL, /* filled in runtime */
+ };
+ 
++#ifdef CONFIG_OF
++static const struct of_device_id ar933x_uart_of_ids[] = {
++      { .compatible = "qca,ar9330-uart", .data = (const void *)UART_IS_AR9330 
},
++      { .compatible = "qca,ar9341-uart", .data = (const void *)UART_IS_AR9341 
},
++      {},
++};
++MODULE_DEVICE_TABLE(of, ar933x_uart_of_ids);
++#endif
++
+ static int ar933x_uart_probe(struct platform_device *pdev)
+ {
+       struct ar933x_uart_port *up;
+@@ -617,9 +649,12 @@ static int ar933x_uart_probe(struct plat
+       struct resource *mem_res;
+       struct resource *irq_res;
+       struct device_node *np;
++      const struct of_device_id *match;
++
+       unsigned int baud;
+       int id;
+       int ret;
++      int subtype = UART_IS_AR9330;
+ 
+       np = pdev->dev.of_node;
+       if (IS_ENABLED(CONFIG_OF) && np) {
+@@ -629,6 +664,10 @@ static int ar933x_uart_probe(struct plat
+                               id);
+                       return id;
+               }
++              match = of_match_node(ar933x_uart_of_ids, np);
++              if (match)
++                      subtype = (int)match->data;
++
+       } else {
+               id = pdev->id;
+               if (id == -1)
+@@ -649,6 +688,8 @@ static int ar933x_uart_probe(struct plat
+       if (!up)
+               return -ENOMEM;
+ 
++      up->subtype = subtype;
++
+       up->clk = devm_clk_get(&pdev->dev, "uart");
+       if (IS_ERR(up->clk)) {
+               dev_err(&pdev->dev, "unable to get UART clock\n");
+@@ -719,14 +760,6 @@ static int ar933x_uart_remove(struct pla
+       return 0;
+ }
+ 
+-#ifdef CONFIG_OF
+-static const struct of_device_id ar933x_uart_of_ids[] = {
+-      { .compatible = "qca,ar9330-uart" },
+-      {},
+-};
+-MODULE_DEVICE_TABLE(of, ar933x_uart_of_ids);
+-#endif
+-
+ static struct platform_driver ar933x_uart_platform_driver = {
+       .probe          = ar933x_uart_probe,
+       .remove         = ar933x_uart_remove,
-- 
2.25.0


_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to