Skip to contentSkip to conversation

Add driver support for ESWIN EIC7700 PWM controller

PATCH In review [email protected] 3 participants 8 messages Dec 5, 2025 – Dec 9, 2025

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover Add driver support for ESWIN EIC7700 PWM controller

From: Xuyang Dong <[email protected]>

Add support for the ESWIN EIC7700 PWM (Pulse Width Modulation) based on Synopsys DWC PWM.

Features:
The EIC7700 PWM driver supports a duty cycle range from 0% to 100%, with explicit support added for both 0% and 100% duty cycles.

Supported chips:
ESWIN EIC7700 series SoC.

Test:
Tested this patch on the Sifive HiFive Premier P550 (which used the EIC7700 SoC).

Xuyang Dong (2):
dt-bindings: pwm: eswin: Add EIC7700 pwm controller
pwm: eswin: Add EIC7700 pwm driver

 .../bindings/pwm/eswin,eic7700-pwm.yaml       |  73 ++++++
 drivers/pwm/Kconfig                           |  12 +
 drivers/pwm/Makefile                          |   1 +
 drivers/pwm/pwm-dwc-core.c                    |  76 ++++--
 drivers/pwm/pwm-dwc-eic7700.c                 | 231 ++++++++++++++++++
 drivers/pwm/pwm-dwc.h                         |  16 +-
 6 files changed, 384 insertions(+), 25 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/pwm/eswin,eic7700-pwm.yaml
 create mode 100644 drivers/pwm/pwm-dwc-eic7700.c

--
2.34.1

#1 lore raw

PATCH 1/2 dt-bindings: pwm: eswin: Add EIC7700 pwm controller

From: Xuyang Dong <[email protected]>

Introduce device-tree binding documentation for ESWIN EIC7700 pwm controller.

---
 .../bindings/pwm/eswin,eic7700-pwm.yaml       | 73 +++++++++++++++++++
 1 file changed, 73 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pwm/eswin,eic7700-pwm.yaml
Documentation/devicetree/bindings/pwm/eswin,eic7700-pwm.yaml new file +73 -0
new file mode 100644
index 000000000000..8b7dc7d4dffe
@@ -0,0 +1,73 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pwm/eswin,eic7700-pwm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ESWIN EIC7700 PWM controller
+
+maintainers:
+  - Xiang Xu <[email protected]>
+  - Guosheng Wang <[email protected]>
+  - Xuyang Dong <[email protected]>
+
+description: |
+  The EIC7700 PWM used the DesignWare APB timers module. The PWM driver
+  supports a duty cycle range from 0% to 100%, with explicit support for
+  both 0% and 100% duty cycles.
+
+allOf:
+  - $ref: pwm.yaml#
+
+properties:
+  compatible:
+    const: eswin,eic7700-pwm
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  resets:
+    maxItems: 1
+
+  "#pwm-cells":
+    const: 3
+
+  pinctrl-0: true
+  pinctrl-1: true
+
+  pinctrl-names:
+    minItems: 1
+    items:
+      - const: default
+      - const: sleep
+
+  snps,pwm-full-range-enable:
+    type: boolean
+    description: |
+      Enable support for 0% and 100% duty cycle.
+      When present, the PWM controller can output 0% and 100% duty cycles.
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - resets
+  - snps,pwm-full-range-enable
+
+additionalProperties: false
+
+examples:
+  - |
+    pwm@50818000 {
+        compatible = "eswin,eic7700-pwm";
+        reg = <0x50818000 0x4000>;
+        clocks = <&clock 242>;
+        resets = <&reset 136>;
+        #pwm-cells = <3>;
+        pinctrl-names = "default";
+        pinctrl-0 = <&fan_pwm>;
+        snps,pwm-full-range-enable;
+    };
Signature · 1 line
2.34.1
#2 lore raw

Re: [PATCH 1/2] dt-bindings: pwm: eswin: Add EIC7700 pwm controller

Quoted 10 lines · On Fri, Dec 05, 2025 at 05:04:50PM +0800, [email protected] wrote:
Documentation/devicetree/bindings/pwm/eswin,eic7700-pwm.yaml new file +4 -0
new file mode 100644
index 000000000000..8b7dc7d4dffe
@@ -0,0 +1,73 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pwm/eswin,eic7700-pwm.yaml#

Documentation/devicetree/bindings/pwm/eswin,eic7700-pwm.yaml line 14

Quoted 10 lines
Documentation/devicetree/bindings/pwm/eswin,eic7700-pwm.yaml new file +10 -0
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ESWIN EIC7700 PWM controller
+
+maintainers:
+  - Xiang Xu <[email protected]>
+  - Guosheng Wang <[email protected]>
+  - Xuyang Dong <[email protected]>
+
+description: |

Do not need '|' unless you need to preserve formatting.

Documentation/devicetree/bindings/pwm/eswin,eic7700-pwm.yaml line 16

Quoted 2 lines
Documentation/devicetree/bindings/pwm/eswin,eic7700-pwm.yaml new file +2 -0
+  The EIC7700 PWM used the DesignWare APB timers module. The PWM driver
+  supports a duty cycle range from 0% to 100%, with explicit support for

Driver is irrelevant here. Describe hardware.

Quoted 21 lines
Documentation/devicetree/bindings/pwm/eswin,eic7700-pwm.yaml new file +21 -0
+  both 0% and 100% duty cycles.
+
+allOf:
+  - $ref: pwm.yaml#
+
+properties:
+  compatible:
+    const: eswin,eic7700-pwm
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  resets:
+    maxItems: 1
+
+  "#pwm-cells":
+    const: 3
+

Documentation/devicetree/bindings/pwm/eswin,eic7700-pwm.yaml line 47

Quoted 10 lines
Documentation/devicetree/bindings/pwm/eswin,eic7700-pwm.yaml new file +10 -0
+  pinctrl-0: true
+  pinctrl-1: true
+
+  pinctrl-names:
+    minItems: 1
+    items:
+      - const: default
+      - const: sleep
+
+  snps,pwm-full-range-enable:

1. Wrong vendor prefix, thats eswin, not snps.
2. Why is this a hardware property? I really do not see that. You described the desired Linux feature or behavior, not the actual hardware. The bindings are about the latter, so instead you need to rephrase the property and its description to match actual hardware capabilities/features/configuration etc.

Best regards,
Krzysztof

#3 lore raw

Re: Re: [PATCH 1/2] dt-bindings: pwm: eswin: Add EIC7700 pwm controller

Quoted 58 lines
Quoted 10 lines
Documentation/devicetree/bindings/pwm/eswin,eic7700-pwm.yaml new file +4 -0
new file mode 100644
index 000000000000..8b7dc7d4dffe
@@ -0,0 +1,73 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pwm/eswin,eic7700-pwm.yaml#

Documentation/devicetree/bindings/pwm/eswin,eic7700-pwm.yaml line 14

Quoted 10 lines
Documentation/devicetree/bindings/pwm/eswin,eic7700-pwm.yaml new file +10 -0
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ESWIN EIC7700 PWM controller
+
+maintainers:
+  - Xiang Xu <[email protected]>
+  - Guosheng Wang <[email protected]>
+  - Xuyang Dong <[email protected]>
+
+description: |

Do not need '|' unless you need to preserve formatting.

Documentation/devicetree/bindings/pwm/eswin,eic7700-pwm.yaml line 16

Quoted 2 lines
Documentation/devicetree/bindings/pwm/eswin,eic7700-pwm.yaml new file +2 -0
+  The EIC7700 PWM used the DesignWare APB timers module. The PWM driver
+  supports a duty cycle range from 0% to 100%, with explicit support for

Driver is irrelevant here. Describe hardware.

Quoted 30 lines
Documentation/devicetree/bindings/pwm/eswin,eic7700-pwm.yaml new file +30 -0
+  both 0% and 100% duty cycles.
+
+allOf:
+  - $ref: pwm.yaml#
+
+properties:
+  compatible:
+    const: eswin,eic7700-pwm
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  resets:
+    maxItems: 1
+
+  "#pwm-cells":
+    const: 3
+
+  pinctrl-0: true
+  pinctrl-1: true
+
+  pinctrl-names:
+    minItems: 1
+    items:
+      - const: default
+      - const: sleep
+
Quoted 9 lines

Documentation/devicetree/bindings/pwm/eswin,eic7700-pwm.yaml line 47

Quoted 1 line
Documentation/devicetree/bindings/pwm/eswin,eic7700-pwm.yaml new file +1 -0
+  snps,pwm-full-range-enable:

1. Wrong vendor prefix, thats eswin, not snps.
2. Why is this a hardware property? I really do not see that. You described the desired Linux feature or behavior, not the actual hardware. The bindings are about the latter, so instead you need to rephrase the property and its description to match actual hardware capabilities/features/configuration etc.

Hi Krzysztof and Ben,

There is a patch [1] submmitted by Ben Dook a few years ago. The intention of this patch is to make DWC pwm controller can be used as platform driver. This is what we are currently working on. It seems that it would be more reasonable to continue improving this patch and make the DWC PWM driver universal, rather than creating a separate ESWIN PWM driver.

The DWC pwm 2.13a version supports "Pulse Width Modulation with 0% and 100% Duty Cycle" by programming TIMER_0N100PWM_EN bit field. We also want to support this new hardware feature. So, adding a new property, like snps,timer-0n100pwm-en, in pwm/snps,dw-apb-timers-pwm2.yaml would be better?

Krzysztof and Ben, do you think the above approach is reasonable and acceptable?

[1] https://lore.kernel.org/lkml/[email protected]/

Regards,
Xuyang Dong

#4 lore raw

Re: [PATCH 1/2] dt-bindings: pwm: eswin: Add EIC7700 pwm controller

Quoted 28 lines · Xuyang Dong
Quoted 10 lines
Quoted 10 lines
Documentation/devicetree/bindings/pwm/eswin,eic7700-pwm.yaml new file +10 -0
+
+  pinctrl-0: true
+  pinctrl-1: true
+
+  pinctrl-names:
+    minItems: 1
+    items:
+      - const: default
+      - const: sleep
+
Quoted 9 lines
Quoted 1 line

+ snps,pwm-full-range-enable:

1. Wrong vendor prefix, thats eswin, not snps.
2. Why is this a hardware property? I really do not see that. You described the desired Linux feature or behavior, not the actual hardware. The bindings are about the latter, so instead you need to rephrase the property and its description to match actual hardware capabilities/features/configuration etc.

Hi Krzysztof and Ben,

There is a patch [1] submmitted by Ben Dook a few years ago. The intention of this patch is to make DWC pwm controller can be used as platform driver. This is what we are currently working on. It seems that it would be more reasonable to continue improving this patch and make the DWC PWM driver universal, rather than creating a separate ESWIN PWM driver.

Quoted 7 lines

The DWC pwm 2.13a version supports "Pulse Width Modulation with 0% and 100% Duty Cycle" by programming TIMER_0N100PWM_EN bit field. We also want to support this new hardware feature. So, adding a new property, like snps,timer-0n100pwm-en, in pwm/snps,dw-apb-timers-pwm2.yaml would be better?

Krzysztof and Ben, do you think the above approach is reasonable and acceptable?

How any of this is related to the binding? We talk here about hardware and binding, but you ask me about driver.... I don't care.

Best regards,
Krzysztof

#5 lore raw

PATCH 2/2 pwm: eswin: Add EIC7700 pwm driver

In reply to [email protected]

From: Xuyang Dong <[email protected]>

Introduce driver for PWM module available on EIC7700 SoC. Add snps,pwm-0-n-100-percent flag to support for both 0% and 100% duty cycles. And remove this flag to support the duty cycle range from 0% to 100%.

---
 drivers/pwm/Kconfig           |  12 ++
 drivers/pwm/Makefile          |   1 +
 drivers/pwm/pwm-dwc-core.c    |  76 ++++++++---
 drivers/pwm/pwm-dwc-eic7700.c | 231 ++++++++++++++++++++++++++++++++++
 drivers/pwm/pwm-dwc.h         |  16 ++-
 5 files changed, 311 insertions(+), 25 deletions(-)
 create mode 100644 drivers/pwm/pwm-dwc-eic7700.c
drivers/pwm/Kconfig +12 -0
index bf2d101f67a1..c2cf0d9c9854 100644
@@ -249,6 +249,18 @@ config PWM_DWC
 	  To compile this driver as a module, choose M here: the module
 	  will be called pwm-dwc.
 
+config PWM_EIC7700
+	tristate "EIC7700 PWM Controller"
+	depends on ARCH_ESWIN || COMPILE_TEST
+	depends on HAS_IOMEM
+	select PWM_DWC_CORE
+	help
+	  PWM driver for Synopsys DWC PWM Controller on a platform for EIC7700
+	  SoCs.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called pwm-dwc-eic7700.
+
 config PWM_EP93XX
 	tristate "Cirrus Logic EP93xx PWM support"
 	depends on ARCH_EP93XX || COMPILE_TEST
drivers/pwm/Makefile +1 -0
index 0dc0d2b69025..2b4b7a5c5b15 100644
@@ -20,6 +20,7 @@ obj-$(CONFIG_PWM_CRC)		+= pwm-crc.o
 obj-$(CONFIG_PWM_CROS_EC)	+= pwm-cros-ec.o
 obj-$(CONFIG_PWM_DWC_CORE)	+= pwm-dwc-core.o
 obj-$(CONFIG_PWM_DWC)		+= pwm-dwc.o
+obj-$(CONFIG_PWM_EIC7700)	+= pwm-dwc-eic7700.o
 obj-$(CONFIG_PWM_EP93XX)	+= pwm-ep93xx.o
 obj-$(CONFIG_PWM_FSL_FTM)	+= pwm-fsl-ftm.o
 obj-$(CONFIG_PWM_GPIO)		+= pwm-gpio.o
drivers/pwm/pwm-dwc-core.c +57 -19

100 lines not on this page · raw message

drivers/pwm/pwm-dwc-eic7700.c new file +231 -0

231 lines not on this page · raw message

drivers/pwm/pwm-dwc.h +10 -6
index 1562594e7f85..27d567e82ac0 100644
@@ -26,12 +26,13 @@ MODULE_IMPORT_NS("dwc_pwm");
 #define DWC_TIMERS_TOTAL	8
 
 /* Timer Control Register */
-#define DWC_TIM_CTRL_EN		BIT(0)
-#define DWC_TIM_CTRL_MODE	BIT(1)
-#define DWC_TIM_CTRL_MODE_FREE	(0 << 1)
-#define DWC_TIM_CTRL_MODE_USER	(1 << 1)
-#define DWC_TIM_CTRL_INT_MASK	BIT(2)
-#define DWC_TIM_CTRL_PWM	BIT(3)
+#define DWC_TIM_CTRL_EN			BIT(0)
+#define DWC_TIM_CTRL_MODE		BIT(1)
+#define DWC_TIM_CTRL_MODE_FREE		(0 << 1)
+#define DWC_TIM_CTRL_MODE_USER		BIT(1)
+#define DWC_TIM_CTRL_INT_MASK		BIT(2)
+#define DWC_TIM_CTRL_PWM		BIT(3)
+#define DWC_TIM_CTRL_0N100PWM_EN	BIT(4)
 
 struct dwc_pwm_info {
 	unsigned int nr;
@@ -53,6 +54,9 @@ struct dwc_pwm_ctx {
 struct dwc_pwm {
 	void __iomem *base;
 	unsigned int clk_ns;
+	struct clk *clk;
+	struct reset_control *rst;
+	bool pwm_0n100_enable;
 	struct dwc_pwm_ctx ctx[DWC_TIMERS_TOTAL];
 };
 
Signature · 1 line
2.34.1
#6 lore raw

Re: [PATCH 2/2] pwm: eswin: Add EIC7700 pwm driver

kernel test robot noticed the following build warnings:

Hi,

kernel test robot noticed the following build warnings:

[auto build test WARNING on robh/for-next]
[also build test WARNING on linus/master v6.18 next-20251205] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/dongxuyang-eswincomputing-com/dt-bindings-pwm-eswin-Add-EIC7700-pwm-controller/20251205-171328
base:   https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
patch link:    https://lore.kernel.org/r/20251205090509.1501-1-dongxuyang%40eswincomputing.com
patch subject: [PATCH 2/2] pwm: eswin: Add EIC7700 pwm driver
config: m68k-allmodconfig (https://download.01.org/0day-ci/archive/20251206/[email protected]/config)
compiler: m68k-linux-gcc (GCC) 15.1.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251206/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All warnings (new ones prefixed by >>):

drivers/pwm/pwm-dwc-core.c: In function '__dwc_pwm_configure_timer':

>> drivers/pwm/pwm-dwc-core.c:54:43: warning: left shift count >= width of type [-Wshift-count-overflow]
      54 |                 if (tmp < 0 || tmp > (1UL << 32))
         |                                           ^~
   drivers/pwm/pwm-dwc-core.c:64:43: warning: left shift count >= width of type [-Wshift-count-overflow]
      64 |                 if (tmp < 0 || tmp > (1UL << 32))
         |                                           ^~

vim +54 drivers/pwm/pwm-dwc-core.c

    37	
    38	static int __dwc_pwm_configure_timer(struct dwc_pwm *dwc,
    39					     struct pwm_device *pwm,
    40					     const struct pwm_state *state)
    41	{
    42		u64 tmp;
    43		u32 ctrl;
    44		u32 high;
    45		u32 low;
    46	
    47		if (dwc->pwm_0n100_enable) {
    48			/*
    49			 * Calculate width of low and high period in terms of input
    50			 * clock periods and check are the result within HW limits
    51			 * between 0 and 2^32 periods.
    52			 */
    53			tmp = DIV_ROUND_CLOSEST_ULL(state->duty_cycle, dwc->clk_ns);
  > 54			if (tmp < 0 || tmp > (1UL << 32))
    55				return -ERANGE;
    56	
    57			if (pwm->args.polarity == PWM_POLARITY_INVERSED)
    58				high = tmp;
    59			else
    60				low = tmp;
    61	
    62			tmp = DIV_ROUND_CLOSEST_ULL(state->period - state->duty_cycle,
    63						    dwc->clk_ns);
    64			if (tmp < 0 || tmp > (1UL << 32))
    65				return -ERANGE;
    66	
    67			if (pwm->args.polarity == PWM_POLARITY_INVERSED)
    68				low = tmp;
    69			else
    70				high = tmp;
    71		} else {
    72			/*
    73			 * Calculate width of low and high period in terms of input
    74			 * clock periods and check are the result within HW limits
    75			 * between 1 and 2^32 periods.
    76			 */
    77			tmp = DIV_ROUND_CLOSEST_ULL(state->duty_cycle, dwc->clk_ns);
    78			if (tmp < 1 || tmp > (1ULL << 32))
    79				return -ERANGE;
    80			low = tmp - 1;
    81	
    82			tmp = DIV_ROUND_CLOSEST_ULL(state->period - state->duty_cycle,
    83						    dwc->clk_ns);
    84			if (tmp < 1 || tmp > (1ULL << 32))
    85				return -ERANGE;
    86			high = tmp - 1;
    87		}
    88	
    89		/*
    90		 * Specification says timer usage flow is to disable timer, then
    91		 * program it followed by enable. It also says Load Count is loaded
    92		 * into timer after it is enabled - either after a disable or
    93		 * a reset. Based on measurements it happens also without disable
    94		 * whenever Load Count is updated. But follow the specification.
    95		 */
    96		__dwc_pwm_set_enable(dwc, pwm->hwpwm, false);
    97	
    98		/*
    99		 * Write Load Count and Load Count 2 registers. Former defines the

100 * width of low period and latter the width of high period in terms
101 * multiple of input clock periods:
102 * Width = ((Count + 1) * input clock period) or
103 * Width = (Count * input clock period) : supported 0% and 100%).
104 */
105 dwc_pwm_writel(dwc, low, DWC_TIM_LD_CNT(pwm->hwpwm));
106 dwc_pwm_writel(dwc, high, DWC_TIM_LD_CNT2(pwm->hwpwm));
107
108 /*
109 * Set user-defined mode, timer reloads from Load Count registers
110 * when it counts down to 0.
111 * Set PWM mode, it makes output to toggle and width of low and high
112 * periods are set by Load Count registers.
113 */
114 ctrl = DWC_TIM_CTRL_MODE_USER | DWC_TIM_CTRL_PWM;
115 if (dwc->pwm_0n100_enable)
116 ctrl |= DWC_TIM_CTRL_0N100PWM_EN;
117
118 dwc_pwm_writel(dwc, ctrl, DWC_TIM_CTRL(pwm->hwpwm));
119
120 /*
121 * Enable timer. Output starts from low period.
122 */
123 __dwc_pwm_set_enable(dwc, pwm->hwpwm, state->enabled);
124
125 return 0;
126 }
127

Signature · 2 lines
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
#7 lore raw

Re: [PATCH 2/2] pwm: eswin: Add EIC7700 pwm driver

In reply to [email protected]

On Fri, Dec 05, 2025 at 05:05:09PM +0800, [email protected] wrote:
+ *

drivers/pwm/pwm-dwc-eic7700.c line 26

Quoted 9 lines

+ * Limitations:
+ * - The duty cycle and period cannot both be set to 0.
+ * - The controller hardware provides up to 3 PWM channels.
+ */

drivers/pwm/pwm-dwc-eic7700.c new file +5 -0
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>

Where do you use half of above headers?

Quoted 27 lines
drivers/pwm/pwm-dwc-eic7700.c new file +27 -0
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/pwm.h>
+#include <linux/reset.h>
+
+#include "pwm-dwc.h"
+
+#define DW_PWMS_TOTAL	3
+
+static int eic7700_pwm_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct dwc_pwm_drvdata *data;
+	struct pwm_chip *chip = NULL;
+	struct dwc_pwm *dwc = NULL;
+	int ret;
+
+	data = devm_kzalloc(dev, sizeof(data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	chip = dwc_pwm_alloc(dev);
+	if (IS_ERR(chip))
+		return dev_err_probe(dev, -ENOMEM, "failed to alloc pwm\n");
+
+	dwc = to_dwc_pwm(chip);

drivers/pwm/pwm-dwc-eic7700.c line 63

Quoted 10 lines
drivers/pwm/pwm-dwc-eic7700.c new file +10 -0
+
+	if (of_property_read_bool(dev->of_node, "snps,pwm-full-range-enable"))
+		dwc->pwm_0n100_enable = true;
+
+	dwc->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(dwc->base))
+		return dev_err_probe(dev, PTR_ERR(dwc->base),
+				     "failed to get base\n");
+
+	dwc->clk = devm_clk_get(dev, NULL);

Just use the enabled varian and drop below prepare enable call.

Quoted 148 lines
drivers/pwm/pwm-dwc-eic7700.c new file +148 -0
+	if (IS_ERR(dwc->clk))
+		return dev_err_probe(dev, PTR_ERR(dwc->clk),
+				     "failed to get clock\n");
+
+	ret = clk_prepare_enable(dwc->clk);
+	if (ret)
+		return dev_err_probe(dev, ret, "failed to enable clock\n");
+
+	dwc->rst = devm_reset_control_get_exclusive(&pdev->dev, NULL);
+	if (IS_ERR(dwc->rst)) {
+		dev_err(dev, "failed to get reset control\n");
+		ret = PTR_ERR(dwc->rst);
+		goto err_clk_disable;
+	}
+
+	ret = reset_control_deassert(dwc->rst);
+	if (ret) {
+		dev_err(dev, "failed to deassert reset: %d\n", ret);
+		goto err_clk_disable;
+	}
+
+	ret = devm_pwmchip_add(dev, chip);
+	if (ret) {
+		dev_err(dev, "failed to add pwmchip: %d\n", ret);
+		goto err_reset_assert;
+	}
+
+	data->chips[0] = chip;
+	dev_set_drvdata(dev, data);
+
+	pm_runtime_set_active(dev);
+	pm_runtime_enable(dev);
+	pm_runtime_get_noresume(dev);
+
+	return 0;
+
+err_reset_assert:
+	reset_control_assert(dwc->rst);
+err_clk_disable:
+	clk_disable_unprepare(dwc->clk);
+
+	return ret;
+}
+
+static void eic7700_pwm_remove(struct platform_device *pdev)
+{
+	struct dwc_pwm_drvdata *data = platform_get_drvdata(pdev);
+	struct pwm_chip *chip = data->chips[0];
+	struct dwc_pwm *dwc = to_dwc_pwm(chip);
+	struct device *dev = &pdev->dev;
+
+	clk_disable_unprepare(dwc->clk);
+	reset_control_assert(dwc->rst);
+
+	pm_runtime_put_sync(dev);
+	pm_runtime_disable(dev);
+}
+
+static int eic7700_pwm_runtime_suspend(struct device *dev)
+{
+	struct dwc_pwm_drvdata *data = dev_get_drvdata(dev);
+	struct pwm_chip *chip = data->chips[0];
+	struct dwc_pwm *dwc = to_dwc_pwm(chip);
+	int idx, ret;
+
+	for (idx = 0; idx < DW_PWMS_TOTAL; idx++) {
+		if (chip->pwms[idx].state.enabled)
+			return -EBUSY;
+
+		dwc->ctx[idx].cnt = dwc_pwm_readl(dwc, DWC_TIM_LD_CNT(idx));
+		dwc->ctx[idx].cnt2 = dwc_pwm_readl(dwc, DWC_TIM_LD_CNT2(idx));
+		dwc->ctx[idx].ctrl = dwc_pwm_readl(dwc, DWC_TIM_CTRL(idx));
+	}
+
+	clk_disable_unprepare(dwc->clk);
+	ret = pinctrl_pm_select_sleep_state(dev);
+	if (ret) {
+		dev_err(dev, "failed to select sleep state: %d\n", ret);
+		clk_prepare_enable(dwc->clk);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int eic7700_pwm_runtime_resume(struct device *dev)
+{
+	struct dwc_pwm_drvdata *data = dev_get_drvdata(dev);
+	struct pwm_chip *chip = data->chips[0];
+	struct dwc_pwm *dwc = to_dwc_pwm(chip);
+	int idx, ret;
+
+	ret = pinctrl_pm_select_default_state(dev);
+	if (ret) {
+		dev_err(dev, "failed to select default state: %d\n", ret);
+		return ret;
+	}
+
+	ret = clk_prepare_enable(dwc->clk);
+	if (ret) {
+		dev_err(dev, "failed to enable clock: %d\n", ret);
+		return ret;
+	}
+
+	for (idx = 0; idx < DW_PWMS_TOTAL; idx++) {
+		dwc_pwm_writel(dwc, dwc->ctx[idx].cnt, DWC_TIM_LD_CNT(idx));
+		dwc_pwm_writel(dwc, dwc->ctx[idx].cnt2, DWC_TIM_LD_CNT2(idx));
+		dwc_pwm_writel(dwc, dwc->ctx[idx].ctrl, DWC_TIM_CTRL(idx));
+	}
+
+	return 0;
+}
+
+static int eic7700_pwm_suspend(struct device *dev)
+{
+	int ret;
+
+	if (!pm_runtime_suspended(dev)) {
+		ret = eic7700_pwm_runtime_suspend(dev);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int eic7700_pwm_resume(struct device *dev)
+{
+	int ret;
+
+	if (!pm_runtime_suspended(dev)) {
+		ret = eic7700_pwm_runtime_resume(dev);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static const struct dev_pm_ops eic7700_pwm_pm_ops = {
+	RUNTIME_PM_OPS(eic7700_pwm_runtime_suspend, eic7700_pwm_runtime_resume,
+		       NULL)
+	SYSTEM_SLEEP_PM_OPS(eic7700_pwm_suspend, eic7700_pwm_resume)
+};
+
+static const struct of_device_id eic7700_pwm_id_table[] = {
+	{ .compatible = "eswin,eic7700-pwm", },
+	{ /* sentinel */ }

drivers/pwm/pwm-dwc-eic7700.c line 221

Quoted 10 lines
drivers/pwm/pwm-dwc-eic7700.c new file +10 -0
+};
+MODULE_DEVICE_TABLE(of, eic7700_pwm_id_table);
+
+static struct platform_driver eic7700_pwm_driver = {
+	.probe = eic7700_pwm_probe,
+	.remove = eic7700_pwm_remove,
+	.driver = {
+		.name	= "eic7700-pwm",
+		.pm = pm_sleep_ptr(&eic7700_pwm_pm_ops),
+		.of_match_table = of_match_ptr(eic7700_pwm_id_table),

Drop of_match_ptr, you have warning here. Look at other drivers how they do it.

Best regards,
Krzysztof