arm: K64F Pulse Width Modulation (PWM) support

PWM support using the Freescale K64 FlexTimer Module (FTM)

Change-Id: Iaad429c01bd877babba04e84d6a4679bd7e38120
Work-by: Mike Hirst <michael.hirst@windriver.com>
Signed-off-by: Jeff Blais <jeff.blais@windriver.com>
This commit is contained in:
Jeff Blais 2016-02-26 15:27:38 -05:00 committed by Benjamin Walsh
commit 1f90470a27
5 changed files with 1580 additions and 0 deletions

View file

@ -157,6 +157,9 @@ config GPIO
config PINMUX config PINMUX
def_bool y def_bool y
config PWM
def_bool n
if GPIO if GPIO
config GPIO_K64 config GPIO_K64
@ -241,4 +244,11 @@ config PRESERVE_JTAG_IO_PINS
endif #PINMUX endif #PINMUX
if PWM
config PWM_K64_FTM
def_bool y
config PWM_K64_FTM_0
def_bool y
endif
endif endif

View file

@ -22,6 +22,10 @@ menuconfig PWM
help help
Enable config options for PWM drivers. Enable config options for PWM drivers.
################################################
# PCA9685
################################################
config PWM_PCA9685 config PWM_PCA9685
bool "PCA9685 I2C-based PWM chip" bool "PCA9685 I2C-based PWM chip"
depends on PWM && I2C depends on PWM && I2C
@ -119,3 +123,482 @@ config PWM_DW_NUM_PORTS
Specify how many PWM ports on the IP block. Specify how many PWM ports on the IP block.
Default is 1. Default is 1.
################################################
# K64 Flex Timer Module (FTM)
################################################
config PWM_K64_FTM
bool "PWM with Freescale K64 Flex Timer Module (FTM)"
depends on PWM
default n
help
Enable Pulse Width Modulation driver for Freescale
K64 Flex Timer Module (FTM).
config PWM_K64_FTM_DEBUG
bool "Enable Debugging for pwm_ftm driver"
depends on PWM_K64_FTM
default n
help
Enable debugging for pwm_ftm driver.
#### FTM0 #####
config PWM_K64_FTM_0
bool "K64 FTM PWM Module 0"
depends on PWM_K64_FTM
default n
help
Enable config PWM options for FTM0 source module.
config PWM_K64_FTM_0_DEV_NAME
string "K64 FTM PWM Module 0 Device Name"
depends on PWM_K64_FTM_0
default "PWM_K64_FTM0"
help
Specify the device name for the FTM0 source module.
config PWM_K64_FTM_0_REG_BASE
hex "K64 FTM0 Register Base Address"
depends on PWM_K64_FTM_0
default 0x40038000
help
Specify the memory mapped base address of FTM0. This is the address
of FTM0_SC which is the first register of the module
config PWM_K64_FTM_0_PRESCALE
int "K64 FTM0 prescale value"
default 1
depends on PWM_K64_FTM_0
help
Specify the FTM timer prescale value. The valid values are
1, 2, 4, 8, 16, 32, 64, or 128.
config PWM_K64_FTM_0_PERIOD
int "K64 FTM0 period value"
default 65535
depends on PWM_K64_FTM_0
help
Specify the FTM0 PWM period in ticks
menu "K64 FTM0 Clock Source"
choice PWM_K64_FTM_0_CLOCK_SOURCE_CHOICE
prompt "Choose the K64 FTM0 clock source"
default PWM_K64_FTM_0_CLOCK_SOURCE_SYSTEM
config PWM_K64_FTM_0_CLOCK_SOURCE_NONE
bool "No clock selected (FTM counter disable)"
config PWM_K64_FTM_0_CLOCK_SOURCE_SYSTEM
bool "System clock"
config PWM_K64_FTM_0_CLOCK_SOURCE_FIXED
bool "Fixed Frequency Clock"
config PWM_K64_FTM_0_CLOCK_SOURCE_EXTERNAL
bool "External Clock"
config PWM_K64_FTM_0_CLOCK_SOURCE_QUAD
bool "Quadrature Decoder"
endchoice
endmenu
config PWM_K64_FTM_0_CLOCK_SOURCE
int
# Omit prompt to signify "hidden" option
default 0 if PWM_K64_FTM_0_CLOCK_SOURCE_NONE
default 1 if PWM_K64_FTM_0_CLOCK_SOURCE_SYSTEM
default 2 if PWM_K64_FTM_0_CLOCK_SOURCE_FIXED
default 3 if PWM_K64_FTM_0_CLOCK_SOURCE_EXTERNAL
default 4 if PWM_K64_FTM_0_CLOCK_SOURCE_QUAD
help
Specify K64 FTM0 clock source
config PWM_K64_FTM_0_PHASE_ENABLE_0
bool "FTM0 Enable Phase for channel 0"
depends on PWM_K64_FTM_0
default n
help
Allow a phase offset on FTM0 channel 0. This configures
channels 0 and 1 to be in combine mode therefore
channel 1 is not valid as an output signal.
Note: phase is an unsupported feature.
config PWM_K64_FTM_0_PHASE_ENABLE_2
bool "FTM0 Enable Phase for channel 2"
depends on PWM_K64_FTM_0
default n
help
Allow a phase offset on FTM0 channel 2. This configures
channels 2 and 3 to be in combine mode therefore
channel 3 is not valid as an output signal.
Note: phase is an unsupported feature.
config PWM_K64_FTM_0_PHASE_ENABLE_4
bool "FTM0 Enable Phase for channel 4"
depends on PWM_K64_FTM_0
default n
help
Allow a phase offset on FTM0 channel 4. This configures
channels 4 and 5 to be in combine mode therefore
channel 5 is not valid as an output signal.
Note: phase is an unsupported feature.
config PWM_K64_FTM_0_PHASE_ENABLE_6
bool "FTM0 Enable Phase for channel 6"
depends on PWM_K64_FTM_0
default n
help
Allow a phase offset on FTM0 channel 6. This configures
channels 6 and 7 to be in combine mode therefore
channel 7 is not valid as an output signal.
Note: phase is an unsupported feature.
#### FTM1 #####
config PWM_K64_FTM_1
bool "K64 FTM PWM Module 1"
depends on PWM_K64_FTM
default n
help
Enable config PWM options for FTM1 source module.
config PWM_K64_FTM_1_DEV_NAME
string "K64 FTM PWM Module 1 Device Name"
depends on PWM_K64_FTM_1
default "PWM_K64_FTM1"
help
Specify the device name for the FTM1 source module.
config PWM_K64_FTM_1_REG_BASE
hex "K64 FTM1 Register Base Address"
depends on PWM_K64_FTM_1
default 0x40039000
help
Specify the memory mapped base address of FTM1. This is the address
of FTM1_SC which is the first register of the module
config PWM_K64_FTM_1_PRESCALE
int "FTM1 prescale value"
default 1
depends on PWM_K64_FTM_1
help
Specify the FTM1 timer prescale value. The valid values are
1, 2, 4, 8, 16, 32, 64, or 128
config PWM_K64_FTM_1_PERIOD
int "FTM1 period value"
default 65535
depends on PWM_K64_FTM_1
help
Specify the FTM1 PWM period in ticks
menu "K64 FTM1 Clock Source"
choice PWM_K64_FTM_1_CLOCK_SOURCE_CHOICE
prompt "Choose the FTM1 clock source"
default PWM_K64_FTM_1_CLOCK_SOURCE_SYSTEM
config PWM_K64_FTM_1_CLOCK_SOURCE_NONE
bool "No clock selected (FTM counter disable)"
config PWM_K64_FTM_1_CLOCK_SOURCE_SYSTEM
bool "System clock"
config PWM_K64_FTM_1_CLOCK_SOURCE_FIXED
bool "Fixed Frequency Clock"
config PWM_K64_FTM_1_CLOCK_SOURCE_EXTERNAL
bool "External Clock"
config PWM_K64_FTM_1_CLOCK_SOURCE_QUAD
bool "Quadrature Decoder"
endchoice
endmenu
config PWM_K64_FTM_1_CLOCK_SOURCE
int
# Omit prompt to signify "hidden" option
default 0 if PWM_K64_FTM_1_CLOCK_SOURCE_NONE
default 1 if PWM_K64_FTM_1_CLOCK_SOURCE_SYSTEM
default 2 if PWM_K64_FTM_1_CLOCK_SOURCE_FIXED
default 3 if PWM_K64_FTM_1_CLOCK_SOURCE_EXTERNAL
default 4 if PWM_K64_FTM_1_CLOCK_SOURCE_QUAD
help
Specify K64 FTM1 clock source
config PWM_K64_FTM_1_PHASE_ENABLE_0
bool "FTM1 Enable Phase for channel 0"
depends on PWM_K64_FTM_1
default n
help
Allow a phase offset on FTM1 channel 0. This configures
channels 0 and 1 to be in combine mode therefore
channel 1 is not valid as an output signal.
Note: phase is an unsupported feature.
config PWM_FTM_1_PHASE_ENABLE_2
bool "FTM1 Enable Phase for channel 2"
depends on PWM_K64_FTM_1
default n
help
Allow a phase offset on FTM1 channel 2. This configures
channels 2 and 3 to be in combine mode therefore
channel 3 is not valid as an output signal.
Note: phase is an unsupported feature.
config PWM_FTM_1_PHASE_ENABLE_4
bool "FTM1 Enable Phase for channel 4"
depends on PWM_K64_FTM_1
default n
help
Allow a phase offset on FTM1 channel 4. This configures
channels 4 and 5 to be in combine mode therefore
channel 5 is not valid as an output signal.
Note: phase is an unsupported feature.
config PWM_FTM_1_PHASE_ENABLE_6
bool "FTM1 Enable Phase for channel 6"
depends on PWM_K64_FTM_1
default n
help
Allow a phase offset on FTM1 channel 6. This configures
channels 6 and 7 to be in combine mode therefore
channel 7 is not valid as an output signal.
Note: phase is an unsupported feature.
#### FTM2 #####
config PWM_K64_FTM_2
bool "K64 FTM PWM Module 2"
depends on PWM_K64_FTM
default n
help
Enable config PWM options for FTM2 source module.
config PWM_K64_FTM_2_DEV_NAME
string "K64 FTM PWM Module 2 Device Name"
depends on PWM_K64_FTM_2
default "PWM_K64_FTM2"
help
Specify the device name for the FTM2 source module.
config PWM_K64_FTM_2_REG_BASE
hex "K64 FTM2 Register Base Address"
depends on PWM_K64_FTM_2
default 0x4003A000
help
Specify the memory mapped base address of FTM2. This is the address
of FTM2_SC which is the first register of the module
config PWM_K64_FTM_2_PRESCALE
int "FTM2 prescale value"
default 1
depends on PWM_K64_FTM_2
help
Specify the FTM2 timer prescale value. The valid values are
1, 2, 4, 8, 16, 32, 64, or 128
config PWM_K64_FTM_2_PERIOD
int "FTM2 period value"
default 65535
depends on PWM_K64_FTM_2
help
Specify the FTM2 PWM period in ticks
menu "K64 FTM2 Clock Source"
choice PWM_K64_FTM_2_CLOCK_SOURCE_CHOICE
prompt "Choose the FTM2 clock source"
default PWM_K64_FTM_2_CLOCK_SOURCE_SYSTEM
config PWM_K64_FTM_2_CLOCK_SOURCE_NONE
bool "No clock selected (FTM counter disable)"
config PWM_K64_FTM_2_CLOCK_SOURCE_SYSTEM
bool "System clock"
config PWM_K64_FTM_2_CLOCK_SOURCE_FIXED
bool "Fixed Frequency Clock"
config PWM_K64_FTM_2_CLOCK_SOURCE_EXTERNAL
bool "External Clock"
config PWM_K64_FTM_2_CLOCK_SOURCE_QUAD
bool "Quadrature Decoder"
endchoice
endmenu
config PWM_K64_FTM_2_CLOCK_SOURCE
int
# Omit prompt to signify "hidden" option
default 0 if PWM_K64_FTM_2_CLOCK_SOURCE_NONE
default 1 if PWM_K64_FTM_2_CLOCK_SOURCE_SYSTEM
default 2 if PWM_K64_FTM_2_CLOCK_SOURCE_FIXED
default 3 if PWM_K64_FTM_2_CLOCK_SOURCE_EXTERNAL
default 4 if PWM_K64_FTM_2_CLOCK_SOURCE_QUAD
help
Specify K64 FTM2 clock source
config PWM_K64_FTM_2_PHASE_ENABLE_0
bool "FTM2 Enable Phase for channel 0"
depends on PWM_K64_FTM_2
default n
help
Allow a phase offset on FTM2 channel 0. This configures
channels 0 and 1 to be in combine mode therefore
channel 1 is not valid as an output signal.
Note: phase is an unsupported feature.
config PWM_K64_FTM_2_PHASE_ENABLE_2
bool "FTM2 Enable Phase for channel 2"
depends on PWM_K64_FTM_2
default n
help
Allow a phase offset on FTM2 channel 2. This configures
channels 2 and 3 to be in combine mode therefore
channel 3 is not valid as an output signal.
Note: phase is an unsupported feature.
config PWM_K64_FTM_2_PHASE_ENABLE_4
bool "FTM2 Enable Phase for channel 4"
depends on PWM_K64_FTM_2
default n
help
Allow a phase offset on FTM2 channel 4. This configures
channels 4 and 5 to be in combine mode therefore
channel 5 is not valid as an output signal.
Note: phase is an unsupported feature.
config PWM_K64_FTM_2_PHASE_ENABLE_6
bool "FTM2 Enable Phase for channel 6"
depends on PWM_K64_FTM_2
default n
help
Allow a phase offset on FTM2 channel 6. This configures
channels 6 and 7 to be in combine mode therefore
channel 7 is not valid as an output signal.
Note: phase is an unsupported feature.
#### FTM3 #####
config PWM_K64_FTM_3
bool "K64 FTM PWM Module 3"
depends on PWM_K64_FTM
default n
help
Enable config PWM options for K64 FTM3 source module.
config PWM_K64_FTM_3_DEV_NAME
string "K64 FTM PWM Module 3 Device Name"
depends on PWM_K64_FTM_3
default "PWM_K64_FTM3"
help
Specify the device name for the FTM3 source module.
config PWM_K64_FTM_3_REG_BASE
hex "K64 FTM3 Register Base Address"
depends on PWM_K64_FTM_3
default 0x400B9000
help
Specify the memory mapped base address of FTM3. This is the address
of FTM3_SC which is the first register of the module
config PWM_K64_FTM_3_PRESCALE
int "FTM3 prescale value"
default 3
depends on PWM_K64_FTM_3
help
Specify the FTM timer prescale value. The valid values are
1, 2, 4, 8, 16, 32, 64, or 128
config PWM_K64_FTM_3_PERIOD
int "FTM3 period value"
default 65535
depends on PWM_K64_FTM_3
help
Specify the FTM3 PWM period in ticks
menu "K64 FTM3 Clock Source"
choice PWM_K64_FTM_3_CLOCK_SOURCE_CHOICE
prompt "Choose the FTM3 clock source"
default PWM_K64_FTM_3_CLOCK_SOURCE_SYSTEM
config PWM_K64_FTM_3_CLOCK_SOURCE_NONE
bool "No clock selected (FTM counter disable)"
config PWM_K64_FTM_3_CLOCK_SOURCE_SYSTEM
bool "System clock"
config PWM_K64_FTM_3_CLOCK_SOURCE_FIXED
bool "Fixed Frequency Clock"
config PWM_K64_FTM_3_CLOCK_SOURCE_EXTERNAL
bool "External Clock"
config PWM_K64_FTM_3_CLOCK_SOURCE_QUAD
bool "Quadrature Decoder"
endchoice
endmenu
config PWM_K64_FTM_3_CLOCK_SOURCE
int
# Omit prompt to signify "hidden" option
default 0 if PWM_K64_FTM_3_CLOCK_SOURCE_NONE
default 1 if PWM_K64_FTM_3_CLOCK_SOURCE_SYSTEM
default 2 if PWM_K64_FTM_3_CLOCK_SOURCE_FIXED
default 3 if PWM_K64_FTM_3_CLOCK_SOURCE_EXTERNAL
default 4 if PWM_K64_FTM_3_CLOCK_SOURCE_QUAD
help
Specify K64 FTM3 clock source
config PWM_K64_FTM_3_PHASE_ENABLE_0
bool "FTM3 Enable Phase for channel 0"
depends on PWM_K64_FTM_3
default n
help
Allow a phase offset on FTM3 channel 0. This configures
channels 0 and 1 to be in combine mode therefore
channel 1 is not valid as an output signal.
Note: phase is an unsupported feature.
config PWM_K64_FTM_3_PHASE_ENABLE_2
bool "FTM3 Enable Phase for channel 2"
depends on PWM_K64_FTM_3
default n
help
Allow a phase offset on FTM3 channel 2. This configures
channels 2 and 3 to be in combine mode therefore
channel 3 is not valid as an output signal.
Note: phase is an unsupported feature.
config PWM_K64_FTM_3_PHASE_ENABLE_4
bool "FTM3 Enable Phase for channel 4"
depends on PWM_K64_FTM_3
default n
help
Allow a phase offset on FTM3 channel 4. This configures
channels 4 and 5 to be in combine mode therefore
channel 5 is not valid as an output signal.
Note: phase is an unsupported feature.
config PWM_K64_FTM_3_PHASE_ENABLE_6
bool "FTM3 Enable Phase for channel 6"
depends on PWM_K64_FTM_3
default n
help
Allow a phase offset on FTM3 channel 6. This configures
channels 6 and 7 to be in combine mode therefore
channel 7 is not valid as an output signal.
Note: phase is an unsupported feature.

View file

@ -5,3 +5,5 @@ ccflags-$(CONFIG_PWM_QMSI) += -I$(CONFIG_QMSI_INSTALL_PATH)/include
obj-$(CONFIG_PWM_PCA9685) += pwm_pca9685.o obj-$(CONFIG_PWM_PCA9685) += pwm_pca9685.o
obj-$(CONFIG_PWM_DW) += pwm_dw.o obj-$(CONFIG_PWM_DW) += pwm_dw.o
obj-$(CONFIG_PWM_QMSI) += pwm_qmsi.o obj-$(CONFIG_PWM_QMSI) += pwm_qmsi.o
obj-$(CONFIG_PWM_K64_FTM) += pwm_k64_ftm.o

900
drivers/pwm/pwm_k64_ftm.c Normal file
View file

@ -0,0 +1,900 @@
/*
* Copyright (c) 2016, Wind River Systems, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file PWM driver for Freescale K64 FlexTimer Module (FTM)
*
* This file implements Pulse Width Modulation using the Freescale FlexTimer
* Module (FTM). Basic functionality is implemented using edge-aligned PWM
* mode. More complex functionality such as non-zero phase is not supported
* since combined mode operation is not implemented.
*
* The following configuration options are supported. ("x" can be one of the
* following values: 0, 1, 2, or 3 representing one of the four FMT modules
* FTM0, FTM1, FTM2, or FTM3.)
*
* - CONFIG_PWM_K64_FTM_x_DEV_NAME: string representing the device name
* - CONFIG_PWM_K64_FTM_x_REG_BASE: the base address of FTM (FTMx_SC)
* - CONFIG_PWM_K64_FTM_x_PRESCALE: the clock prescaler value
* - CONFIG_PWM_K64_FTM_x_CLOCK_SOURCE: the clock source
* - CONFIG_PWM_K64_FTM_DEBUG: enable debug log output for the driver
* - CONFIG_STDOUT_CONSOLE: choose debug logs using printf of printk
*
* The following configuration options are not supported. These are place
* holders for future functionality
*
* - CONFIG_PWM_K64_FTM_x_PHASE_ENABLE_0 support non-zero phase on channel 0
* - CONFIG_PWM_K64_FTM_x_PHASE_ENABLE_1 support non-zero phase on channel 1
* - CONFIG_PWM_K64_FTM_x_PHASE_ENABLE_2 support non-zero phase on channel 2
* - CONFIG_PWM_K64_FTM_x_PHASE_ENABLE_3 support non-zero phase on channel 3
*/
#include <nanokernel.h>
#include <board.h>
#include <k20_sim.h>
#include <pwm.h>
#include "pwm_k64_ftm.h"
#include <stdio.h>
/*
* Non-zero phase is not supported because combine mode is not yet
* implemented.
*/
#undef COMBINE_MODE_SUPPORT
#ifndef CONFIG_PWM_K64_FTM_DEBUG
#define DBG(...) do { } while ((0))
#else /* CONFIG_PWM_K64_FTM_DEBUG */
#if defined(CONFIG_STDOUT_CONSOLE)
#include <stdio.h>
#define DBG printf
#else
#include <misc/printk.h>
#define DBG printk
#endif /* CONFIG_STDOUT_CONSOLE */
#endif /* CONFIG_PWM_K64_FTM_DEBUG */
/* Maximum PWM outputs */
#define MAX_PWM_OUT 8
/**
* @brief Enable the clock for the FTM subsystem
*
* This function must be called before writing to FTM registers. Failure to
* do so may result in bus fault.
*
* @param ftm_num index indicating which FTM
*
* @return DEV_OK if successful, failed otherwise
*/
static int pwm_ftm_clk_enable(uint8_t ftm_num)
{
volatile struct K20_SIM *sim =
(volatile struct K20_SIM *)PERIPH_ADDR_BASE_SIM; /* sys integ. ctl */
if (ftm_num > 3) {
DBG("ERROR: Illegal FTM number (%d).\n"
" Cannot enable PWM clock\n", ftm_num);
return DEV_INVALID_CONF;
}
/* enabling the FTM by setting one of the bits SIM_SCGC6[26:24] */
sim->scgc6 |= 1 << (24 + ftm_num);
return DEV_OK;
}
/**
* @brief Initial FTM configuration
*
* Initialize the FTM hardware based on configuration options.
*
* @param dev Device struct
* @param access_op Access operation (pin or port)
* @param channel The pwm channel number
* @param flags Device flags (unused)
*
* @return DEV_OK if successful, failed otherwise
*/
static int pwm_ftm_configure(struct device *dev, int access_op,
uint32_t channel, int flags)
{
int return_val = DEV_OK;
uint32_t clock_source;
uint32_t prescale;
uint32_t polarity;
uint32_t reg_val;
DBG("pwm_ftm_configure...\n");
const struct pwm_ftm_config * const config =
dev->config->config_info;
ARG_UNUSED(access_op);
ARG_UNUSED(flags);
/* enable the clock for the FTM subsystem */
pwm_ftm_clk_enable(config->ftm_num);
/*
* Initialize:
* clock source = x (system, fixed, external) from config
* prescaler divide-by x=(1,2,4,8,16,32,64,128) from config
* free-running count-up
* edge-aligned PWM mode
* pair: independent outputs
* polarity +
* no interrupt
*/
/*
* PS[2:0] = prescale
* MOD = pulse width
*/
clock_source = (config->clock_source & 0x3) << PWM_K64_FTM_SC_CLKS_SHIFT;
if (clock_source == 0) {
DBG("Warning: no clock source. PWM is disabled\n");
}
switch (config->prescale) {
case PWM_K64_FTM_PRESCALE_1:
prescale = PWM_K64_FTM_SC_PS_D1;
break;
case PWM_K64_FTM_PRESCALE_2:
prescale = PWM_K64_FTM_SC_PS_D2;
break;
case PWM_K64_FTM_PRESCALE_4:
prescale = PWM_K64_FTM_SC_PS_D4;
break;
case PWM_K64_FTM_PRESCALE_8:
prescale = PWM_K64_FTM_SC_PS_D8;
break;
case PWM_K64_FTM_PRESCALE_16:
prescale = PWM_K64_FTM_SC_PS_D16;
break;
case PWM_K64_FTM_PRESCALE_32:
prescale = PWM_K64_FTM_SC_PS_D32;
break;
case PWM_K64_FTM_PRESCALE_64:
prescale = PWM_K64_FTM_SC_PS_D64;
break;
case PWM_K64_FTM_PRESCALE_128:
prescale = PWM_K64_FTM_SC_PS_D128;
break;
default:
/* Illegal prescale value. Default to 1. */
prescale = PWM_K64_FTM_SC_PS_D1;
return_val = DEV_INVALID_OP;
break;
}
#ifdef COMBINE_MODE_SUPPORT
/* Enable FTMEN=1 and set outputs to initial value */
mode_reg_val = sys_read32(PWM_K64_FTM_MODE(config->reg_base));
mode_reg_val |= PWM_K64_FTM_MODE_FTMEN | PWM_K64_FTM_MODE_INIT;
DBG("pwm_ftm_configure sys_write32(0x%08x, 0x%08x)..\n",
mode_reg_val, PWM_K64_FTM_MODE(config->reg_base));
sys_write32(mode_reg_val, PWM_K64_FTM_MODE(config->reg_base));
/* Enable enhanced synchronization */
DBG("pwm_ftm_configure sys_write32(0x%08x, 0x%08x)..\n",
PWM_K64_FTM_SYNCONF_SYNCMODE|PWM_K64_FTM_SYNCONF_CNTINC,
PWM_K64_FTM_SYNCONF(config->reg_base));
sys_write32(PWM_K64_FTM_SYNCONF_SYNCMODE|PWM_K64_FTM_SYNCONF_CNTINC,
PWM_K64_FTM_SYNCONF(config->reg_base));
#endif /*COMBINE_MODE_SUPPORT*/
/* Configure: PS | CLKS | up-counter | disable TOF intr */
reg_val = prescale | clock_source;
DBG("pwm_ftm_configure sys_write32(0x%08x, 0x%08x)..\n",
reg_val, PWM_K64_FTM_SC(config->reg_base));
sys_write32(reg_val, PWM_K64_FTM_SC(config->reg_base));
DBG("pwm_ftm_configure sys_write32(0x%08x, 0x%08x)..\n",
config->period, PWM_K64_FTM_MOD(config->reg_base));
/* set MOD to max */
sys_write32(config->period, PWM_K64_FTM_MOD(config->reg_base));
/* set channel control to edge-aligned */
reg_val = PWM_K64_FTM_CNSC_MSB | PWM_K64_FTM_CNSC_ELSB;
DBG("pwm_ftm_configure sys_write32(0x%08x, 0x%08x)..\n",
reg_val, PWM_K64_FTM_CNSC(config->reg_base, channel));
sys_write32(reg_val, PWM_K64_FTM_CNSC(config->reg_base, channel));
DBG("pwm_ftm_configure sys_read32 4..\n");
/* set polarity high for this channel */
polarity = sys_read32(PWM_K64_FTM_POL(config->reg_base));
polarity &= ~(1<<channel);
DBG("pwm_ftm_configure sys_write32(0x%08x, 0x%08x)..\n",
polarity, PWM_K64_FTM_POL(config->reg_base));
sys_write32(polarity, PWM_K64_FTM_POL(config->reg_base));
return return_val;
}
/**
* @brief API call to set the on/off timer values
*
* @param dev Device struct
* @param access_op Access operation (pin or port)
* @param channel The pwm channel number
* @param on Timer count value for the start of the pulse on each cycle
* (must be 0)
* @param off Timer count value for the end of the pulse. After this, the
* signal will be off (low if positive polarity) for the rest of
* the cycle.
*
* @return DEV_OK if successful, failed otherwise
*/
static int pwm_ftm_set_values(struct device *dev, int access_op,
uint32_t channel, uint32_t on, uint32_t off)
{
const struct pwm_ftm_config * const config =
dev->config->config_info;
struct pwm_ftm_drv_data * const drv_data =
(struct pwm_ftm_drv_data * const)dev->driver_data;
DBG("pwm_ftm_set_values (on=%d, off=%d)\n", on, off);
uint32_t pwm_pair;
uint32_t combine;
switch (access_op) {
case PWM_ACCESS_BY_PIN:
break;
case PWM_ACCESS_ALL:
return DEV_INVALID_OP;
default:
return DEV_INVALID_OP;
}
/* If either ON and/or OFF > max ticks, treat PWM as 100%.
* If OFF value == 0, treat it as 0%.
* Otherwise, populate registers accordingly.
*/
if ((on >= config->period) || (off >= config->period)) {
/* Fully on. Set to 100% */
DBG("pwm_ftm_set_values sys_write32(0x%08x, 0x%08x)..\n",
config->period, PWM_K64_FTM_CNV(config->reg_base, channel));
/* CnV = pulse width */
sys_write32(config->period, PWM_K64_FTM_CNV(config->reg_base, channel));
} else if (off == 0) {
/* Fully off. Set to 0% */
DBG("pwm_ftm_set_values sys_write32(0x%08x, 0x%08x)..\n",
0, PWM_K64_FTM_CNV(config->reg_base, channel));
/* CnV = 0 */
sys_write32(0, PWM_K64_FTM_CNV(config->reg_base, channel));
} else {
/* if on != 0 then set to combine mode and pwm must be even */
if (on != 0) {
#ifdef COMBINE_MODE_SUPPORT
/* TODO should verify that the other channel is not in
* use in non-combine mode
*/
/* If phase != 0 enable combine mode */
if (channel % 2 != 0) {
DBG("If Phase is non-zero pwm must be 0, 2, 4, 6.\n");
return DEV_INVALID_CONF;
}
DBG("Note: Enabling phase on pwm%d therefore "
"pwm%d is not valid for output\n", channel, channel+1);
pwm_pair = channel / 2;
/* verify that the pair is configured for non-zero phase */
switch (pwm_pair) {
case 0:
if (!config->phase_enable0) {
DBG("Error: Phase capability must be enabled on FTM0\n");
return DEV_INVALID_CONF;
}
break;
case 1:
if (!config->phase_enable2) {
DBG("Error: Phase capability must be enabled on FTM2\n");
return DEV_INVALID_CONF;
}
drv_data->phase[1] = on;
break;
case 2:
if (!config->phase_enable4) {
DBG("Error: Phase capability must be enabled on FTM4\n");
return DEV_INVALID_CONF;
}
break;
case 3:
if (!config->phase_enable6) {
DBG("Error: Phase capability must be enabled on FTM0\n");
return DEV_INVALID_CONF;
}
break;
default:
return DEV_INVALID_CONF;
}
drv_data->phase[pwm_pair] = on;
combine =
sys_read32(PWM_K64_FTM_COMBINE(config->reg_base));
combine |= 1 << (pwm_pair * 8);
DBG("pwm_ftm_set_values sys_write32(0x%08x, 0x%08x)..\n",
combine, PWM_K64_FTM_COMBINE(config->reg_base));
sys_write32(combine, PWM_K64_FTM_COMBINE(config->reg_base));
DBG("pwm_ftm_set_values sys_write32(0x%08x, 0x%08x)..\n",
on, PWM_K64_FTM_CNV(config->reg_base, channel));
/* set the on value */
sys_write32(on, PWM_K64_FTM_CNV(config->reg_base, channel));
DBG("pwm_ftm_set_values sys_write32(0x%08x, 0x%08x)..\n",
off, PWM_K64_FTM_CNV(config->reg_base, channel+1));
/* set the off value */
sys_write32(off, PWM_K64_FTM_CNV(config->reg_base, channel+1));
#else /*COMBINE_MODE_SUPPORT*/
DBG("Error: \"on\" value must be zero. Phase is not supported\n");
return DEV_INVALID_CONF;
#endif /*COMBINE_MODE_SUPPORT*/
} else {
/* zero phase. No need to combine two channels. */
if (channel % 2 != 0) {
pwm_pair = (channel - 1) / 2;
} else {
pwm_pair = channel / 2;
}
drv_data->phase[pwm_pair] = 0;
combine =
sys_read32(PWM_K64_FTM_COMBINE(config->reg_base));
combine &= ~(1 << (pwm_pair * 8));
DBG("pwm_ftm_set_values sys_write32(0x%08x, 0x%08x)..\n",
combine, PWM_K64_FTM_COMBINE(config->reg_base));
sys_write32(combine, PWM_K64_FTM_COMBINE(config->reg_base));
/* set the off value */
DBG("pwm_ftm_set_values sys_write32(0x%08x, 0x%08x)..\n",
off, PWM_K64_FTM_CNV(config->reg_base, channel));
sys_write32(off, PWM_K64_FTM_CNV(config->reg_base, channel));
}
}
DBG("pwm_ftm_set_values done.\n");
return DEV_OK;
}
/**
* @brief API call to set the duty cycle
*
* Duty cycle describes the percentage of time a signal is in the ON state.
*
* @param dev Device struct
* @param access_op Access operation (pin or port)
* @param channel The pwm channel number
* @param duty Percentage of time signal is on (value between 0 and 100)
*
* @return DEV_OK if successful, failed otherwise
*/
static int pwm_ftm_set_duty_cycle(struct device *dev, int access_op,
uint32_t channel, uint8_t duty)
{
uint32_t on, off;
const struct pwm_ftm_config * const config =
dev->config->config_info;
struct pwm_ftm_drv_data * const drv_data =
(struct pwm_ftm_drv_data * const)dev->driver_data;
ARG_UNUSED(access_op);
DBG("pwm_ftm_set_duty_cycle...\n");
if (duty == 0) {
/* Turn off PWM */
on = 0;
off = 0;
} else if (duty >= 100) {
/* Force PWM to be 100% */
on = 0;
off = config->period + 1;
} else {
on = 0;
/*
* Set the "on" value to the phase offset if it was set by
* pwm_ftm_set_phase()
*/
switch (channel) {
case 0:
if (config->phase_enable0)
on = drv_data->phase[0];
break;
case 2:
if (config->phase_enable2)
on = drv_data->phase[1];
break;
case 4:
if (config->phase_enable4)
on = drv_data->phase[2];
break;
case 6:
if (config->phase_enable6)
on = drv_data->phase[3];
break;
default:
break;
}
/* Calculate the timer value for when to stop the pulse */
off = on + config->period * duty / 100;
DBG("pwm_ftm_set_duty_cycle on=%d, off=%d, "
"period=%d, duty=%d.\n",
on, off, config->period, duty);
/* check for valid off value */
if (off > config->period)
return DEV_INVALID_OP;
}
return pwm_ftm_set_values(dev, access_op, channel, on, off);
DBG("pwm_ftm_set_duty_cycle done.\n");
}
/**
* @brief API call to set the phase
*
* Phase describes number of clock ticks of delay before the start of the
* pulse. The maximum count of the FTM timer is 65536 so the phase value is
* an integer from 0 to 65536.
*
* A non-zero phase value requires the timer pair to be set to combined mode
* so the odd-numbered (n+1) channel is not available for output
*
* Note: non-zero phase is not supported in this implementation
*
* @param dev Device struct
* @param access_op Access operation (pin or port)
* @param channel The pwm channel number
* @param phase Clock ticks of delay before start of the pulse (must be 0)
*
* @return DEV_OK if successful, failed otherwise
*/
static int pwm_ftm_set_phase(struct device *dev, int access_op,
uint32_t channel, uint8_t phase)
{
#ifdef COMBINE_MODE_SUPPORT
const struct pwm_ftm_config * const config =
dev->config->config_info;
struct pwm_ftm_drv_data * const drv_data =
(struct pwm_ftm_drv_data * const)dev->driver_data;
ARG_UNUSED(access_op);
DBG("pwm_ftm_set_phase...\n");
if ((phase < 0) || (phase > config->period))
return DEV_INVALID_OP;
switch (channel) {
case 0:
if (!config->phase_enable0)
return DEV_INVALID_OP;
drv_data->phase[0] = phase;
break;
case 2:
if (!config->phase_enable2)
return DEV_INVALID_OP;
drv_data->phase[1] = phase;
break;
case 4:
if (!config->phase_enable4)
return DEV_INVALID_OP;
drv_data->phase[2] = phase;
break;
case 6:
if (!config->phase_enable6)
return DEV_INVALID_OP;
drv_data->phase[3] = phase;
break;
default:
/* channel must be 0, 2, 4, or 6 */
return DEV_INVALID_OP;
}
DBG("pwm_ftm_set_phase done.\n");
return DEV_OK;
#else /*COMBINE_MODE_SUPPORT*/
ARG_UNUSED(dev);
ARG_UNUSED(access_op);
ARG_UNUSED(channel);
ARG_UNUSED(phase);
DBG("ERROR: non-zero phase is not supported.\n");
return DEV_INVALID_OP;
#endif /*COMBINE_MODE_SUPPORT*/
}
/**
* @brief API call to disable FTM
*
* This function simply sets the clock source to "no clock selected" thus
* disabling the FTM
*
* @param dev Device struct
*
* @return DEV_OK if successful, failed otherwise
*/
static int pwm_ftm_suspend(struct device *dev)
{
uint32_t reg_val;
const struct pwm_ftm_config * const config =
dev->config->config_info;
DBG("pwm_ftm_suspend...\n");
/* set clock source to "no clock selected" */
reg_val = sys_read32(PWM_K64_FTM_SC(config->reg_base));
reg_val &= ~PWM_K64_FTM_SC_CLKS_MASK;
reg_val |= PWM_K64_FTM_SC_CLKS_DISABLE;
sys_write32(reg_val, PWM_K64_FTM_SC(config->reg_base));
DBG("pwm_ftm_suspend done.\n");
return DEV_OK;
}
/**
* @brief API call to reenable FTM
*
* This function simply sets the clock source to the configuration value with
* the assumption that FTM was previously disabled by setting the clock source
* to "no clock selected" due to a call to pwm_ftm_suspend.
*
* @param dev Device struct
*
* @return DEV_OK if successful, failed otherwise
*/
static int pwm_ftm_resume(struct device *dev)
{
uint32_t clock_source;
uint32_t reg_val;
/* set clock source to config value */
const struct pwm_ftm_config * const config =
dev->config->config_info;
DBG("pwm_ftm_resume...\n");
clock_source = (config->clock_source << PWM_K64_FTM_SC_CLKS_SHIFT) &&
PWM_K64_FTM_SC_CLKS_MASK;
reg_val = sys_read32(PWM_K64_FTM_SC(config->reg_base));
reg_val &= ~PWM_K64_FTM_SC_CLKS_MASK;
reg_val |= clock_source;
sys_write32(reg_val, PWM_K64_FTM_SC(config->reg_base));
DBG("pwm_ftm_resume done.\n");
return DEV_OK;
}
static struct pwm_driver_api pwm_ftm_drv_api_funcs = {
.config = pwm_ftm_configure,
.set_values = pwm_ftm_set_values,
.set_duty_cycle = pwm_ftm_set_duty_cycle,
.set_phase = pwm_ftm_set_phase,
.suspend = pwm_ftm_suspend,
.resume = pwm_ftm_resume,
};
/**
* @brief Initialization function of FTM
*
* @param dev Device struct
* @return DEV_OK if successful, failed otherwise.
*/
int pwm_ftm_init(struct device *dev)
{
DBG("pwm_ftm_init...\n");
dev->driver_api = &pwm_ftm_drv_api_funcs;
return DEV_OK;
}
/* Initialization for PWM_K64_FTM_0 */
#ifdef CONFIG_PWM_K64_FTM_0
#include <device.h>
#include <init.h>
static struct pwm_ftm_config pwm_ftm_0_cfg = {
.ftm_num = 0,
.reg_base = CONFIG_PWM_K64_FTM_0_REG_BASE,
.prescale = CONFIG_PWM_K64_FTM_0_PRESCALE,
.clock_source = CONFIG_PWM_K64_FTM_0_CLOCK_SOURCE,
#ifdef CONFIG_PWM_K64_FTM_0_PHASE_ENABLE_0
.phase_enable0 = 1,
#else
.phase_enable0 = 0,
#endif
#ifdef CONFIG_PWM_K64_FTM_0_PHASE_ENABLE_2
.phase_enable2 = 1,
#else
.phase_enable2 = 0,
#endif
#ifdef CONFIG_PWM_K64_FTM_0_PHASE_ENABLE_4
.phase_enable4 = 1,
#else
.phase_enable4 = 0,
#endif
#ifdef CONFIG_PWM_K64_FTM_0_PHASE_ENABLE_6
.phase_enable6 = 1,
#else
.phase_enable6 = 0,
#endif
.period = CONFIG_PWM_K64_FTM_0_PERIOD,
};
static struct pwm_ftm_drv_data pwm_ftm_0_drvdata;
DEVICE_INIT(pwm_ftm_0, CONFIG_PWM_K64_FTM_0_DEV_NAME, pwm_ftm_init,
&pwm_ftm_0_drvdata, &pwm_ftm_0_cfg,
SECONDARY, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
#endif /* CONFIG_PWM_K64_FTM_0 */
/* Initialization for PWM_K64_FTM_1 */
#ifdef CONFIG_PWM_K64_FTM_1
#include <device.h>
#include <init.h>
static struct pwm_ftm_config pwm_ftm_1_cfg = {
.ftm_num = 1,
.reg_base = CONFIG_PWM_K64_FTM_1_REG_BASE,
.prescale = CONFIG_PWM_K64_FTM_1_PRESCALE,
.clock_source = CONFIG_PWM_K64_FTM_1_CLOCK_SOURCE,
#ifdef CONFIG_PWM_K64_FTM_1_PHASE_ENABLE_0
.phase_enable0 = 1,
#else
.phase_enable0 = 0,
#endif
#ifdef CONFIG_PWM_K64_FTM_1_PHASE_ENABLE_2
.phase_enable2 = 1,
#else
.phase_enable2 = 0,
#endif
#ifdef CONFIG_PWM_K64_FTM_1_PHASE_ENABLE_4
.phase_enable4 = 1,
#else
.phase_enable4 = 0,
#endif
#ifdef CONFIG_PWM_K64_FTM_1_PHASE_ENABLE_6
.phase_enable6 = 1,
#else
.phase_enable6 = 0,
#endif
};
static struct pwm_ftm_drv_data pwm_ftm_1_drvdata;
DEVICE_INIT(pwm_ftm_1, CONFIG_PWM_K64_FTM_1_DEV_NAME, pwm_ftm_init,
&pwm_ftm_1_drvdata, &pwm_ftm_1_cfg,
SECONDARY, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
#endif /* CONFIG_PWM_K64_FTM_1 */
/* Initialization for PWM_K64_FTM_2 */
#ifdef CONFIG_PWM_K64_FTM_2
#include <device.h>
#include <init.h>
static struct pwm_ftm_config pwm_ftm_2_cfg = {
.ftm_num = 2,
.reg_base = CONFIG_PWM_K64_FTM_2_REG_BASE,
.prescale = CONFIG_PWM_K64_FTM_2_PRESCALE,
.clock_source = CONFIG_PWM_K64_FTM_2_CLOCK_SOURCE,
#ifdef CONFIG_PWM_K64_FTM_2_PHASE_ENABLE_0
.phase_enable0 = 1,
#else
.phase_enable0 = 0,
#endif
#ifdef CONFIG_PWM_K64_FTM_2_PHASE_ENABLE_2
.phase_enable2 = 1,
#else
.phase_enable2 = 0,
#endif
#ifdef CONFIG_PWM_K64_FTM_2_PHASE_ENABLE_4
.phase_enable4 = 1,
#else
.phase_enable4 = 0,
#endif
#ifdef CONFIG_PWM_K64_FTM_2_PHASE_ENABLE_6
.phase_enable6 = 1,
#else
.phase_enable6 = 0,
#endif
};
static struct pwm_ftm_drv_data pwm_ftm_2_drvdata;
DEVICE_INIT(pwm_ftm_2, CONFIG_PWM_K64_FTM_2_DEV_NAME, pwm_ftm_init,
&pwm_ftm_2_drvdata, &pwm_ftm_2_cfg,
SECONDARY, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
#endif /* CONFIG_PWM_K64_FTM_2 */
/* Initialization for PWM_K64_FTM_3 */
#ifdef CONFIG_PWM_K64_FTM_3
#include <device.h>
#include <init.h>
static struct pwm_ftm_config pwm_ftm_3_cfg = {
.ftm_num = 3,
.reg_base = CONFIG_PWM_K64_FTM_3_REG_BASE,
.prescale = CONFIG_PWM_K64_FTM_3_PRESCALE,
.clock_source = CONFIG_PWM_K64_FTM_3_CLOCK_SOURCE,
#ifdef CONFIG_PWM_K64_FTM_3_PHASE_ENABLE_0
.phase_enable0 = 1,
#else
.phase_enable0 = 0,
#endif
#ifdef CONFIG_PWM_K64_FTM_3_PHASE_ENABLE_2
.phase_enable2 = 1,
#else
.phase_enable2 = 0,
#endif
#ifdef CONFIG_PWM_K64_FTM_3_PHASE_ENABLE_4
.phase_enable4 = 1,
#else
.phase_enable4 = 0,
#endif
#ifdef CONFIG_PWM_K64_FTM_3_PHASE_ENABLE_6
.phase_enable6 = 1,
#else
.phase_enable6 = 0,
#endif
};
static struct pwm_ftm_drv_data pwm_ftm_3_drvdata;
DEVICE_INIT(pwm_ftm_3, CONFIG_PWM_K64_FTM_3_DEV_NAME, pwm_ftm_init,
&pwm_ftm_3_drvdata, &pwm_ftm_3_cfg,
SECONDARY, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
#endif /* CONFIG_PWM_K64_FTM_3 */

185
drivers/pwm/pwm_k64_ftm.h Normal file
View file

@ -0,0 +1,185 @@
/*
* Copyright (c) 2016, Wind River Systems, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file Header file for the PWM driver for Freescale K64 FlexTimer Module (FTM)
*/
#ifndef __PWM_K64_FTM_H__
#define __PWM_K64_FTM_H__
#include <stdbool.h>
/* Valid prescale values */
#define PWM_K64_FTM_PRESCALE_1 1
#define PWM_K64_FTM_PRESCALE_2 2
#define PWM_K64_FTM_PRESCALE_4 4
#define PWM_K64_FTM_PRESCALE_8 8
#define PWM_K64_FTM_PRESCALE_16 16
#define PWM_K64_FTM_PRESCALE_32 32
#define PWM_K64_FTM_PRESCALE_64 64
#define PWM_K64_FTM_PRESCALE_128 128
/* flags are not used. This value can be passed into pwm_pin_configure */
#define PWM_K64_FTM_FLAG_NONE 0
/* FTM register bit definitions */
#define PWM_K64_FTM_SC(base) ((base)+0x00) /* Status And Control */
#define PWM_K64_FTM_CNT(base) ((base)+0x04) /* Counter */
#define PWM_K64_FTM_MOD(base) ((base)+0x08) /* Modulo */
#define PWM_K64_FTM_CNSC(base, ch) ((base)+0x0C+(ch)*8) /* Channel Status&Ctrl*/
#define PWM_K64_FTM_CNV(base, ch) ((base)+0x10+(ch)*8) /* Channel Value */
#define PWM_K64_FTM_CNTIN(base) ((base)+0x4C) /* Counter Initial Value */
#define PWM_K64_FTM_STATUS(base) ((base)+0x50) /* Capture And Compare Status*/
#define PWM_K64_FTM_MODE(base) ((base)+0x54) /* Features Mode Selection */
#define PWM_K64_FTM_SYNC(base) ((base)+0x58) /* Synchronization */
#define PWM_K64_FTM_OUTINIT(base) ((base)+0x5C) /* Initial Channels Output */
#define PWM_K64_FTM_OUTMASK(base) ((base)+0x60) /* Output Mask */
#define PWM_K64_FTM_COMBINE(base) ((base)+0x64) /* Function For Linked Chans */
#define PWM_K64_FTM_DEADTIME(base) ((base)+0x68) /* Deadtime Insertion Ctrl */
#define PWM_K64_FTM_EXTTRIG(base) ((base)+0x6C) /* FTM External Trigger */
#define PWM_K64_FTM_POL(base) ((base)+0x70) /* Channels Polarity */
#define PWM_K64_FTM_FMS(base) ((base)+0x74) /* Fault Mode Status */
#define PWM_K64_FTM_FILTER(base) ((base)+0x78) /* Input Capture Filter Ctrl */
#define PWM_K64_FTM_FLTCTRL(base) ((base)+0x7C) /* Fault Control */
#define PWM_K64_FTM_QDCTRL(base) ((base)+0x80) /* Quadrature Decoder Ctrl */
#define PWM_K64_FTM_CONF(base) ((base)+0x84) /* Configuration */
#define PWM_K64_FTM_FLTPOL(base) ((base)+0x88) /* FTM Fault Input Polarity */
#define PWM_K64_FTM_SYNCONF(base) ((base)+0x8C) /* Synchronization Config */
#define PWM_K64_FTM_INVCTRL(base) ((base)+0x90) /* FTM Inverting Control */
#define PWM_K64_FTM_SWOCTRL(base) ((base)+0x94) /* FTM Software Output Ctrl */
#define PWM_K64_FTM_PWMLOAD(base) ((base)+0x98) /* FTM PWM Load */
/* PWM_K64_FTM_SC Status And Control */
#define PWM_K64_FTM_SC_CLKS_MASK 0x18
#define PWM_K64_FTM_SC_CLKS_SHIFT 3
#define PWM_K64_FTM_SC_CLKS_DISABLE 0x0
#define PWM_K64_FTM_SC_CLKS_SYSTEM 0x1
#define PWM_K64_FTM_SC_CLKS_FIXED 0x2
#define PWM_K64_FTM_SC_CLKS_EXTERNAL 0x3
#define PWM_K64_FTM_SC_PS_D1 (0x0<<0)
#define PWM_K64_FTM_SC_PS_D2 (0x1<<0)
#define PWM_K64_FTM_SC_PS_D4 (0x2<<0)
#define PWM_K64_FTM_SC_PS_D8 (0x3<<0)
#define PWM_K64_FTM_SC_PS_D16 (0x4<<0)
#define PWM_K64_FTM_SC_PS_D32 (0x5<<0)
#define PWM_K64_FTM_SC_PS_D64 (0x6<<0)
#define PWM_K64_FTM_SC_PS_D128 (0x7<<0)
#define PWM_K64_FTM_SC_PS_MASK (0x7<<0)
/* PWM_K64_FTM_CNSC (FTMx_CnSC) Channel-n Status And Control */
#define PWM_K64_FTM_CNSC_DMA (0x1<<0)
#define PWM_K64_FTM_CNSC_ELSA (0x1<<2)
#define PWM_K64_FTM_CNSC_ELSB (0x1<<3)
#define PWM_K64_FTM_CNSC_MSA (0x1<<4)
#define PWM_K64_FTM_CNSC_MSB (0x1<<5)
#define PWM_K64_FTM_CNSC_CHIE (0x1<<6)
#define PWM_K64_FTM_CNSC_CHF (0x1<<7)
/* PWM_K64_FTM_MODE Features Mode Selection */
#define PWM_K64_FTM_MODE_FTMEN (0x1<<0)
#define PWM_K64_FTM_MODE_INIT (0x1<<1)
#define PWM_K64_FTM_MODE_WPDIS (0x1<<2)
#define PWM_K64_FTM_MODE_PWMSYNC (0x1<<3)
#define PWM_K64_FTM_MODE_CAPTEST (0x1<<4)
#define PWM_K64_FTM_MODE_FAULTM_DISABLE (0x0<<5)
#define PWM_K64_FTM_MODE_FAULTM_EVEN (0x1<<5)
#define PWM_K64_FTM_MODE_FAULTM_MANUAL (0x2<<5)
#define PWM_K64_FTM_MODE_FAULTM_AUTO (0x3<<5)
#define PWM_K64_FTM_MODE_FAULTM_MASK (0x3<<5)
#define PWM_K64_FTM_MODE_FAULTIE (0x1<<7)
/* PWM_K64_FTM_SYNC PWM Synchronization */
#define PWM_K64_FTM_SYNC_CNTMIN (0x1<<0)
#define PWM_K64_FTM_SYNC_CNTMAX (0x1<<1)
#define PWM_K64_FTM_SYNC_REINIT (0x1<<2)
#define PWM_K64_FTM_SYNC_SYNCHOM (0x1<<3)
#define PWM_K64_FTM_SYNC_TRIG0 (0x1<<4)
#define PWM_K64_FTM_SYNC_TRIG1 (0x1<<5)
#define PWM_K64_FTM_SYNC_TRIG2 (0x1<<6)
#define PWM_K64_FTM_SYNC_SWSYNC (0x1<<7)
/* PWM_K64_FTM_EXTTRIG FTM External Trigger */
#define PWM_K64_FTM_EXTTRIG_CH2TRIG (0x1<<0)
#define PWM_K64_FTM_EXTTRIG_CH3TRIG (0x1<<1)
#define PWM_K64_FTM_EXTTRIG_CH4TRIG (0x1<<2)
#define PWM_K64_FTM_EXTTRIG_CH5TRIG (0x1<<3)
#define PWM_K64_FTM_EXTTRIG_CH0TRIG (0x1<<4)
#define PWM_K64_FTM_EXTTRIG_CH1TRIG (0x1<<5)
#define PWM_K64_FTM_EXTTRIG_INTTRIGEN (0x1<<6)
#define PWM_K64_FTM_EXTTRIG_TRIGF (0x1<<7)
/* PWM_K64_FTM_QDCTRL Quadrature Decoder Ctrl&Status */
#define PWM_K64_FTM_QDCTRL_QUADEN (0x1<<0)
/* PWM_K64_FTM_SYNCONF Syncronization Configuration */
#define PWM_K64_FTM_SYNCONF_HWTRIGMODE (0x1<<0)
#define PWM_K64_FTM_SYNCONF_CNTINC (0x1<<2)
#define PWM_K64_FTM_SYNCONF_INVC (0x1<<4)
#define PWM_K64_FTM_SYNCONF_SWOC (0x1<<5)
#define PWM_K64_FTM_SYNCONF_SYNCMODE (0x1<<7)
/**
* @brief Initialization function for FlexTimer Module FTM (PWM mode)
*
* @param dev Device struct
* @return DEV_OK if successful, failed otherwise
*/
extern int pwm_ftm_init(struct device *dev);
/** Configuration data */
struct pwm_ftm_config {
/* FTM register base address */
uint32_t ftm_num;
/* FTM register base address */
uint32_t reg_base;
/* FTM prescale (1,2,4,8,16,32,64,128) */
uint32_t prescale;
/* FTM clock source */
uint32_t clock_source;
/* If phase is not 0, the odd-numbered channel is not available */
bool phase_enable0; /* combine pwm0, pwm1 for phase capability */
bool phase_enable2; /* combine pwm2, pwm3 for phase capability */
bool phase_enable4; /* combine pwm4, pwm4 for phase capability */
bool phase_enable6; /* combine pwm6, pwm5 for phase capability */
/* FTM period (clock ticks) */
uint32_t period;
};
/** Runtime driver data */
struct pwm_ftm_drv_data {
uint32_t phase[4];
};
#endif /* __PWM_K64_FTM_H__ */