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 <anthonytexdev@gmail.com>
This commit is contained in:
Antonio Tessarolo 2021-10-20 15:20:29 +02:00 committed by David Leach
commit cc1cd4d65b
10 changed files with 311 additions and 9 deletions

View file

@ -172,7 +172,7 @@ static const struct pwm_driver_api imx_pwm_driver_api = {
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
&imx_pwm_driver_api);
#if DT_HAS_COMPAT_STATUS_OKAY(fsl_imx7d_pwm)
#define DT_DRV_COMPAT fsl_imx7d_pwm
#if DT_HAS_COMPAT_STATUS_OKAY(fsl_imx27_pwm)
#define DT_DRV_COMPAT fsl_imx27_pwm
DT_INST_FOREACH_STATUS_OKAY(PWM_IMX_INIT)
#endif

View file

@ -339,6 +339,119 @@
label = "I2C_4";
status = "disabled";
};
pwm1: pwm@42080000 {
compatible = "fsl,imx6sx-pwm", "fsl,imx27-pwm";
reg = <0x42080000 0x4000>;
interrupts = <83 0>;
rdc = <(RDC_DOMAIN_PERM(A9_DOMAIN_ID,\
RDC_DOMAIN_PERM_RW)|\
RDC_DOMAIN_PERM(M4_DOMAIN_ID,\
RDC_DOMAIN_PERM_RW))>;
label = "PWM_1";
prescaler = <0>;
#pwm-cells = <2>;
status = "disabled";
};
pwm2: pwm@42084000 {
compatible = "fsl,imx6sx-pwm", "fsl,imx27-pwm";
reg = <0x42084000 0x4000>;
interrupts = <84 0>;
rdc = <(RDC_DOMAIN_PERM(A9_DOMAIN_ID,\
RDC_DOMAIN_PERM_RW)|\
RDC_DOMAIN_PERM(M4_DOMAIN_ID,\
RDC_DOMAIN_PERM_RW))>;
label = "PWM_2";
prescaler = <0>;
#pwm-cells = <2>;
status = "disabled";
};
pwm3: pwm@42088000 {
compatible = "fsl,imx6sx-pwm", "fsl,imx27-pwm";
reg = <0x42088000 0x4000>;
interrupts = <85 0>;
rdc = <(RDC_DOMAIN_PERM(A9_DOMAIN_ID,\
RDC_DOMAIN_PERM_RW)|\
RDC_DOMAIN_PERM(M4_DOMAIN_ID,\
RDC_DOMAIN_PERM_RW))>;
label = "PWM_3";
prescaler = <0>;
#pwm-cells = <2>;
status = "disabled";
};
pwm4: pwm@4208c000 {
compatible = "fsl,imx6sx-pwm", "fsl,imx27-pwm";
reg = <0x4208c000 0x4000>;
interrupts = <86 0>;
rdc = <(RDC_DOMAIN_PERM(A9_DOMAIN_ID,\
RDC_DOMAIN_PERM_RW)|\
RDC_DOMAIN_PERM(M4_DOMAIN_ID,\
RDC_DOMAIN_PERM_RW))>;
label = "PWM_4";
prescaler = <0>;
#pwm-cells = <2>;
status = "disabled";
};
pwm5: pwm@422a4000 {
compatible = "fsl,imx6sx-pwm", "fsl,imx27-pwm";
reg = <0x422a4000 0x4000>;
interrupts = <83 0>;
rdc = <(RDC_DOMAIN_PERM(A9_DOMAIN_ID,\
RDC_DOMAIN_PERM_RW)|\
RDC_DOMAIN_PERM(M4_DOMAIN_ID,\
RDC_DOMAIN_PERM_RW))>;
label = "PWM_5";
prescaler = <0>;
#pwm-cells = <2>;
status = "disabled";
};
pwm6: pwm@422a8000 {
compatible = "fsl,imx6sx-pwm", "fsl,imx27-pwm";
reg = <0x422a8000 0x4000>;
interrupts = <84 0>;
rdc = <(RDC_DOMAIN_PERM(A9_DOMAIN_ID,\
RDC_DOMAIN_PERM_RW)|\
RDC_DOMAIN_PERM(M4_DOMAIN_ID,\
RDC_DOMAIN_PERM_RW))>;
label = "PWM_6";
prescaler = <0>;
#pwm-cells = <2>;
status = "disabled";
};
pwm7: pwm@422ac000 {
compatible = "fsl,imx6sx-pwm", "fsl,imx27-pwm";
reg = <0x422ac000 0x4000>;
interrupts = <85 0>;
rdc = <(RDC_DOMAIN_PERM(A9_DOMAIN_ID,\
RDC_DOMAIN_PERM_RW)|\
RDC_DOMAIN_PERM(M4_DOMAIN_ID,\
RDC_DOMAIN_PERM_RW))>;
label = "PWM_7";
prescaler = <0>;
#pwm-cells = <2>;
status = "disabled";
};
pwm8: pwm@422ab000 {
compatible = "fsl,imx6sx-pwm", "fsl,imx27-pwm";
reg = <0x422ab000 0x4000>;
interrupts = <86 0>;
rdc = <(RDC_DOMAIN_PERM(A9_DOMAIN_ID,\
RDC_DOMAIN_PERM_RW)|\
RDC_DOMAIN_PERM(M4_DOMAIN_ID,\
RDC_DOMAIN_PERM_RW))>;
label = "PWM_8";
prescaler = <0>;
#pwm-cells = <2>;
status = "disabled";
};
};
};

View file

@ -331,7 +331,7 @@
};
pwm1: pwm@30660000 {
compatible = "fsl,imx7d-pwm";
compatible = "fsl,imx7d-pwm", "fsl,imx27-pwm";
reg = <0x30660000 0x10000>;
interrupts = <81 0>;
prescaler = <0>;
@ -345,7 +345,7 @@
};
pwm2: pwm@30670000 {
compatible = "fsl,imx7d-pwm";
compatible = "fsl,imx7d-pwm", "fsl,imx27-pwm";
reg = <0x30670000 0x10000>;
interrupts = <82 0>;
prescaler = <0>;
@ -359,7 +359,7 @@
};
pwm3: pwm@30680000 {
compatible = "fsl,imx7d-pwm";
compatible = "fsl,imx7d-pwm", "fsl,imx27-pwm";
reg = <0x30680000 0x10000>;
interrupts = <83 0>;
prescaler = <0>;
@ -373,7 +373,7 @@
};
pwm4: pwm@30690000 {
compatible = "fsl,imx7d-pwm";
compatible = "fsl,imx7d-pwm", "fsl,imx27-pwm";
reg = <0x30690000 0x10000>;
interrupts = <84 0>;
prescaler = <0>;

View file

@ -1,9 +1,14 @@
# Copyright (c) 2018, Diego Sueiro <diego.sueiro@gmail.com>
# SPDX-License-Identifier: Apache-2.0
description: i.MX7D PWM
description: |
This driver supports both i.MX6SX and i.MX7D PWM.
The compatible string is named "imx27" because the hardware module is the
same module present starting from imx27 CPUs and this driver can potentially
support other CPUs with imx27 module. This is also the same string used
in the Linux kernel.
compatible: "fsl,imx7d-pwm"
compatible: "fsl,imx27-pwm"
include: [pwm-controller.yaml, base.yaml]

View file

@ -4,4 +4,7 @@
# SPDX-License-Identifier: Apache-2.0
#
zephyr_sources(soc.c)
zephyr_sources(
soc.c
soc_clk_freq.c
)

View file

@ -31,4 +31,8 @@ config COUNTER_IMX_EPIT
default y
depends on COUNTER
config PWM_IMX
default y
depends on PWM
endif # SOC_MCIMX6X_M4

View file

@ -104,6 +104,39 @@ static void SOC_RdcInit(void)
/* Set access to I2C-4 for M4 core */
RDC_SetPdapAccess(RDC, rdcPdapI2c4, RDC_DT_VAL(i2c4), false, false);
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm1), okay)
/* Set access to PWM-1 for M4 core */
RDC_SetPdapAccess(RDC, rdcPdapPwm1, RDC_DT_VAL(pwm1), false, false);
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm2), okay)
/* Set access to PWM-2 for M4 core */
RDC_SetPdapAccess(RDC, rdcPdapPwm2, RDC_DT_VAL(pwm2), false, false);
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm3), okay)
/* Set access to PWM-3 for M4 core */
RDC_SetPdapAccess(RDC, rdcPdapPwm3, RDC_DT_VAL(pwm3), false, false);
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm4), okay)
/* Set access to PWM-4 for M4 core */
RDC_SetPdapAccess(RDC, rdcPdapPwm4, RDC_DT_VAL(pwm4), false, false);
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm5), okay)
/* Set access to PWM-5 for M4 core */
RDC_SetPdapAccess(RDC, rdcPdapPwm5, RDC_DT_VAL(pwm5), false, false);
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm6), okay)
/* Set access to PWM-6 for M4 core */
RDC_SetPdapAccess(RDC, rdcPdapPwm6, RDC_DT_VAL(pwm6), false, false);
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm7), okay)
/* Set access to PWM-7 for M4 core */
RDC_SetPdapAccess(RDC, rdcPdapPwm7, RDC_DT_VAL(pwm7), false, false);
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm8), okay)
/* Set access to PWM-8 for M4 core */
RDC_SetPdapAccess(RDC, rdcPdapPwm8, RDC_DT_VAL(pwm8), false, false);
#endif
}
/* Initialize cache. */
@ -196,7 +229,41 @@ static void SOC_ClockInit(void)
#if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c4), okay)
CCM_ControlGate(CCM, ccmCcgrGateI2c4Serialclk, ccmClockNeededAll);
#endif
#endif /* CONFIG_I2C_IMX */
#ifdef CONFIG_PWM_IMX
/* Select PWM clock is derived from OSC (24M) */
CCM_SetRootMux(CCM, ccmRootPerclkClkSel, ccmRootmuxPerclkClkOsc24m);
/* Set relevant divider = 1. */
CCM_SetRootDivider(CCM, ccmRootPerclkPodf, 0);
/* Enable PWM clock */
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm1), okay)
CCM_ControlGate(CCM, ccmCcgrGatePwm1Clk, ccmClockNeededAll);
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm2), okay)
CCM_ControlGate(CCM, ccmCcgrGatePwm2Clk, ccmClockNeededAll);
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm3), okay)
CCM_ControlGate(CCM, ccmCcgrGatePwm3Clk, ccmClockNeededAll);
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm4), okay)
CCM_ControlGate(CCM, ccmCcgrGatePwm4Clk, ccmClockNeededAll);
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm5), okay)
CCM_ControlGate(CCM, ccmCcgrGatePwm5Clk, ccmClockNeededAll);
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm6), okay)
CCM_ControlGate(CCM, ccmCcgrGatePwm6Clk, ccmClockNeededAll);
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm7), okay)
CCM_ControlGate(CCM, ccmCcgrGatePwm7Clk, ccmClockNeededAll);
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm8), okay)
CCM_ControlGate(CCM, ccmCcgrGatePwm8Clk, ccmClockNeededAll);
#endif
#endif /* CONFIG_PWM_IMX */
}
/**

View file

@ -13,6 +13,7 @@
#include "rdc_defs_imx6sx.h"
#include "ccm_imx6sx.h"
#include "clock_freq.h"
#include "soc_clk_freq.h"
#endif /* !_ASMLANGUAGE */

View file

@ -0,0 +1,79 @@
/*
* Copyright (c) 2021, Antonio Tessarolo
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <ccm_imx6sx.h>
#include <ccm_analog_imx6sx.h>
#include "soc_clk_freq.h"
#ifdef CONFIG_PWM_IMX
uint32_t get_pwm_clock_freq(PWM_Type *base)
{
uint32_t root;
uint32_t hz;
uint32_t divPerclkPodf, divIpgPodf, divAhbPodf, divPeriphClk2Podf;
/* Different instance has the same clock root, it's different from i.mx7d. */
/* Get the clock root according to the mux node of clock tree. */
if (CCM_GetRootMux(CCM, ccmRootPerclkClkSel) ==
ccmRootmuxPerclkClkOsc24m) {
root = ccmRootmuxPerclkClkOsc24m;
hz = 24000000;
divPerclkPodf = CCM_GetRootDivider(CCM, ccmRootPerclkPodf);
divIpgPodf = 0;
divAhbPodf = 0;
divPeriphClk2Podf = 0;
} else if (CCM_GetRootMux(CCM, ccmRootPeriphClkSel) ==
ccmRootmuxPeriphClkPrePeriphClkSel) {
root = CCM_GetRootMux(CCM, ccmRootPrePeriphClkSel);
/* Here do not show all the clock root source,
* if user use other clock root source, such as PLL2_PFD2, please
* add it as follows according to the clock tree of CCM in reference manual.
*/
switch (root) {
case ccmRootmuxPrePeriphClkPll2:
hz = CCM_ANALOG_GetPllFreq(CCM_ANALOG, ccmAnalogPllSysControl);
divPerclkPodf = CCM_GetRootDivider(CCM, ccmRootPerclkPodf);
divIpgPodf = CCM_GetRootDivider(CCM, ccmRootIpgPodf);
divAhbPodf = CCM_GetRootDivider(CCM, ccmRootAhbPodf);
divPeriphClk2Podf = 0;
break;
default:
return 0;
}
} else if (CCM_GetRootMux(CCM, ccmRootPeriphClk2Sel) ==
ccmRootmuxPeriphClk2OSC24m) {
root = ccmRootmuxPeriphClk2OSC24m;
hz = 24000000;
divPerclkPodf = CCM_GetRootDivider(CCM, ccmRootPerclkPodf);
divIpgPodf = CCM_GetRootDivider(CCM, ccmRootIpgPodf);
divAhbPodf = CCM_GetRootDivider(CCM, ccmRootAhbPodf);
divPeriphClk2Podf = CCM_GetRootDivider(CCM, ccmRootPeriphClk2Podf);
} else {
root = CCM_GetRootMux(CCM, ccmRootPll3SwClkSel);
/* Here do not show all the clock root source,
* if user use other clock root source, such as PLL3_BYP, please
* add it as follows according to the clock tree of CCM in reference manual.
*/
switch (root) {
case ccmRootmuxPll3SwClkPll3:
hz = CCM_ANALOG_GetPllFreq(CCM_ANALOG, ccmAnalogPllUsb1Control);
divPerclkPodf = CCM_GetRootDivider(CCM, ccmRootPerclkPodf);
divIpgPodf = CCM_GetRootDivider(CCM, ccmRootIpgPodf);
divAhbPodf = CCM_GetRootDivider(CCM, ccmRootAhbPodf);
divPeriphClk2Podf =
CCM_GetRootDivider(CCM, ccmRootPeriphClk2Podf);
break;
default:
return 0;
}
}
return hz / (divPerclkPodf + 1) / (divIpgPodf + 1) /
(divAhbPodf + 1) / (divPeriphClk2Podf + 1);
}
#endif /* CONFIG_PWM_IMX */

View file

@ -0,0 +1,30 @@
/*
* Copyright (c) 2021, Antonio Tessarolo
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __SOC_CLOCK_FREQ_H__
#define __SOC_CLOCK_FREQ_H__
#include "device_imx.h"
#include <zephyr/types.h>
#if defined(__cplusplus)
extern "C" {
#endif
#ifdef CONFIG_PWM_IMX
/*!
* @brief Get clock frequency applies to the PWM module
*
* @param base PWM base pointer.
* @return clock frequency (in HZ) applies to the PWM module
*/
uint32_t get_pwm_clock_freq(PWM_Type *base);
#endif /* CONFIG_PWM_IMX */
#if defined(__cplusplus)
}
#endif
#endif /* __SOC_CLOCK_FREQ_H__ */