From 84c74993d4b3477b8e041ab13608379ae26093cd Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 19 May 2019 23:42:28 +0200 Subject: [PATCH] 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 --- drivers/pwm/pwm_mcux_ftm.c | 47 ++++++++++++++----- dts/arm/nxp/nxp_k6x.dtsi | 9 +++- dts/arm/nxp/nxp_kw2xd.dtsi | 8 +++- .../nxp_kinetis/k6x/Kconfig.defconfig.mk64f12 | 3 ++ soc/arm/nxp_kinetis/k6x/dts_fixup.h | 4 ++ .../kwx/Kconfig.defconfig.mkw2xd512 | 3 ++ soc/arm/nxp_kinetis/kwx/dts_fixup.h | 4 ++ 7 files changed, 65 insertions(+), 13 deletions(-) diff --git a/drivers/pwm/pwm_mcux_ftm.c b/drivers/pwm/pwm_mcux_ftm.c index 3c202bef987..64187d6db17 100644 --- a/drivers/pwm/pwm_mcux_ftm.c +++ b/drivers/pwm/pwm_mcux_ftm.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include #include @@ -18,7 +19,8 @@ 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; @@ -26,6 +28,7 @@ struct mcux_ftm_config { }; 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), diff --git a/dts/arm/nxp/nxp_k6x.dtsi b/dts/arm/nxp/nxp_k6x.dtsi index 76e49b98099..7cb61147e78 100644 --- a/dts/arm/nxp/nxp_k6x.dtsi +++ b/dts/arm/nxp/nxp_k6x.dtsi @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -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>; diff --git a/dts/arm/nxp/nxp_kw2xd.dtsi b/dts/arm/nxp/nxp_kw2xd.dtsi index e452fdd6b61..88980723432 100644 --- a/dts/arm/nxp/nxp_kw2xd.dtsi +++ b/dts/arm/nxp/nxp_kw2xd.dtsi @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -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>; diff --git a/soc/arm/nxp_kinetis/k6x/Kconfig.defconfig.mk64f12 b/soc/arm/nxp_kinetis/k6x/Kconfig.defconfig.mk64f12 index 09acf35b8d0..93a4bffe200 100644 --- a/soc/arm/nxp_kinetis/k6x/Kconfig.defconfig.mk64f12 +++ b/soc/arm/nxp_kinetis/k6x/Kconfig.defconfig.mk64f12 @@ -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 diff --git a/soc/arm/nxp_kinetis/k6x/dts_fixup.h b/soc/arm/nxp_kinetis/k6x/dts_fixup.h index b8e9e34a6e3..fd292d52e57 100644 --- a/soc/arm/nxp_kinetis/k6x/dts_fixup.h +++ b/soc/arm/nxp_kinetis/k6x/dts_fixup.h @@ -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 diff --git a/soc/arm/nxp_kinetis/kwx/Kconfig.defconfig.mkw2xd512 b/soc/arm/nxp_kinetis/kwx/Kconfig.defconfig.mkw2xd512 index f51379cc48b..34a902ab1fd 100644 --- a/soc/arm/nxp_kinetis/kwx/Kconfig.defconfig.mkw2xd512 +++ b/soc/arm/nxp_kinetis/kwx/Kconfig.defconfig.mkw2xd512 @@ -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 diff --git a/soc/arm/nxp_kinetis/kwx/dts_fixup.h b/soc/arm/nxp_kinetis/kwx/dts_fixup.h index 208190a451a..cebede7704a 100644 --- a/soc/arm/nxp_kinetis/kwx/dts_fixup.h +++ b/soc/arm/nxp_kinetis/kwx/dts_fixup.h @@ -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