[PATCH v2 19/30] pwm: ti: am33xx: add subsystem driver
Lokesh Vutla
lokeshvutla at ti.com
Mon Sep 7 07:32:02 CEST 2020
Hi Dario,
On 06/09/20 5:41 pm, Dario Binacchi wrote:
> The TI PWMSS driver is a simple bus driver for providing clock and power
> management for the PWM peripherals on TI AM33xx SoCs, namely eCAP,
> eHRPWM and eQEP.
>
> Based on more recent versions of the device tree inside the linux kernel,
> I added the clock domain for each subsystem in am33x.dtsi so it can be
> enabled before probing the peripheral child device and disabled after
> its removal.
>
> Signed-off-by: Dario Binacchi <dariobin at libero.it>
> ---
>
> (no changes since v1)
>
> arch/arm/dts/am33xx.dtsi | 9 +++
> doc/device-tree-bindings/pwm/ti,pwmss.txt | 58 ++++++++++++++
> drivers/pwm/Kconfig | 9 ++-
> drivers/pwm/Makefile | 1 +
> drivers/pwm/pwm-ti-pwmss.c | 95 +++++++++++++++++++++++
> 5 files changed, 171 insertions(+), 1 deletion(-)
> create mode 100644 doc/device-tree-bindings/pwm/ti,pwmss.txt
> create mode 100644 drivers/pwm/pwm-ti-pwmss.c
>
> diff --git a/arch/arm/dts/am33xx.dtsi b/arch/arm/dts/am33xx.dtsi
> index d3dd6a16e7..fa7492a9b6 100644
> --- a/arch/arm/dts/am33xx.dtsi
> +++ b/arch/arm/dts/am33xx.dtsi
> @@ -758,6 +758,9 @@
> 0x48300180 0x48300180 0x80 /* EQEP */
> 0x48300200 0x48300200 0x80>; /* EHRPWM */
>
> + clocks = <&l4_per_clkctrl AM3_EPWMSS0_CLKCTRL 0>;
> + clock-names = "fck";
> +
> ecap0: ecap at 48300100 {
> compatible = "ti,am3352-ecap",
> "ti,am33xx-ecap";
> @@ -792,6 +795,9 @@
> 0x48302180 0x48302180 0x80 /* EQEP */
> 0x48302200 0x48302200 0x80>; /* EHRPWM */
>
> + clocks = <&l4_per_clkctrl AM3_EPWMSS1_CLKCTRL 0>;
> + clock-names = "fck";
> +
> ecap1: ecap at 48302100 {
> compatible = "ti,am3352-ecap",
> "ti,am33xx-ecap";
> @@ -826,6 +832,9 @@
> 0x48304180 0x48304180 0x80 /* EQEP */
> 0x48304200 0x48304200 0x80>; /* EHRPWM */
>
> + clocks = <&l4_per_clkctrl AM3_EPWMSS2_CLKCTRL 0>;
> + clock-names = "fck";
hmm..I do not see these changes in upstream kernel v5.9-rc3 DT. Which version of
kernel are you using? I see al PWM nodes under am33xx-l4.dtsi
> +
> ecap2: ecap at 48304100 {
> compatible = "ti,am3352-ecap",
> "ti,am33xx-ecap";
> diff --git a/doc/device-tree-bindings/pwm/ti,pwmss.txt b/doc/device-tree-bindings/pwm/ti,pwmss.txt
> new file mode 100644
> index 0000000000..4633697fbd
> --- /dev/null
> +++ b/doc/device-tree-bindings/pwm/ti,pwmss.txt
> @@ -0,0 +1,58 @@
> +TI SOC based PWM Subsystem
> +
> +Required properties:
> +- compatible: Must be "ti,<soc>-pwmss".
> + for am33xx - compatible = "ti,am33xx-pwmss";
> + for am4372 - compatible = "ti,am4372-pwmss","ti,am33xx-pwmss";
> + for dra746 - compatible = "ti,dra746-pwmss", "ti,am33xx-pwmss"
> +
> +- reg: physical base address and size of the registers map.
> +- address-cells: Specify the number of u32 entries needed in child nodes.
> + Should set to 1.
> +- size-cells: specify number of u32 entries needed to specify child nodes size
> + in reg property. Should set to 1.
> +- ranges: describes the address mapping of a memory-mapped bus. Should set to
> + physical address map of child's base address, physical address within
> + parent's address space and length of the address map. For am33xx,
> + 3 set of child register maps present, ECAP register space, EQEP
> + register space, EHRPWM register space.
> +
> +Also child nodes should also populated under PWMSS DT node.
> +
> +Example:
> +epwmss0: epwmss at 48300000 { /* PWMSS for am33xx */
> + compatible = "ti,am33xx-pwmss";
> + reg = <0x48300000 0x10>;
> + ti,hwmods = "epwmss0";
> + #address-cells = <1>;
> + #size-cells = <1>;
> + ranges = <0x48300100 0x48300100 0x80 /* ECAP */
> + 0x48300180 0x48300180 0x80 /* EQEP */
> + 0x48300200 0x48300200 0x80>; /* EHRPWM */
> +
> + /* child nodes go here */
> +};
> +
> +epwmss0: epwmss at 48300000 { /* PWMSS for am4372 */
> + compatible = "ti,am4372-pwmss","ti,am33xx-pwmss"
> + reg = <0x48300000 0x10>;
> + ti,hwmods = "epwmss0";
> + #address-cells = <1>;
> + #size-cells = <1>;
> + ranges = <0x48300100 0x48300100 0x80 /* ECAP */
> + 0x48300180 0x48300180 0x80 /* EQEP */
> + 0x48300200 0x48300200 0x80>; /* EHRPWM */
> +
> + /* child nodes go here */
> +};
> +
> +epwmss0: epwmss at 4843e000 { /* PWMSS for DRA7xx */
> + compatible = "ti,dra746-pwmss", "ti,am33xx-pwmss";
> + reg = <0x4843e000 0x30>;
> + ti,hwmods = "epwmss0";
> + #address-cells = <1>;
> + #size-cells = <1>;
> + ranges;
> +
> + /* child nodes go here */
> +};
> diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
> index e4ba8b3d80..129f5d77ca 100644
> --- a/drivers/pwm/Kconfig
> +++ b/drivers/pwm/Kconfig
> @@ -69,8 +69,15 @@ config PWM_SUNXI
> This PWM is found on H3, A64 and other Allwinner SoCs. It supports a
> programmable period and duty cycle. A 16-bit counter is used.
>
> +config PWM_TI_PWMSS
> + bool "Enable support for the AM335x PWM Subsystem"
> + depends on DM_PWM
> + help
> + This enables the AM335x PWM subsystem driver support on TI's SOCs.
> +
> config PWM_TI_EHRPWM
> bool "Enable support for the AM335x EHRPWM"
> - depends on DM_PWM
> + depends on PWM_TI_PWMSS
> + default y
> help
> This enables the AM335x EHRPWM driver support on TI's SoCs.
> diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
> index c5f88f7501..df9c54e764 100644
> --- a/drivers/pwm/Makefile
> +++ b/drivers/pwm/Makefile
> @@ -19,3 +19,4 @@ obj-$(CONFIG_PWM_SIFIVE) += pwm-sifive.o
> obj-$(CONFIG_PWM_TEGRA) += tegra_pwm.o
> obj-$(CONFIG_PWM_SUNXI) += sunxi_pwm.o
> obj-$(CONFIG_PWM_TI_EHRPWM) += pwm-ti-ehrpwm.o
> +obj-$(CONFIG_PWM_TI_PWMSS) += pwm-ti-pwmss.o
> diff --git a/drivers/pwm/pwm-ti-pwmss.c b/drivers/pwm/pwm-ti-pwmss.c
> new file mode 100644
> index 0000000000..57f86512d6
> --- /dev/null
> +++ b/drivers/pwm/pwm-ti-pwmss.c
> @@ -0,0 +1,95 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Pulse-Width Modulation Subsystem (pwmss)
> + *
> + * Copyright (C) 2020 Dario Binacchi <dariobin at libero.it>
> + */
> +#define DEBUG
> +#undef CONFIG_LOGLEVEL
> +#define CONFIG_LOGLEVEL 8
> +
> +#include <common.h>
> +#include <clk.h>
> +#include <dm.h>
> +
> +struct ti_pwmss_priv {
> + int child_count;
> + struct clk clkdm;
> +};
> +
> +static const struct udevice_id ti_pwmss_ids[] = {
> + {.compatible = "ti,am33xx-pwmss"},
> + {}
> +};
> +
> +static int ti_pwmss_child_post_remove(struct udevice *dev)
> +{
> + struct ti_pwmss_priv *priv = dev_get_priv(dev->parent);
> + int err;
> +
> + if (--priv->child_count > 0)
> + return 0;
> +
> + err = clk_disable(&priv->clkdm);
> + if (err) {
> + dev_err(dev->parent, "%s: failed to disable clock domain\n",
> + __func__);
> + goto clkdm_disable_err;
> + }
> +
> + err = clk_release_all(&priv->clkdm, 1);
> + if (err) {
> + dev_err(dev->parent, "%s: failed to release clock domain\n",
> + __func__);
> + goto clkdm_release_err;
> + }
> +
> + return 0;
> +
> +clkdm_release_err:
> + clk_enable(&priv->clkdm);
> +clkdm_disable_err:
> + priv->child_count++;
> + return err;
> +}
> +
> +static int ti_pwmss_child_pre_probe(struct udevice *dev)
> +{
> + struct ti_pwmss_priv *priv = dev_get_priv(dev->parent);
> + int err;
> +
> + if (++priv->child_count > 1)
> + return 0;
> +
> + err = clk_get_by_name(dev->parent, "fck", &priv->clkdm);
> + if (err) {
> + dev_err(dev->parent, "%s: failed to get clock domain\n",
> + __func__);
> + goto clkdm_get_err;
> + }
> +
> + err = clk_enable(&priv->clkdm);
> + if (err) {
> + dev_err(dev->parent, "%s: failed to enable clock domain\n",
> + __func__);
> + goto clkdm_enable_err;
> + }
Do we need a whole subsystem driver just for enabling the clocks? Can't the same
be happen in driver?
Thanks and regards,
Lokesh
More information about the U-Boot
mailing list