drivers: mfd: npm1300: Initial version

Added an MFD driver for the nPM1300.
This driver has register access helper functions that can be used
by subsystems.  This will avoid each subsystem having to duplicate
the register access code.

Signed-off-by: Andy Sinclair <andy.sinclair@nordicsemi.no>
This commit is contained in:
Andy Sinclair 2023-05-31 12:52:54 +01:00 committed by Carles Cufí
commit d7964cd212
6 changed files with 236 additions and 0 deletions

View file

@ -22,6 +22,12 @@
@{ @{
@} @}
@brief Multi Function Device Drivers APIs
@defgroup mfd_interfaces Multi Function Device Drivers APIs
@ingroup io_interfaces
@{
@}
@brief Testing @brief Testing
@defgroup testing Testing @defgroup testing Testing
@{ @{

View file

@ -3,4 +3,5 @@
zephyr_library() zephyr_library()
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)

View file

@ -18,6 +18,7 @@ config MFD_INIT_PRIORITY
help help
Multi-function devices initialization priority. Multi-function devices initialization priority.
source "drivers/mfd/Kconfig.npm1300"
source "drivers/mfd/Kconfig.npm6001" source "drivers/mfd/Kconfig.npm6001"
endif # MFD endif # MFD

View file

@ -0,0 +1,10 @@
# Copyright (c) 2023 Nordic Semiconductor ASA
# SPDX -License-Identifier: Apache-2.0
config MFD_NPM1300
bool "nPM1300 PMIC multi-function device driver"
default y
depends on DT_HAS_NORDIC_NPM1300_ENABLED
select I2C
help
Enable the Nordic nPM1300 PMIC multi-function device driver

122
drivers/mfd/mfd_npm1300.c Normal file
View file

@ -0,0 +1,122 @@
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT nordic_npm1300
#include <errno.h>
#include <zephyr/drivers/i2c.h>
#include <zephyr/sys/util.h>
#include <zephyr/drivers/mfd/npm1300.h>
struct mfd_npm1300_config {
struct i2c_dt_spec i2c;
};
struct mfd_npm1300_data {
struct k_mutex mutex;
};
static int mfd_npm1300_init(const struct device *dev)
{
const struct mfd_npm1300_config *config = dev->config;
struct mfd_npm1300_data *mfd_data = dev->data;
if (!i2c_is_ready_dt(&config->i2c)) {
return -ENODEV;
}
k_mutex_init(&mfd_data->mutex);
return 0;
}
int mfd_npm1300_reg_read_burst(const struct device *dev, uint8_t base, uint8_t offset, void *data,
size_t len)
{
const struct mfd_npm1300_config *config = dev->config;
struct mfd_npm1300_data *mfd_data = dev->data;
uint8_t buff[] = {base, offset};
int ret;
k_mutex_lock(&mfd_data->mutex, K_FOREVER);
ret = i2c_write_read_dt(&config->i2c, buff, sizeof(buff), data, len);
k_mutex_unlock(&mfd_data->mutex);
return ret;
}
int mfd_npm1300_reg_read(const struct device *dev, uint8_t base, uint8_t offset, uint8_t *data)
{
return mfd_npm1300_reg_read_burst(dev, base, offset, data, 1U);
}
int mfd_npm1300_reg_write(const struct device *dev, uint8_t base, uint8_t offset, uint8_t data)
{
const struct mfd_npm1300_config *config = dev->config;
struct mfd_npm1300_data *mfd_data = dev->data;
uint8_t buff[] = {base, offset, data};
int ret;
k_mutex_lock(&mfd_data->mutex, K_FOREVER);
ret = i2c_write_dt(&config->i2c, buff, sizeof(buff));
k_mutex_unlock(&mfd_data->mutex);
return ret;
}
int mfd_npm1300_reg_write2(const struct device *dev, uint8_t base, uint8_t offset, uint8_t data1,
uint8_t data2)
{
const struct mfd_npm1300_config *config = dev->config;
struct mfd_npm1300_data *mfd_data = dev->data;
uint8_t buff[] = {base, offset, data1, data2};
int ret;
k_mutex_lock(&mfd_data->mutex, K_FOREVER);
ret = i2c_write_dt(&config->i2c, buff, sizeof(buff));
k_mutex_unlock(&mfd_data->mutex);
return ret;
}
int mfd_npm1300_reg_update(const struct device *dev, uint8_t base, uint8_t offset, uint8_t data,
uint8_t mask)
{
struct mfd_npm1300_data *mfd_data = dev->data;
uint8_t reg;
int ret;
k_mutex_lock(&mfd_data->mutex, K_FOREVER);
ret = mfd_npm1300_reg_read(dev, base, offset, &reg);
if (ret == 0) {
reg = (reg & ~mask) | (data & mask);
ret = mfd_npm1300_reg_write(dev, base, offset, reg);
}
k_mutex_unlock(&mfd_data->mutex);
return ret;
}
#define MFD_NPM1300_DEFINE(inst) \
static struct mfd_npm1300_data data_##inst; \
\
static const struct mfd_npm1300_config config##inst = { \
.i2c = I2C_DT_SPEC_INST_GET(inst), \
}; \
\
DEVICE_DT_INST_DEFINE(inst, mfd_npm1300_init, NULL, &data_##inst, &config##inst, \
POST_KERNEL, CONFIG_MFD_INIT_PRIORITY, NULL);
DT_INST_FOREACH_STATUS_OKAY(MFD_NPM1300_DEFINE)

View file

@ -0,0 +1,96 @@
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_DRIVERS_MFD_NPM1300_H_
#define ZEPHYR_INCLUDE_DRIVERS_MFD_NPM1300_H_
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup mdf_interface_npm1300 MFD NPM1300 Interface
* @ingroup mfd_interfaces
* @{
*/
#include <stddef.h>
#include <stdint.h>
#include <zephyr/device.h>
/**
* @brief Read multiple registers from npm1300
*
* @param dev npm1300 mfd device
* @param base Register base address (bits 15..8 of 16-bit address)
* @param offset Register offset address (bits 7..0 of 16-bit address)
* @param data Pointer to buffer for received data
* @param len Number of bytes to read
* @retval 0 If successful
* @retval -errno In case of any bus error (see i2c_write_read_dt())
*/
int mfd_npm1300_reg_read_burst(const struct device *dev, uint8_t base, uint8_t offset,
void *data, size_t len);
/**
* @brief Read single register from npm1300
*
* @param dev npm1300 mfd device
* @param base Register base address (bits 15..8 of 16-bit address)
* @param offset Register offset address (bits 7..0 of 16-bit address)
* @param data Pointer to buffer for received data
* @retval 0 If successful
* @retval -errno In case of any bus error (see i2c_write_read_dt())
*/
int mfd_npm1300_reg_read(const struct device *dev, uint8_t base, uint8_t offset, uint8_t *data);
/**
* @brief Write single register to npm1300
*
* @param dev npm1300 mfd device
* @param base Register base address (bits 15..8 of 16-bit address)
* @param offset Register offset address (bits 7..0 of 16-bit address)
* @param data data to write
* @retval 0 If successful
* @retval -errno In case of any bus error (see i2c_write_dt())
*/
int mfd_npm1300_reg_write(const struct device *dev, uint8_t base, uint8_t offset, uint8_t data);
/**
* @brief Write two registers to npm1300
*
* @param dev npm1300 mfd device
* @param base Register base address (bits 15..8 of 16-bit address)
* @param offset Register offset address (bits 7..0 of 16-bit address)
* @param data1 first byte of data to write
* @param data2 second byte of data to write
* @retval 0 If successful
* @retval -errno In case of any bus error (see i2c_write_dt())
*/
int mfd_npm1300_reg_write2(const struct device *dev, uint8_t base, uint8_t offset, uint8_t data1,
uint8_t data2);
/**
* @brief Update selected bits in npm1300 register
*
* @param dev npm1300 mfd device
* @param base Register base address (bits 15..8 of 16-bit address)
* @param offset Register offset address (bits 7..0 of 16-bit address)
* @param data data to write
* @param mask mask of bits to be modified
* @retval 0 If successful
* @retval -errno In case of any bus error (see i2c_write_read_dt(), i2c_write_dt())
*/
int mfd_npm1300_reg_update(const struct device *dev, uint8_t base, uint8_t offset, uint8_t data,
uint8_t mask);
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* ZEPHYR_INCLUDE_DRIVERS_MFD_NPM1300_H_ */