Skip to content
Permalink
Browse files

drivers: pwm: mcux_ftm: use device tree for obtaining clock frequency

Use clock specified in the device tree for obtaining the source clock
frequency for the pwm_mcux_ftm driver instead of relying on having an
NXP Kinetis MCG clock available in all SoCs supporting FlexTimer (FTM)
modules.

Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
  • Loading branch information...
henrikbrixandersen authored and MaureenHelm committed May 19, 2019
1 parent a9a8391 commit 84c74993d4b3477b8e041ab13608379ae26093cd
@@ -4,6 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

#include <drivers/clock_control.h>
#include <errno.h>
#include <drivers/pwm.h>
#include <soc.h>
@@ -18,14 +19,16 @@ LOG_MODULE_REGISTER(pwm_mcux_ftm);

struct mcux_ftm_config {
FTM_Type *base;
clock_name_t clock_source;
char *clock_name;
clock_control_subsys_t clock_subsys;
ftm_clock_source_t ftm_clock_source;
ftm_clock_prescale_t prescale;
u8_t channel_count;
ftm_pwm_mode_t mode;
};

struct mcux_ftm_data {
u32_t clock_freq;
u32_t period_cycles;
ftm_chnl_pwm_signal_param_t channel[MAX_CHANNELS];
};
@@ -55,7 +58,6 @@ static int mcux_ftm_pin_set(struct device *dev, u32_t pwm,
pulse_cycles, period_cycles, duty_cycle);

if (period_cycles != data->period_cycles) {
u32_t clock_freq;
u32_t pwm_freq;
status_t status;

@@ -66,10 +68,11 @@ static int mcux_ftm_pin_set(struct device *dev, u32_t pwm,

data->period_cycles = period_cycles;

clock_freq = CLOCK_GetFreq(config->clock_source);
pwm_freq = (clock_freq >> config->prescale) / period_cycles;
pwm_freq = (data->clock_freq >> config->prescale) /
period_cycles;

LOG_DBG("pwm_freq=%d, clock_freq=%d", pwm_freq, clock_freq);
LOG_DBG("pwm_freq=%d, clock_freq=%d", pwm_freq,
data->clock_freq);

if (pwm_freq == 0U) {
LOG_ERR("Could not set up pwm_freq=%d", pwm_freq);
@@ -80,7 +83,7 @@ static int mcux_ftm_pin_set(struct device *dev, u32_t pwm,

status = FTM_SetupPwm(config->base, data->channel,
config->channel_count, config->mode,
pwm_freq, clock_freq);
pwm_freq, data->clock_freq);

if (status != kStatus_Success) {
LOG_ERR("Could not set up pwm");
@@ -102,8 +105,9 @@ static int mcux_ftm_get_cycles_per_sec(struct device *dev, u32_t pwm,
u64_t *cycles)
{
const struct mcux_ftm_config *config = dev->config->config_info;
struct mcux_ftm_data *data = dev->driver_data;

*cycles = CLOCK_GetFreq(config->clock_source) >> config->prescale;
*cycles = data->clock_freq >> config->prescale;

return 0;
}
@@ -113,6 +117,7 @@ static int mcux_ftm_init(struct device *dev)
const struct mcux_ftm_config *config = dev->config->config_info;
struct mcux_ftm_data *data = dev->driver_data;
ftm_chnl_pwm_signal_param_t *channel = data->channel;
struct device *clock_dev;
ftm_config_t ftm_config;
int i;

@@ -121,6 +126,18 @@ static int mcux_ftm_init(struct device *dev)
return -EINVAL;
}

clock_dev = device_get_binding(config->clock_name);
if (clock_dev == NULL) {
LOG_ERR("Could not get clock device");
return -EINVAL;
}

if (clock_control_get_rate(clock_dev, config->clock_subsys,
&data->clock_freq)) {
LOG_ERR("Could not get clock frequency");
return -EINVAL;
}

for (i = 0; i < config->channel_count; i++) {
channel->chnlNumber = i;
channel->level = kFTM_LowTrue;
@@ -145,7 +162,9 @@ static const struct pwm_driver_api mcux_ftm_driver_api = {
#ifdef CONFIG_PWM_0
static const struct mcux_ftm_config mcux_ftm_config_0 = {
.base = (FTM_Type *)DT_FTM_0_BASE_ADDRESS,
.clock_source = kCLOCK_McgFixedFreqClk,
.clock_name = DT_FTM_0_CLOCK_NAME,
.clock_subsys =
(clock_control_subsys_t) DT_FTM_0_CLOCK_SUBSYS,
.ftm_clock_source = kFTM_FixedClock,
.prescale = kFTM_Prescale_Divide_16,
.channel_count = FSL_FEATURE_FTM_CHANNEL_COUNTn(FTM0),
@@ -163,7 +182,9 @@ DEVICE_AND_API_INIT(mcux_ftm_0, DT_FTM_0_NAME, &mcux_ftm_init,
#ifdef CONFIG_PWM_1
static const struct mcux_ftm_config mcux_ftm_config_1 = {
.base = (FTM_Type *)DT_FTM_1_BASE_ADDRESS,
.clock_source = kCLOCK_McgFixedFreqClk,
.clock_name = DT_FTM_1_CLOCK_NAME,
.clock_subsys =
(clock_control_subsys_t) DT_FTM_1_CLOCK_SUBSYS,
.ftm_clock_source = kFTM_FixedClock,
.prescale = kFTM_Prescale_Divide_16,
.channel_count = FSL_FEATURE_FTM_CHANNEL_COUNTn(FTM1),
@@ -181,7 +202,9 @@ DEVICE_AND_API_INIT(mcux_ftm_1, DT_FTM_1_NAME, &mcux_ftm_init,
#ifdef CONFIG_PWM_2
static const struct mcux_ftm_config mcux_ftm_config_2 = {
.base = (FTM_Type *)DT_FTM_2_BASE_ADDRESS,
.clock_source = kCLOCK_McgFixedFreqClk,
.clock_name = DT_FTM_2_CLOCK_NAME,
.clock_subsys =
(clock_control_subsys_t) DT_FTM_2_CLOCK_SUBSYS,
.ftm_clock_source = kFTM_FixedClock,
.prescale = kFTM_Prescale_Divide_16,
.channel_count = FSL_FEATURE_FTM_CHANNEL_COUNTn(FTM2),
@@ -199,7 +222,9 @@ DEVICE_AND_API_INIT(mcux_ftm_2, DT_FTM_2_NAME, &mcux_ftm_init,
#ifdef CONFIG_PWM_3
static const struct mcux_ftm_config mcux_ftm_config_3 = {
.base = (FTM_Type *)DT_FTM_3_BASE_ADDRESS,
.clock_source = kCLOCK_McgFixedFreqClk,
.clock_name = DT_FTM_3_CLOCK_NAME,
.clock_subsys =
(clock_control_subsys_t) DT_FTM_3_CLOCK_SUBSYS,
.ftm_clock_source = kFTM_FixedClock,
.prescale = kFTM_Prescale_Divide_16,
.channel_count = FSL_FEATURE_FTM_CHANNEL_COUNTn(FTM3),
@@ -2,6 +2,7 @@

#include <arm/armv7-m.dtsi>
#include <dt-bindings/clock/kinetis_sim.h>
#include <dt-bindings/clock/kinetis_mcg.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/i2c/i2c.h>

@@ -46,9 +47,11 @@
};

mcg: clock-controller@40064000 {
compatible = "nxp,k64f-mcg";
compatible = "nxp,kinetis-mcg";
reg = <0x40064000 0xd>;
label = "MCG";
system-clock-frequency = <120000000>;
#clock-cells = <1>;
};

clock-controller@40065000 {
@@ -338,6 +341,7 @@
compatible = "nxp,kinetis-ftm";
reg = <0x40038000 0x98>;
interrupts = <42 0>;
clocks = <&mcg KINETIS_MCG_FIXED_FREQ_CLK>;
label = "PWM_0";
status = "disabled";
#pwm-cells = <2>;
@@ -347,6 +351,7 @@
compatible = "nxp,kinetis-ftm";
reg = <0x40039000 0x98>;
interrupts = <43 0>;
clocks = <&mcg KINETIS_MCG_FIXED_FREQ_CLK>;
label = "PWM_1";
status = "disabled";
#pwm-cells = <2>;
@@ -356,6 +361,7 @@
compatible = "nxp,kinetis-ftm";
reg = <0x4003a000 0x98>;
interrupts = <44 0>;
clocks = <&mcg KINETIS_MCG_FIXED_FREQ_CLK>;
label = "PWM_2";
status = "disabled";
#pwm-cells = <2>;
@@ -365,6 +371,7 @@
compatible = "nxp,kinetis-ftm";
reg = <0x400b9000 0x98>;
interrupts = <71 0>;
clocks = <&mcg KINETIS_MCG_FIXED_FREQ_CLK>;
label = "PWM_3";
status = "disabled";
#pwm-cells = <2>;
@@ -2,6 +2,7 @@

#include <arm/armv7-m.dtsi>
#include <dt-bindings/clock/kinetis_sim.h>
#include <dt-bindings/clock/kinetis_mcg.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/i2c/i2c.h>

@@ -25,9 +26,11 @@
soc {

mcg: clock-controller@40064000 {
compatible = "nxp,k64f-mcg";
compatible = "nxp,kinetis-mcg";
reg = <0x40064000 0xd>;
label = "MCG";
system-clock-frequency = <48000000>;
#clock-cells = <1>;
};

clock-controller@40065000 {
@@ -275,6 +278,7 @@
compatible = "nxp,kinetis-ftm";
reg = <0x40038000 0x98>;
interrupts = <42 0>;
clocks = <&mcg KINETIS_MCG_FIXED_FREQ_CLK>;
label = "PWM_0";
status = "disabled";
#pwm-cells = <2>;
@@ -284,6 +288,7 @@
compatible = "nxp,kinetis-ftm";
reg = <0x40039000 0x98>;
interrupts = <43 0>;
clocks = <&mcg KINETIS_MCG_FIXED_FREQ_CLK>;
label = "PWM_1";
status = "disabled";
#pwm-cells = <2>;
@@ -293,6 +298,7 @@
compatible = "nxp,kinetis-ftm";
reg = <0x4003a000 0x98>;
interrupts = <44 0>;
clocks = <&mcg KINETIS_MCG_FIXED_FREQ_CLK>;
label = "PWM_2";
status = "disabled";
#pwm-cells = <2>;
@@ -31,6 +31,9 @@ if CLOCK_CONTROL
config CLOCK_CONTROL_MCUX_SIM
default y

config CLOCK_CONTROL_MCUX_MCG
default y

endif # CLOCK_CONTROL

if PINMUX
@@ -77,10 +77,14 @@
#define DT_FTM_3_IRQ DT_NXP_KINETIS_FTM_400B9000_IRQ_0
#define DT_FTM_3_IRQ_PRI DT_NXP_KINETIS_FTM_400B9000_IRQ_0_PRIORITY
#define DT_FTM_3_NAME DT_NXP_KINETIS_FTM_400B9000_LABEL
#define DT_FTM_3_CLOCK_NAME DT_NXP_KINETIS_FTM_400B9000_CLOCK_CONTROLLER
#define DT_FTM_3_CLOCK_SUBSYS DT_NXP_KINETIS_FTM_400B9000_CLOCK_NAME

#define DT_SIM_BASE_ADDRESS DT_NXP_KINETIS_SIM_40047000_BASE_ADDRESS
#define DT_SIM_NAME DT_NXP_KINETIS_SIM_40047000_LABEL

#define DT_MCG_NAME DT_NXP_KINETIS_MCG_40064000_LABEL

#define CONFIG_I2C_0_NAME DT_NXP_KINETIS_I2C_40066000_LABEL
#define DT_I2C_MCUX_0_BASE_ADDRESS DT_NXP_KINETIS_I2C_40066000_BASE_ADDRESS
#define DT_I2C_MCUX_0_IRQ DT_NXP_KINETIS_I2C_40066000_IRQ_0
@@ -39,6 +39,9 @@ if CLOCK_CONTROL
config CLOCK_CONTROL_MCUX_SIM
default y

config CLOCK_CONTROL_MCUX_MCG
default y

endif # CLOCK_CONTROL

if PINMUX
@@ -23,10 +23,14 @@
#define DT_FTM_1_IRQ DT_NXP_KINETIS_FTM_40039000_IRQ_0
#define DT_FTM_1_IRQ_PRI DT_NXP_KINETIS_FTM_40039000_IRQ_0_PRIORITY
#define DT_FTM_1_NAME DT_NXP_KINETIS_FTM_40039000_LABEL
#define DT_FTM_1_CLOCK_NAME DT_NXP_KINETIS_FTM_40039000_CLOCK_CONTROLLER
#define DT_FTM_1_CLOCK_SUBSYS DT_NXP_KINETIS_FTM_40039000_CLOCK_NAME

#define DT_SIM_BASE_ADDRESS DT_NXP_KINETIS_SIM_40047000_BASE_ADDRESS
#define DT_SIM_NAME DT_NXP_KINETIS_SIM_40047000_LABEL

#define DT_MCG_NAME DT_NXP_KINETIS_MCG_40064000_LABEL

#define DT_RTC_MCUX_0_BASE_ADDRESS DT_NXP_KINETIS_RTC_4003D000_BASE_ADDRESS
#define DT_RTC_MCUX_0_IRQ_PRI DT_NXP_KINETIS_RTC_4003D000_IRQ_0_PRIORITY
#define DT_RTC_MCUX_0_IRQ DT_NXP_KINETIS_RTC_4003D000_IRQ_0

0 comments on commit 84c7499

Please sign in to comment.
You can’t perform that action at this time.