[PATCH] pwm: Add driver for cadence TTC

Michal Simek michal.simek at xilinx.com
Mon Aug 30 11:32:16 CEST 2021



On 8/27/21 8:13 PM, Sean Anderson wrote:
> 
> 
> On 8/27/21 7:55 AM, Michal Simek wrote:
>> TTC has three modes of operations. Timer, PWM and input counters.
>>
>> There is already driver for timer under CADENCE_TTC_TIMER which is
>> used for
>> ZynqMP R5 configuration.
>> This driver is targeting PWM which is for example configuration which can
>> be used for fan control.
>> The driver has been tested on Xilinx Kria SOM platform where fan is
>> connected to one PL pin. When TTC output is connected via EMIO to PL pin
>> TTC pwm can be configured and tested for example like this:
>> pwm config 0 0 10000 1200
>> pwm enable 0 0
>> pwm config 0 0 10000 1400
>> pwm config 0 0 10000 1600
>>
>> Signed-off-by: Michal Simek <michal.simek at xilinx.com>
>> ---
>>
>>   MAINTAINERS                   |   1 +
>>   drivers/pwm/Kconfig           |   7 ++
>>   drivers/pwm/Makefile          |   1 +
>>   drivers/pwm/pwm-cadence-ttc.c | 217 ++++++++++++++++++++++++++++++++++
>>   4 files changed, 226 insertions(+)
>>   create mode 100644 drivers/pwm/pwm-cadence-ttc.c
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 4cf0c33c5d58..889813382249 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -600,6 +600,7 @@ F:    drivers/mmc/zynq_sdhci.c
>>   F:    drivers/mtd/nand/raw/zynq_nand.c
>>   F:    drivers/net/phy/xilinx_phy.c
>>   F:    drivers/net/zynq_gem.c
>> +F:    drivers/pwm/pwm-cadence-ttc.c
>>   F:    drivers/serial/serial_zynq.c
>>   F:    drivers/reset/reset-zynqmp.c
>>   F:    drivers/rtc/zynqmp_rtc.c
>> diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
>> index cf7f4c6840ce..176e703c8fbb 100644
>> --- a/drivers/pwm/Kconfig
>> +++ b/drivers/pwm/Kconfig
>> @@ -9,6 +9,13 @@ config DM_PWM
>>         frequency/period can be controlled along with the proportion
>> of that
>>         time that the signal is high.
>>
>> +config PWM_CADENCE_TTC
>> +    bool "Enable support for the Cadence TTC PWM"
>> +    depends on DM_PWM && !CADENCE_TTC_TIMER
>> +    help
>> +      Cadence TTC can be configured as timer which is done via
>> +      CONFIG_CADENCE_TTC_TIMER or as PWM. This is covering only PWM now.
>> +
>>   config PWM_CROS_EC
>>       bool "Enable support for the Chrome OS EC PWM"
>>       depends on DM_PWM
>> diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
>> index 10d244bfb79d..abf5af41d2cc 100644
>> --- a/drivers/pwm/Makefile
>> +++ b/drivers/pwm/Makefile
>> @@ -10,6 +10,7 @@
>>
>>   obj-$(CONFIG_DM_PWM)        += pwm-uclass.o
>>
>> +obj-$(CONFIG_PWM_CADENCE_TTC)    += pwm-cadence-ttc.o
>>   obj-$(CONFIG_PWM_CROS_EC)    += cros_ec_pwm.o
>>   obj-$(CONFIG_PWM_EXYNOS)    += exynos_pwm.o
>>   obj-$(CONFIG_PWM_IMX)        += pwm-imx.o pwm-imx-util.o
>> diff --git a/drivers/pwm/pwm-cadence-ttc.c
>> b/drivers/pwm/pwm-cadence-ttc.c
>> new file mode 100644
>> index 000000000000..1d007676bb3b
>> --- /dev/null
>> +++ b/drivers/pwm/pwm-cadence-ttc.c
>> @@ -0,0 +1,217 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * (C) Copyright 2021 Xilinx, Inc. Michal Simek
>> + */
>> +
>> +#include <clk.h>
>> +#include <common.h>
>> +#include <div64.h>
>> +#include <dm.h>
>> +#include <log.h>
>> +#include <pwm.h>
>> +#include <asm/io.h>
>> +#include <log.h>
>> +#include <div64.h>
>> +#include <linux/math64.h>
>> +#include <linux/log2.h>
>> +#include <dm/device_compat.h>
>> +
>> +#define TTC_COUNTER_CONTROL_1    0xc
>> +#define TTC_INTERVAL_COUNTER_1    0x24
>> +#define TTC_MATCH_1_COUNTER_1    0x30
>> +
>> +#define CPWM_CLK_FALLING_EDGE        0x40
> 
> BIT(6)
> 
>> +#define CPWM_CLK_SRC_EXTERNAL        0x20
> 
> BIT(5)
> 
>> +#define CPWM_CLK_PRESCALE_SHIFT        1
>> +#define CPWM_CLK_PRESCALE_MASK        (15 << 1)
> 
> GENMASK(4, 1)
> 
>> +#define CPWM_CLK_PRESCALE_ENABLE    1
> 
> Why CPWM_? And please use register names which match the datasheet. E.g.
> XXX_EX_E instead of XXX_FALLING_EDGE.
> 
>> +
>> +#define CPWM_COUNTER_CTRL_WAVE_POL        0x40
>> +#define CPWM_COUNTER_CTRL_WAVE_DISABLE        0x20
>> +#define CPWM_COUNTER_CTRL_RESET            0x10
>> +#define CPWM_COUNTER_CTRL_MATCH_ENABLE        0x8
>> +#define CPWM_COUNTER_CTRL_DECREMENT_ENABLE    0x4
>> +#define CPWM_COUNTER_CTRL_INTERVAL_ENABLE    0x2
>> +#define CPWM_COUNTER_CTRL_COUNTING_DISABLE    0x1
> 
> ditto
> 
>> +
>> +struct cadence_ttc_pwm_priv {
>> +    uchar *regs;
>> +    unsigned long frequency;
>> +    bool invert[2];
>> +};
>> +
>> +static int cadence_ttc_pwm_set_invert(struct udevice *dev, uint channel,
>> +                      bool polarity)
>> +{
>> +    struct cadence_ttc_pwm_priv *priv = dev_get_priv(dev);
>> +
>> +    if (channel > 2) {
>> +        dev_err(dev, "Unsupported channel number %d(max 2)\n", channel);
>> +        return -EINVAL;
>> +    }
>> +
>> +    priv->invert[channel] = polarity;
>> +
>> +    dev_dbg(dev, "polarity=%u. Please config PWM again\n", polarity);
>> +
>> +    return 0;
>> +}
>> +
>> +static int cadence_ttc_pwm_set_config(struct udevice *dev, uint channel,
>> +                      uint period_ns, uint duty_ns)
>> +{
>> +    struct cadence_ttc_pwm_priv *priv = dev_get_priv(dev);
>> +    u32 counter_ctrl, x;
>> +    int period_clocks, duty_clocks, prescaler;
>> +
>> +    dev_dbg(dev, "channel %d, duty %d/ period %d ns\n", channel,
>> +        duty_ns, period_ns);
>> +
>> +    if (channel > 2) {
>> +        dev_err(dev, "Unsupported channel number %d(max 2)\n", channel);
>> +        return -EINVAL;
>> +    }
>> +
>> +    /* Make sure counter is stopped */
> 
> Shouldn't this be a write? And do we even need to check for this?

As you see counter_ctrl is used below that's why this read here.

I have fixed all reported issue and will send v2.

Thanks,
Michal


More information about the U-Boot mailing list