Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
CTCaer
GitHub Repository: CTCaer/hekate
Path: blob/master/bdk/power/max7762x.c
1476 views
1
/*
2
* Copyright (c) 2018 naehrwert
3
* Copyright (c) 2019-2020 CTCaer
4
*
5
* This program is free software; you can redistribute it and/or modify it
6
* under the terms and conditions of the GNU General Public License,
7
* version 2, as published by the Free Software Foundation.
8
*
9
* This program is distributed in the hope it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12
* more details.
13
*
14
* You should have received a copy of the GNU General Public License
15
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16
*/
17
18
#include <power/max7762x.h>
19
#include <power/max77620.h>
20
#include <power/max77812.h>
21
#include <soc/fuse.h>
22
#include <soc/i2c.h>
23
#include <soc/timer.h>
24
#include <soc/t210.h>
25
26
#define REGULATOR_SD 0
27
#define REGULATOR_LDO 1
28
#define REGULATOR_BC0 2
29
#define REGULATOR_BC1 3
30
31
typedef struct _max77620_fps_t
32
{
33
u8 fps_addr;
34
u8 fps_src;
35
u8 pd_period;
36
u8 pu_period;
37
} max77620_fps_t;
38
39
typedef struct _max77621_ctrl_t
40
{
41
u8 ctrl1_por;
42
u8 ctrl1_hos;
43
u8 ctrl2_por;
44
u8 ctrl2_hos;
45
} max77621_ctrl_t;
46
47
typedef struct _max77812_ctrl_t
48
{
49
u8 mask;
50
u8 shift;
51
u8 rsvd0;
52
u8 rsvd1;
53
} max77812_en_t;
54
55
typedef struct _max77620_regulator_t
56
{
57
const char *name;
58
59
u32 uv_step;
60
u32 uv_min;
61
u32 uv_default;
62
u32 uv_max;
63
64
u8 type;
65
u8 volt_addr;
66
u8 cfg_addr;
67
u8 volt_mask;
68
69
union {
70
max77620_fps_t fps;
71
max77621_ctrl_t ctrl;
72
max77812_en_t enable;
73
};
74
} max77620_regulator_t;
75
76
static const max77620_regulator_t _pmic_regulators[] = {
77
{ "sd0", 12500, 600000, 625000, 1400000, REGULATOR_SD, MAX77620_REG_SD0, MAX77620_REG_SD0_CFG, MAX77620_SD0_VOLT_MASK, {{ MAX77620_REG_FPS_SD0, 1, 7, 1 }} },
78
{ "sd1", 12500, 600000, 1125000, 1237500, REGULATOR_SD, MAX77620_REG_SD1, MAX77620_REG_SD1_CFG, MAX77620_SD1_VOLT_MASK, {{ MAX77620_REG_FPS_SD1, 0, 1, 5 }} },
79
{ "sd2", 12500, 600000, 1325000, 1350000, REGULATOR_SD, MAX77620_REG_SD2, MAX77620_REG_SD2_CFG, MAX77620_SDX_VOLT_MASK, {{ MAX77620_REG_FPS_SD2, 1, 5, 2 }} },
80
{ "sd3", 12500, 600000, 1800000, 1800000, REGULATOR_SD, MAX77620_REG_SD3, MAX77620_REG_SD3_CFG, MAX77620_SDX_VOLT_MASK, {{ MAX77620_REG_FPS_SD3, 0, 3, 3 }} },
81
{ "ldo0", 25000, 800000, 1200000, 1200000, REGULATOR_LDO, MAX77620_REG_LDO0_CFG, MAX77620_REG_LDO0_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO0, 3, 7, 0 }} },
82
{ "ldo1", 25000, 800000, 1050000, 1050000, REGULATOR_LDO, MAX77620_REG_LDO1_CFG, MAX77620_REG_LDO1_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO1, 3, 7, 0 }} },
83
{ "ldo2", 50000, 800000, 1800000, 3300000, REGULATOR_LDO, MAX77620_REG_LDO2_CFG, MAX77620_REG_LDO2_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO2, 3, 7, 0 }} },
84
{ "ldo3", 50000, 800000, 3100000, 3100000, REGULATOR_LDO, MAX77620_REG_LDO3_CFG, MAX77620_REG_LDO3_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO3, 3, 7, 0 }} },
85
{ "ldo4", 12500, 800000, 850000, 1000000, REGULATOR_LDO, MAX77620_REG_LDO4_CFG, MAX77620_REG_LDO4_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO4, 0, 7, 1 }} },
86
{ "ldo5", 50000, 800000, 1800000, 1800000, REGULATOR_LDO, MAX77620_REG_LDO5_CFG, MAX77620_REG_LDO5_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO5, 3, 7, 0 }} },
87
{ "ldo6", 50000, 800000, 2900000, 2900000, REGULATOR_LDO, MAX77620_REG_LDO6_CFG, MAX77620_REG_LDO6_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO6, 3, 7, 0 }} },
88
{ "ldo7", 50000, 800000, 1050000, 1050000, REGULATOR_LDO, MAX77620_REG_LDO7_CFG, MAX77620_REG_LDO7_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO7, 1, 4, 3 }} },
89
{ "ldo8", 50000, 800000, 1050000, 2800000, REGULATOR_LDO, MAX77620_REG_LDO8_CFG, MAX77620_REG_LDO8_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO8, 3, 7, 0 }} },
90
91
{ "max77621_CPU", 6250, 606250, 1000000, 1400000, REGULATOR_BC0, MAX77621_REG_VOUT, MAX77621_REG_VOUT_DVS, MAX77621_DVC_DVS_VOLT_MASK, {{ MAX77621_CPU_CTRL1_POR_DEFAULT, MAX77621_CPU_CTRL1_HOS_DEFAULT, MAX77621_CPU_CTRL2_POR_DEFAULT, MAX77621_CPU_CTRL2_HOS_DEFAULT }} },
92
{ "max77621_GPU", 6250, 606250, 1200000, 1400000, REGULATOR_BC0, MAX77621_REG_VOUT, MAX77621_REG_VOUT_DVS, MAX77621_DVC_DVS_VOLT_MASK, {{ MAX77621_CPU_CTRL1_POR_DEFAULT, MAX77621_CPU_CTRL1_HOS_DEFAULT, MAX77621_CPU_CTRL2_POR_DEFAULT, MAX77621_CPU_CTRL2_HOS_DEFAULT }} },
93
{ "max77812_CPU", 5000, 250000, 600000, 1525000, REGULATOR_BC1, MAX77812_REG_M4_VOUT, MAX77812_REG_EN_CTRL, MAX77812_BUCK_VOLT_MASK, {{ MAX77812_EN_CTRL_EN_M4_MASK, MAX77812_EN_CTRL_EN_M4_SHIFT, 0, 0 }} },
94
{ "max77812_RAM", 5000, 250000, 600000, 650000, REGULATOR_BC1, MAX77812_REG_M3_VOUT, MAX77812_REG_EN_CTRL, MAX77812_BUCK_VOLT_MASK, {{ MAX77812_EN_CTRL_EN_M3_MASK, MAX77812_EN_CTRL_EN_M3_SHIFT, 0, 0 }} } // Only on PHASE211 configuration.
95
//{ "max77812_GPU", 5000, 250000, 600000, 1525000, REGULATOR_BC1, MAX77812_REG_M1_VOUT, MAX77812_REG_EN_CTRL, MAX77812_BUCK_VOLT_MASK, {{ MAX77812_EN_CTRL_EN_M1_MASK, MAX77812_EN_CTRL_EN_M1_SHIFT, 0, 0 }} },
96
};
97
98
static u8 _max77812_get_address()
99
{
100
static u8 max77812_i2c_addr = 0;
101
102
if (max77812_i2c_addr)
103
return max77812_i2c_addr;
104
105
max77812_i2c_addr =
106
!(FUSE(FUSE_RESERVED_ODM28_B01) & 1) ? MAX77812_PHASE31_CPU_I2C_ADDR : MAX77812_PHASE211_CPU_I2C_ADDR;
107
108
return max77812_i2c_addr;
109
}
110
111
static u8 _max7762x_get_i2c_address(u32 id)
112
{
113
const max77620_regulator_t *reg = &_pmic_regulators[id];
114
115
// Choose the correct i2c address.
116
switch (reg->type)
117
{
118
case REGULATOR_SD:
119
case REGULATOR_LDO:
120
return MAX77620_I2C_ADDR;
121
case REGULATOR_BC0:
122
return (id == REGULATOR_CPU0 ? MAX77621_CPU_I2C_ADDR : MAX77621_GPU_I2C_ADDR);
123
case REGULATOR_BC1:
124
{
125
u8 reg_addr = _max77812_get_address();
126
if (id == REGULATOR_RAM0 && reg_addr == MAX77812_PHASE31_CPU_I2C_ADDR)
127
reg_addr = 0;
128
return reg_addr;
129
}
130
default:
131
return 0;
132
}
133
}
134
135
static void _max7762x_set_reg(u8 addr, u8 reg, u8 val)
136
{
137
u32 retries = 100;
138
while (retries)
139
{
140
if (i2c_send_byte(I2C_5, addr, reg, val))
141
break;
142
143
usleep(50);
144
retries--;
145
}
146
}
147
148
int max77620_regulator_get_status(u32 id)
149
{
150
if (id > REGULATOR_LDO8)
151
return 0;
152
153
const max77620_regulator_t *reg = &_pmic_regulators[id];
154
155
// SD power OK status.
156
if (reg->type == REGULATOR_SD)
157
{
158
u8 mask = 1u << (7 - id);
159
return (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_STATSD) & mask) ? 0 : 1;
160
}
161
162
// LDO power OK status.
163
return (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, reg->cfg_addr) & MAX77620_LDO_CFG2_POK_MASK) ? 1 : 0;
164
}
165
166
int max77620_regulator_config_fps(u32 id)
167
{
168
if (id > REGULATOR_LDO8)
169
return 0;
170
171
const max77620_regulator_t *reg = &_pmic_regulators[id];
172
173
// Set FPS configuration.
174
_max7762x_set_reg(MAX77620_I2C_ADDR,
175
reg->fps.fps_addr,
176
(reg->fps.fps_src << MAX77620_FPS_SRC_SHIFT) |
177
(reg->fps.pu_period << MAX77620_FPS_PU_PERIOD_SHIFT) |
178
(reg->fps.pd_period << MAX77620_FPS_PD_PERIOD_SHIFT));
179
180
return 1;
181
}
182
183
int max7762x_regulator_set_voltage(u32 id, u32 uv)
184
{
185
if (id > REGULATOR_MAX)
186
return 0;
187
188
const max77620_regulator_t *reg = &_pmic_regulators[id];
189
190
if (uv < reg->uv_min || uv > reg->uv_max)
191
return 0;
192
193
u8 addr = _max7762x_get_i2c_address(id);
194
if (!addr)
195
return 0;
196
197
// Calculate voltage multiplier.
198
u32 mult = (uv + reg->uv_step - 1 - reg->uv_min) / reg->uv_step;
199
u8 val = i2c_recv_byte(I2C_5, addr, reg->volt_addr);
200
val = (val & ~reg->volt_mask) | (mult & reg->volt_mask);
201
202
// Set voltage.
203
_max7762x_set_reg(addr, reg->volt_addr, val);
204
205
// If max77621 set DVS voltage also.
206
if (reg->type == REGULATOR_BC0)
207
_max7762x_set_reg(addr, reg->cfg_addr, MAX77621_VOUT_ENABLE_MASK | val);
208
209
// Wait for ramp up/down delay.
210
usleep(1000);
211
212
return 1;
213
}
214
215
int max7762x_regulator_enable(u32 id, bool enable)
216
{
217
u8 reg_addr;
218
u8 enable_val;
219
u8 enable_mask;
220
u8 enable_shift;
221
222
if (id > REGULATOR_MAX)
223
return 0;
224
225
const max77620_regulator_t *reg = &_pmic_regulators[id];
226
227
// Choose the correct i2c and register addresses and mask/shift for each type.
228
switch (reg->type)
229
{
230
case REGULATOR_SD:
231
reg_addr = reg->cfg_addr;
232
enable_val = MAX77620_POWER_MODE_NORMAL;
233
enable_mask = MAX77620_SD_POWER_MODE_MASK;
234
enable_shift = MAX77620_SD_POWER_MODE_SHIFT;
235
break;
236
case REGULATOR_LDO:
237
reg_addr = reg->volt_addr;
238
enable_val = MAX77620_POWER_MODE_NORMAL;
239
enable_mask = MAX77620_LDO_POWER_MODE_MASK;
240
enable_shift = MAX77620_LDO_POWER_MODE_SHIFT;
241
break;
242
case REGULATOR_BC0:
243
reg_addr = reg->volt_addr;
244
enable_val = MAX77621_VOUT_ENABLE;
245
enable_mask = MAX77621_DVC_DVS_ENABLE_MASK;
246
enable_shift = MAX77621_DVC_DVS_ENABLE_SHIFT;
247
break;
248
case REGULATOR_BC1:
249
reg_addr = reg->cfg_addr;
250
enable_val = MAX77812_EN_CTRL_ENABLE;
251
enable_mask = reg->enable.mask;
252
enable_shift = reg->enable.shift;
253
break;
254
default:
255
return 0;
256
}
257
258
u8 addr = _max7762x_get_i2c_address(id);
259
if (!addr)
260
return 0;
261
262
// Read and enable/disable.
263
u8 val = i2c_recv_byte(I2C_5, addr, reg_addr);
264
val &= ~enable_mask;
265
266
if (enable)
267
val |= (enable_val << enable_shift);
268
269
// Set enable.
270
_max7762x_set_reg(addr, reg_addr, val);
271
272
// Wait for enable/disable ramp delay.
273
usleep(1000);
274
275
return 1;
276
}
277
278
void max77620_config_gpio(u32 gpio_id, bool enable)
279
{
280
if (gpio_id > 7)
281
return;
282
283
// Configure as standard GPIO.
284
u8 val = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_AME_GPIO);
285
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_AME_GPIO, val & ~BIT(gpio_id));
286
287
// Set GPIO configuration.
288
if (enable)
289
val = MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH | MAX77620_CNFG_GPIO_DIR_OUTPUT | MAX77620_CNFG_GPIO_DRV_PUSHPULL;
290
else
291
val = MAX77620_CNFG_GPIO_DIR_INPUT | MAX77620_CNFG_GPIO_DRV_OPENDRAIN;
292
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO0 + gpio_id, val);
293
}
294
295
void max77621_config_default(u32 id, bool por)
296
{
297
const max77620_regulator_t *reg = &_pmic_regulators[id];
298
299
if (reg->type != REGULATOR_BC0)
300
return;
301
302
u8 addr = _max7762x_get_i2c_address(id);
303
if (!addr)
304
return;
305
306
if (por)
307
{
308
// Set voltage and disable power before changing the inductor.
309
max7762x_regulator_set_voltage(id, 1000000);
310
max7762x_regulator_enable(id, false);
311
312
// Configure to default.
313
i2c_send_byte(I2C_5, addr, MAX77621_REG_CONTROL1, reg->ctrl.ctrl1_por);
314
i2c_send_byte(I2C_5, addr, MAX77621_REG_CONTROL2, reg->ctrl.ctrl2_por);
315
}
316
else
317
{
318
i2c_send_byte(I2C_5, addr, MAX77621_REG_CONTROL1, reg->ctrl.ctrl1_hos);
319
i2c_send_byte(I2C_5, addr, MAX77621_REG_CONTROL2, reg->ctrl.ctrl2_hos);
320
}
321
}
322
323
void max77620_config_default()
324
{
325
// Check if Erista OTP.
326
if (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_CID4) != 0x35)
327
return;
328
329
// Set default voltages and enable regulators.
330
for (u32 i = REGULATOR_SD1; i <= REGULATOR_LDO8; i++)
331
{
332
max77620_regulator_config_fps(i);
333
max7762x_regulator_set_voltage(i, _pmic_regulators[i].uv_default);
334
if (_pmic_regulators[i].fps.fps_src != MAX77620_FPS_SRC_NONE)
335
max7762x_regulator_enable(i, true);
336
}
337
338
// Enable SD0 output voltage sense and disable for SD1. Additionally disable the reserved bit.
339
_max7762x_set_reg(MAX77620_I2C_ADDR, MAX77620_REG_SD_CFG2, MAX77620_SD_CNF2_ROVS_EN_SD0);
340
}
341
342
// Stock HOS: disabled.
343
void max77620_low_battery_monitor_config(bool enable)
344
{
345
_max7762x_set_reg(MAX77620_I2C_ADDR, MAX77620_REG_CNFGGLBL1,
346
MAX77620_CNFGGLBL1_LBDAC_EN |
347
(enable ? MAX77620_CNFGGLBL1_MPPLD : 0) |
348
MAX77620_CNFGGLBL1_LBHYST_200 |
349
MAX77620_CNFGGLBL1_LBDAC_2800);
350
}
351
352