From 615a3e909e36d7e615f5da1c2c46e58e0025d23f Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Mon, 15 Apr 2024 12:49:26 +0200 Subject: serial: msm_serial: remove .clk_rate from debug UART MSM serial in DEBUG UART mode is trying to set .clk_rate, but the msm_serial_data structure does not have such property at all, so lets remove it as otherwise it will fail compiling. Fixes: 90023bdfe979 ("serial: msm: add debug UART") Signed-off-by: Robert Marko Reviewed-by: Caleb Connolly Signed-off-by: Caleb Connolly --- drivers/serial/serial_msm.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/serial/serial_msm.c') diff --git a/drivers/serial/serial_msm.c b/drivers/serial/serial_msm.c index ac4280c6c4c..8044d38518d 100644 --- a/drivers/serial/serial_msm.c +++ b/drivers/serial/serial_msm.c @@ -242,7 +242,6 @@ U_BOOT_DRIVER(serial_msm) = { static struct msm_serial_data init_serial_data = { .base = CONFIG_VAL(DEBUG_UART_BASE), - .clk_rate = 7372800, }; #include -- cgit v1.2.3 From 69e9b3428bfee99ef3a5ece6e6c69a1ad1b39bd9 Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Mon, 15 Apr 2024 16:03:40 +0100 Subject: serial: msm: calculate bit clock divider The driver currently requires the bit clock divider be hardcoded in devicetree (or use the hardcoded default from apq8016). The bit clock divider is used to derive the baud rate from the core clock: baudrate = clk_rate / csr_div clk_rate is the actual programmed core clock rate which is returned by clk_set_rate(), and this UART driver only supports a baudrate of 115200. We can therefore determine the appropriate value for UARTDM_CSR by iterating over the possible values and finding the one where the equation above holds true for a baudrate of 115200. Implement this logic and drop the non-standard DT bindings for this driver. Tested on dragonboard410c. Tested-by: Robert Marko Signed-off-by: Caleb Connolly --- drivers/serial/serial_msm.c | 87 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 70 insertions(+), 17 deletions(-) (limited to 'drivers/serial/serial_msm.c') diff --git a/drivers/serial/serial_msm.c b/drivers/serial/serial_msm.c index 8044d38518d..c05dda8bdb9 100644 --- a/drivers/serial/serial_msm.c +++ b/drivers/serial/serial_msm.c @@ -32,6 +32,16 @@ #define UARTDM_RXFS_BUF_MASK 0x7 #define UARTDM_MR1 0x00 #define UARTDM_MR2 0x04 +/* + * This is documented on page 1817 of the apq8016e technical reference manual. + * section 6.2.5.3.26 + * + * The upper nybble contains the bit clock divider for the RX pin, the lower + * nybble defines the TX pin. In almost all cases these should be the same value. + * + * The baud rate is the core clock frequency divided by the fixed divider value + * programmed into this register (defined in calc_csr_bitrate()). + */ #define UARTDM_CSR 0xA0 #define UARTDM_SR 0xA4 /* Status register */ @@ -53,7 +63,6 @@ #define UARTDM_TF 0x100 /* UART Transmit FIFO register */ #define UARTDM_RF 0x140 /* UART Receive FIFO register */ -#define UART_DM_CLK_RX_TX_BIT_RATE 0xCC #define MSM_BOOT_UART_DM_8_N_1_MODE 0x34 #define MSM_BOOT_UART_DM_CMD_RESET_RX 0x10 #define MSM_BOOT_UART_DM_CMD_RESET_TX 0x20 @@ -64,7 +73,7 @@ struct msm_serial_data { phys_addr_t base; unsigned chars_cnt; /* number of buffered chars */ uint32_t chars_buf; /* buffered chars */ - uint32_t clk_bit_rate; /* data mover mode bit rate register value */ + uint32_t clk_rate; /* core clock rate */ }; static int msm_serial_fetch(struct udevice *dev) @@ -156,32 +165,61 @@ static const struct dm_serial_ops msm_serial_ops = { .getc = msm_serial_getc, }; -static int msm_uart_clk_init(struct udevice *dev) +static long msm_uart_clk_init(struct udevice *dev) { - uint clk_rate = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev), - "clock-frequency", 115200); + struct msm_serial_data *priv = dev_get_priv(dev); struct clk clk; int ret; + long rate; ret = clk_get_by_name(dev, "core", &clk); if (ret < 0) { pr_warn("%s: Failed to get clock: %d\n", __func__, ret); - return ret; + return 0; } - ret = clk_set_rate(&clk, clk_rate); - if (ret < 0) - return ret; + rate = clk_set_rate(&clk, priv->clk_rate); - return 0; + return rate; +} + +static int calc_csr_bitrate(struct msm_serial_data *priv) +{ + /* This table is from the TRE. See the definition of UARTDM_CSR */ + unsigned int csr_div_table[] = {24576, 12288, 6144, 3072, 1536, 768, 512, 384, + 256, 192, 128, 96, 64, 48, 32, 16}; + int i = ARRAY_SIZE(csr_div_table) - 1; + /* Currently we only support one baudrate */ + int baud = 115200; + + for (; i >= 0; i--) { + int x = priv->clk_rate / csr_div_table[i]; + + if (x == baud) + /* Duplicate the configuration for RX + * as the lower nybble only configures TX + */ + return i + (i << 4); + } + + return -EINVAL; } static void uart_dm_init(struct msm_serial_data *priv) { /* Delay initialization for a bit to let pins stabilize if necessary */ mdelay(5); + int bitrate = calc_csr_bitrate(priv); + if (bitrate < 0) { + log_warning("Couldn't calculate bit clock divider! Using default\n"); + /* This happens to be the value used on MSM8916 for the hardcoded clockrate + * in clock-apq8016. It's at least a better guess than a value we *know* + * is wrong... + */ + bitrate = 0xCC; + } - writel(priv->clk_bit_rate, priv->base + UARTDM_CSR); + writel(bitrate, priv->base + UARTDM_CSR); writel(0x0, priv->base + UARTDM_MR1); writel(MSM_BOOT_UART_DM_8_N_1_MODE, priv->base + UARTDM_MR2); writel(MSM_BOOT_UART_DM_CMD_RESET_RX, priv->base + UARTDM_CR); @@ -192,16 +230,25 @@ static void uart_dm_init(struct msm_serial_data *priv) } static int msm_serial_probe(struct udevice *dev) { - int ret; struct msm_serial_data *priv = dev_get_priv(dev); + long rate; /* No need to reinitialize the UART after relocation */ if (gd->flags & GD_FLG_RELOC) return 0; - ret = msm_uart_clk_init(dev); - if (ret) - return ret; + rate = msm_uart_clk_init(dev); + if (rate < 0) + return rate; + if (!rate) { + log_err("Got core clock rate of 0... Please fix your clock driver\n"); + return -EINVAL; + } + + /* Update the clock rate to the actual programmed rate returned by the + * clock driver + */ + priv->clk_rate = rate; uart_dm_init(priv); @@ -211,13 +258,18 @@ static int msm_serial_probe(struct udevice *dev) static int msm_serial_of_to_plat(struct udevice *dev) { struct msm_serial_data *priv = dev_get_priv(dev); + int ret; priv->base = dev_read_addr(dev); if (priv->base == FDT_ADDR_T_NONE) return -EINVAL; - priv->clk_bit_rate = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), - "bit-rate", UART_DM_CLK_RX_TX_BIT_RATE); + ret = dev_read_u32(dev, "clock-frequency", &priv->clk_rate); + if (ret < 0) { + log_debug("No clock frequency specified, using default rate\n"); + /* Default for APQ8016 */ + priv->clk_rate = 7372800; + } return 0; } @@ -242,6 +294,7 @@ U_BOOT_DRIVER(serial_msm) = { static struct msm_serial_data init_serial_data = { .base = CONFIG_VAL(DEBUG_UART_BASE), + .clk_rate = CONFIG_VAL(DEBUG_UART_CLOCK), }; #include -- cgit v1.2.3 From 6e992a6bc85ce40a9b24924db52ce90c9efc3005 Mon Sep 17 00:00:00 2001 From: Sumit Garg Date: Fri, 12 Apr 2024 15:24:33 +0530 Subject: apq8016: Add support for UART1 clocks and pinmux SE HMIBSC board uses UART1 as the main debug console, so add corresponding clocks and pinmux support. Along with that update instructions to enable clocks for debug UART support. Reviewed-by: Caleb Connolly Signed-off-by: Sumit Garg Signed-off-by: Caleb Connolly --- drivers/serial/serial_msm.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers/serial/serial_msm.c') diff --git a/drivers/serial/serial_msm.c b/drivers/serial/serial_msm.c index c05dda8bdb9..06a948a2f64 100644 --- a/drivers/serial/serial_msm.c +++ b/drivers/serial/serial_msm.c @@ -300,12 +300,17 @@ static struct msm_serial_data init_serial_data = { #include /* Uncomment to turn on UART clocks when debugging U-Boot as aboot on MSM8916 */ -//int apq8016_clk_init_uart(phys_addr_t gcc_base); +//int apq8016_clk_init_uart(phys_addr_t gcc_base, unsigned long id); static inline void _debug_uart_init(void) { - /* Uncomment to turn on UART clocks when debugging U-Boot as aboot on MSM8916 */ - //apq8016_clk_init_uart(0x1800000); + /* + * Uncomment to turn on UART clocks when debugging U-Boot as aboot + * on MSM8916. Supported debug UART clock IDs: + * - db410c: GCC_BLSP1_UART2_APPS_CLK + * - HMIBSC: GCC_BLSP1_UART1_APPS_CLK + */ + //apq8016_clk_init_uart(0x1800000, ); uart_dm_init(&init_serial_data); } -- cgit v1.2.3 From 512672492ccf09adb98e185243f2edace54e3ef4 Mon Sep 17 00:00:00 2001 From: Sumit Garg Date: Fri, 12 Apr 2024 15:24:34 +0530 Subject: serial_msm: Enable RS232 flow control SE HMIBSC board debug console requires RS232 flow control, so enable corresponding support if RS232 gpios are present. Reviewed-by: Caleb Connolly Signed-off-by: Sumit Garg Signed-off-by: Caleb Connolly --- drivers/serial/serial_msm.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/serial/serial_msm.c') diff --git a/drivers/serial/serial_msm.c b/drivers/serial/serial_msm.c index 06a948a2f64..a472e0b3683 100644 --- a/drivers/serial/serial_msm.c +++ b/drivers/serial/serial_msm.c @@ -63,9 +63,10 @@ #define UARTDM_TF 0x100 /* UART Transmit FIFO register */ #define UARTDM_RF 0x140 /* UART Receive FIFO register */ -#define MSM_BOOT_UART_DM_8_N_1_MODE 0x34 -#define MSM_BOOT_UART_DM_CMD_RESET_RX 0x10 -#define MSM_BOOT_UART_DM_CMD_RESET_TX 0x20 +#define MSM_BOOT_UART_DM_8_N_1_MODE 0x34 +#define MSM_BOOT_UART_DM_CMD_RESET_RX 0x10 +#define MSM_BOOT_UART_DM_CMD_RESET_TX 0x20 +#define MSM_UART_MR1_RX_RDY_CTL BIT(7) DECLARE_GLOBAL_DATA_PTR; @@ -220,7 +221,8 @@ static void uart_dm_init(struct msm_serial_data *priv) } writel(bitrate, priv->base + UARTDM_CSR); - writel(0x0, priv->base + UARTDM_MR1); + /* Enable RS232 flow control to support RS232 db9 connector */ + writel(MSM_UART_MR1_RX_RDY_CTL, priv->base + UARTDM_MR1); writel(MSM_BOOT_UART_DM_8_N_1_MODE, priv->base + UARTDM_MR2); writel(MSM_BOOT_UART_DM_CMD_RESET_RX, priv->base + UARTDM_CR); writel(MSM_BOOT_UART_DM_CMD_RESET_TX, priv->base + UARTDM_CR); -- cgit v1.2.3