drivers: pwm: split up driver for MAX31790 into a MFD
Split up the driver for the PWM controller MAX31790 into a multi function device driver. Signed-off-by: Benedikt Schmidt <benedikt.schmidt@embedded-solutions.at>
This commit is contained in:
parent
68eb97ea05
commit
961c985ee4
11 changed files with 254 additions and 176 deletions
|
@ -9,5 +9,6 @@ zephyr_library_sources_ifdef(CONFIG_MFD_NPM1300 mfd_npm1300.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_MFD_NPM6001 mfd_npm6001.c)
|
zephyr_library_sources_ifdef(CONFIG_MFD_NPM6001 mfd_npm6001.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_MFD_AXP192 mfd_axp192.c)
|
zephyr_library_sources_ifdef(CONFIG_MFD_AXP192 mfd_axp192.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_MFD_AD5592 mfd_ad5592.c)
|
zephyr_library_sources_ifdef(CONFIG_MFD_AD5592 mfd_ad5592.c)
|
||||||
|
zephyr_library_sources_ifdef(CONFIG_MFD_MAX31790 mfd_max31790.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_NXP_LP_FLEXCOMM mfd_nxp_lp_flexcomm.c)
|
zephyr_library_sources_ifdef(CONFIG_NXP_LP_FLEXCOMM mfd_nxp_lp_flexcomm.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_MFD_BD8LB600FS mfd_bd8lb600fs.c)
|
zephyr_library_sources_ifdef(CONFIG_MFD_BD8LB600FS mfd_bd8lb600fs.c)
|
||||||
|
|
|
@ -22,6 +22,7 @@ source "drivers/mfd/Kconfig.ad5592"
|
||||||
source "drivers/mfd/Kconfig.axp192"
|
source "drivers/mfd/Kconfig.axp192"
|
||||||
source "drivers/mfd/Kconfig.bd8lb600fs"
|
source "drivers/mfd/Kconfig.bd8lb600fs"
|
||||||
source "drivers/mfd/Kconfig.max20335"
|
source "drivers/mfd/Kconfig.max20335"
|
||||||
|
source "drivers/mfd/Kconfig.max31790"
|
||||||
source "drivers/mfd/Kconfig.nct38xx"
|
source "drivers/mfd/Kconfig.nct38xx"
|
||||||
source "drivers/mfd/Kconfig.npm1300"
|
source "drivers/mfd/Kconfig.npm1300"
|
||||||
source "drivers/mfd/Kconfig.npm6001"
|
source "drivers/mfd/Kconfig.npm6001"
|
||||||
|
|
10
drivers/mfd/Kconfig.max31790
Normal file
10
drivers/mfd/Kconfig.max31790
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
# Copyright (c) 2024 SILA Embedded Solutions GmbH
|
||||||
|
# SPDX -License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
config MFD_MAX31790
|
||||||
|
bool "Maxim Integrated MAX31790 I2C configurable PWM controller"
|
||||||
|
default y
|
||||||
|
depends on DT_HAS_MAXIM_MAX31790_ENABLED
|
||||||
|
select I2C
|
||||||
|
help
|
||||||
|
Enable driver for Maxim Integrated MAX31790.
|
81
drivers/mfd/mfd_max31790.c
Normal file
81
drivers/mfd/mfd_max31790.c
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 SILA Embedded Solutions GmbH
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DT_DRV_COMPAT maxim_max31790
|
||||||
|
|
||||||
|
#include <zephyr/device.h>
|
||||||
|
#include <zephyr/drivers/i2c.h>
|
||||||
|
#include <zephyr/drivers/mfd/max31790.h>
|
||||||
|
#include <zephyr/sys/util.h>
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
#include <zephyr/logging/log.h>
|
||||||
|
|
||||||
|
|
||||||
|
LOG_MODULE_REGISTER(max_max31790, CONFIG_MFD_LOG_LEVEL);
|
||||||
|
|
||||||
|
struct max31790_config {
|
||||||
|
struct i2c_dt_spec i2c;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void max31790_set_globalconfiguration_i2cwatchdog(uint8_t *destination, uint8_t value)
|
||||||
|
{
|
||||||
|
uint8_t length = MAX37190_GLOBALCONFIGURATION_I2CWATCHDOG_LENGTH;
|
||||||
|
uint8_t pos = MAX37190_GLOBALCONFIGURATION_I2CWATCHDOG_POS;
|
||||||
|
|
||||||
|
*destination &= ~GENMASK(pos + length - 1, pos);
|
||||||
|
*destination |= FIELD_PREP(GENMASK(pos + length - 1, pos), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int max31790_init(const struct device *dev)
|
||||||
|
{
|
||||||
|
const struct max31790_config *config = dev->config;
|
||||||
|
int result;
|
||||||
|
uint8_t reg_value;
|
||||||
|
|
||||||
|
if (!i2c_is_ready_dt(&config->i2c)) {
|
||||||
|
LOG_ERR("I2C device not ready");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
reg_value = 0;
|
||||||
|
reg_value &= ~MAX37190_GLOBALCONFIGURATION_STANDBY_BIT;
|
||||||
|
reg_value |= MAX37190_GLOBALCONFIGURATION_RESET_BIT;
|
||||||
|
reg_value |= MAX37190_GLOBALCONFIGURATION_BUSTIMEOUT_BIT;
|
||||||
|
reg_value &= ~MAX37190_GLOBALCONFIGURATION_OSCILLATORSELECTION_BIT;
|
||||||
|
max31790_set_globalconfiguration_i2cwatchdog(®_value, 0);
|
||||||
|
reg_value &= ~MAX37190_GLOBALCONFIGURATION_I2CWATCHDOGSTATUS_BIT;
|
||||||
|
|
||||||
|
result = i2c_reg_write_byte_dt(&config->i2c, MAX37190_REGISTER_GLOBALCONFIGURATION,
|
||||||
|
reg_value);
|
||||||
|
if (result != 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
k_sleep(K_USEC(MAX31790_RESET_TIMEOUT_IN_US));
|
||||||
|
|
||||||
|
result = i2c_reg_read_byte_dt(&config->i2c, MAX37190_REGISTER_GLOBALCONFIGURATION,
|
||||||
|
®_value);
|
||||||
|
if (result != 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((reg_value & MAX37190_GLOBALCONFIGURATION_STANDBY_BIT) != 0) {
|
||||||
|
LOG_ERR("PWM controller is still in standby");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAX31790_INIT(inst) \
|
||||||
|
static const struct max31790_config max31790_##inst##_config = { \
|
||||||
|
.i2c = I2C_DT_SPEC_INST_GET(inst), \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
DEVICE_DT_INST_DEFINE(inst, max31790_init, NULL, NULL, &max31790_##inst##_config, \
|
||||||
|
POST_KERNEL, CONFIG_MFD_INIT_PRIORITY, NULL);
|
||||||
|
|
||||||
|
DT_INST_FOREACH_STATUS_OKAY(MAX31790_INIT);
|
|
@ -7,7 +7,7 @@
|
||||||
config PWM_MAX31790
|
config PWM_MAX31790
|
||||||
bool "MAX31790 6-channel I2C-bus PWM controller"
|
bool "MAX31790 6-channel I2C-bus PWM controller"
|
||||||
default y
|
default y
|
||||||
depends on DT_HAS_MAXIM_MAX31790_ENABLED
|
depends on DT_HAS_MAXIM_MAX31790_PWM_ENABLED
|
||||||
select I2C
|
select MFD
|
||||||
help
|
help
|
||||||
Enable driver for MAX31790 6-channel I2C-bus PWM controller.
|
Enable driver for MAX31790 6-channel I2C-bus PWM controller.
|
||||||
|
|
|
@ -4,68 +4,28 @@
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define DT_DRV_COMPAT maxim_max31790
|
#define DT_DRV_COMPAT maxim_max31790_pwm
|
||||||
|
|
||||||
#include <zephyr/device.h>
|
#include <zephyr/device.h>
|
||||||
#include <zephyr/drivers/i2c.h>
|
#include <zephyr/drivers/i2c.h>
|
||||||
|
#include <zephyr/drivers/mfd/max31790.h>
|
||||||
#include <zephyr/drivers/pwm.h>
|
#include <zephyr/drivers/pwm.h>
|
||||||
#include <zephyr/drivers/pwm/max31790.h>
|
#include <zephyr/drivers/pwm/max31790.h>
|
||||||
|
#include <zephyr/sys/byteorder.h>
|
||||||
#include <zephyr/sys/util.h>
|
#include <zephyr/sys/util.h>
|
||||||
#include <zephyr/kernel.h>
|
#include <zephyr/kernel.h>
|
||||||
#include <zephyr/logging/log.h>
|
#include <zephyr/logging/log.h>
|
||||||
|
|
||||||
LOG_MODULE_REGISTER(pwm_max31790, CONFIG_PWM_LOG_LEVEL);
|
LOG_MODULE_REGISTER(pwm_max31790, CONFIG_PWM_LOG_LEVEL);
|
||||||
|
|
||||||
#define MAX31790_OSCILLATOR_FREQUENCY_IN_HZ 32768
|
struct max31790_pwm_config {
|
||||||
#define MAX31790_PWMTARGETDUTYCYCLE_MAXIMUM ((1 << 9) - 1)
|
|
||||||
#define MAX31790_CHANNEL_COUNT 6
|
|
||||||
|
|
||||||
struct max31790_config {
|
|
||||||
struct i2c_dt_spec i2c;
|
struct i2c_dt_spec i2c;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct max31790_data {
|
struct max31790_pwm_data {
|
||||||
struct k_mutex lock;
|
struct k_mutex lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAX37190_REGISTER_GLOBALCONFIGURATION 0x00
|
|
||||||
#define MAX37190_REGISTER_PWMFREQUENCY 0x01
|
|
||||||
#define MAX37190_REGISTER_FANCONFIGURATION(channel) (0x02 + channel)
|
|
||||||
#define MAX31790_REGISTER_PWMOUTTARGETDUTYCYCLEMSB(channel) (0x40 + 2 * channel)
|
|
||||||
#define MAX31790_REGISTER_FANDYNAMICS(channel) (0x08 + channel)
|
|
||||||
#define MAX31790_REGISTER_TACHTARGETCOUNTMSB(channel) (0x50 + 2 * channel)
|
|
||||||
|
|
||||||
#define MAX37190_GLOBALCONFIGURATION_STANDBY_BIT BIT(7)
|
|
||||||
#define MAX37190_FANXCONFIGURATION_MONITOR_BIT BIT(4)
|
|
||||||
#define MAX37190_FANXCONFIGURATION_TACHINPUTENABLED_BIT BIT(3)
|
|
||||||
#define MAX37190_FANXCONFIGURATION_LOCKEDROTOR_BIT BIT(2)
|
|
||||||
#define MAX37190_FANXCONFIGURATION_LOCKEDROTORPOLARITY_BIT BIT(1)
|
|
||||||
#define MAX37190_FANXCONFIGURATION_TACH_BIT BIT(0)
|
|
||||||
#define MAX37190_FANXCONFIGURATION_MODE_BIT BIT(7)
|
|
||||||
#define MAX37190_FANXDYNAMICS_ASYMMETRICRATEOFCHANGE_BIT BIT(1)
|
|
||||||
|
|
||||||
#define MAX37190_FANXDYNAMICS_SPEEDRANGE_LENGTH 3
|
|
||||||
#define MAX37190_FANXDYNAMICS_SPEEDRANGE_POS 5
|
|
||||||
#define MAX37190_FANXDYNAMICS_PWMRATEOFCHANGE_LENGTH 3
|
|
||||||
#define MAX37190_FANXDYNAMICS_PWMRATEOFCHANGE_POS 2
|
|
||||||
#define MAX37190_PWMFREQUENCY_PWM_LENGTH 4
|
|
||||||
#define MAX37190_PWMFREQUENCY_PWM4TO6_POS 4
|
|
||||||
#define MAX37190_PWMFREQUENCY_PWM1TO3_LENGTH 4
|
|
||||||
#define MAX37190_PWMFREQUENCY_PWM1TO3_POS 0
|
|
||||||
#define MAX37190_FANXCONFIGURATION_SPINUP_LENGTH 2
|
|
||||||
#define MAX37190_FANXCONFIGURATION_SPINUP_POS 5
|
|
||||||
|
|
||||||
#define PWM_MAX31790_FLAG_SPEED_RANGE_GET(flags) \
|
|
||||||
FIELD_GET(GENMASK(MAX37190_FANXDYNAMICS_SPEEDRANGE_LENGTH + \
|
|
||||||
PWM_MAX31790_FLAG_SPEED_RANGE_POS - 1, \
|
|
||||||
PWM_MAX31790_FLAG_SPEED_RANGE_POS), \
|
|
||||||
flags)
|
|
||||||
#define PWM_MAX31790_FLAG_PWM_RATE_OF_CHANGE_GET(flags) \
|
|
||||||
FIELD_GET(GENMASK(MAX37190_FANXDYNAMICS_PWMRATEOFCHANGE_LENGTH + \
|
|
||||||
PWM_MAX31790_FLAG_PWM_RATE_OF_CHANGE_POS - 1, \
|
|
||||||
PWM_MAX31790_FLAG_PWM_RATE_OF_CHANGE_POS), \
|
|
||||||
flags)
|
|
||||||
|
|
||||||
static void max31790_set_fandynamics_speedrange(uint8_t *destination, uint8_t value)
|
static void max31790_set_fandynamics_speedrange(uint8_t *destination, uint8_t value)
|
||||||
{
|
{
|
||||||
uint8_t length = MAX37190_FANXDYNAMICS_SPEEDRANGE_LENGTH;
|
uint8_t length = MAX37190_FANXDYNAMICS_SPEEDRANGE_LENGTH;
|
||||||
|
@ -110,54 +70,6 @@ static void max31790_set_fanconfiguration_spinup(uint8_t *destination, uint8_t v
|
||||||
*destination |= FIELD_PREP(GENMASK(pos + length - 1, pos), value);
|
*destination |= FIELD_PREP(GENMASK(pos + length - 1, pos), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int max31790_read_register(const struct device *dev, uint8_t address, uint8_t *value)
|
|
||||||
{
|
|
||||||
const struct max31790_config *config = dev->config;
|
|
||||||
int result;
|
|
||||||
|
|
||||||
result = i2c_reg_read_byte_dt(&config->i2c, address, value);
|
|
||||||
if (result != 0) {
|
|
||||||
LOG_ERR("unable to read register 0x%02X, error %i", address, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_DBG("read value 0x%02X from register 0x%02X", *value, address);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int max31790_write_register_uint8(const struct device *dev, uint8_t address, uint8_t value)
|
|
||||||
{
|
|
||||||
const struct max31790_config *config = dev->config;
|
|
||||||
int result;
|
|
||||||
|
|
||||||
LOG_DBG("writing value 0x%02X to register 0x%02X", value, address);
|
|
||||||
result = i2c_reg_write_byte_dt(&config->i2c, address, value);
|
|
||||||
if (result != 0) {
|
|
||||||
LOG_ERR("unable to write register 0x%02X, error %i", address, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int max31790_write_register_uint16(const struct device *dev, uint8_t address, uint16_t value)
|
|
||||||
{
|
|
||||||
const struct max31790_config *config = dev->config;
|
|
||||||
int result;
|
|
||||||
uint8_t buffer[] = {
|
|
||||||
address,
|
|
||||||
value >> 8,
|
|
||||||
value,
|
|
||||||
};
|
|
||||||
|
|
||||||
LOG_DBG("writing value 0x%04X to address 0x%02X", value, address);
|
|
||||||
result = i2c_write_dt(&config->i2c, buffer, sizeof(buffer));
|
|
||||||
if (result != 0) {
|
|
||||||
LOG_ERR("unable to write to address 0x%02X, error %i", address, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool max31790_convert_pwm_frequency_into_hz(uint16_t *result, uint8_t pwm_frequency)
|
static bool max31790_convert_pwm_frequency_into_hz(uint16_t *result, uint8_t pwm_frequency)
|
||||||
{
|
{
|
||||||
switch (pwm_frequency) {
|
switch (pwm_frequency) {
|
||||||
|
@ -252,28 +164,31 @@ static int max31790_set_cycles_internal(const struct device *dev, uint32_t chann
|
||||||
uint32_t period_count, uint32_t pulse_count,
|
uint32_t period_count, uint32_t pulse_count,
|
||||||
pwm_flags_t flags)
|
pwm_flags_t flags)
|
||||||
{
|
{
|
||||||
|
const struct max31790_pwm_config *config = dev->config;
|
||||||
int result;
|
int result;
|
||||||
uint8_t pwm_frequency_channel_value;
|
uint8_t pwm_frequency_channel_value;
|
||||||
uint8_t value_pwm_frequency;
|
uint8_t value_pwm_frequency;
|
||||||
uint8_t value_fan_configuration;
|
uint8_t value_fan_configuration;
|
||||||
uint8_t value_fan_dynamics;
|
uint8_t value_fan_dynamics;
|
||||||
uint8_t value_speed_range = PWM_MAX31790_FLAG_SPEED_RANGE_GET(flags);
|
uint8_t value_speed_range = MAX31790_FLAG_SPEED_RANGE_GET(flags);
|
||||||
uint8_t value_pwm_rate_of_change = PWM_MAX31790_FLAG_PWM_RATE_OF_CHANGE_GET(flags);
|
uint8_t value_pwm_rate_of_change = MAX31790_FLAG_PWM_RATE_OF_CHANGE_GET(flags);
|
||||||
|
uint8_t buffer[3];
|
||||||
|
|
||||||
if (!max31790_convert_pwm_frequency_into_register(&pwm_frequency_channel_value,
|
if (!max31790_convert_pwm_frequency_into_register(&pwm_frequency_channel_value,
|
||||||
period_count)) {
|
period_count)) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = max31790_read_register(dev, MAX37190_REGISTER_PWMFREQUENCY, &value_pwm_frequency);
|
result = i2c_reg_read_byte_dt(&config->i2c, MAX37190_REGISTER_PWMFREQUENCY,
|
||||||
|
&value_pwm_frequency);
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
max31790_set_pwmfrequency(&value_pwm_frequency, channel, pwm_frequency_channel_value);
|
max31790_set_pwmfrequency(&value_pwm_frequency, channel, pwm_frequency_channel_value);
|
||||||
|
|
||||||
result = max31790_write_register_uint8(dev, MAX37190_REGISTER_PWMFREQUENCY,
|
result = i2c_reg_write_byte_dt(&config->i2c, MAX37190_REGISTER_PWMFREQUENCY,
|
||||||
value_pwm_frequency);
|
value_pwm_frequency);
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -299,46 +214,56 @@ static int max31790_set_cycles_internal(const struct device *dev, uint32_t chann
|
||||||
|
|
||||||
if ((flags & PWM_MAX31790_FLAG_RPM_MODE) == 0) {
|
if ((flags & PWM_MAX31790_FLAG_RPM_MODE) == 0) {
|
||||||
LOG_DBG("PWM mode");
|
LOG_DBG("PWM mode");
|
||||||
uint16_t pwm_target_duty_cycle =
|
uint16_t tach_target_count = MAX31790_TACHTARGETCOUNT_MAXIMUM;
|
||||||
pulse_count * MAX31790_PWMTARGETDUTYCYCLE_MAXIMUM / period_count;
|
|
||||||
value_fan_configuration &= ~MAX37190_FANXCONFIGURATION_MODE_BIT;
|
value_fan_configuration &= ~MAX37190_FANXCONFIGURATION_MODE_BIT;
|
||||||
|
buffer[0] = MAX31790_REGISTER_TACHTARGETCOUNTMSB(channel);
|
||||||
|
sys_put_be16(tach_target_count << 5, buffer + 1);
|
||||||
|
|
||||||
result = max31790_write_register_uint16(
|
result = i2c_write_dt(&config->i2c, buffer, sizeof(buffer));
|
||||||
dev, MAX31790_REGISTER_PWMOUTTARGETDUTYCYCLEMSB(channel),
|
|
||||||
pwm_target_duty_cycle);
|
|
||||||
if (result != 0) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
LOG_DBG("RPM mode");
|
LOG_DBG("RPM mode");
|
||||||
value_fan_configuration |= MAX37190_FANXCONFIGURATION_MODE_BIT;
|
value_fan_configuration |= MAX37190_FANXCONFIGURATION_MODE_BIT;
|
||||||
|
buffer[0] = MAX31790_REGISTER_TACHTARGETCOUNTMSB(channel);
|
||||||
|
sys_put_be16(pulse_count << 5, buffer + 1);
|
||||||
|
|
||||||
result = max31790_write_register_uint16(
|
result = i2c_write_dt(&config->i2c, buffer, sizeof(buffer));
|
||||||
dev, MAX31790_REGISTER_TACHTARGETCOUNTMSB(channel), pulse_count);
|
}
|
||||||
|
|
||||||
|
if (result != 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = i2c_reg_write_byte_dt(&config->i2c, MAX37190_REGISTER_FANCONFIGURATION(channel),
|
||||||
|
value_fan_configuration);
|
||||||
|
if (result != 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = i2c_reg_write_byte_dt(&config->i2c, MAX31790_REGISTER_FANDYNAMICS(channel),
|
||||||
|
value_fan_dynamics);
|
||||||
|
if (result != 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flags & PWM_MAX31790_FLAG_RPM_MODE) == 0) {
|
||||||
|
uint16_t pwm_target_duty_cycle =
|
||||||
|
pulse_count * MAX31790_PWMTARGETDUTYCYCLE_MAXIMUM / period_count;
|
||||||
|
buffer[0] = MAX31790_REGISTER_PWMOUTTARGETDUTYCYCLEMSB(channel);
|
||||||
|
sys_put_be16(pwm_target_duty_cycle << 7, buffer + 1);
|
||||||
|
|
||||||
|
result = i2c_write_dt(&config->i2c, buffer, sizeof(buffer));
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result = max31790_write_register_uint8(dev, MAX37190_REGISTER_FANCONFIGURATION(channel),
|
|
||||||
value_fan_configuration);
|
|
||||||
if (result != 0) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = max31790_write_register_uint8(dev, MAX31790_REGISTER_FANDYNAMICS(channel),
|
|
||||||
value_fan_dynamics);
|
|
||||||
if (result != 0) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int max31790_set_cycles(const struct device *dev, uint32_t channel, uint32_t period_count,
|
static int max31790_set_cycles(const struct device *dev, uint32_t channel, uint32_t period_count,
|
||||||
uint32_t pulse_count, pwm_flags_t flags)
|
uint32_t pulse_count, pwm_flags_t flags)
|
||||||
{
|
{
|
||||||
struct max31790_data *data = dev->data;
|
struct max31790_pwm_data *data = dev->data;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
LOG_DBG("set period %i with pulse %i for channel %i and flags 0x%04X", period_count,
|
LOG_DBG("set period %i with pulse %i for channel %i and flags 0x%04X", period_count,
|
||||||
|
@ -362,7 +287,8 @@ static int max31790_set_cycles(const struct device *dev, uint32_t channel, uint3
|
||||||
|
|
||||||
static int max31790_get_cycles_per_sec(const struct device *dev, uint32_t channel, uint64_t *cycles)
|
static int max31790_get_cycles_per_sec(const struct device *dev, uint32_t channel, uint64_t *cycles)
|
||||||
{
|
{
|
||||||
struct max31790_data *data = dev->data;
|
const struct max31790_pwm_config *config = dev->config;
|
||||||
|
struct max31790_pwm_data *data = dev->data;
|
||||||
int result;
|
int result;
|
||||||
bool success;
|
bool success;
|
||||||
uint8_t pwm_frequency_register;
|
uint8_t pwm_frequency_register;
|
||||||
|
@ -375,9 +301,8 @@ static int max31790_get_cycles_per_sec(const struct device *dev, uint32_t channe
|
||||||
}
|
}
|
||||||
|
|
||||||
k_mutex_lock(&data->lock, K_FOREVER);
|
k_mutex_lock(&data->lock, K_FOREVER);
|
||||||
result = max31790_read_register(dev, MAX37190_REGISTER_GLOBALCONFIGURATION,
|
result = i2c_reg_read_byte_dt(&config->i2c, MAX37190_REGISTER_GLOBALCONFIGURATION,
|
||||||
&pwm_frequency_register);
|
&pwm_frequency_register);
|
||||||
|
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
k_mutex_unlock(&data->lock);
|
k_mutex_unlock(&data->lock);
|
||||||
return result;
|
return result;
|
||||||
|
@ -385,7 +310,6 @@ static int max31790_get_cycles_per_sec(const struct device *dev, uint32_t channe
|
||||||
|
|
||||||
pwm_frequency = max31790_get_pwmfrequency(pwm_frequency_register, channel);
|
pwm_frequency = max31790_get_pwmfrequency(pwm_frequency_register, channel);
|
||||||
success = max31790_convert_pwm_frequency_into_hz(&pwm_frequency_in_hz, pwm_frequency);
|
success = max31790_convert_pwm_frequency_into_hz(&pwm_frequency_in_hz, pwm_frequency);
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
k_mutex_unlock(&data->lock);
|
k_mutex_unlock(&data->lock);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -397,17 +321,15 @@ static int max31790_get_cycles_per_sec(const struct device *dev, uint32_t channe
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct pwm_driver_api max31790_api = {
|
static const struct pwm_driver_api max31790_pwm_api = {
|
||||||
.set_cycles = max31790_set_cycles,
|
.set_cycles = max31790_set_cycles,
|
||||||
.get_cycles_per_sec = max31790_get_cycles_per_sec,
|
.get_cycles_per_sec = max31790_get_cycles_per_sec,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int max31790_init(const struct device *dev)
|
static int max31790_pwm_init(const struct device *dev)
|
||||||
{
|
{
|
||||||
const struct max31790_config *config = dev->config;
|
const struct max31790_pwm_config *config = dev->config;
|
||||||
struct max31790_data *data = dev->data;
|
struct max31790_pwm_data *data = dev->data;
|
||||||
int result;
|
|
||||||
uint8_t reg_value;
|
|
||||||
|
|
||||||
k_mutex_init(&data->lock);
|
k_mutex_init(&data->lock);
|
||||||
|
|
||||||
|
@ -416,45 +338,18 @@ static int max31790_init(const struct device *dev)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = max31790_read_register(dev, MAX37190_REGISTER_GLOBALCONFIGURATION, ®_value);
|
|
||||||
if (result != 0) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((reg_value & MAX37190_GLOBALCONFIGURATION_STANDBY_BIT) != 0) {
|
|
||||||
LOG_DBG("taking PWM controller out of standby");
|
|
||||||
|
|
||||||
reg_value &= ~MAX37190_GLOBALCONFIGURATION_STANDBY_BIT;
|
|
||||||
result = max31790_write_register_uint8(dev, MAX37190_REGISTER_GLOBALCONFIGURATION,
|
|
||||||
reg_value);
|
|
||||||
if (result != 0) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = max31790_read_register(dev, MAX37190_REGISTER_GLOBALCONFIGURATION,
|
|
||||||
®_value);
|
|
||||||
if (result != 0) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((reg_value & MAX37190_GLOBALCONFIGURATION_STANDBY_BIT) != 0) {
|
|
||||||
LOG_ERR("unable to take PWM controller out of standby");
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAX31790_INIT(inst) \
|
#define MAX31790_PWM_INIT(inst) \
|
||||||
static const struct max31790_config max31790_##inst##_config = { \
|
static const struct max31790_pwm_config max31790_pwm_##inst##_config = { \
|
||||||
.i2c = I2C_DT_SPEC_INST_GET(inst), \
|
.i2c = I2C_DT_SPEC_GET(DT_INST_PARENT(inst)), \
|
||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
static struct max31790_data max31790_##inst##_data; \
|
static struct max31790_pwm_data max31790_pwm_##inst##_data; \
|
||||||
\
|
\
|
||||||
DEVICE_DT_INST_DEFINE(inst, max31790_init, NULL, &max31790_##inst##_data, \
|
DEVICE_DT_INST_DEFINE(inst, max31790_pwm_init, NULL, &max31790_pwm_##inst##_data, \
|
||||||
&max31790_##inst##_config, POST_KERNEL, CONFIG_PWM_INIT_PRIORITY, \
|
&max31790_pwm_##inst##_config, POST_KERNEL, \
|
||||||
&max31790_api);
|
CONFIG_PWM_INIT_PRIORITY, &max31790_pwm_api);
|
||||||
|
|
||||||
DT_INST_FOREACH_STATUS_OKAY(MAX31790_INIT);
|
DT_INST_FOREACH_STATUS_OKAY(MAX31790_PWM_INIT);
|
||||||
|
|
14
dts/bindings/mfd/maxim,max31790.yaml
Normal file
14
dts/bindings/mfd/maxim,max31790.yaml
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
# Copyright (c) 2024 SILA Embedded Solutions GmbH
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
description: Maxim MAX31790 6-channel I2C-bus PWM controller, MFD device
|
||||||
|
|
||||||
|
compatible: "maxim,max31790"
|
||||||
|
|
||||||
|
include: i2c-device.yaml
|
||||||
|
|
||||||
|
bus: max31790
|
||||||
|
|
||||||
|
properties:
|
||||||
|
reg:
|
||||||
|
required: true
|
|
@ -3,14 +3,13 @@
|
||||||
|
|
||||||
description: Maxim MAX31790 6-channel I2C-bus PWM controller
|
description: Maxim MAX31790 6-channel I2C-bus PWM controller
|
||||||
|
|
||||||
compatible: "maxim,max31790"
|
compatible: "maxim,max31790-pwm"
|
||||||
|
|
||||||
include: [pwm-controller.yaml, i2c-device.yaml, base.yaml]
|
include: [pwm-controller.yaml, base.yaml]
|
||||||
|
|
||||||
|
on-bus: max31790
|
||||||
|
|
||||||
properties:
|
properties:
|
||||||
reg:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
"#pwm-cells":
|
"#pwm-cells":
|
||||||
const: 2
|
const: 2
|
||||||
|
|
70
include/zephyr/drivers/mfd/max31790.h
Normal file
70
include/zephyr/drivers/mfd/max31790.h
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 SILA Embedded Solutions GmbH
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZEPHYR_INCLUDE_DRIVERS_MFD_MAX31790_H_
|
||||||
|
#define ZEPHYR_INCLUDE_DRIVERS_MFD_MAX31790_H_
|
||||||
|
|
||||||
|
#include <zephyr/sys/util.h>
|
||||||
|
#include <zephyr/sys/util_macro.h>
|
||||||
|
|
||||||
|
#define MAX31790_OSCILLATOR_FREQUENCY_IN_HZ 32768
|
||||||
|
#define MAX31790_PWMTARGETDUTYCYCLE_MAXIMUM ((1 << 9) - 1)
|
||||||
|
#define MAX31790_TACHTARGETCOUNT_MAXIMUM ((1 << 11) - 1)
|
||||||
|
#define MAX31790_CHANNEL_COUNT 6
|
||||||
|
#define MAX31790_RESET_TIMEOUT_IN_US 1000
|
||||||
|
|
||||||
|
#define MAX37190_REGISTER_GLOBALCONFIGURATION 0x00
|
||||||
|
#define MAX37190_REGISTER_PWMFREQUENCY 0x01
|
||||||
|
#define MAX37190_REGISTER_FANCONFIGURATION(channel) (0x02 + channel)
|
||||||
|
#define MAX31790_REGISTER_FANDYNAMICS(channel) (0x08 + channel)
|
||||||
|
#define MAX37190_REGISTER_FANFAULTSTATUS1 0x11
|
||||||
|
#define MAX37190_REGISTER_TACHCOUNTMSB(channel) (0x18 + 2 * channel)
|
||||||
|
#define MAX31790_REGISTER_PWMOUTTARGETDUTYCYCLEMSB(channel) (0x40 + 2 * channel)
|
||||||
|
#define MAX31790_REGISTER_TACHTARGETCOUNTMSB(channel) (0x50 + 2 * channel)
|
||||||
|
|
||||||
|
#define MAX37190_GLOBALCONFIGURATION_STANDBY_BIT BIT(7)
|
||||||
|
#define MAX37190_GLOBALCONFIGURATION_RESET_BIT BIT(6)
|
||||||
|
#define MAX37190_GLOBALCONFIGURATION_BUSTIMEOUT_BIT BIT(5)
|
||||||
|
#define MAX37190_GLOBALCONFIGURATION_OSCILLATORSELECTION_BIT BIT(3)
|
||||||
|
#define MAX37190_GLOBALCONFIGURATION_I2CWATCHDOGSTATUS_BIT BIT(0)
|
||||||
|
#define MAX37190_FANXCONFIGURATION_MONITOR_BIT BIT(4)
|
||||||
|
#define MAX37190_FANXCONFIGURATION_TACHINPUTENABLED_BIT BIT(3)
|
||||||
|
#define MAX37190_FANXCONFIGURATION_LOCKEDROTOR_BIT BIT(2)
|
||||||
|
#define MAX37190_FANXCONFIGURATION_LOCKEDROTORPOLARITY_BIT BIT(1)
|
||||||
|
#define MAX37190_FANXCONFIGURATION_TACH_BIT BIT(0)
|
||||||
|
#define MAX37190_FANXCONFIGURATION_MODE_BIT BIT(7)
|
||||||
|
#define MAX37190_FANXDYNAMICS_ASYMMETRICRATEOFCHANGE_BIT BIT(1)
|
||||||
|
|
||||||
|
#define MAX37190_GLOBALCONFIGURATION_I2CWATCHDOG_LENGTH 2
|
||||||
|
#define MAX37190_GLOBALCONFIGURATION_I2CWATCHDOG_POS 1
|
||||||
|
#define MAX37190_FANXDYNAMICS_SPEEDRANGE_LENGTH 3
|
||||||
|
#define MAX37190_FANXDYNAMICS_SPEEDRANGE_POS 5
|
||||||
|
#define MAX37190_FANXDYNAMICS_PWMRATEOFCHANGE_LENGTH 3
|
||||||
|
#define MAX37190_FANXDYNAMICS_PWMRATEOFCHANGE_POS 2
|
||||||
|
#define MAX37190_PWMFREQUENCY_PWM_LENGTH 4
|
||||||
|
#define MAX37190_PWMFREQUENCY_PWM4TO6_POS 4
|
||||||
|
#define MAX37190_PWMFREQUENCY_PWM1TO3_LENGTH 4
|
||||||
|
#define MAX37190_PWMFREQUENCY_PWM1TO3_POS 0
|
||||||
|
#define MAX37190_FANXCONFIGURATION_SPINUP_LENGTH 2
|
||||||
|
#define MAX37190_FANXCONFIGURATION_SPINUP_POS 5
|
||||||
|
|
||||||
|
#define MAX31790_FANXDYNAMCIS_SPEED_RANGE_GET(value) \
|
||||||
|
FIELD_GET(GENMASK(MAX37190_FANXDYNAMICS_SPEEDRANGE_LENGTH + \
|
||||||
|
MAX37190_FANXDYNAMICS_SPEEDRANGE_POS - 1, \
|
||||||
|
MAX37190_FANXDYNAMICS_SPEEDRANGE_POS), \
|
||||||
|
value)
|
||||||
|
|
||||||
|
#define MAX31790_FLAG_SPEED_RANGE_GET(flags) \
|
||||||
|
FIELD_GET(GENMASK(MAX37190_FANXDYNAMICS_SPEEDRANGE_LENGTH + \
|
||||||
|
PWM_MAX31790_FLAG_SPEED_RANGE_POS - 1, \
|
||||||
|
PWM_MAX31790_FLAG_SPEED_RANGE_POS), \
|
||||||
|
flags)
|
||||||
|
#define MAX31790_FLAG_PWM_RATE_OF_CHANGE_GET(flags) \
|
||||||
|
FIELD_GET(GENMASK(MAX37190_FANXDYNAMICS_PWMRATEOFCHANGE_LENGTH + \
|
||||||
|
PWM_MAX31790_FLAG_PWM_RATE_OF_CHANGE_POS - 1, \
|
||||||
|
PWM_MAX31790_FLAG_PWM_RATE_OF_CHANGE_POS), \
|
||||||
|
flags)
|
||||||
|
|
||||||
|
#endif /* ZEPHYR_INCLUDE_DRIVERS_MFD_MAX31790_H_ */
|
|
@ -11,7 +11,12 @@
|
||||||
compatible = "maxim,max31790";
|
compatible = "maxim,max31790";
|
||||||
status = "okay";
|
status = "okay";
|
||||||
reg = <0x20>;
|
reg = <0x20>;
|
||||||
pwm-controller;
|
|
||||||
#pwm-cells = <2>;
|
max31790_max31790_pwm: max31790_max31790_pwm {
|
||||||
|
compatible = "maxim,max31790-pwm";
|
||||||
|
status = "okay";
|
||||||
|
pwm-controller;
|
||||||
|
#pwm-cells = <2>;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1 +1,3 @@
|
||||||
CONFIG_PWM=y
|
CONFIG_PWM=y
|
||||||
|
CONFIG_MFD_INIT_PRIORITY=80
|
||||||
|
CONFIG_PWM_INIT_PRIORITY=81
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue