Skip to content

Commit cc1cd4d

Browse files
anthonytexdleach02
authored andcommitted
arm: Nxp imx6sx added PWM support
This commit adds support for IMX6SX PWM. The PWM module is the same module present on the IMX7D and so dts bindings has been renamed following the one present on linux. Signed-off-by: Antonio Tessarolo <[email protected]>
1 parent ee6c552 commit cc1cd4d

File tree

10 files changed

+312
-10
lines changed

10 files changed

+312
-10
lines changed

drivers/pwm/pwm_imx.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ static const struct pwm_driver_api imx_pwm_driver_api = {
172172
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
173173
&imx_pwm_driver_api);
174174

175-
#if DT_HAS_COMPAT_STATUS_OKAY(fsl_imx7d_pwm)
176-
#define DT_DRV_COMPAT fsl_imx7d_pwm
175+
#if DT_HAS_COMPAT_STATUS_OKAY(fsl_imx27_pwm)
176+
#define DT_DRV_COMPAT fsl_imx27_pwm
177177
DT_INST_FOREACH_STATUS_OKAY(PWM_IMX_INIT)
178178
#endif

dts/arm/nxp/nxp_imx6sx_m4.dtsi

+113
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,119 @@
339339
label = "I2C_4";
340340
status = "disabled";
341341
};
342+
343+
pwm1: pwm@42080000 {
344+
compatible = "fsl,imx6sx-pwm", "fsl,imx27-pwm";
345+
reg = <0x42080000 0x4000>;
346+
interrupts = <83 0>;
347+
rdc = <(RDC_DOMAIN_PERM(A9_DOMAIN_ID,\
348+
RDC_DOMAIN_PERM_RW)|\
349+
RDC_DOMAIN_PERM(M4_DOMAIN_ID,\
350+
RDC_DOMAIN_PERM_RW))>;
351+
label = "PWM_1";
352+
prescaler = <0>;
353+
#pwm-cells = <2>;
354+
status = "disabled";
355+
};
356+
357+
pwm2: pwm@42084000 {
358+
compatible = "fsl,imx6sx-pwm", "fsl,imx27-pwm";
359+
reg = <0x42084000 0x4000>;
360+
interrupts = <84 0>;
361+
rdc = <(RDC_DOMAIN_PERM(A9_DOMAIN_ID,\
362+
RDC_DOMAIN_PERM_RW)|\
363+
RDC_DOMAIN_PERM(M4_DOMAIN_ID,\
364+
RDC_DOMAIN_PERM_RW))>;
365+
label = "PWM_2";
366+
prescaler = <0>;
367+
#pwm-cells = <2>;
368+
status = "disabled";
369+
};
370+
371+
pwm3: pwm@42088000 {
372+
compatible = "fsl,imx6sx-pwm", "fsl,imx27-pwm";
373+
reg = <0x42088000 0x4000>;
374+
interrupts = <85 0>;
375+
rdc = <(RDC_DOMAIN_PERM(A9_DOMAIN_ID,\
376+
RDC_DOMAIN_PERM_RW)|\
377+
RDC_DOMAIN_PERM(M4_DOMAIN_ID,\
378+
RDC_DOMAIN_PERM_RW))>;
379+
label = "PWM_3";
380+
prescaler = <0>;
381+
#pwm-cells = <2>;
382+
status = "disabled";
383+
};
384+
385+
pwm4: pwm@4208c000 {
386+
compatible = "fsl,imx6sx-pwm", "fsl,imx27-pwm";
387+
reg = <0x4208c000 0x4000>;
388+
interrupts = <86 0>;
389+
rdc = <(RDC_DOMAIN_PERM(A9_DOMAIN_ID,\
390+
RDC_DOMAIN_PERM_RW)|\
391+
RDC_DOMAIN_PERM(M4_DOMAIN_ID,\
392+
RDC_DOMAIN_PERM_RW))>;
393+
label = "PWM_4";
394+
prescaler = <0>;
395+
#pwm-cells = <2>;
396+
status = "disabled";
397+
};
398+
399+
400+
pwm5: pwm@422a4000 {
401+
compatible = "fsl,imx6sx-pwm", "fsl,imx27-pwm";
402+
reg = <0x422a4000 0x4000>;
403+
interrupts = <83 0>;
404+
rdc = <(RDC_DOMAIN_PERM(A9_DOMAIN_ID,\
405+
RDC_DOMAIN_PERM_RW)|\
406+
RDC_DOMAIN_PERM(M4_DOMAIN_ID,\
407+
RDC_DOMAIN_PERM_RW))>;
408+
label = "PWM_5";
409+
prescaler = <0>;
410+
#pwm-cells = <2>;
411+
status = "disabled";
412+
};
413+
414+
pwm6: pwm@422a8000 {
415+
compatible = "fsl,imx6sx-pwm", "fsl,imx27-pwm";
416+
reg = <0x422a8000 0x4000>;
417+
interrupts = <84 0>;
418+
rdc = <(RDC_DOMAIN_PERM(A9_DOMAIN_ID,\
419+
RDC_DOMAIN_PERM_RW)|\
420+
RDC_DOMAIN_PERM(M4_DOMAIN_ID,\
421+
RDC_DOMAIN_PERM_RW))>;
422+
label = "PWM_6";
423+
prescaler = <0>;
424+
#pwm-cells = <2>;
425+
status = "disabled";
426+
};
427+
428+
pwm7: pwm@422ac000 {
429+
compatible = "fsl,imx6sx-pwm", "fsl,imx27-pwm";
430+
reg = <0x422ac000 0x4000>;
431+
interrupts = <85 0>;
432+
rdc = <(RDC_DOMAIN_PERM(A9_DOMAIN_ID,\
433+
RDC_DOMAIN_PERM_RW)|\
434+
RDC_DOMAIN_PERM(M4_DOMAIN_ID,\
435+
RDC_DOMAIN_PERM_RW))>;
436+
label = "PWM_7";
437+
prescaler = <0>;
438+
#pwm-cells = <2>;
439+
status = "disabled";
440+
};
441+
442+
pwm8: pwm@422ab000 {
443+
compatible = "fsl,imx6sx-pwm", "fsl,imx27-pwm";
444+
reg = <0x422ab000 0x4000>;
445+
interrupts = <86 0>;
446+
rdc = <(RDC_DOMAIN_PERM(A9_DOMAIN_ID,\
447+
RDC_DOMAIN_PERM_RW)|\
448+
RDC_DOMAIN_PERM(M4_DOMAIN_ID,\
449+
RDC_DOMAIN_PERM_RW))>;
450+
label = "PWM_8";
451+
prescaler = <0>;
452+
#pwm-cells = <2>;
453+
status = "disabled";
454+
};
342455
};
343456
};
344457

dts/arm/nxp/nxp_imx7d_m4.dtsi

+4-4
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@
331331
};
332332

333333
pwm1: pwm@30660000 {
334-
compatible = "fsl,imx7d-pwm";
334+
compatible = "fsl,imx7d-pwm", "fsl,imx27-pwm";
335335
reg = <0x30660000 0x10000>;
336336
interrupts = <81 0>;
337337
prescaler = <0>;
@@ -345,7 +345,7 @@
345345
};
346346

347347
pwm2: pwm@30670000 {
348-
compatible = "fsl,imx7d-pwm";
348+
compatible = "fsl,imx7d-pwm", "fsl,imx27-pwm";
349349
reg = <0x30670000 0x10000>;
350350
interrupts = <82 0>;
351351
prescaler = <0>;
@@ -359,7 +359,7 @@
359359
};
360360

361361
pwm3: pwm@30680000 {
362-
compatible = "fsl,imx7d-pwm";
362+
compatible = "fsl,imx7d-pwm", "fsl,imx27-pwm";
363363
reg = <0x30680000 0x10000>;
364364
interrupts = <83 0>;
365365
prescaler = <0>;
@@ -373,7 +373,7 @@
373373
};
374374

375375
pwm4: pwm@30690000 {
376-
compatible = "fsl,imx7d-pwm";
376+
compatible = "fsl,imx7d-pwm", "fsl,imx27-pwm";
377377
reg = <0x30690000 0x10000>;
378378
interrupts = <84 0>;
379379
prescaler = <0>;

dts/bindings/pwm/fsl,imx7d-pwm.yaml renamed to dts/bindings/pwm/fsl,imx27-pwm.yaml

+8-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
# Copyright (c) 2018, Diego Sueiro <[email protected]>
22
# SPDX-License-Identifier: Apache-2.0
33

4-
description: i.MX7D PWM
5-
6-
compatible: "fsl,imx7d-pwm"
4+
description: |
5+
This driver supports both i.MX6SX and i.MX7D PWM.
6+
The compatible string is named "imx27" because the hardware module is the
7+
same module present starting from imx27 CPUs and this driver can potentially
8+
support other CPUs with imx27 module. This is also the same string used
9+
in the Linux kernel.
10+
11+
compatible: "fsl,imx27-pwm"
712

813
include: [pwm-controller.yaml, base.yaml]
914

soc/arm/nxp_imx/mcimx6x_m4/CMakeLists.txt

+4-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,7 @@
44
# SPDX-License-Identifier: Apache-2.0
55
#
66

7-
zephyr_sources(soc.c)
7+
zephyr_sources(
8+
soc.c
9+
soc_clk_freq.c
10+
)

soc/arm/nxp_imx/mcimx6x_m4/Kconfig.defconfig.mcimx6x_m4

+4
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,8 @@ config COUNTER_IMX_EPIT
3131
default y
3232
depends on COUNTER
3333

34+
config PWM_IMX
35+
default y
36+
depends on PWM
37+
3438
endif # SOC_MCIMX6X_M4

soc/arm/nxp_imx/mcimx6x_m4/soc.c

+67
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,39 @@ static void SOC_RdcInit(void)
104104
/* Set access to I2C-4 for M4 core */
105105
RDC_SetPdapAccess(RDC, rdcPdapI2c4, RDC_DT_VAL(i2c4), false, false);
106106
#endif
107+
108+
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm1), okay)
109+
/* Set access to PWM-1 for M4 core */
110+
RDC_SetPdapAccess(RDC, rdcPdapPwm1, RDC_DT_VAL(pwm1), false, false);
111+
#endif
112+
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm2), okay)
113+
/* Set access to PWM-2 for M4 core */
114+
RDC_SetPdapAccess(RDC, rdcPdapPwm2, RDC_DT_VAL(pwm2), false, false);
115+
#endif
116+
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm3), okay)
117+
/* Set access to PWM-3 for M4 core */
118+
RDC_SetPdapAccess(RDC, rdcPdapPwm3, RDC_DT_VAL(pwm3), false, false);
119+
#endif
120+
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm4), okay)
121+
/* Set access to PWM-4 for M4 core */
122+
RDC_SetPdapAccess(RDC, rdcPdapPwm4, RDC_DT_VAL(pwm4), false, false);
123+
#endif
124+
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm5), okay)
125+
/* Set access to PWM-5 for M4 core */
126+
RDC_SetPdapAccess(RDC, rdcPdapPwm5, RDC_DT_VAL(pwm5), false, false);
127+
#endif
128+
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm6), okay)
129+
/* Set access to PWM-6 for M4 core */
130+
RDC_SetPdapAccess(RDC, rdcPdapPwm6, RDC_DT_VAL(pwm6), false, false);
131+
#endif
132+
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm7), okay)
133+
/* Set access to PWM-7 for M4 core */
134+
RDC_SetPdapAccess(RDC, rdcPdapPwm7, RDC_DT_VAL(pwm7), false, false);
135+
#endif
136+
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm8), okay)
137+
/* Set access to PWM-8 for M4 core */
138+
RDC_SetPdapAccess(RDC, rdcPdapPwm8, RDC_DT_VAL(pwm8), false, false);
139+
#endif
107140
}
108141

109142
/* Initialize cache. */
@@ -196,7 +229,41 @@ static void SOC_ClockInit(void)
196229
#if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c4), okay)
197230
CCM_ControlGate(CCM, ccmCcgrGateI2c4Serialclk, ccmClockNeededAll);
198231
#endif
232+
#endif /* CONFIG_I2C_IMX */
233+
234+
#ifdef CONFIG_PWM_IMX
235+
/* Select PWM clock is derived from OSC (24M) */
236+
CCM_SetRootMux(CCM, ccmRootPerclkClkSel, ccmRootmuxPerclkClkOsc24m);
237+
238+
/* Set relevant divider = 1. */
239+
CCM_SetRootDivider(CCM, ccmRootPerclkPodf, 0);
240+
241+
/* Enable PWM clock */
242+
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm1), okay)
243+
CCM_ControlGate(CCM, ccmCcgrGatePwm1Clk, ccmClockNeededAll);
244+
#endif
245+
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm2), okay)
246+
CCM_ControlGate(CCM, ccmCcgrGatePwm2Clk, ccmClockNeededAll);
247+
#endif
248+
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm3), okay)
249+
CCM_ControlGate(CCM, ccmCcgrGatePwm3Clk, ccmClockNeededAll);
250+
#endif
251+
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm4), okay)
252+
CCM_ControlGate(CCM, ccmCcgrGatePwm4Clk, ccmClockNeededAll);
253+
#endif
254+
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm5), okay)
255+
CCM_ControlGate(CCM, ccmCcgrGatePwm5Clk, ccmClockNeededAll);
256+
#endif
257+
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm6), okay)
258+
CCM_ControlGate(CCM, ccmCcgrGatePwm6Clk, ccmClockNeededAll);
259+
#endif
260+
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm7), okay)
261+
CCM_ControlGate(CCM, ccmCcgrGatePwm7Clk, ccmClockNeededAll);
262+
#endif
263+
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm8), okay)
264+
CCM_ControlGate(CCM, ccmCcgrGatePwm8Clk, ccmClockNeededAll);
199265
#endif
266+
#endif /* CONFIG_PWM_IMX */
200267
}
201268

202269
/**

soc/arm/nxp_imx/mcimx6x_m4/soc.h

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "rdc_defs_imx6sx.h"
1414
#include "ccm_imx6sx.h"
1515
#include "clock_freq.h"
16+
#include "soc_clk_freq.h"
1617

1718
#endif /* !_ASMLANGUAGE */
1819

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* Copyright (c) 2021, Antonio Tessarolo
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <ccm_imx6sx.h>
8+
#include <ccm_analog_imx6sx.h>
9+
#include "soc_clk_freq.h"
10+
11+
#ifdef CONFIG_PWM_IMX
12+
13+
uint32_t get_pwm_clock_freq(PWM_Type *base)
14+
{
15+
uint32_t root;
16+
uint32_t hz;
17+
uint32_t divPerclkPodf, divIpgPodf, divAhbPodf, divPeriphClk2Podf;
18+
19+
/* Different instance has the same clock root, it's different from i.mx7d. */
20+
/* Get the clock root according to the mux node of clock tree. */
21+
if (CCM_GetRootMux(CCM, ccmRootPerclkClkSel) ==
22+
ccmRootmuxPerclkClkOsc24m) {
23+
root = ccmRootmuxPerclkClkOsc24m;
24+
hz = 24000000;
25+
divPerclkPodf = CCM_GetRootDivider(CCM, ccmRootPerclkPodf);
26+
divIpgPodf = 0;
27+
divAhbPodf = 0;
28+
divPeriphClk2Podf = 0;
29+
} else if (CCM_GetRootMux(CCM, ccmRootPeriphClkSel) ==
30+
ccmRootmuxPeriphClkPrePeriphClkSel) {
31+
root = CCM_GetRootMux(CCM, ccmRootPrePeriphClkSel);
32+
/* Here do not show all the clock root source,
33+
* if user use other clock root source, such as PLL2_PFD2, please
34+
* add it as follows according to the clock tree of CCM in reference manual.
35+
*/
36+
switch (root) {
37+
case ccmRootmuxPrePeriphClkPll2:
38+
hz = CCM_ANALOG_GetPllFreq(CCM_ANALOG, ccmAnalogPllSysControl);
39+
divPerclkPodf = CCM_GetRootDivider(CCM, ccmRootPerclkPodf);
40+
divIpgPodf = CCM_GetRootDivider(CCM, ccmRootIpgPodf);
41+
divAhbPodf = CCM_GetRootDivider(CCM, ccmRootAhbPodf);
42+
divPeriphClk2Podf = 0;
43+
break;
44+
default:
45+
return 0;
46+
}
47+
} else if (CCM_GetRootMux(CCM, ccmRootPeriphClk2Sel) ==
48+
ccmRootmuxPeriphClk2OSC24m) {
49+
root = ccmRootmuxPeriphClk2OSC24m;
50+
hz = 24000000;
51+
divPerclkPodf = CCM_GetRootDivider(CCM, ccmRootPerclkPodf);
52+
divIpgPodf = CCM_GetRootDivider(CCM, ccmRootIpgPodf);
53+
divAhbPodf = CCM_GetRootDivider(CCM, ccmRootAhbPodf);
54+
divPeriphClk2Podf = CCM_GetRootDivider(CCM, ccmRootPeriphClk2Podf);
55+
} else {
56+
root = CCM_GetRootMux(CCM, ccmRootPll3SwClkSel);
57+
/* Here do not show all the clock root source,
58+
* if user use other clock root source, such as PLL3_BYP, please
59+
* add it as follows according to the clock tree of CCM in reference manual.
60+
*/
61+
switch (root) {
62+
case ccmRootmuxPll3SwClkPll3:
63+
hz = CCM_ANALOG_GetPllFreq(CCM_ANALOG, ccmAnalogPllUsb1Control);
64+
divPerclkPodf = CCM_GetRootDivider(CCM, ccmRootPerclkPodf);
65+
divIpgPodf = CCM_GetRootDivider(CCM, ccmRootIpgPodf);
66+
divAhbPodf = CCM_GetRootDivider(CCM, ccmRootAhbPodf);
67+
divPeriphClk2Podf =
68+
CCM_GetRootDivider(CCM, ccmRootPeriphClk2Podf);
69+
break;
70+
default:
71+
return 0;
72+
}
73+
}
74+
75+
return hz / (divPerclkPodf + 1) / (divIpgPodf + 1) /
76+
(divAhbPodf + 1) / (divPeriphClk2Podf + 1);
77+
}
78+
79+
#endif /* CONFIG_PWM_IMX */

0 commit comments

Comments
 (0)