blob: 6fa0d0a59c9572b2399e5fa59d89f53fc7987185 [file] [log] [blame]
Yann Gautiere4f559f2018-07-16 17:55:07 +02001/*
Benjamin Gaignard42822842020-02-24 13:57:40 +01002 * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved
Yann Gautiere4f559f2018-07-16 17:55:07 +02003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
Yann Gautiere4f559f2018-07-16 17:55:07 +02007#include <errno.h>
Antonio Nino Diaz09d40e02018-12-14 00:18:21 +00008
Antonio Nino Diaz09d40e02018-12-14 00:18:21 +00009#include <common/debug.h>
10#include <drivers/delay_timer.h>
Yann Gautierd82d4ff2019-02-14 11:15:03 +010011#include <drivers/st/stm32_i2c.h>
Yann Gautier23684d02019-01-16 18:31:00 +010012#include <drivers/st/stm32mp_pmic.h>
Yann Gautier23684d02019-01-16 18:31:00 +010013#include <drivers/st/stpmic1.h>
Antonio Nino Diaz09d40e02018-12-14 00:18:21 +000014#include <lib/mmio.h>
15#include <lib/utils_def.h>
Nicolas Le Bayon16e56a72019-09-19 11:24:50 +020016#include <libfdt.h>
17
18#include <platform_def.h>
Antonio Nino Diaz09d40e02018-12-14 00:18:21 +000019
Yann Gautier23684d02019-01-16 18:31:00 +010020#define STPMIC1_LDO12356_OUTPUT_MASK (uint8_t)(GENMASK(6, 2))
21#define STPMIC1_LDO12356_OUTPUT_SHIFT 2
22#define STPMIC1_LDO3_MODE (uint8_t)(BIT(7))
23#define STPMIC1_LDO3_DDR_SEL 31U
24#define STPMIC1_LDO3_1800000 (9U << STPMIC1_LDO12356_OUTPUT_SHIFT)
Yann Gautiere4f559f2018-07-16 17:55:07 +020025
Yann Gautier23684d02019-01-16 18:31:00 +010026#define STPMIC1_BUCK_OUTPUT_SHIFT 2
27#define STPMIC1_BUCK3_1V8 (39U << STPMIC1_BUCK_OUTPUT_SHIFT)
Yann Gautiere4f559f2018-07-16 17:55:07 +020028
Yann Gautier23684d02019-01-16 18:31:00 +010029#define STPMIC1_DEFAULT_START_UP_DELAY_MS 1
Yann Gautiere4f559f2018-07-16 17:55:07 +020030
31static struct i2c_handle_s i2c_handle;
32static uint32_t pmic_i2c_addr;
33
34static int dt_get_pmic_node(void *fdt)
35{
Yann Gautier23684d02019-01-16 18:31:00 +010036 return fdt_node_offset_by_compatible(fdt, -1, "st,stpmic1");
Yann Gautiere4f559f2018-07-16 17:55:07 +020037}
38
Yann Gautierd82d4ff2019-02-14 11:15:03 +010039int dt_pmic_status(void)
Yann Gautiere4f559f2018-07-16 17:55:07 +020040{
41 int node;
42 void *fdt;
43
44 if (fdt_get_address(&fdt) == 0) {
Yann Gautierd82d4ff2019-02-14 11:15:03 +010045 return -ENOENT;
Yann Gautiere4f559f2018-07-16 17:55:07 +020046 }
47
48 node = dt_get_pmic_node(fdt);
Yann Gautierd82d4ff2019-02-14 11:15:03 +010049 if (node <= 0) {
50 return -FDT_ERR_NOTFOUND;
Yann Gautiere4f559f2018-07-16 17:55:07 +020051 }
52
Yann Gautier1fc21302019-01-17 19:17:47 +010053 return fdt_get_status(node);
Yann Gautiere4f559f2018-07-16 17:55:07 +020054}
55
Etienne Carrieref564d432019-12-02 10:10:08 +010056static bool dt_pmic_is_secure(void)
57{
58 int status = dt_pmic_status();
59
60 return (status >= 0) &&
61 (status == DT_SECURE) &&
62 (i2c_handle.dt_status == DT_SECURE);
63}
64
Yann Gautierd82d4ff2019-02-14 11:15:03 +010065/*
66 * Get PMIC and its I2C bus configuration from the device tree.
67 * Return 0 on success, negative on error, 1 if no PMIC node is found.
68 */
69static int dt_pmic_i2c_config(struct dt_node_info *i2c_info,
70 struct stm32_i2c_init_s *init)
Yann Gautiere4f559f2018-07-16 17:55:07 +020071{
72 int pmic_node, i2c_node;
73 void *fdt;
74 const fdt32_t *cuint;
75
76 if (fdt_get_address(&fdt) == 0) {
77 return -ENOENT;
78 }
79
80 pmic_node = dt_get_pmic_node(fdt);
81 if (pmic_node < 0) {
Yann Gautierd82d4ff2019-02-14 11:15:03 +010082 return 1;
Yann Gautiere4f559f2018-07-16 17:55:07 +020083 }
84
85 cuint = fdt_getprop(fdt, pmic_node, "reg", NULL);
86 if (cuint == NULL) {
87 return -FDT_ERR_NOTFOUND;
88 }
89
90 pmic_i2c_addr = fdt32_to_cpu(*cuint) << 1;
91 if (pmic_i2c_addr > UINT16_MAX) {
92 return -EINVAL;
93 }
94
95 i2c_node = fdt_parent_offset(fdt, pmic_node);
96 if (i2c_node < 0) {
97 return -FDT_ERR_NOTFOUND;
98 }
99
100 dt_fill_device_info(i2c_info, i2c_node);
101 if (i2c_info->base == 0U) {
102 return -FDT_ERR_NOTFOUND;
103 }
104
Yann Gautierd82d4ff2019-02-14 11:15:03 +0100105 return stm32_i2c_get_setup_from_fdt(fdt, i2c_node, init);
Yann Gautiere4f559f2018-07-16 17:55:07 +0200106}
107
Yann Gautierd82d4ff2019-02-14 11:15:03 +0100108int dt_pmic_configure_boot_on_regulators(void)
Yann Gautiere4f559f2018-07-16 17:55:07 +0200109{
110 int pmic_node, regulators_node, regulator_node;
111 void *fdt;
112
113 if (fdt_get_address(&fdt) == 0) {
114 return -ENOENT;
115 }
116
117 pmic_node = dt_get_pmic_node(fdt);
118 if (pmic_node < 0) {
119 return -FDT_ERR_NOTFOUND;
120 }
121
122 regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators");
Nicolas Le Bayona4bcfe92020-03-10 18:18:45 +0100123 if (regulators_node < 0) {
124 return -ENOENT;
125 }
Yann Gautiere4f559f2018-07-16 17:55:07 +0200126
127 fdt_for_each_subnode(regulator_node, fdt, regulators_node) {
128 const fdt32_t *cuint;
Yann Gautierd82d4ff2019-02-14 11:15:03 +0100129 const char *node_name = fdt_get_name(fdt, regulator_node, NULL);
Yann Gautiere4f559f2018-07-16 17:55:07 +0200130 uint16_t voltage;
Yann Gautierd82d4ff2019-02-14 11:15:03 +0100131 int status;
Yann Gautiere4f559f2018-07-16 17:55:07 +0200132
Yann Gautierd82d4ff2019-02-14 11:15:03 +0100133#if defined(IMAGE_BL2)
134 if ((fdt_getprop(fdt, regulator_node, "regulator-boot-on",
135 NULL) == NULL) &&
136 (fdt_getprop(fdt, regulator_node, "regulator-always-on",
137 NULL) == NULL)) {
138#else
Yann Gautiere4f559f2018-07-16 17:55:07 +0200139 if (fdt_getprop(fdt, regulator_node, "regulator-boot-on",
140 NULL) == NULL) {
Yann Gautierd82d4ff2019-02-14 11:15:03 +0100141#endif
Yann Gautiere4f559f2018-07-16 17:55:07 +0200142 continue;
143 }
144
Yann Gautierd82d4ff2019-02-14 11:15:03 +0100145 if (fdt_getprop(fdt, regulator_node, "regulator-pull-down",
146 NULL) != NULL) {
147
148 status = stpmic1_regulator_pull_down_set(node_name);
149 if (status != 0) {
150 return status;
151 }
152 }
153
154 if (fdt_getprop(fdt, regulator_node, "st,mask-reset",
155 NULL) != NULL) {
156
157 status = stpmic1_regulator_mask_reset_set(node_name);
158 if (status != 0) {
159 return status;
160 }
161 }
162
Yann Gautiere4f559f2018-07-16 17:55:07 +0200163 cuint = fdt_getprop(fdt, regulator_node,
164 "regulator-min-microvolt", NULL);
165 if (cuint == NULL) {
166 continue;
167 }
168
169 /* DT uses microvolts, whereas driver awaits millivolts */
170 voltage = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U);
Yann Gautierd82d4ff2019-02-14 11:15:03 +0100171
172 status = stpmic1_regulator_voltage_set(node_name, voltage);
173 if (status != 0) {
174 return status;
175 }
Yann Gautiere4f559f2018-07-16 17:55:07 +0200176
Nicolas Le Bayon16e56a72019-09-19 11:24:50 +0200177 if (!stpmic1_is_regulator_enabled(node_name)) {
Yann Gautier23684d02019-01-16 18:31:00 +0100178 status = stpmic1_regulator_enable(node_name);
Yann Gautiere4f559f2018-07-16 17:55:07 +0200179 if (status != 0) {
180 return status;
181 }
182 }
183 }
184
185 return 0;
186}
187
Yann Gautierd82d4ff2019-02-14 11:15:03 +0100188bool initialize_pmic_i2c(void)
Yann Gautiere4f559f2018-07-16 17:55:07 +0200189{
190 int ret;
191 struct dt_node_info i2c_info;
Yann Gautierd82d4ff2019-02-14 11:15:03 +0100192 struct i2c_handle_s *i2c = &i2c_handle;
193 struct stm32_i2c_init_s i2c_init;
Yann Gautiere4f559f2018-07-16 17:55:07 +0200194
Yann Gautierd82d4ff2019-02-14 11:15:03 +0100195 ret = dt_pmic_i2c_config(&i2c_info, &i2c_init);
196 if (ret < 0) {
197 ERROR("I2C configuration failed %d\n", ret);
Yann Gautiere4f559f2018-07-16 17:55:07 +0200198 panic();
199 }
200
Yann Gautierd82d4ff2019-02-14 11:15:03 +0100201 if (ret != 0) {
202 return false;
Yann Gautiere4f559f2018-07-16 17:55:07 +0200203 }
204
205 /* Initialize PMIC I2C */
Yann Gautierd82d4ff2019-02-14 11:15:03 +0100206 i2c->i2c_base_addr = i2c_info.base;
207 i2c->dt_status = i2c_info.status;
208 i2c->clock = i2c_info.clock;
Benjamin Gaignard42822842020-02-24 13:57:40 +0100209 i2c->i2c_state = I2C_STATE_RESET;
Yann Gautierd82d4ff2019-02-14 11:15:03 +0100210 i2c_init.own_address1 = pmic_i2c_addr;
211 i2c_init.addressing_mode = I2C_ADDRESSINGMODE_7BIT;
212 i2c_init.dual_address_mode = I2C_DUALADDRESS_DISABLE;
213 i2c_init.own_address2 = 0;
214 i2c_init.own_address2_masks = I2C_OAR2_OA2NOMASK;
215 i2c_init.general_call_mode = I2C_GENERALCALL_DISABLE;
216 i2c_init.no_stretch_mode = I2C_NOSTRETCH_DISABLE;
217 i2c_init.analog_filter = 1;
218 i2c_init.digital_filter_coef = 0;
Yann Gautiere4f559f2018-07-16 17:55:07 +0200219
Yann Gautierd82d4ff2019-02-14 11:15:03 +0100220 ret = stm32_i2c_init(i2c, &i2c_init);
Yann Gautiere4f559f2018-07-16 17:55:07 +0200221 if (ret != 0) {
222 ERROR("Cannot initialize I2C %x (%d)\n",
Yann Gautierd82d4ff2019-02-14 11:15:03 +0100223 i2c->i2c_base_addr, ret);
Yann Gautiere4f559f2018-07-16 17:55:07 +0200224 panic();
225 }
226
Yann Gautierd82d4ff2019-02-14 11:15:03 +0100227 if (!stm32_i2c_is_device_ready(i2c, pmic_i2c_addr, 1,
228 I2C_TIMEOUT_BUSY_MS)) {
229 ERROR("I2C device not ready\n");
Yann Gautiere4f559f2018-07-16 17:55:07 +0200230 panic();
231 }
232
Yann Gautierd82d4ff2019-02-14 11:15:03 +0100233 stpmic1_bind_i2c(i2c, (uint16_t)pmic_i2c_addr);
Yann Gautiere4f559f2018-07-16 17:55:07 +0200234
Yann Gautierd82d4ff2019-02-14 11:15:03 +0100235 return true;
Yann Gautiere4f559f2018-07-16 17:55:07 +0200236}
237
Etienne Carrieref564d432019-12-02 10:10:08 +0100238static void register_pmic_shared_peripherals(void)
239{
240 uintptr_t i2c_base = i2c_handle.i2c_base_addr;
241
242 if (dt_pmic_is_secure()) {
243 stm32mp_register_secure_periph_iomem(i2c_base);
244 } else {
245 if (i2c_base != 0U) {
246 stm32mp_register_non_secure_periph_iomem(i2c_base);
247 }
248 }
249}
250
Yann Gautiere4f559f2018-07-16 17:55:07 +0200251void initialize_pmic(void)
252{
Yann Gautierd82d4ff2019-02-14 11:15:03 +0100253 unsigned long pmic_version;
Yann Gautiere4f559f2018-07-16 17:55:07 +0200254
Yann Gautierd82d4ff2019-02-14 11:15:03 +0100255 if (!initialize_pmic_i2c()) {
256 VERBOSE("No PMIC\n");
257 return;
258 }
Yann Gautiere4f559f2018-07-16 17:55:07 +0200259
Etienne Carrieref564d432019-12-02 10:10:08 +0100260 register_pmic_shared_peripherals();
261
Yann Gautierd82d4ff2019-02-14 11:15:03 +0100262 if (stpmic1_get_version(&pmic_version) != 0) {
263 ERROR("Failed to access PMIC\n");
Yann Gautiere4f559f2018-07-16 17:55:07 +0200264 panic();
265 }
266
Yann Gautierd82d4ff2019-02-14 11:15:03 +0100267 INFO("PMIC version = 0x%02lx\n", pmic_version);
268 stpmic1_dump_regulators();
Yann Gautiere4f559f2018-07-16 17:55:07 +0200269
Yann Gautierd82d4ff2019-02-14 11:15:03 +0100270#if defined(IMAGE_BL2)
271 if (dt_pmic_configure_boot_on_regulators() != 0) {
Yann Gautiere4f559f2018-07-16 17:55:07 +0200272 panic();
Yann Gautierd82d4ff2019-02-14 11:15:03 +0100273 };
274#endif
Yann Gautiere4f559f2018-07-16 17:55:07 +0200275}
276
277int pmic_ddr_power_init(enum ddr_type ddr_type)
278{
279 bool buck3_at_1v8 = false;
280 uint8_t read_val;
281 int status;
282
283 switch (ddr_type) {
284 case STM32MP_DDR3:
285 /* Set LDO3 to sync mode */
Yann Gautier23684d02019-01-16 18:31:00 +0100286 status = stpmic1_register_read(LDO3_CONTROL_REG, &read_val);
Yann Gautiere4f559f2018-07-16 17:55:07 +0200287 if (status != 0) {
288 return status;
289 }
290
Yann Gautier23684d02019-01-16 18:31:00 +0100291 read_val &= ~STPMIC1_LDO3_MODE;
292 read_val &= ~STPMIC1_LDO12356_OUTPUT_MASK;
293 read_val |= STPMIC1_LDO3_DDR_SEL <<
294 STPMIC1_LDO12356_OUTPUT_SHIFT;
Yann Gautiere4f559f2018-07-16 17:55:07 +0200295
Yann Gautier23684d02019-01-16 18:31:00 +0100296 status = stpmic1_register_write(LDO3_CONTROL_REG, read_val);
Yann Gautiere4f559f2018-07-16 17:55:07 +0200297 if (status != 0) {
298 return status;
299 }
300
Yann Gautier23684d02019-01-16 18:31:00 +0100301 status = stpmic1_regulator_voltage_set("buck2", 1350);
Yann Gautiere4f559f2018-07-16 17:55:07 +0200302 if (status != 0) {
303 return status;
304 }
305
Yann Gautier23684d02019-01-16 18:31:00 +0100306 status = stpmic1_regulator_enable("buck2");
Yann Gautiere4f559f2018-07-16 17:55:07 +0200307 if (status != 0) {
308 return status;
309 }
310
Yann Gautier23684d02019-01-16 18:31:00 +0100311 mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
Yann Gautiere4f559f2018-07-16 17:55:07 +0200312
Yann Gautier23684d02019-01-16 18:31:00 +0100313 status = stpmic1_regulator_enable("vref_ddr");
Yann Gautiere4f559f2018-07-16 17:55:07 +0200314 if (status != 0) {
315 return status;
316 }
317
Yann Gautier23684d02019-01-16 18:31:00 +0100318 mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
Yann Gautiere4f559f2018-07-16 17:55:07 +0200319
Yann Gautier23684d02019-01-16 18:31:00 +0100320 status = stpmic1_regulator_enable("ldo3");
Yann Gautiere4f559f2018-07-16 17:55:07 +0200321 if (status != 0) {
322 return status;
323 }
324
Yann Gautier23684d02019-01-16 18:31:00 +0100325 mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
Yann Gautiere4f559f2018-07-16 17:55:07 +0200326 break;
327
328 case STM32MP_LPDDR2:
Yann Gautier4b549b22019-04-16 16:20:58 +0200329 case STM32MP_LPDDR3:
Yann Gautiere4f559f2018-07-16 17:55:07 +0200330 /*
331 * Set LDO3 to 1.8V
332 * Set LDO3 to bypass mode if BUCK3 = 1.8V
333 * Set LDO3 to normal mode if BUCK3 != 1.8V
334 */
Yann Gautier23684d02019-01-16 18:31:00 +0100335 status = stpmic1_register_read(BUCK3_CONTROL_REG, &read_val);
Yann Gautiere4f559f2018-07-16 17:55:07 +0200336 if (status != 0) {
337 return status;
338 }
339
Yann Gautier23684d02019-01-16 18:31:00 +0100340 if ((read_val & STPMIC1_BUCK3_1V8) == STPMIC1_BUCK3_1V8) {
Yann Gautiere4f559f2018-07-16 17:55:07 +0200341 buck3_at_1v8 = true;
342 }
343
Yann Gautier23684d02019-01-16 18:31:00 +0100344 status = stpmic1_register_read(LDO3_CONTROL_REG, &read_val);
Yann Gautiere4f559f2018-07-16 17:55:07 +0200345 if (status != 0) {
346 return status;
347 }
348
Yann Gautier23684d02019-01-16 18:31:00 +0100349 read_val &= ~STPMIC1_LDO3_MODE;
350 read_val &= ~STPMIC1_LDO12356_OUTPUT_MASK;
351 read_val |= STPMIC1_LDO3_1800000;
Yann Gautiere4f559f2018-07-16 17:55:07 +0200352 if (buck3_at_1v8) {
Yann Gautier23684d02019-01-16 18:31:00 +0100353 read_val |= STPMIC1_LDO3_MODE;
Yann Gautiere4f559f2018-07-16 17:55:07 +0200354 }
355
Yann Gautier23684d02019-01-16 18:31:00 +0100356 status = stpmic1_register_write(LDO3_CONTROL_REG, read_val);
Yann Gautiere4f559f2018-07-16 17:55:07 +0200357 if (status != 0) {
358 return status;
359 }
360
Yann Gautier23684d02019-01-16 18:31:00 +0100361 status = stpmic1_regulator_voltage_set("buck2", 1200);
Yann Gautiere4f559f2018-07-16 17:55:07 +0200362 if (status != 0) {
363 return status;
364 }
365
Yann Gautier23684d02019-01-16 18:31:00 +0100366 status = stpmic1_regulator_enable("ldo3");
Yann Gautiere4f559f2018-07-16 17:55:07 +0200367 if (status != 0) {
368 return status;
369 }
370
Yann Gautier23684d02019-01-16 18:31:00 +0100371 mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
Yann Gautiere4f559f2018-07-16 17:55:07 +0200372
Yann Gautier23684d02019-01-16 18:31:00 +0100373 status = stpmic1_regulator_enable("buck2");
Yann Gautiere4f559f2018-07-16 17:55:07 +0200374 if (status != 0) {
375 return status;
376 }
377
Yann Gautier23684d02019-01-16 18:31:00 +0100378 mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
Yann Gautiere4f559f2018-07-16 17:55:07 +0200379
Yann Gautier23684d02019-01-16 18:31:00 +0100380 status = stpmic1_regulator_enable("vref_ddr");
Yann Gautiere4f559f2018-07-16 17:55:07 +0200381 if (status != 0) {
382 return status;
383 }
384
Yann Gautier23684d02019-01-16 18:31:00 +0100385 mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
Yann Gautiere4f559f2018-07-16 17:55:07 +0200386 break;
387
388 default:
389 break;
390 };
391
392 return 0;
393}