1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
|
// SPDX-License-Identifier: GPL-2.0+
/*
* AXP PMIC SPL driver
* (C) Copyright 2024 Arm Ltd.
*/
#include <errno.h>
#include <linux/types.h>
#include <asm/arch/pmic_bus.h>
#include <axp_pmic.h>
struct axp_reg_desc_spl {
u8 enable_reg;
u8 enable_mask;
u8 volt_reg;
u8 volt_mask;
u16 min_mV;
u16 max_mV;
u8 step_mV;
u8 split;
};
#define NA 0xff
#if defined(CONFIG_AXP717_POWER) /* AXP717 */
static const struct axp_reg_desc_spl axp_spl_dcdc_regulators[] = {
{ 0x80, BIT(0), 0x83, 0x7f, 500, 1540, 10, 70 },
{ 0x80, BIT(1), 0x84, 0x7f, 500, 1540, 10, 70 },
{ 0x80, BIT(2), 0x85, 0x7f, 500, 1840, 10, 70 },
};
#define AXP_CHIP_VERSION 0x0
#define AXP_CHIP_VERSION_MASK 0x0
#define AXP_CHIP_ID 0x0
#define AXP_SHUTDOWN_REG 0x27
#define AXP_SHUTDOWN_MASK BIT(0)
#elif defined(CONFIG_AXP313_POWER) /* AXP313 */
static const struct axp_reg_desc_spl axp_spl_dcdc_regulators[] = {
{ 0x10, BIT(0), 0x13, 0x7f, 500, 1540, 10, 70 },
{ 0x10, BIT(1), 0x14, 0x7f, 500, 1540, 10, 70 },
{ 0x10, BIT(2), 0x15, 0x7f, 500, 1840, 10, 70 },
};
#define AXP_CHIP_VERSION 0x3
#define AXP_CHIP_VERSION_MASK 0xc8
#define AXP_CHIP_ID 0x48
#define AXP_SHUTDOWN_REG 0x1a
#define AXP_SHUTDOWN_MASK BIT(7)
#elif defined(CONFIG_AXP305_POWER) /* AXP305 */
static const struct axp_reg_desc_spl axp_spl_dcdc_regulators[] = {
{ 0x10, BIT(0), 0x12, 0x7f, 600, 1520, 10, 50 },
{ 0x10, BIT(1), 0x13, 0x1f, 1000, 2550, 50, NA },
{ 0x10, BIT(2), 0x14, 0x7f, 600, 1520, 10, 50 },
{ 0x10, BIT(3), 0x15, 0x3f, 600, 1500, 20, NA },
{ 0x10, BIT(4), 0x16, 0x1f, 1100, 3400, 100, NA },
};
#define AXP_CHIP_VERSION 0x3
#define AXP_CHIP_VERSION_MASK 0xcf
#define AXP_CHIP_ID 0x40
#define AXP_SHUTDOWN_REG 0x32
#define AXP_SHUTDOWN_MASK BIT(7)
#else
#error "Please define the regulator registers in axp_spl_regulators[]."
#endif
static u8 axp_mvolt_to_cfg(int mvolt, const struct axp_reg_desc_spl *reg)
{
if (mvolt < reg->min_mV)
mvolt = reg->min_mV;
else if (mvolt > reg->max_mV)
mvolt = reg->max_mV;
mvolt -= reg->min_mV;
/* voltage in the first range ? */
if (mvolt <= reg->split * reg->step_mV)
return mvolt / reg->step_mV;
mvolt -= reg->split * reg->step_mV;
return reg->split + mvolt / (reg->step_mV * 2);
}
static int axp_set_dcdc(int dcdc_num, unsigned int mvolt)
{
const struct axp_reg_desc_spl *reg;
int ret;
if (dcdc_num < 1 || dcdc_num > ARRAY_SIZE(axp_spl_dcdc_regulators))
return -EINVAL;
reg = &axp_spl_dcdc_regulators[dcdc_num - 1];
if (mvolt == 0)
return pmic_bus_clrbits(reg->enable_reg, reg->enable_mask);
ret = pmic_bus_write(reg->volt_reg, axp_mvolt_to_cfg(mvolt, reg));
if (ret)
return ret;
return pmic_bus_setbits(reg->enable_reg, reg->enable_mask);
}
int axp_set_dcdc1(unsigned int mvolt)
{
return axp_set_dcdc(1, mvolt);
}
int axp_set_dcdc2(unsigned int mvolt)
{
return axp_set_dcdc(2, mvolt);
}
int axp_set_dcdc3(unsigned int mvolt)
{
return axp_set_dcdc(3, mvolt);
}
int axp_set_dcdc4(unsigned int mvolt)
{
return axp_set_dcdc(4, mvolt);
}
int axp_set_dcdc5(unsigned int mvolt)
{
return axp_set_dcdc(5, mvolt);
}
int axp_init(void)
{
int ret = pmic_bus_init();
if (ret)
return ret;
if (AXP_CHIP_VERSION_MASK) {
u8 axp_chip_id;
ret = pmic_bus_read(AXP_CHIP_VERSION, &axp_chip_id);
if (ret)
return ret;
if ((axp_chip_id & AXP_CHIP_VERSION_MASK) != AXP_CHIP_ID) {
debug("unknown PMIC: 0x%x\n", axp_chip_id);
return -EINVAL;
}
}
return 0;
}
#if !CONFIG_IS_ENABLED(ARM_PSCI_FW) && !IS_ENABLED(CONFIG_SYSRESET_CMD_POWEROFF)
int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
pmic_bus_setbits(AXP_SHUTDOWN_REG, AXP_SHUTDOWN_MASK);
/* infinite loop during shutdown */
while (1)
;
/* not reached */
return 0;
}
#endif
|