[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