SmartAudio/lichee/linux-4.9/drivers/power/supply/axp/axp22x/axp22x-regulator.c

655 lines
17 KiB
C
Executable File

/*
* drivers/power/axp/axp22x/axp22x-regulator.c
* (C) Copyright 2010-2016
* Allwinner Technology Co., Ltd. <www.allwinnertech.com>
* Pannan <pannan@allwinnertech.com>
*
* regulator driver of axp22x
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
*/
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/regmap.h>
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/module.h>
#include <linux/power/axp_depend.h>
#include "../axp-core.h"
#include "../axp-regulator.h"
#include "axp22x.h"
#include "axp22x-regulator.h"
enum AXP_REGLS {
VCC_DCDC1,
VCC_DCDC2,
VCC_DCDC3,
VCC_DCDC4,
VCC_DCDC5,
VCC_LDO1,
VCC_LDO2,
VCC_LDO3,
VCC_LDO4,
VCC_LDO5,
VCC_LDO6,
#ifdef CONFIG_AW_AXP233
#else
VCC_LDO7,
VCC_LDO8,
#endif
VCC_LDO9,
VCC_LDO10,
VCC_LDO11,
VCC_LDOIO0,
VCC_LDOIO1,
#ifdef CONFIG_AW_AXP233
VCC_SW0,
#endif
VCC_DC1SW,
VCC_LDO12,
VCC_22X_MAX,
};
struct axp22x_regulators {
struct regulator_dev *regulators[VCC_22X_MAX];
struct axp_dev *chip;
};
#define AXP22X_LDO(_id, min, max, step1, vreg, shift, nbits,\
ereg, emask, enval, disval, switch_vol, step2, new_level,\
mode_addr, freq_addr, dvm_ereg, dvm_ebit, dvm_flag) \
AXP_LDO(AXP22X, _id, min, max, step1, vreg, shift, nbits,\
ereg, emask, enval, disval, switch_vol, step2, new_level,\
mode_addr, freq_addr, dvm_ereg, dvm_ebit, dvm_flag)
#define AXP22X_DCDC(_id, min, max, step1, vreg, shift, nbits,\
ereg, emask, enval, disval, switch_vol, step2, new_level,\
mode_addr, mode_bit, freq_addr, dvm_ereg, dvm_ebit, dvm_flag) \
AXP_DCDC(AXP22X, _id, min, max, step1, vreg, shift, nbits,\
ereg, emask, enval, disval, switch_vol, step2, new_level,\
mode_addr, mode_bit, freq_addr, dvm_ereg, dvm_ebit, dvm_flag)
#define AXP22X_SW(_id, min, max, step1, vreg, shift, nbits,\
ereg, emask, enval, disval, switch_vol, step2, new_level,\
mode_addr, freq_addr, dvm_ereg, dvm_ebit, dvm_flag) \
AXP_SW(AXP22X, _id, min, max, step1, vreg, shift, nbits,\
ereg, emask, enval, disval, switch_vol, step2, new_level,\
mode_addr, freq_addr, dvm_ereg, dvm_ebit, dvm_flag)
static struct axp_regulator_info axp22x_regulator_info[] = {
#ifdef CONFIG_AW_AXP233
AXP22X_DCDC(1, 1600, 3400, 100, DCDC1, 0, 5, DCDC1EN, 0x02, 0x02,
0x00, 0, 0, 0, 0x80, 0x01, 0x3B, 0, 0, 0),
AXP22X_DCDC(2, 600, 1540, 20, DCDC2, 0, 6, DCDC2EN, 0x04, 0x04,
0x00, 0, 0, 0, 0x80, 0x02, 0x3B, 0x27, 2, 0),
AXP22X_DCDC(3, 600, 1860, 20, DCDC3, 0, 6, DCDC3EN, 0x08, 0x08,
0x00, 0, 0, 0, 0x80, 0x04, 0x3B, 0x27, 3, 0),
AXP22X_DCDC(4, 600, 2600, 20, DCDC4, 0, 6, DCDC4EN, 0x10, 0x10,
0x00, 1800, 100, 0, 0x80, 0x08, 0x3B, 0, 0, 0),
AXP22X_DCDC(5, 1000, 2550, 50, DCDC5, 0, 5, DCDC5EN, 0x20, 0x20,
0x00, 0, 0, 0, 0x80, 0x10, 0x3B, 0, 0, 0),
#else
AXP22X_DCDC(1, 1600, 3400, 100, DCDC1, 0, 5, DCDC1EN, 0x02, 0x02,
0x00, 0, 0, 0, 0x80, 0x01, 0x37, 0, 0, 0),
AXP22X_DCDC(2, 600, 1540, 20, DCDC2, 0, 6, DCDC2EN, 0x04, 0x04,
0x00, 0, 0, 0, 0x80, 0x02, 0x37, 0x27, 2, 0),
AXP22X_DCDC(3, 600, 1860, 20, DCDC3, 0, 6, DCDC3EN, 0x08, 0x08,
0x00, 0, 0, 0, 0x80, 0x04, 0x37, 0x27, 3, 0),
AXP22X_DCDC(4, 600, 1540, 20, DCDC4, 0, 6, DCDC4EN, 0x10, 0x10,
0x00, 0, 0, 0, 0x80, 0x08, 0x37, 0, 0, 0),
AXP22X_DCDC(5, 1000, 2550, 50, DCDC5, 0, 5, DCDC5EN, 0x20, 0x20,
0x00, 0, 0, 0, 0x80, 0x10, 0x37, 0, 0, 0),
#endif
AXP22X_LDO(1, 3000, 3000, 0, LDO1, 0, 0, LDO1EN, 0x01, 0x01,
0x00, 0, 0, 0, 0, 0, 0, 0, 0),
AXP22X_LDO(2, 700, 3300, 100, LDO2, 0, 5, LDO2EN, 0x40, 0x40,
0x00, 0, 0, 0, 0, 0, 0, 0, 0),
AXP22X_LDO(3, 700, 3300, 100, LDO3, 0, 5, LDO3EN, 0x80, 0x80,
0x00, 0, 0, 0, 0, 0, 0, 0, 0),
#ifdef CONFIG_AW_AXP233
AXP22X_LDO(4, 700, 4200, 100, LDO4, 0, 5, LDO4EN, 0x20, 0x20,
0x00, 3400, 200, 0, 0, 0, 0, 0, 0),
AXP22X_LDO(5, 700, 3300, 100, LDO5, 0, 5, LDO5EN, 0x08, 0x08,
0x00, 0, 0, 0, 0, 0, 0, 0, 0),
#else
AXP22X_LDO(4, 700, 3300, 100, LDO4, 0, 5, LDO4EN, 0x80, 0x80,
0x00, 0, 0, 0, 0, 0, 0, 0, 0),
AXP22X_LDO(5, 700, 3300, 100, LDO5, 0, 5, LDO5EN, 0x08, 0x08,
0x00, 0, 0, 0, 0, 0, 0, 0, 0),
#endif
AXP22X_LDO(6, 700, 3300, 100, LDO6, 0, 5, LDO6EN, 0x10, 0x10,
0x00, 0, 0, 0, 0, 0, 0, 0, 0),
#ifdef CONFIG_AW_AXP233
#else
AXP22X_LDO(7, 700, 3300, 100, LDO7, 0, 5, LDO7EN, 0x20, 0x20,
0x00, 0, 0, 0, 0, 0, 0, 0, 0),
AXP22X_LDO(8, 700, 3300, 100, LDO8, 0, 5, LDO8EN, 0x40, 0x40,
0x00, 0, 0, 0, 0, 0, 0, 0, 0),
#endif
AXP22X_LDO(9, 700, 3300, 100, LDO9, 0, 5, LDO9EN, 0x01, 0x01,
0x00, 0, 0, 0, 0, 0, 0, 0, 0),
AXP22X_LDO(10, 700, 3300, 100, LDO10, 0, 5, LDO10EN, 0x02, 0x02,
0x00, 0, 0, 0, 0, 0, 0, 0, 0),
AXP22X_LDO(11, 700, 3300, 100, LDO11, 0, 5, LDO11EN, 0x04, 0x04,
0x00, 0, 0, 0, 0, 0, 0, 0, 0),
AXP22X_LDO(IO0, 700, 3300, 100, LDOIO0, 0, 5, LDOIO0EN, 0x07, 0x03,
0x00, 0, 0, 0, 0, 0, 0, 0, 0),
AXP22X_LDO(IO1, 700, 3300, 100, LDOIO1, 0, 5, LDOIO1EN, 0x07, 0x03,
0x00, 0, 0, 0, 0, 0, 0, 0, 0),
#ifdef CONFIG_AW_AXP233
AXP22X_SW(0, 3300, 3300, 100, SW0, 0, 0, SW0EN, 0x40, 0x40,
0x00, 0, 0, 0, 0, 0, 0, 0, 0),
#endif
AXP22X_SW(1, 3300, 3300, 100, DC1SW, 0, 0, DC1SWEN, 0x80, 0x80,
0x00, 0, 0, 0, 0, 0, 0, 0, 0),
AXP22X_LDO(12, 700, 1400, 100, LDO12, 0, 3, LDO12EN, 0x01, 0x01,
0x00, 0, 0, 0, 0, 0, 0, 0, 0),
};
static struct regulator_init_data axp22x_regulator_init_data[] = {
[VCC_DCDC1] = {
.constraints = {
.name = "axp22x_dcdc1",
.min_uV = 1600000,
.max_uV = 3400000,
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
| REGULATOR_CHANGE_STATUS,
#ifdef CONFIG_ARCH_SUN8IW11
.always_on = 1,
#endif
},
},
[VCC_DCDC2] = {
.constraints = {
.name = "axp22x_dcdc2",
.min_uV = 600000,
.max_uV = 1540000,
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
| REGULATOR_CHANGE_STATUS,
},
},
[VCC_DCDC3] = {
.constraints = {
.name = "axp22x_dcdc3",
.min_uV = 600000,
.max_uV = 1860000,
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
| REGULATOR_CHANGE_STATUS,
},
},
[VCC_DCDC4] = {
.constraints = {
.name = "axp22x_dcdc4",
.min_uV = 600000,
#ifdef CONFIG_AW_AXP233
.max_uV = 2600000,
#else
.max_uV = 1540000,
#endif
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
| REGULATOR_CHANGE_STATUS,
},
},
[VCC_DCDC5] = {
.constraints = {
.name = "axp22x_dcdc5",
.min_uV = 1000000,
.max_uV = 2550000,
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
| REGULATOR_CHANGE_STATUS,
},
},
[VCC_LDO1] = {
.constraints = {
.name = "axp22x_rtc",
.min_uV = 3000000,
.max_uV = 3000000,
},
},
[VCC_LDO2] = {
.constraints = {
.name = "axp22x_aldo1",
.min_uV = 700000,
.max_uV = 3300000,
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
| REGULATOR_CHANGE_STATUS,
},
},
[VCC_LDO3] = {
.constraints = {
.name = "axp22x_aldo2",
.min_uV = 700000,
.max_uV = 3300000,
#ifdef CONFIG_ARCH_SUN8IW11
.always_on = 1,
#endif
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
| REGULATOR_CHANGE_STATUS,
},
},
[VCC_LDO4] = {
.constraints = {
.name = "axp22x_aldo3",
.min_uV = 700000,
.max_uV = 3300000,
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
| REGULATOR_CHANGE_STATUS,
},
},
[VCC_LDO5] = {
.constraints = {
.name = "axp22x_dldo1",
.min_uV = 700000,
#ifdef CONFIG_AW_AXP233
.max_uV = 4200000,
#else
.max_uV = 3300000,
#endif
#ifdef CONFIG_ARCH_SUN8IW10
.always_on = 1,
#endif
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
| REGULATOR_CHANGE_STATUS,
},
},
[VCC_LDO6] = {
.constraints = {
.name = "axp22x_dldo2",
.min_uV = 700000,
.max_uV = 3300000,
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
| REGULATOR_CHANGE_STATUS,
},
},
#ifdef CONFIG_AW_AXP233
#else
[VCC_LDO7] = {
.constraints = {
.name = "axp22x_dldo3",
.min_uV = 700000,
.max_uV = 3300000,
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
| REGULATOR_CHANGE_STATUS,
},
},
[VCC_LDO8] = {
.constraints = {
.name = "axp22x_dldo4",
.min_uV = 700000,
.max_uV = 3300000,
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
| REGULATOR_CHANGE_STATUS,
},
},
#endif
[VCC_LDO9] = {
.constraints = {
.name = "axp22x_eldo1",
.min_uV = 700000,
.max_uV = 3300000,
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
| REGULATOR_CHANGE_STATUS,
},
},
[VCC_LDO10] = {
.constraints = {
.name = "axp22x_eldo2",
.min_uV = 700000,
.max_uV = 3300000,
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
| REGULATOR_CHANGE_STATUS,
},
},
[VCC_LDO11] = {
.constraints = {
.name = "axp22x_eldo3",
.min_uV = 700000,
.max_uV = 3300000,
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
| REGULATOR_CHANGE_STATUS,
},
},
[VCC_LDOIO0] = {
.constraints = {
.name = "axp22x_ldoio0",
.min_uV = 700000,
.max_uV = 3300000,
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
| REGULATOR_CHANGE_STATUS,
},
},
[VCC_LDOIO1] = {
.constraints = {
.name = "axp22x_ldoio1",
.min_uV = 700000,
.max_uV = 3300000,
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
| REGULATOR_CHANGE_STATUS,
},
},
#ifdef CONFIG_AW_AXP233
[VCC_SW0] = {
.constraints = {
.name = "axp22x_sw0",
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
},
#endif
[VCC_DC1SW] = {
.constraints = {
.name = "axp22x_dc1sw",
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
},
[VCC_LDO12] = {
.constraints = {
.name = "axp22x_dc5ldo",
.min_uV = 700000,
.max_uV = 1400000,
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
| REGULATOR_CHANGE_STATUS,
},
},
};
static s32 axp22x_regulator_dependence(const char *ldo_name)
{
s32 axp22x_dependence = 0;
if (strstr(ldo_name, "dcdc1") != NULL)
axp22x_dependence |= AXP22X_DCDC1_BIT;
else if (strstr(ldo_name, "dcdc2") != NULL)
axp22x_dependence |= AXP22X_DCDC2_BIT;
else if (strstr(ldo_name, "dcdc3") != NULL)
axp22x_dependence |= AXP22X_DCDC3_BIT;
else if (strstr(ldo_name, "dcdc4") != NULL)
axp22x_dependence |= AXP22X_DCDC4_BIT;
else if (strstr(ldo_name, "dcdc5") != NULL)
axp22x_dependence |= AXP22X_DCDC5_BIT;
else if (strstr(ldo_name, "aldo1") != NULL)
axp22x_dependence |= AXP22X_ALDO1_BIT;
else if (strstr(ldo_name, "aldo2") != NULL)
axp22x_dependence |= AXP22X_ALDO2_BIT;
else if (strstr(ldo_name, "aldo3") != NULL)
axp22x_dependence |= AXP22X_ALDO3_BIT;
else if (strstr(ldo_name, "dldo1") != NULL)
axp22x_dependence |= AXP22X_DLDO1_BIT;
else if (strstr(ldo_name, "dldo2") != NULL)
axp22x_dependence |= AXP22X_DLDO2_BIT;
#ifdef CONFIG_AW_AXP233
#else
else if (strstr(ldo_name, "dldo3") != NULL)
axp22x_dependence |= AXP22X_DLDO3_BIT;
else if (strstr(ldo_name, "dldo4") != NULL)
axp22x_dependence |= AXP22X_DLDO4_BIT;
#endif
else if (strstr(ldo_name, "eldo1") != NULL)
axp22x_dependence |= AXP22X_ELDO1_BIT;
else if (strstr(ldo_name, "eldo2") != NULL)
axp22x_dependence |= AXP22X_ELDO2_BIT;
else if (strstr(ldo_name, "eldo3") != NULL)
axp22x_dependence |= AXP22X_ELDO3_BIT;
else if (strstr(ldo_name, "dc5ldo") != NULL)
axp22x_dependence |= AXP22X_DC5LDO_BIT;
else if (strstr(ldo_name, "ldoio0") != NULL)
axp22x_dependence |= AXP22X_LDOIO0_BIT;
else if (strstr(ldo_name, "ldoio1") != NULL)
axp22x_dependence |= AXP22X_LDOIO1_BIT;
#ifdef CONFIG_AW_AXP233
else if (strstr(ldo_name, "sw0") != NULL)
axp22x_dependence |= AXP22X_SW0_BIT;
#endif
else if (strstr(ldo_name, "dc1sw") != NULL)
axp22x_dependence |= AXP22X_DC1SW_BIT;
else if (strstr(ldo_name, "rtc") != NULL)
axp22x_dependence |= AXP22X_RTC_BIT;
else
return -1;
axp22x_dependence |= (0 << 30);
return axp22x_dependence;
}
int axp22x_need_save_regulator;
static axp_mem_data_t *regu_list;
static u32 ldo_count;
int axp22x_regulator_save(void)
{
struct regulator *regu = NULL;
char *spy_id = NULL;
char *rtc_id = NULL;
int ret = 0, ldo_idx = 0;
if (axp22x_need_save_regulator) {
for (ldo_idx = 0; ldo_idx < ldo_count; ldo_idx++) {
spy_id = (char *)((regu_list + ldo_idx)->id_name);
rtc_id = strstr(spy_id, "rtc");
if (rtc_id != NULL) {
(regu_list + ldo_idx)->mem_data = 0;
rtc_id = NULL;
continue;
}
regu = regulator_get(NULL, spy_id);
if (IS_ERR(regu)) {
pr_err("%s: fail to get regulator %s\n",
__func__, spy_id);
return -1;
}
ret = regulator_get_voltage(regu);
if (ret < 0) {
pr_err("%s: fail to get %s voltage!\n",
__func__, spy_id);
return -1;
}
(regu_list + ldo_idx)->mem_data = ret;
ret = regulator_is_enabled(regu);
if (ret > 0)
(regu_list + ldo_idx)->mem_data |= (1 << 31);
else
(regu_list + ldo_idx)->mem_data &= (~(1 << 31));
regulator_put(regu);
}
}
return 0;
}
void axp22x_regulator_restore(void)
{
struct regulator *regu = NULL;
char *spy_id = NULL;
int ret = 0, volt = 0, ldo_idx = 0;
if (axp22x_need_save_regulator) {
for (ldo_idx = 0; ldo_idx < ldo_count; ldo_idx++) {
if (0 == (regu_list + ldo_idx)->mem_data)
continue;
spy_id = (char *)((regu_list + ldo_idx)->id_name);
regu = regulator_get(NULL, spy_id);
if (IS_ERR(regu)) {
pr_err("%s: fail to get regulator %s\n",
__func__, spy_id);
continue;
}
ret = regulator_get_voltage(regu);
volt = (regu_list + ldo_idx)->mem_data & 0x0fffffff;
if (ret != volt) {
ret = regulator_set_voltage(regu, volt, volt);
if (ret != 0) {
pr_err("%s: fail to set %s voltage!\n",
__func__, spy_id);
continue;
}
}
if ((regu_list + ldo_idx)->mem_data & (1 << 31)) {
ret = regu->rdev->desc->ops->enable(regu->rdev);
if (ret != 0) {
pr_err("%s: fail to enable %s!\n",
__func__, spy_id);
continue;
}
} else {
ret = regu->rdev->desc->ops->disable(
regu->rdev);
if (ret != 0) {
pr_err("%s: fail to enable %s!\n",
__func__, spy_id);
continue;
}
}
regulator_put(regu);
}
}
}
static int axp22x_regulator_probe(struct platform_device *pdev)
{
s32 i, ret = 0;
struct axp_regulator_info *info;
struct axp22x_regulators *regu_data;
struct axp_dev *axp_dev = dev_get_drvdata(pdev->dev.parent);
if (pdev->dev.of_node) {
ret = axp_regulator_dt_parse(pdev->dev.of_node,
axp22x_regulator_init_data,
axp22x_regulator_dependence);
if (ret) {
pr_err("%s parse device tree err\n", __func__);
return -EINVAL;
}
} else {
pr_err("axp22x regulator device tree err!\n");
return -EBUSY;
}
regu_data = devm_kzalloc(&pdev->dev, sizeof(*regu_data),
GFP_KERNEL);
if (!regu_data)
return -ENOMEM;
regu_data->chip = axp_dev;
platform_set_drvdata(pdev, regu_data);
for (i = 0; i < VCC_22X_MAX; i++) {
info = &axp22x_regulator_info[i];
info->pmu_num = axp_dev->pmu_num;
regu_data->regulators[i] = axp_regulator_register(&pdev->dev,
axp_dev->regmap,
&axp22x_regulator_init_data[i], info);
if (IS_ERR(regu_data->regulators[i])) {
dev_err(&pdev->dev, "failed to register regulator %s\n",
info->desc.name);
while (--i >= 0)
axp_regulator_unregister(
regu_data->regulators[i]);
return -1;
}
if (info->desc.id >= AXP_DCDC_ID_START) {
ret = axp_regulator_create_attrs(
&regu_data->regulators[i]->dev);
if (ret)
dev_err(&pdev->dev,
"failed to register regulator attr %s\n",
info->desc.name);
}
}
/* voltage not to the OTP default when wakeup */
if (axp22x_need_save_regulator == 0) {
axp_regmap_set_bits(axp_dev->regmap, AXP22X_HOTOVER_CTL, 0x02);
} else {
ret = axp_get_ldo_count(pdev->dev.of_node, &ldo_count);
if (ret) {
dev_err(&pdev->dev, "failed to get ldo count\n");
return ret;
}
regu_list = (axp_mem_data_t *)kzalloc(
sizeof(axp_mem_data_t) * ldo_count, GFP_KERNEL);
if (!regu_list) {
pr_err("%s: request regu_list failed\n", __func__);
return -1;
}
ret = axp_mem_regu_init(pdev->dev.of_node,
regu_list, ldo_count);
if (ret) {
dev_err(&pdev->dev, "failed to init mem regu\n");
return ret;
}
}
return 0;
}
static int axp22x_regulator_remove(struct platform_device *pdev)
{
struct axp22x_regulators *regu_data = platform_get_drvdata(pdev);
int i;
for (i = 0; i < VCC_22X_MAX; i++)
regulator_unregister(regu_data->regulators[i]);
return 0;
}
static const struct of_device_id axp22x_regulator_dt_ids[] = {
{ .compatible = "axp221s-regulator", },
{ .compatible = "axp223-regulator", },
{ .compatible = "axp227-regulator", },
{ .compatible = "axp233-regulator", },
{},
};
MODULE_DEVICE_TABLE(of, axp22x_regulator_dt_ids);
static struct platform_driver axp22x_regulator_driver = {
.driver = {
.name = "axp22x-regulator",
.of_match_table = axp22x_regulator_dt_ids,
},
.probe = axp22x_regulator_probe,
.remove = axp22x_regulator_remove,
};
static int __init axp22x_regulator_initcall(void)
{
int ret;
ret = platform_driver_register(&axp22x_regulator_driver);
if (IS_ERR_VALUE(ret)) {
pr_err("%s: failed, errno %d\n", __func__, ret);
return -EINVAL;
}
return 0;
}
subsys_initcall(axp22x_regulator_initcall);
MODULE_DESCRIPTION("Regulator Driver of axp22x");
MODULE_AUTHOR("pannan");
MODULE_LICENSE("GPL");