Re: [PATCH 3/3] serial: msm: calculate bit clock divider

2024-04-15 Thread Robert Marko
On Mon, Apr 15, 2024 at 4:18 PM Caleb Connolly
 wrote:
>
>
>
> On 15/04/2024 14:05, Robert Marko wrote:
> > On Mon, Apr 15, 2024 at 2:44 PM Caleb Connolly
> >  wrote:
> >>
> >> 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.
> >>
> >> Signed-off-by: Caleb Connolly 
> >
> > Works on Alfa AP120C (IPQ4018) with full DM UART, but debug UART
> > prints junk since .clk_rate = 7372800 is not correct for IPQ40xx.
> > I would suggest using .clk_rate = CONFIG_VAL(DEBUG_UART_CLOCK) instead
> > to populate the value per board, this also avoids per ARCH ifdefs.
>
> Ok awesome, thanks for trying this out. I'll send a v2 with your suggestion.
>
> Can I add your Tested-by?

Sure,
Tested-by: Robert Marko 

Regards,
Robert
> >
> > Regards,
> > Robert
> >> ---
> >> Cc: Robert Marko 
> >> ---
> >>  doc/device-tree-bindings/serial/msm-serial.txt | 10 ---
> >>  drivers/serial/serial_msm.c| 87 
> >> +-
> >>  2 files changed, 70 insertions(+), 27 deletions(-)
> >>
> >> diff --git a/doc/device-tree-bindings/serial/msm-serial.txt 
> >> b/doc/device-tree-bindings/serial/msm-serial.txt
> >> deleted file mode 100644
> >> index dca995798a90..
> >> --- a/doc/device-tree-bindings/serial/msm-serial.txt
> >> +++ /dev/null
> >> @@ -1,10 +0,0 @@
> >> -Qualcomm UART (Data Mover mode)
> >> -
> >> -Required properties:
> >> -- compatible: must be "qcom,msm-uartdm-v1.4"
> >> -- reg: start address and size of the registers
> >> -- clock: interface clock (must accept baudrate as a frequency)
> >> -
> >> -Optional properties:
> >> -- bit-rate: Data Mover bit rate register value
> >> -   (If not defined then 0xCC is used as default)
> >> diff --git a/drivers/serial/serial_msm.c b/drivers/serial/serial_msm.c
> >> index 8044d38518db..e461929b4338 100644
> >> --- a/drivers/serial/serial_msm.c
> >> +++ b/drivers/serial/serial_msm.c
> >> @@ -31,8 +31,18 @@
> >>  #define UARTDM_RXFS_BUF_SHIFT   0x7  /* Number of bytes in the packing 
> >> buffer */
> >>  #define UARTDM_RXFS_BUF_MASK0x7
> >>  #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_SR0xA4 /* Status register */
> >>  #define UARTDM_SR_RX_READY   (1 << 0) /* Word is the receiver FIFO */
> >> @@ -52,9 +62,8 @@
> >>
> >>  #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
> >>
> >> @@ -63,9 +72,9 @@ DECLARE_GLOBAL_DATA_PTR;
> >>  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)
> >>  {
> >> @@ -155,34 +164,63 @@ static const struct dm_serial_ops msm_serial_ops = {
> >> .pending = msm_serial_pending,
> >> .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;

Re: [PATCH 3/3] serial: msm: calculate bit clock divider

2024-04-15 Thread Caleb Connolly



On 15/04/2024 14:05, Robert Marko wrote:
> On Mon, Apr 15, 2024 at 2:44 PM Caleb Connolly
>  wrote:
>>
>> 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.
>>
>> Signed-off-by: Caleb Connolly 
> 
> Works on Alfa AP120C (IPQ4018) with full DM UART, but debug UART
> prints junk since .clk_rate = 7372800 is not correct for IPQ40xx.
> I would suggest using .clk_rate = CONFIG_VAL(DEBUG_UART_CLOCK) instead
> to populate the value per board, this also avoids per ARCH ifdefs.

Ok awesome, thanks for trying this out. I'll send a v2 with your suggestion.

Can I add your Tested-by?
> 
> Regards,
> Robert
>> ---
>> Cc: Robert Marko 
>> ---
>>  doc/device-tree-bindings/serial/msm-serial.txt | 10 ---
>>  drivers/serial/serial_msm.c| 87 
>> +-
>>  2 files changed, 70 insertions(+), 27 deletions(-)
>>
>> diff --git a/doc/device-tree-bindings/serial/msm-serial.txt 
>> b/doc/device-tree-bindings/serial/msm-serial.txt
>> deleted file mode 100644
>> index dca995798a90..
>> --- a/doc/device-tree-bindings/serial/msm-serial.txt
>> +++ /dev/null
>> @@ -1,10 +0,0 @@
>> -Qualcomm UART (Data Mover mode)
>> -
>> -Required properties:
>> -- compatible: must be "qcom,msm-uartdm-v1.4"
>> -- reg: start address and size of the registers
>> -- clock: interface clock (must accept baudrate as a frequency)
>> -
>> -Optional properties:
>> -- bit-rate: Data Mover bit rate register value
>> -   (If not defined then 0xCC is used as default)
>> diff --git a/drivers/serial/serial_msm.c b/drivers/serial/serial_msm.c
>> index 8044d38518db..e461929b4338 100644
>> --- a/drivers/serial/serial_msm.c
>> +++ b/drivers/serial/serial_msm.c
>> @@ -31,8 +31,18 @@
>>  #define UARTDM_RXFS_BUF_SHIFT   0x7  /* Number of bytes in the packing 
>> buffer */
>>  #define UARTDM_RXFS_BUF_MASK0x7
>>  #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_SR0xA4 /* Status register */
>>  #define UARTDM_SR_RX_READY   (1 << 0) /* Word is the receiver FIFO */
>> @@ -52,9 +62,8 @@
>>
>>  #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
>>
>> @@ -63,9 +72,9 @@ DECLARE_GLOBAL_DATA_PTR;
>>  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)
>>  {
>> @@ -155,34 +164,63 @@ static const struct dm_serial_ops msm_serial_ops = {
>> .pending = msm_serial_pending,
>> .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", );
>> if (ret < 0) {
>> pr_warn("%s: Failed to get clock: %d\n", __func__, ret);
>> -   return ret;
>> +   return 0;
>> }
>>
>> -   ret = clk_set_rate(, clk_rate);
>> -   if (ret < 0)
>> -   return ret;
>> +   rate = clk_set_rate(, 

Re: [PATCH 3/3] serial: msm: calculate bit clock divider

2024-04-15 Thread Robert Marko
On Mon, Apr 15, 2024 at 2:44 PM Caleb Connolly
 wrote:
>
> 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.
>
> Signed-off-by: Caleb Connolly 

Works on Alfa AP120C (IPQ4018) with full DM UART, but debug UART
prints junk since .clk_rate = 7372800 is not correct for IPQ40xx.
I would suggest using .clk_rate = CONFIG_VAL(DEBUG_UART_CLOCK) instead
to populate the value per board, this also avoids per ARCH ifdefs.

Regards,
Robert
> ---
> Cc: Robert Marko 
> ---
>  doc/device-tree-bindings/serial/msm-serial.txt | 10 ---
>  drivers/serial/serial_msm.c| 87 
> +-
>  2 files changed, 70 insertions(+), 27 deletions(-)
>
> diff --git a/doc/device-tree-bindings/serial/msm-serial.txt 
> b/doc/device-tree-bindings/serial/msm-serial.txt
> deleted file mode 100644
> index dca995798a90..
> --- a/doc/device-tree-bindings/serial/msm-serial.txt
> +++ /dev/null
> @@ -1,10 +0,0 @@
> -Qualcomm UART (Data Mover mode)
> -
> -Required properties:
> -- compatible: must be "qcom,msm-uartdm-v1.4"
> -- reg: start address and size of the registers
> -- clock: interface clock (must accept baudrate as a frequency)
> -
> -Optional properties:
> -- bit-rate: Data Mover bit rate register value
> -   (If not defined then 0xCC is used as default)
> diff --git a/drivers/serial/serial_msm.c b/drivers/serial/serial_msm.c
> index 8044d38518db..e461929b4338 100644
> --- a/drivers/serial/serial_msm.c
> +++ b/drivers/serial/serial_msm.c
> @@ -31,8 +31,18 @@
>  #define UARTDM_RXFS_BUF_SHIFT   0x7  /* Number of bytes in the packing 
> buffer */
>  #define UARTDM_RXFS_BUF_MASK0x7
>  #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_SR0xA4 /* Status register */
>  #define UARTDM_SR_RX_READY   (1 << 0) /* Word is the receiver FIFO */
> @@ -52,9 +62,8 @@
>
>  #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
>
> @@ -63,9 +72,9 @@ DECLARE_GLOBAL_DATA_PTR;
>  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)
>  {
> @@ -155,34 +164,63 @@ static const struct dm_serial_ops msm_serial_ops = {
> .pending = msm_serial_pending,
> .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", );
> if (ret < 0) {
> pr_warn("%s: Failed to get clock: %d\n", __func__, ret);
> -   return ret;
> +   return 0;
> }
>
> -   ret = clk_set_rate(, clk_rate);
> -   if (ret < 0)
> -   return ret;
> +   rate = clk_set_rate(, 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,