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:
parent
717853088c
commit
845c1185a2
|
@ -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)
|
||||
|
|
|
@ -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>;
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue