From 0036d7e628cfa58fe873cf273b79d538b1e17293 Mon Sep 17 00:00:00 2001 From: YuzukiTsuru Date: Wed, 20 Mar 2024 15:11:36 +0800 Subject: [PATCH] [pmu] axp driver reconfiguration --- include/drivers/pmu/axp.h | 27 ++++++++ src/drivers/CMakeLists.txt | 1 + src/drivers/pmu/axp.c | 131 +++++++++++++++++++++++++++++++++++++ src/drivers/pmu/axp1530.c | 115 +------------------------------- src/drivers/pmu/axp2202.c | 91 +------------------------- 5 files changed, 163 insertions(+), 202 deletions(-) create mode 100644 src/drivers/pmu/axp.c diff --git a/include/drivers/pmu/axp.h b/include/drivers/pmu/axp.h index 0a6cf97bd..0c49cad43 100644 --- a/include/drivers/pmu/axp.h +++ b/include/drivers/pmu/axp.h @@ -41,6 +41,33 @@ typedef struct _axp_contrl_info { axp_step_info_t axp_step_tbl[4];// Voltage step table for the domain. } axp_contrl_info; +/* Common function */ + +/** + * @brief Set the voltage for a specific power domain controlled by AXP. + * + * @param i2c_dev Pointer to the I2C device structure. + * @param name Name of the power domain. + * @param set_vol Voltage value to set. + * @param onoff Whether to turn on or off the power domain (1 for on, 0 for off). + * @param axp_ctrl_tbl Pointer to the AXP control information table. + * @param axp_ctrl_tbl_size Size of the AXP control information table. + * @param axp_addr AXP device address. + * @return Integer indicating the success status of the operation. + */ +int axp_set_vol(sunxi_i2c_t *i2c_dev, char *name, int set_vol, int onoff, axp_contrl_info *axp_ctrl_tbl, uint8_t axp_ctrl_tbl_size, uint8_t axp_addr); + +/** + * @brief Get the voltage value for a specific power domain controlled by AXP. + * + * @param i2c_dev Pointer to the I2C device structure. + * @param name Name of the power domain. + * @param axp_ctrl_tbl Pointer to the AXP control information table. + * @param axp_ctrl_tbl_size Size of the AXP control information table. + * @param axp_addr AXP device address. + * @return The voltage value of the specified power domain. + */ +int axp_get_vol(sunxi_i2c_t *i2c_dev, char *name, axp_contrl_info *axp_ctrl_tbl, uint8_t axp_ctrl_tbl_size, uint8_t axp_addr); /* AXP1530 */ diff --git a/src/drivers/CMakeLists.txt b/src/drivers/CMakeLists.txt index f852686bf..0580b705f 100644 --- a/src/drivers/CMakeLists.txt +++ b/src/drivers/CMakeLists.txt @@ -42,6 +42,7 @@ endif() if (CONFIG_CHIP_WITHPMU) set(DRIVER_PMU + pmu/axp.c pmu/axp1530.c pmu/axp2202.c ) diff --git a/src/drivers/pmu/axp.c b/src/drivers/pmu/axp.c new file mode 100644 index 000000000..811340317 --- /dev/null +++ b/src/drivers/pmu/axp.c @@ -0,0 +1,131 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +/** + * Get control information from the table based on the given name. + * + * @param name The name of the control information to retrieve. + * @return A pointer to the axp_contrl_info structure corresponding to the given name, + * or NULL if the name is not found in the table. + */ +static axp_contrl_info *get_ctrl_info_from_tbl(char *name, axp_contrl_info *axp_ctrl_tbl, uint8_t axp_ctrl_tbl_size) { + int i = 0; + for (i = 0; i < axp_ctrl_tbl_size; i++) { + if (!strncmp(name, axp_ctrl_tbl[i].name, strlen(axp_ctrl_tbl[i].name))) { + break; + } + } + if (i >= axp_ctrl_tbl_size) { + return NULL; + } + return (axp_ctrl_tbl + i); +} + +int axp_set_vol(sunxi_i2c_t *i2c_dev, char *name, int set_vol, int onoff, axp_contrl_info *axp_ctrl_tbl, uint8_t axp_ctrl_tbl_size, uint8_t axp_addr) { + uint8_t reg_value, i; + axp_contrl_info *p_item = NULL; + uint8_t base_step = 0; + + p_item = get_ctrl_info_from_tbl(name, axp_ctrl_tbl, axp_ctrl_tbl_size); + if (!p_item) { + return -1; + } + + if ((set_vol > 0) && (p_item->min_vol)) { + if (set_vol < p_item->min_vol) { + set_vol = p_item->min_vol; + } else if (set_vol > p_item->max_vol) { + set_vol = p_item->max_vol; + } + + if (sunxi_i2c_read(i2c_dev, axp_addr, p_item->cfg_reg_addr, ®_value)) { + return -1; + } + + reg_value &= ~p_item->cfg_reg_mask; + + for (i = 0; p_item->axp_step_tbl[i].step_max_vol != 0; i++) { + if ((set_vol > p_item->axp_step_tbl[i].step_max_vol) && (set_vol < p_item->axp_step_tbl[i + 1].step_min_vol)) { + set_vol = p_item->axp_step_tbl[i].step_max_vol; + } + if (p_item->axp_step_tbl[i].step_max_vol >= set_vol) { + reg_value |= ((base_step + ((set_vol - p_item->axp_step_tbl[i].step_min_vol) / p_item->axp_step_tbl[i].step_val)) << p_item->reg_addr_offset); + if (p_item->axp_step_tbl[i].regation) { + u8 reg_value_temp = (~reg_value & p_item->cfg_reg_mask); + reg_value &= ~p_item->cfg_reg_mask; + reg_value |= reg_value_temp; + } + break; + } else { + base_step += ((p_item->axp_step_tbl[i].step_max_vol - p_item->axp_step_tbl[i].step_min_vol + p_item->axp_step_tbl[i].step_val) / p_item->axp_step_tbl[i].step_val); + } + } + + if (sunxi_i2c_write(i2c_dev, axp_addr, p_item->cfg_reg_addr, reg_value)) { + return -1; + } + } + + if (onoff < 0) { + return 0; + } + if (sunxi_i2c_read(i2c_dev, axp_addr, p_item->ctrl_reg_addr, ®_value)) { + return -1; + } + if (onoff == 0) { + reg_value &= ~(1 << p_item->ctrl_bit_ofs); + } else { + reg_value |= (1 << p_item->ctrl_bit_ofs); + } + if (sunxi_i2c_write(i2c_dev, axp_addr, p_item->ctrl_reg_addr, reg_value)) { + return -1; + } + return 0; +} + +int axp_get_vol(sunxi_i2c_t *i2c_dev, char *name, axp_contrl_info *axp_ctrl_tbl, uint8_t axp_ctrl_tbl_size, uint8_t axp_addr) { + uint8_t reg_value, i; + axp_contrl_info *p_item = NULL; + uint8_t base_step1 = 0; + uint8_t base_step2 = 0; + int vol; + + p_item = get_ctrl_info_from_tbl(name, axp_ctrl_tbl, axp_ctrl_tbl_size); + if (!p_item) { + return -1; + } + + if (sunxi_i2c_read(i2c_dev, axp_addr, p_item->ctrl_reg_addr, ®_value)) { + return -1; + } + + if (!(reg_value & (0x01 << p_item->ctrl_bit_ofs))) { + return 0; + } + + if (sunxi_i2c_read(i2c_dev, axp_addr, p_item->cfg_reg_addr, ®_value)) { + return -1; + } + reg_value &= p_item->cfg_reg_mask; + reg_value >>= p_item->reg_addr_offset; + for (i = 0; p_item->axp_step_tbl[i].step_max_vol != 0; i++) { + base_step1 += ((p_item->axp_step_tbl[i].step_max_vol - p_item->axp_step_tbl[i].step_min_vol + p_item->axp_step_tbl[i].step_val) / p_item->axp_step_tbl[i].step_val); + if (reg_value < base_step1) { + vol = (reg_value - base_step2) * p_item->axp_step_tbl[i].step_val + p_item->axp_step_tbl[i].step_min_vol; + return vol; + } + base_step2 += ((p_item->axp_step_tbl[i].step_max_vol - p_item->axp_step_tbl[i].step_min_vol + p_item->axp_step_tbl[i].step_val) / p_item->axp_step_tbl[i].step_val); + } + return -1; +} \ No newline at end of file diff --git a/src/drivers/pmu/axp1530.c b/src/drivers/pmu/axp1530.c index b0931e39c..afc972ce2 100644 --- a/src/drivers/pmu/axp1530.c +++ b/src/drivers/pmu/axp1530.c @@ -31,27 +31,6 @@ static axp_contrl_info axp_ctrl_tbl[] = { }; /* clang-format on */ -/** - * Get control information from the table based on the given name. - * - * @param name The name of the control information to retrieve. - * @return A pointer to the axp_contrl_info structure corresponding to the given name, - * or NULL if the name is not found in the table. - */ -static axp_contrl_info *get_ctrl_info_from_tbl(char *name) { - int i = 0; - int size = ARRAY_SIZE(axp_ctrl_tbl); - for (i = 0; i < size; i++) { - if (!strncmp(name, axp_ctrl_tbl[i].name, strlen(axp_ctrl_tbl[i].name))) { - break; - } - } - if (i >= size) { - return NULL; - } - return (axp_ctrl_tbl + i); -} - int pmu_axp1530_init(sunxi_i2c_t *i2c_dev) { uint8_t axp_val; int ret; @@ -121,101 +100,11 @@ int pmu_axp1530_set_dual_phase(sunxi_i2c_t *i2c_dev) { } int pmu_axp1530_set_vol(sunxi_i2c_t *i2c_dev, char *name, int set_vol, int onoff) { - uint8_t reg_value, i; - axp_contrl_info *p_item = NULL; - uint8_t base_step = 0; - - p_item = get_ctrl_info_from_tbl(name); - if (!p_item) { - return -1; - } - - if ((set_vol > 0) && (p_item->min_vol)) { - if (set_vol < p_item->min_vol) { - set_vol = p_item->min_vol; - } else if (set_vol > p_item->max_vol) { - set_vol = p_item->max_vol; - } - - if (sunxi_i2c_read(i2c_dev, AXP1530_RUNTIME_ADDR, p_item->cfg_reg_addr, ®_value)) { - return -1; - } - - reg_value &= ~p_item->cfg_reg_mask; - - for (i = 0; p_item->axp_step_tbl[i].step_max_vol != 0; i++) { - if ((set_vol > p_item->axp_step_tbl[i].step_max_vol) && (set_vol < p_item->axp_step_tbl[i + 1].step_min_vol)) { - set_vol = p_item->axp_step_tbl[i].step_max_vol; - } - if (p_item->axp_step_tbl[i].step_max_vol >= set_vol) { - reg_value |= ((base_step + ((set_vol - p_item->axp_step_tbl[i].step_min_vol) / p_item->axp_step_tbl[i].step_val)) << p_item->reg_addr_offset); - if (p_item->axp_step_tbl[i].regation) { - u8 reg_value_temp = (~reg_value & p_item->cfg_reg_mask); - reg_value &= ~p_item->cfg_reg_mask; - reg_value |= reg_value_temp; - } - break; - } else { - base_step += ((p_item->axp_step_tbl[i].step_max_vol - p_item->axp_step_tbl[i].step_min_vol + p_item->axp_step_tbl[i].step_val) / p_item->axp_step_tbl[i].step_val); - } - } - - if (sunxi_i2c_write(i2c_dev, AXP1530_RUNTIME_ADDR, p_item->cfg_reg_addr, reg_value)) { - return -1; - } - } - - if (onoff < 0) { - return 0; - } - if (sunxi_i2c_read(i2c_dev, AXP1530_RUNTIME_ADDR, p_item->ctrl_reg_addr, ®_value)) { - return -1; - } - if (onoff == 0) { - reg_value &= ~(1 << p_item->ctrl_bit_ofs); - } else { - reg_value |= (1 << p_item->ctrl_bit_ofs); - } - if (sunxi_i2c_write(i2c_dev, AXP1530_RUNTIME_ADDR, p_item->ctrl_reg_addr, reg_value)) { - return -1; - } - return 0; + return axp_set_vol(i2c_dev, name, set_vol, onoff, axp_ctrl_tbl, ARRAY_SIZE(axp_ctrl_tbl), AXP1530_RUNTIME_ADDR); } int pmu_axp1530_get_vol(sunxi_i2c_t *i2c_dev, char *name) { - uint8_t reg_value, i; - axp_contrl_info *p_item = NULL; - uint8_t base_step1 = 0; - uint8_t base_step2 = 0; - int vol; - - p_item = get_ctrl_info_from_tbl(name); - if (!p_item) { - return -1; - } - - if (sunxi_i2c_read(i2c_dev, AXP1530_RUNTIME_ADDR, p_item->ctrl_reg_addr, ®_value)) { - return -1; - } - - if (!(reg_value & (0x01 << p_item->ctrl_bit_ofs))) { - return 0; - } - - if (sunxi_i2c_read(i2c_dev, AXP1530_RUNTIME_ADDR, p_item->cfg_reg_addr, ®_value)) { - return -1; - } - reg_value &= p_item->cfg_reg_mask; - reg_value >>= p_item->reg_addr_offset; - for (i = 0; p_item->axp_step_tbl[i].step_max_vol != 0; i++) { - base_step1 += ((p_item->axp_step_tbl[i].step_max_vol - p_item->axp_step_tbl[i].step_min_vol + p_item->axp_step_tbl[i].step_val) / p_item->axp_step_tbl[i].step_val); - if (reg_value < base_step1) { - vol = (reg_value - base_step2) * p_item->axp_step_tbl[i].step_val + p_item->axp_step_tbl[i].step_min_vol; - return vol; - } - base_step2 += ((p_item->axp_step_tbl[i].step_max_vol - p_item->axp_step_tbl[i].step_min_vol + p_item->axp_step_tbl[i].step_val) / p_item->axp_step_tbl[i].step_val); - } - return -1; + return axp_get_vol(i2c_dev, name, axp_ctrl_tbl, ARRAY_SIZE(axp_ctrl_tbl), AXP1530_RUNTIME_ADDR); } void pmu_axp1530_dump(sunxi_i2c_t *i2c_dev) { diff --git a/src/drivers/pmu/axp2202.c b/src/drivers/pmu/axp2202.c index db70d69a6..19520488e 100644 --- a/src/drivers/pmu/axp2202.c +++ b/src/drivers/pmu/axp2202.c @@ -155,98 +155,11 @@ int pmu_axp2202_init(sunxi_i2c_t *i2c_dev) { } int pmu_axp2202_set_vol(sunxi_i2c_t *i2c_dev, char *name, int set_vol, int onoff) { - uint8_t reg_value, i; - axp_contrl_info *p_item = NULL; - uint8_t base_step = 0; - - p_item = get_ctrl_info_from_tbl(name); - if (!p_item) { - return -1; - } - - if ((set_vol > 0) && (p_item->min_vol)) { - if (set_vol < p_item->min_vol) { - set_vol = p_item->min_vol; - } else if (set_vol > p_item->max_vol) { - set_vol = p_item->max_vol; - } - if (sunxi_i2c_read(i2c_dev, AXP2202_RUNTIME_ADDR, p_item->cfg_reg_addr, ®_value)) { - return -1; - } - reg_value &= ~p_item->cfg_reg_mask; - for (i = 0; p_item->axp_step_tbl[i].step_max_vol != 0; i++) { - if ((set_vol > p_item->axp_step_tbl[i].step_max_vol) && (set_vol < p_item->axp_step_tbl[i + 1].step_min_vol)) { - set_vol = p_item->axp_step_tbl[i].step_max_vol; - } - if (p_item->axp_step_tbl[i].step_max_vol >= set_vol) { - reg_value |= ((base_step + ((set_vol - p_item->axp_step_tbl[i].step_min_vol) / p_item->axp_step_tbl[i].step_val)) << p_item->reg_addr_offset); - if (p_item->axp_step_tbl[i].regation) { - uint8_t reg_value_temp = (~reg_value & p_item->cfg_reg_mask); - reg_value &= ~p_item->cfg_reg_mask; - reg_value |= reg_value_temp; - } - break; - } else { - base_step += ((p_item->axp_step_tbl[i].step_max_vol - p_item->axp_step_tbl[i].step_min_vol + p_item->axp_step_tbl[i].step_val) / p_item->axp_step_tbl[i].step_val); - } - } - - if (sunxi_i2c_write(i2c_dev, AXP2202_RUNTIME_ADDR, p_item->cfg_reg_addr, reg_value)) { - return -1; - } - } - - if (onoff < 0) { - return 0; - } - if (sunxi_i2c_read(i2c_dev, AXP2202_RUNTIME_ADDR, p_item->ctrl_reg_addr, ®_value)) { - return -1; - } - if (onoff == 0) { - reg_value &= ~(1 << p_item->ctrl_bit_ofs); - } else { - reg_value |= (1 << p_item->ctrl_bit_ofs); - } - if (sunxi_i2c_write(i2c_dev, AXP2202_RUNTIME_ADDR, p_item->ctrl_reg_addr, reg_value)) { - return -1; - } - return 0; + return axp_set_vol(i2c_dev, name, set_vol, onoff, axp_ctrl_tbl, ARRAY_SIZE(axp_ctrl_tbl), AXP2202_RUNTIME_ADDR); } int pmu_axp2202_get_vol(sunxi_i2c_t *i2c_dev, char *name) { - uint8_t reg_value, i; - axp_contrl_info *p_item = NULL; - uint8_t base_step1 = 0; - uint8_t base_step2 = 0; - int vol; - - p_item = get_ctrl_info_from_tbl(name); - if (!p_item) { - return -1; - } - - if (sunxi_i2c_read(i2c_dev, AXP2202_RUNTIME_ADDR, p_item->ctrl_reg_addr, ®_value)) { - return -1; - } - - if (!(reg_value & (0x01 << p_item->ctrl_bit_ofs))) { - return 0; - } - - if (sunxi_i2c_read(i2c_dev, AXP2202_RUNTIME_ADDR, p_item->cfg_reg_addr, ®_value)) { - return -1; - } - reg_value &= p_item->cfg_reg_mask; - reg_value >>= p_item->reg_addr_offset; - for (i = 0; p_item->axp_step_tbl[i].step_max_vol != 0; i++) { - base_step1 += ((p_item->axp_step_tbl[i].step_max_vol - p_item->axp_step_tbl[i].step_min_vol + p_item->axp_step_tbl[i].step_val) / p_item->axp_step_tbl[i].step_val); - if (reg_value < base_step1) { - vol = (reg_value - base_step2) * p_item->axp_step_tbl[i].step_val + p_item->axp_step_tbl[i].step_min_vol; - return vol; - } - base_step2 += ((p_item->axp_step_tbl[i].step_max_vol - p_item->axp_step_tbl[i].step_min_vol + p_item->axp_step_tbl[i].step_val) / p_item->axp_step_tbl[i].step_val); - } - return -1; + return axp_get_vol(i2c_dev, name, axp_ctrl_tbl, ARRAY_SIZE(axp_ctrl_tbl), AXP2202_RUNTIME_ADDR); } void pmu_axp2202_dump(sunxi_i2c_t *i2c_dev) {