samv7: add support for PWM fault protection
This commit adds configurable fault protection to SAMv7 PWM driver. The fault input can be used from peripherals as ADC or GPIO inputs. Inputs from GPIO have configurable polarity (high or low). The PWM output is automatically set to zero if fault input is active and restored if fault input is not actived. Signed-off-by: Michal Lenc <michallenc@seznam.cz>
This commit is contained in:
parent
16ea80e53b
commit
93097be705
@ -770,6 +770,75 @@ config SAMV7_PWM
|
||||
|
||||
endmenu
|
||||
|
||||
menu "PWM Fault inputs"
|
||||
|
||||
config SAMV7_PWM0_PA9
|
||||
bool "External fault input from PA9"
|
||||
default n
|
||||
|
||||
if SAMV7_PWM1_PA9
|
||||
|
||||
config SAMV7_PWM1_PA9_POL
|
||||
bool "Inverted polarity"
|
||||
default n
|
||||
---help---
|
||||
Fault input is by default active on high level. This config
|
||||
inverts the logic and makes fault active on low level.
|
||||
|
||||
endif
|
||||
|
||||
config SAMV7_PWM0_PD8
|
||||
bool "External fault input from PD8"
|
||||
default n
|
||||
|
||||
if SAMV7_PWM1_PD8
|
||||
|
||||
config SAMV7_PWM1_PD8_POL
|
||||
bool "Inverted polarity"
|
||||
default n
|
||||
---help---
|
||||
Fault input is by default active on high level. This config
|
||||
inverts the logic and makes fault active on low level.
|
||||
|
||||
endif
|
||||
|
||||
config SAMV7_PWM0_PD9
|
||||
bool "External fault input from PD9"
|
||||
default n
|
||||
|
||||
if SAMV7_PWM1_PD9
|
||||
|
||||
config SAMV7_PWM1_PD9_POL
|
||||
bool "Inverted polarity"
|
||||
default n
|
||||
---help---
|
||||
Fault input is by default active on high level. This config
|
||||
inverts the logic and makes fault active on low level.
|
||||
|
||||
endif
|
||||
|
||||
config SAMV7_PWM0_PMC
|
||||
bool "External fault input from PMC"
|
||||
default n
|
||||
|
||||
config SAMV7_PWM0_AFEC0
|
||||
bool "External fault input from AFEC0"
|
||||
default n
|
||||
|
||||
config SAMV7_PWM0_AFEC1
|
||||
bool "External fault input from AFEC1"
|
||||
default n
|
||||
|
||||
config SAMV7_PWM0_ACC
|
||||
bool "External fault input from ACC"
|
||||
default n
|
||||
|
||||
config SAMV7_PWM0_TIM0
|
||||
bool "External fault input from Timer 0"
|
||||
default n
|
||||
|
||||
endmenu
|
||||
|
||||
config SAMV7_PWM0_EVENT0
|
||||
bool "Generate trigger on Event Line 0"
|
||||
default n
|
||||
@ -915,6 +984,76 @@ config SAMV7_PWM1_TRIG7
|
||||
|
||||
endmenu
|
||||
|
||||
menu "PWM Fault inputs"
|
||||
|
||||
config SAMV7_PWM1_PA21
|
||||
bool "External fault input from PA21"
|
||||
default n
|
||||
|
||||
if SAMV7_PWM1_PA21
|
||||
|
||||
config SAMV7_PWM1_PA21_POL
|
||||
bool "Inverted polarity"
|
||||
default n
|
||||
---help---
|
||||
Fault input is by default active on high level. This config
|
||||
inverts the logic and makes fault active on low level.
|
||||
|
||||
endif
|
||||
|
||||
config SAMV7_PWM1_PA26
|
||||
bool "External fault input from PA26"
|
||||
default n
|
||||
|
||||
if SAMV7_PWM1_PA26
|
||||
|
||||
config SAMV7_PWM1_PA26_POL
|
||||
bool "Inverted polarity"
|
||||
default n
|
||||
---help---
|
||||
Fault input is by default active on high level. This config
|
||||
inverts the logic and makes fault active on low level.
|
||||
|
||||
endif
|
||||
|
||||
config SAMV7_PWM1_PA28
|
||||
bool "External fault input from PA28"
|
||||
default n
|
||||
|
||||
if SAMV7_PWM1_PA28
|
||||
|
||||
config SAMV7_PWM1_PA28_POL
|
||||
bool "Inverted polarity"
|
||||
default n
|
||||
---help---
|
||||
Fault input is by default active on high level. This config
|
||||
inverts the logic and makes fault active on low level.
|
||||
|
||||
endif
|
||||
|
||||
config SAMV7_PWM1_PMC
|
||||
bool "External fault input from PMC"
|
||||
default n
|
||||
|
||||
config SAMV7_PWM1_AFEC0
|
||||
bool "External fault input from AFEC0"
|
||||
default n
|
||||
|
||||
config SAMV7_PWM1_AFEC1
|
||||
bool "External fault input from AFEC1"
|
||||
default n
|
||||
|
||||
config SAMV7_PWM1_ACC
|
||||
bool "External fault input from ACC"
|
||||
default n
|
||||
|
||||
config SAMV7_PWM1_TIM0
|
||||
bool "External fault input from Timer 0"
|
||||
default n
|
||||
|
||||
endmenu
|
||||
|
||||
|
||||
config SAMV7_PWM1_EVENT0
|
||||
bool "Generate trigger on Event Line 0"
|
||||
default n
|
||||
|
@ -60,6 +60,7 @@
|
||||
|
||||
#define CHANNEL_OFFSET 0x20
|
||||
#define COMP_OFFSET 0x10
|
||||
#define FAULT_SEL_OFFSET 0x8
|
||||
#define CLK_FREQ BOARD_MCK_FREQUENCY
|
||||
#define PWM_RES 65535
|
||||
#define COMP_UNITS_NUM 8
|
||||
@ -86,11 +87,21 @@ struct sam_pwm_comparison_s
|
||||
int event1;
|
||||
};
|
||||
|
||||
struct sam_pwm_fault_s
|
||||
{
|
||||
uint8_t source; /* Source of fault input */
|
||||
uint8_t polarity;
|
||||
gpio_pinset_t gpio_0; /* GPIO 1 fault input */
|
||||
gpio_pinset_t gpio_1; /* GPIO 2 fault input */
|
||||
gpio_pinset_t gpio_2; /* GPIO 3 fault input */
|
||||
};
|
||||
|
||||
struct sam_pwm_s
|
||||
{
|
||||
const struct pwm_ops_s *ops; /* PWM operations */
|
||||
const struct sam_pwm_channel_s *channels;
|
||||
const struct sam_pwm_comparison_s *comparison;
|
||||
const struct sam_pwm_fault_s *fault;
|
||||
uint8_t channels_num; /* Number of channels */
|
||||
uintptr_t base; /* Base address of peripheral register */
|
||||
};
|
||||
@ -189,11 +200,21 @@ static struct sam_pwm_comparison_s g_pwm0_comparison =
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct sam_pwm_fault_s g_pwm0_fault =
|
||||
{
|
||||
.source = PWM0_FAULTS,
|
||||
.polarity = PWM0_POL,
|
||||
.gpio_0 = GPIO_PWMC0_FI0,
|
||||
.gpio_1 = GPIO_PWMC0_FI1,
|
||||
.gpio_2 = GPIO_PWMC0_FI2,
|
||||
};
|
||||
|
||||
static struct sam_pwm_s g_pwm0 =
|
||||
{
|
||||
.ops = &g_pwmops,
|
||||
.channels = g_pwm0_channels,
|
||||
.comparison = &g_pwm0_comparison,
|
||||
.fault = &g_pwm0_fault,
|
||||
.channels_num = PWM0_NCHANNELS,
|
||||
.base = SAM_PWM0_BASE,
|
||||
};
|
||||
@ -270,17 +291,26 @@ static struct sam_pwm_comparison_s g_pwm1_comparison =
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct sam_pwm_fault_s g_pwm1_fault =
|
||||
{
|
||||
.source = PWM1_FAULTS,
|
||||
.polarity = PWM1_POL,
|
||||
.gpio_0 = GPIO_PWMC1_FI0,
|
||||
.gpio_1 = GPIO_PWMC1_FI1,
|
||||
.gpio_2 = GPIO_PWMC1_FI2,
|
||||
};
|
||||
|
||||
static struct sam_pwm_s g_pwm1 =
|
||||
{
|
||||
.ops = &g_pwmops,
|
||||
.channels = g_pwm1_channels,
|
||||
.comparison = &g_pwm1_comparison,
|
||||
.fault = &g_pwm1_fault,
|
||||
.channels_num = PWM1_NCHANNELS,
|
||||
.base = SAM_PWM1_BASE,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
@ -566,13 +596,45 @@ static int pwm_setup(struct pwm_lowerhalf_s *dev)
|
||||
|
||||
pwm_putreg(priv, SAMV7_PWM_DTX + (channel * CHANNEL_OFFSET), 0);
|
||||
|
||||
/* Fault protection registers */
|
||||
/* Enable fault protection if configured. The protection has to
|
||||
* be enabled for every configured channel separately.
|
||||
*/
|
||||
|
||||
pwm_putreg(priv, SAMV7_PWM_FPV1, 0);
|
||||
pwm_putreg(priv, SAMV7_PWM_FPV2, 0);
|
||||
pwm_putreg(priv, SAMV7_PWM_FPE, 0);
|
||||
regval = pwm_getreg(priv, SAMV7_PWM_FPE);
|
||||
regval |= priv->fault->source << (FAULT_SEL_OFFSET * channel);
|
||||
pwm_putreg(priv, SAMV7_PWM_FPE, regval);
|
||||
}
|
||||
|
||||
/* Configure fault GPIOs if used */
|
||||
|
||||
if (priv->fault->source & 1)
|
||||
{
|
||||
sam_configgpio(priv->fault->gpio_0);
|
||||
}
|
||||
|
||||
if (priv->fault->source & (1 << 1))
|
||||
{
|
||||
sam_configgpio(priv->fault->gpio_1);
|
||||
}
|
||||
|
||||
if (priv->fault->source & (1 << 2))
|
||||
{
|
||||
sam_configgpio(priv->fault->gpio_2);
|
||||
}
|
||||
|
||||
/* Set fault polarity. This has to be 1 for peripheral fault
|
||||
* generation (from ADC for example), GPIO generated fault
|
||||
* is set via configuration options.
|
||||
*/
|
||||
|
||||
regval = FMR_FPOL_SEL(priv->fault->polarity);
|
||||
pwm_putreg(priv, SAMV7_PWM_FMR, regval);
|
||||
|
||||
/* Force both outputs to 0 if fault occurs */
|
||||
|
||||
pwm_putreg(priv, SAMV7_PWM_FPV1, 0);
|
||||
pwm_putreg(priv, SAMV7_PWM_FPV2, 0);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
@ -653,7 +715,6 @@ static int pwm_start(struct pwm_lowerhalf_s *dev,
|
||||
info->frequency);
|
||||
pwm_set_output(dev, priv->channels[index - 1].channel,
|
||||
info->channels[i].duty);
|
||||
|
||||
#ifdef CONFIG_PWM_OVERWRITE
|
||||
if (info->channels[i].ch_outp_ovrwr)
|
||||
{
|
||||
|
@ -88,6 +88,154 @@
|
||||
|
||||
#define PWM1_NCHANNELS (PWM1_CH0 + PWM1_CH1 + PWM1_CH2 + PWM1_CH3)
|
||||
|
||||
/* Fault protection */
|
||||
|
||||
#ifdef CONFIG_SAMV7_PWM0_PA9
|
||||
#define PWM0_PA9 1
|
||||
#ifdef CONFIG_SAMV7_PWM0_PA9_POL
|
||||
#define PWM0_PA9_POL 0
|
||||
#else
|
||||
#define PWM0_PA9_POL 1
|
||||
#endif
|
||||
#else
|
||||
#define PWM0_PA9 0
|
||||
#define PWM0_PA9_POL 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SAMV7_PWM0_PD8
|
||||
#define PWM0_PD8 (1 << 1)
|
||||
#ifdef CONFIG_SAMV7_PWM0_PD8_POL
|
||||
#define PWM0_PD8_POL 0
|
||||
#else
|
||||
#define PWM0_PD8_POL (1 << 1)
|
||||
#endif
|
||||
#else
|
||||
#define PWM0_PD8 0
|
||||
#define PWM0_PD8_POL 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SAMV7_PWM0_PD9
|
||||
#define PWM0_PD9 (1 << 2)
|
||||
#ifdef CONFIG_SAMV7_PWM0_PD9_POL
|
||||
#define PWM0_PD9_POL 0
|
||||
#else
|
||||
#define PWM0_PD9_POL (1 << 2)
|
||||
#endif
|
||||
#else
|
||||
#define PWM0_PD9 0
|
||||
#define PWM0_PD9_POL 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SAMV7_PWM0_PMC
|
||||
#define PWM0_PMC (1 << 3)
|
||||
#else
|
||||
#define PWM0_PMC 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SAMV7_PWM0_AFEC0
|
||||
#define PWM0_AFEC0 (1 << 4)
|
||||
#else
|
||||
#define PWM0_AFEC0 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SAMV7_PWM0_AFEC1
|
||||
#define PWM0_AFEC1 (1 << 5)
|
||||
#else
|
||||
#define PWM0_AFEC1 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SAMV7_PWM0_ACC
|
||||
#define PWM0_ACC (1 << 6)
|
||||
#else
|
||||
#define PWM0_ACC 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SAMV7_PWM0_TIM0
|
||||
#define PWM0_TIM0 (1 << 7)
|
||||
#else
|
||||
#define PWM0_TIM0 0
|
||||
#endif
|
||||
|
||||
#define PWM0_FAULTS (PWM0_PA9 + PWM0_PD8 + PWM0_PD9 + PWM0_PMC + \
|
||||
PWM0_AFEC0 + PWM0_AFEC1 + PWM0_ACC + PWM0_TIM0)
|
||||
|
||||
#define PWM0_POL (PWM0_PA9_POL + PWM0_PD8_POL + PWM0_PD9_POL + \
|
||||
PWM0_PMC + PWM0_AFEC0 + PWM0_AFEC1 + PWM0_ACC + \
|
||||
PWM0_TIM0)
|
||||
|
||||
#ifdef CONFIG_SAMV7_PWM1_PA21
|
||||
#define PWM1_PA21 1
|
||||
#ifdef CONFIG_SAMV7_PWM1_PA21_POL
|
||||
#define PWM1_PA21_POL 0
|
||||
#else
|
||||
#define PWM1_PA21_POL 1
|
||||
#endif
|
||||
#else
|
||||
#define PWM1_PA21 0
|
||||
#define PWM1_PA21_POL 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SAMV7_PWM1_PA26
|
||||
#define PWM1_PA26 (1 << 1)
|
||||
#ifdef CONFIG_SAMV7_PWM1_PA26_POL
|
||||
#define PWM1_PA26_POL 0
|
||||
#else
|
||||
#define PWM1_PA26_POL (1 << 1)
|
||||
#endif
|
||||
#else
|
||||
#define PWM1_PA26 0
|
||||
#define PWM1_PA26_POL 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SAMV7_PWM1_PA28
|
||||
#define PWM1_PA28 (1 << 2)
|
||||
#ifdef CONFIG_SAMV7_PWM1_PA28_POL
|
||||
#define PWM1_PA28_POL 0
|
||||
#else
|
||||
#define PWM1_PA28_POL (1 << 2)
|
||||
#endif
|
||||
#else
|
||||
#define PWM1_PA28 0
|
||||
#define PWM1_PA28_POL 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SAMV7_PWM1_PMC
|
||||
#define PWM1_PMC (1 << 3)
|
||||
#else
|
||||
#define PWM1_PMC 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SAMV7_PWM1_AFEC0
|
||||
#define PWM1_AFEC0 (1 << 4)
|
||||
#else
|
||||
#define PWM1_AFEC0 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SAMV7_PWM1_AFEC1
|
||||
#define PWM1_AFEC1 (1 << 5)
|
||||
#else
|
||||
#define PWM1_AFEC1 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SAMV7_PWM1_ACC
|
||||
#define PWM1_ACC (1 << 6)
|
||||
#else
|
||||
#define PWM1_ACC 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SAMV7_PWM1_TIM0
|
||||
#define PWM1_TIM0 (1 << 7)
|
||||
#else
|
||||
#define PWM1_TIM0 0
|
||||
#endif
|
||||
|
||||
#define PWM1_FAULTS (PWM1_PA21 + PWM1_PA26 + PWM1_PA28 + PWM1_PMC + \
|
||||
PWM1_AFEC0 + PWM1_AFEC1 + PWM1_ACC + PWM1_TIM0)
|
||||
|
||||
#define PWM1_POL (PWM1_PA21_POL + PWM1_PA26_POL + PWM1_PA28_POL + \
|
||||
PWM1_PMC + PWM1_AFEC0 + PWM1_AFEC1 + PWM1_ACC + \
|
||||
PWM1_TIM0)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
Loading…
Reference in New Issue
Block a user