drivers: pwm: Microchip XEC PWM add MEC172x support

Add support for MEC172x series to Microchip XEC PWM driver.
Standardize device tree properties for both SoC families.
Standardize device structure usage.

Signed-off-by: Jay Vasanth <jay.vasanth@microchip.com>
This commit is contained in:
Jay Vasanth 2022-03-11 14:37:39 -05:00 committed by Anas Nashif
parent 717853088c
commit 845c1185a2
4 changed files with 94 additions and 60 deletions

View file

@ -1,22 +1,30 @@
/* pwm_mchp_xec.c - Microchip XEC PWM driver */
#define DT_DRV_COMPAT microchip_xec_pwm
/*
* Copyright (c) 2019 Intel Corporation
* Copyright (c) 2022 Microchip Technololgy Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <logging/log.h>
LOG_MODULE_REGISTER(pwm_mchp_xec, CONFIG_PWM_LOG_LEVEL);
#define DT_DRV_COMPAT microchip_xec_pwm
#include <drivers/pwm.h>
#include <soc.h>
#include <errno.h>
#include <soc.h>
#include <drivers/pwm.h>
#ifdef CONFIG_SOC_SERIES_MEC172X
#include <drivers/clock_control/mchp_xec_clock_control.h>
#include <drivers/interrupt_controller/intc_mchp_xec_ecia.h>
#endif
#include <device.h>
#include <errno.h>
#include <kernel.h>
#include <init.h>
#include <pm/device.h>
#include <stdlib.h>
#include <logging/log.h>
LOG_MODULE_REGISTER(pwm_mchp_xec, CONFIG_PWM_LOG_LEVEL);
/* Minimal on/off are 1 & 1 both are incremented, so 4.
* 0 cannot be set (used for full low/high output) so a
* combination of on_off of 2 is not possible.
@ -43,18 +51,11 @@ LOG_MODULE_REGISTER(pwm_mchp_xec, CONFIG_PWM_LOG_LEVEL);
#define XEC_PWM_FREQ_LIMIT 1 /* 0.1hz * XEC_PWM_FREQ_PF */
struct pwm_xec_config {
uint32_t base_address;
struct pwm_regs * const regs;
uint8_t pcr_idx;
uint8_t pcr_pos;
};
#define PWM_XEC_REG_BASE(_dev) \
((PWM_Type *) \
((const struct pwm_xec_config * const) \
_dev->config)->base_address)
#define PWM_XEC_CONFIG(_dev) \
(((const struct pwm_xec_config * const) \
_dev->config))
struct xec_params {
uint32_t on;
uint32_t off;
@ -63,7 +64,7 @@ struct xec_params {
#define NUM_DIV_ELEMS 16
uint32_t max_freq_high_on_div[NUM_DIV_ELEMS] = {
static const uint32_t max_freq_high_on_div[NUM_DIV_ELEMS] = {
48000000,
24000000,
16000000,
@ -82,7 +83,7 @@ uint32_t max_freq_high_on_div[NUM_DIV_ELEMS] = {
3000000
};
uint32_t max_freq_low_on_div[NUM_DIV_ELEMS] = {
static const uint32_t max_freq_low_on_div[NUM_DIV_ELEMS] = {
100000,
50000,
33333,
@ -106,7 +107,7 @@ static uint32_t xec_compute_frequency(uint32_t clk, uint32_t on, uint32_t off)
return ((clk * XEC_PWM_FREQ_PF)/((on + 1) + (off + 1)));
}
static uint16_t xec_select_div(uint32_t freq, uint32_t max_freq[16])
static uint16_t xec_select_div(uint32_t freq, const uint32_t max_freq[16])
{
uint8_t i;
@ -147,9 +148,9 @@ static uint32_t xec_compute_dc(uint32_t on, uint32_t off)
}
static uint16_t xec_compare_div_on_off(uint32_t target_freq, uint32_t dc,
uint32_t max_freq[16],
uint8_t div_a, uint8_t div_b,
uint32_t *on_a, uint32_t *off_a)
const uint32_t max_freq[16],
uint8_t div_a, uint8_t div_b,
uint32_t *on_a, uint32_t *off_a)
{
uint32_t freq_a, freq_b, on_b, off_b;
@ -180,8 +181,8 @@ static uint16_t xec_compare_div_on_off(uint32_t target_freq, uint32_t dc,
}
static uint8_t xec_select_best_div_on_off(uint32_t target_freq, uint32_t dc,
uint32_t max_freq[16],
uint32_t *on, uint32_t *off)
const uint32_t max_freq[16],
uint32_t *on, uint32_t *off)
{
int div_comp;
uint8_t div;
@ -237,12 +238,13 @@ static void xec_compute_and_set_parameters(const struct device *dev,
uint32_t target_freq,
uint32_t on, uint32_t off)
{
PWM_Type *pwm_regs = PWM_XEC_REG_BASE(dev);
const struct pwm_xec_config * const cfg = dev->config;
struct pwm_regs * const regs = cfg->regs;
bool compute_high, compute_low;
struct xec_params hc_params;
struct xec_params lc_params;
struct xec_params *params;
uint32_t dc, reg;
uint32_t dc, cfgval;
dc = xec_compute_dc(on, off);
@ -287,30 +289,31 @@ static void xec_compute_and_set_parameters(const struct device *dev,
lc_params.div = UINT8_MAX;
}
done:
pwm_regs->CONFIG &= ~MCHP_PWM_CFG_ENABLE;
regs->CONFIG &= ~MCHP_PWM_CFG_ENABLE;
reg = pwm_regs->CONFIG;
cfgval = regs->CONFIG;
params = xec_compare_params(target_freq, &hc_params, &lc_params);
if (params == &hc_params) {
reg |= MCHP_PWM_CFG_CLK_SEL_48M;
cfgval |= MCHP_PWM_CFG_CLK_SEL_48M;
} else {
reg |= MCHP_PWM_CFG_CLK_SEL_100K;
cfgval |= MCHP_PWM_CFG_CLK_SEL_100K;
}
pwm_regs->COUNT_ON = params->on;
pwm_regs->COUNT_OFF = params->off;
reg |= MCHP_PWM_CFG_CLK_PRE_DIV(params->div);
reg |= MCHP_PWM_CFG_ENABLE;
regs->COUNT_ON = params->on;
regs->COUNT_OFF = params->off;
cfgval |= MCHP_PWM_CFG_CLK_PRE_DIV(params->div);
cfgval |= MCHP_PWM_CFG_ENABLE;
pwm_regs->CONFIG = reg;
regs->CONFIG = cfgval;
}
static int pwm_xec_pin_set(const struct device *dev, uint32_t pwm,
uint32_t period_cycles, uint32_t pulse_cycles,
pwm_flags_t flags)
{
PWM_Type *pwm_regs = PWM_XEC_REG_BASE(dev);
const struct pwm_xec_config * const cfg = dev->config;
struct pwm_regs * const regs = cfg->regs;
uint32_t target_freq;
uint32_t on, off;
@ -337,13 +340,13 @@ static int pwm_xec_pin_set(const struct device *dev, uint32_t pwm,
}
if ((pulse_cycles == 0U) && (period_cycles == 0U)) {
pwm_regs->CONFIG &= ~MCHP_PWM_CFG_ENABLE;
regs->CONFIG &= ~MCHP_PWM_CFG_ENABLE;
} else if ((pulse_cycles == 0U) && (period_cycles > 0U)) {
pwm_regs->COUNT_ON = 0;
pwm_regs->COUNT_OFF = 1;
regs->COUNT_ON = 0;
regs->COUNT_OFF = 1;
} else if ((pulse_cycles > 0U) && (period_cycles == 0U)) {
pwm_regs->COUNT_ON = 1;
pwm_regs->COUNT_OFF = 0;
regs->COUNT_ON = 1;
regs->COUNT_OFF = 0;
} else {
xec_compute_and_set_parameters(dev, target_freq, on, off);
}
@ -370,6 +373,11 @@ static int pwm_xec_get_cycles_per_sec(const struct device *dev, uint32_t pwm,
return 0;
}
static const struct pwm_driver_api pwm_xec_driver_api = {
.pin_set = pwm_xec_pin_set,
.get_cycles_per_sec = pwm_xec_get_cycles_per_sec,
};
static int pwm_xec_init(const struct device *dev)
{
ARG_UNUSED(dev);
@ -377,23 +385,22 @@ static int pwm_xec_init(const struct device *dev)
return 0;
}
static struct pwm_driver_api pwm_xec_api = {
.pin_set = pwm_xec_pin_set,
.get_cycles_per_sec = pwm_xec_get_cycles_per_sec
};
#define XEC_PWM_CONFIG(inst) \
static struct pwm_xec_config pwm_xec_config_##inst = { \
.regs = (struct pwm_regs * const)DT_INST_REG_ADDR(inst), \
.pcr_idx = (uint8_t)DT_INST_PROP_BY_IDX(inst, pcrs, 0), \
.pcr_pos = (uint8_t)DT_INST_PROP_BY_IDX(inst, pcrs, 1), \
};
#define XEC_INST_INIT(inst) \
static struct pwm_xec_config pwm_xec_dev_config_##inst = { \
.base_address = DT_INST_REG_ADDR(inst) \
}; \
#define XEC_PWM_DEVICE_INIT(index) \
\
DEVICE_DT_INST_DEFINE(inst, \
pwm_xec_init, \
NULL, \
NULL, \
&pwm_xec_dev_config_##inst, \
POST_KERNEL, \
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
&pwm_xec_api);
XEC_PWM_CONFIG(index); \
\
DEVICE_DT_INST_DEFINE(index, &pwm_xec_init, \
NULL, \
NULL, \
&pwm_xec_config_##index, POST_KERNEL, \
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
&pwm_xec_driver_api);
DT_INST_FOREACH_STATUS_OKAY(XEC_INST_INIT)
DT_INST_FOREACH_STATUS_OKAY(XEC_PWM_DEVICE_INIT)

View file

@ -341,6 +341,7 @@
pwm0: pwm@40005800 {
compatible = "microchip,xec-pwm";
reg = <0x40005800 0x20>;
pcrs = <1 4>;
label = "PWM_0";
status = "disabled";
#pwm-cells = <1>;
@ -348,6 +349,7 @@
pwm1: pwm@40005810 {
compatible = "microchip,xec-pwm";
reg = <0x40005810 0x20>;
pcrs = <1 20>;
label = "PWM_1";
status = "disabled";
#pwm-cells = <1>;
@ -355,6 +357,7 @@
pwm2: pwm@40005820 {
compatible = "microchip,xec-pwm";
reg = <0x40005820 0x20>;
pcrs = <1 21>;
label = "PWM_2";
status = "disabled";
#pwm-cells = <1>;
@ -362,6 +365,7 @@
pwm3: pwm@40005830 {
compatible = "microchip,xec-pwm";
reg = <0x40005830 0x20>;
pcrs = <1 22>;
label = "PWM_3";
status = "disabled";
#pwm-cells = <1>;
@ -369,6 +373,7 @@
pwm4: pwm@40005840 {
compatible = "microchip,xec-pwm";
reg = <0x40005840 0x20>;
pcrs = <1 23>;
label = "PWM_4";
status = "disabled";
#pwm-cells = <1>;
@ -376,6 +381,7 @@
pwm5: pwm@40005850 {
compatible = "microchip,xec-pwm";
reg = <0x40005850 0x20>;
pcrs = <1 24>;
label = "PWM_5";
status = "disabled";
#pwm-cells = <1>;
@ -383,6 +389,7 @@
pwm6: pwm@40005860 {
compatible = "microchip,xec-pwm";
reg = <0x40005860 0x20>;
pcrs = <1 25>;
label = "PWM_6";
status = "disabled";
#pwm-cells = <1>;
@ -390,6 +397,7 @@
pwm7: pwm@40005870 {
compatible = "microchip,xec-pwm";
reg = <0x40005870 0x20>;
pcrs = <1 26>;
label = "PWM_7";
status = "disabled";
#pwm-cells = <1>;
@ -397,6 +405,7 @@
pwm8: pwm@40005880 {
compatible = "microchip,xec-pwm";
reg = <0x40005880 0x20>;
pcrs = <1 27>;
label = "PWM_8";
status = "disabled";
#pwm-cells = <1>;

View file

@ -587,6 +587,7 @@
status = "disabled";
};
pwm0: pwm@40005800 {
compatible = "microchip,xec-pwm";
reg = <0x40005800 0x20>;
pcrs = <1 4>;
label = "PWM_0";
@ -594,6 +595,7 @@
#pwm-cells = <1>;
};
pwm1: pwm@40005810 {
compatible = "microchip,xec-pwm";
reg = <0x40005810 0x20>;
pcrs = <1 20>;
label = "PWM_1";
@ -601,6 +603,7 @@
#pwm-cells = <1>;
};
pwm2: pwm@40005820 {
compatible = "microchip,xec-pwm";
reg = <0x40005820 0x20>;
pcrs = <1 21>;
label = "PWM_2";
@ -608,6 +611,7 @@
#pwm-cells = <1>;
};
pwm3: pwm@40005830 {
compatible = "microchip,xec-pwm";
reg = <0x40005830 0x20>;
pcrs = <1 22>;
label = "PWM_3";
@ -615,6 +619,7 @@
#pwm-cells = <1>;
};
pwm4: pwm@40005840 {
compatible = "microchip,xec-pwm";
reg = <0x40005840 0x20>;
pcrs = <1 23>;
label = "PWM_4";
@ -622,6 +627,7 @@
#pwm-cells = <1>;
};
pwm5: pwm@40005850 {
compatible = "microchip,xec-pwm";
reg = <0x40005850 0x20>;
pcrs = <1 24>;
label = "PWM_5";
@ -629,6 +635,7 @@
#pwm-cells = <1>;
};
pwm6: pwm@40005860 {
compatible = "microchip,xec-pwm";
reg = <0x40005860 0x20>;
pcrs = <1 25>;
label = "PWM_6";
@ -636,6 +643,7 @@
#pwm-cells = <1>;
};
pwm7: pwm@40005870 {
compatible = "microchip,xec-pwm";
reg = <0x40005870 0x20>;
pcrs = <1 26>;
label = "PWM_7";
@ -643,6 +651,7 @@
#pwm-cells = <1>;
};
pwm8: pwm@40005880 {
compatible = "microchip,xec-pwm";
reg = <0x40005880 0x20>;
pcrs = <1 27>;
label = "PWM_8";

View file

@ -13,3 +13,12 @@ properties:
label:
required: true
pcrs:
type: array
required: true
description: PWM PCR register index and bit position
pcr-cells:
- regidx
- bitpos