[PATCH 6/6] serial: msm-geni: correct oversampling value based on QUP hardware revision

Vladimir Zapolskiy vladimir.zapolskiy at linaro.org
Wed Apr 12 14:41:51 CEST 2023


Hi Konrad,

On 3/31/23 04:36, Konrad Dybcio wrote:
> 
> 
> On 30.03.2023 21:47, Vladimir Zapolskiy wrote:
>> Starting from QUP v2.5 the value of oversampling is changed from 32
>> to 16, keeping the old value on newer platforms results on wrong set
>> UART IP clock divider, thus the asked baudrate does not correspond to
>> the actually set with all the consequencies for a user.
>>
>> The change links the driver to a new Qualcomm GENI SE QUP driver
>> to get its hardware version and update the oversampling value.
>>
>> Deliberately the code under CONFIG_DEBUG_UART_MSM_GENI is not touched,
>> since a wanted baudrate can be controlled by setting a modified
>> CONFIG_DEBUG_UART_CLOCK build time variable.
>>
>> Signed-off-by: Vladimir Zapolskiy <vladimir.zapolskiy at linaro.org>
>> ---
>>   drivers/serial/serial_msm_geni.c | 32 +++++++++++++++++++++++++++++++-
>>   1 file changed, 31 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/serial/serial_msm_geni.c b/drivers/serial/serial_msm_geni.c
>> index 03fc704182d3..cdca7e83daa6 100644
>> --- a/drivers/serial/serial_msm_geni.c
>> +++ b/drivers/serial/serial_msm_geni.c
>> @@ -13,6 +13,7 @@
>>   #include <dm.h>
>>   #include <errno.h>
>>   #include <linux/delay.h>
>> +#include <misc.h>
>>   #include <serial.h>
>>   
>>   #define UART_OVERSAMPLING	32
>> @@ -110,6 +111,10 @@
>>   #define TX_FIFO_DEPTH_MSK	(GENMASK(21, 16))
>>   #define TX_FIFO_DEPTH_SHFT	16
>>   
>> +/* GENI SE QUP Registers */
>> +#define QUP_HW_VER_REG		0x4
>> +#define  QUP_SE_VERSION_2_5	0x20050000
> Should we perhaps store this in the parent's dev / priv data?
> If we had to take care of it for other GENI peripherals, we
> would have to redo it over and over again.

Generally speaking the defines should be found in a (not introduced) GENI SE
header, but for the matter of simplicity I decide to put it right in the
consumer driver, and it allows to stick to the generic misc DM interface.

Looking at the Linux source code, there is no other users of the define but
the GENI serial driver, so I hope there is a minimal risk of spreading of
the macro over the drivers.

>> +
>>   /*
>>    * Predefined packing configuration of the serial engine (CFG0, CFG1 regs)
>>    * for uart mode.
>> @@ -127,6 +132,7 @@ DECLARE_GLOBAL_DATA_PTR;
>>   struct msm_serial_data {
>>   	phys_addr_t base;
>>   	u32 baud;
>> +	u32 oversampling;
>>   };
>>   
>>   unsigned long root_freq[] = {7372800,  14745600, 19200000, 29491200,
>> @@ -246,7 +252,7 @@ static int msm_serial_setbrg(struct udevice *dev, int baud)
>>   
>>   	priv->baud = baud;
>>   
>> -	clk_rate = get_clk_div_rate(baud, UART_OVERSAMPLING, &clk_div);
>> +	clk_rate = get_clk_div_rate(baud, priv->oversampling, &clk_div);
>>   	geni_serial_set_clock_rate(dev, clk_rate);
>>   	geni_serial_baud(priv->base, clk_div, baud);
>>   
>> @@ -480,6 +486,27 @@ static const struct dm_serial_ops msm_serial_ops = {
>>   	.setbrg = msm_serial_setbrg,
>>   };
>>   
>> +static inline void geni_get_oversampling(struct udevice *dev)
> Nit: functions with _get_ in their names are generally expected to
> return the value they're getting, perhaps _adjust_ or _set_ would
> be more fitting.

Acked, I'll rename it to 'set'.

>> +{
>> +	struct msm_serial_data *priv = dev_get_priv(dev);
>> +	struct udevice *parent_dev = dev_get_parent(dev);
>> +	u32 geni_se_version;
>> +	int ret;
>> +
>> +	priv->oversampling = UART_OVERSAMPLING;
>> +
>> +	/*
>> +	 * It could happen that GENI SE QUP driver is disabled or GENI UART
>> +	 * device tree node is a direct child of SoC device tree node.
>> +	 */
>> +	if (device_get_uclass_id(parent_dev) != UCLASS_MISC)
>> +		return;
>> +
>> +	ret = misc_read(parent_dev, QUP_HW_VER_REG, &geni_se_version, 4);
> sizeof(int) or sizeof(geni_se_version)?

Sure, no objections.

>> +	if (!ret && geni_se_version >= QUP_SE_VERSION_2_5)
>> +		priv->oversampling /= 2;
>> +}
>> +
>>   static inline void geni_serial_init(struct udevice *dev)
>>   {
>>   	struct msm_serial_data *priv = dev_get_priv(dev);
>> @@ -523,6 +550,8 @@ static int msm_serial_probe(struct udevice *dev)
>>   {
>>   	struct msm_serial_data *priv = dev_get_priv(dev);
>>   
>> +	geni_get_oversampling(dev);
>> +
>>   	/* No need to reinitialize the UART after relocation */
>>   	if (gd->flags & GD_FLG_RELOC)
>>   		return 0;
>> @@ -557,6 +586,7 @@ U_BOOT_DRIVER(serial_msm_geni) = {
>>   	.priv_auto = sizeof(struct msm_serial_data),
>>   	.probe = msm_serial_probe,
>>   	.ops = &msm_serial_ops,
>> +	.flags = DM_FLAG_PRE_RELOC,
> This change was not mentioned in the commit message. You can
> pick up
> 
> https://lore.kernel.org/u-boot/20230327-qc_cleanups-v2-4-9a80cc563c76@linaro.org/
> 
> which also cleans up the remnants of this in the DTs.
> It will however need to be rebased against the `next` branch and
> 
> 8c103c33fb14 ("dm: dts: Convert driver model tags to use new schema")

Sure, I'll take your change to the v2 of the series.

Thank you for review!

--
Best wishes,
Vladimir


More information about the U-Boot mailing list