123684d0eSYann Gautier /* 247065ffeSYann Gautier * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved 323684d0eSYann Gautier * 423684d0eSYann Gautier * SPDX-License-Identifier: BSD-3-Clause 523684d0eSYann Gautier */ 623684d0eSYann Gautier 785fb175bSYann Gautier #include <assert.h> 823684d0eSYann Gautier #include <errno.h> 923684d0eSYann Gautier 1023684d0eSYann Gautier #include <common/debug.h> 1123684d0eSYann Gautier #include <drivers/delay_timer.h> 1285fb175bSYann Gautier #include <drivers/st/regulator.h> 13d82d4ff0SYann Gautier #include <drivers/st/stm32_i2c.h> 1423684d0eSYann Gautier #include <drivers/st/stm32mp_pmic.h> 1523684d0eSYann Gautier #include <drivers/st/stpmic1.h> 1623684d0eSYann Gautier #include <lib/mmio.h> 1723684d0eSYann Gautier #include <lib/utils_def.h> 1816e56a75SNicolas Le Bayon #include <libfdt.h> 1916e56a75SNicolas Le Bayon 2016e56a75SNicolas Le Bayon #include <platform_def.h> 2123684d0eSYann Gautier 22c77c7d9eSNicolas Le Bayon #define PMIC_NODE_NOT_FOUND 1 23*3cebeec2SYann Gautier #define NB_REG 14U 2423684d0eSYann Gautier 2523684d0eSYann Gautier static struct i2c_handle_s i2c_handle; 2623684d0eSYann Gautier static uint32_t pmic_i2c_addr; 2723684d0eSYann Gautier 2885fb175bSYann Gautier static int register_pmic(void); 2985fb175bSYann Gautier 3023684d0eSYann Gautier static int dt_get_pmic_node(void *fdt) 3123684d0eSYann Gautier { 32c77c7d9eSNicolas Le Bayon static int node = -FDT_ERR_BADOFFSET; 33c77c7d9eSNicolas Le Bayon 34c77c7d9eSNicolas Le Bayon if (node == -FDT_ERR_BADOFFSET) { 35c77c7d9eSNicolas Le Bayon node = fdt_node_offset_by_compatible(fdt, -1, "st,stpmic1"); 36c77c7d9eSNicolas Le Bayon } 37c77c7d9eSNicolas Le Bayon 38c77c7d9eSNicolas Le Bayon return node; 3923684d0eSYann Gautier } 4023684d0eSYann Gautier 41d82d4ff0SYann Gautier int dt_pmic_status(void) 4223684d0eSYann Gautier { 43c77c7d9eSNicolas Le Bayon static int status = -FDT_ERR_BADVALUE; 4423684d0eSYann Gautier int node; 4523684d0eSYann Gautier void *fdt; 4623684d0eSYann Gautier 47c77c7d9eSNicolas Le Bayon if (status != -FDT_ERR_BADVALUE) { 48c77c7d9eSNicolas Le Bayon return status; 49c77c7d9eSNicolas Le Bayon } 50c77c7d9eSNicolas Le Bayon 5123684d0eSYann Gautier if (fdt_get_address(&fdt) == 0) { 52d82d4ff0SYann Gautier return -ENOENT; 5323684d0eSYann Gautier } 5423684d0eSYann Gautier 5523684d0eSYann Gautier node = dt_get_pmic_node(fdt); 56d82d4ff0SYann Gautier if (node <= 0) { 57c77c7d9eSNicolas Le Bayon status = -FDT_ERR_NOTFOUND; 58c77c7d9eSNicolas Le Bayon 59c77c7d9eSNicolas Le Bayon return status; 6023684d0eSYann Gautier } 6123684d0eSYann Gautier 62c77c7d9eSNicolas Le Bayon status = (int)fdt_get_status(node); 63c77c7d9eSNicolas Le Bayon 64c77c7d9eSNicolas Le Bayon return status; 6523684d0eSYann Gautier } 6623684d0eSYann Gautier 67f564d439SEtienne Carriere static bool dt_pmic_is_secure(void) 68f564d439SEtienne Carriere { 69f564d439SEtienne Carriere int status = dt_pmic_status(); 70f564d439SEtienne Carriere 71f564d439SEtienne Carriere return (status >= 0) && 72f564d439SEtienne Carriere (status == DT_SECURE) && 73f564d439SEtienne Carriere (i2c_handle.dt_status == DT_SECURE); 74f564d439SEtienne Carriere } 75f564d439SEtienne Carriere 76d82d4ff0SYann Gautier /* 77d82d4ff0SYann Gautier * Get PMIC and its I2C bus configuration from the device tree. 78c77c7d9eSNicolas Le Bayon * Return 0 on success, negative on error, 1 if no PMIC node is defined. 79d82d4ff0SYann Gautier */ 80d82d4ff0SYann Gautier static int dt_pmic_i2c_config(struct dt_node_info *i2c_info, 81d82d4ff0SYann Gautier struct stm32_i2c_init_s *init) 8223684d0eSYann Gautier { 83c77c7d9eSNicolas Le Bayon static int i2c_node = -FDT_ERR_NOTFOUND; 8423684d0eSYann Gautier void *fdt; 8523684d0eSYann Gautier 8623684d0eSYann Gautier if (fdt_get_address(&fdt) == 0) { 87c77c7d9eSNicolas Le Bayon return -FDT_ERR_NOTFOUND; 8823684d0eSYann Gautier } 8923684d0eSYann Gautier 90c77c7d9eSNicolas Le Bayon if (i2c_node == -FDT_ERR_NOTFOUND) { 91c77c7d9eSNicolas Le Bayon int pmic_node; 92c77c7d9eSNicolas Le Bayon const fdt32_t *cuint; 93c77c7d9eSNicolas Le Bayon 9423684d0eSYann Gautier pmic_node = dt_get_pmic_node(fdt); 9523684d0eSYann Gautier if (pmic_node < 0) { 96c77c7d9eSNicolas Le Bayon return PMIC_NODE_NOT_FOUND; 9723684d0eSYann Gautier } 9823684d0eSYann Gautier 9923684d0eSYann Gautier cuint = fdt_getprop(fdt, pmic_node, "reg", NULL); 10023684d0eSYann Gautier if (cuint == NULL) { 10123684d0eSYann Gautier return -FDT_ERR_NOTFOUND; 10223684d0eSYann Gautier } 10323684d0eSYann Gautier 10423684d0eSYann Gautier pmic_i2c_addr = fdt32_to_cpu(*cuint) << 1; 10523684d0eSYann Gautier if (pmic_i2c_addr > UINT16_MAX) { 106c77c7d9eSNicolas Le Bayon return -FDT_ERR_BADVALUE; 10723684d0eSYann Gautier } 10823684d0eSYann Gautier 10923684d0eSYann Gautier i2c_node = fdt_parent_offset(fdt, pmic_node); 11023684d0eSYann Gautier if (i2c_node < 0) { 11123684d0eSYann Gautier return -FDT_ERR_NOTFOUND; 11223684d0eSYann Gautier } 113c77c7d9eSNicolas Le Bayon } 11423684d0eSYann Gautier 11523684d0eSYann Gautier dt_fill_device_info(i2c_info, i2c_node); 11623684d0eSYann Gautier if (i2c_info->base == 0U) { 11723684d0eSYann Gautier return -FDT_ERR_NOTFOUND; 11823684d0eSYann Gautier } 11923684d0eSYann Gautier 120d82d4ff0SYann Gautier return stm32_i2c_get_setup_from_fdt(fdt, i2c_node, init); 12123684d0eSYann Gautier } 12223684d0eSYann Gautier 123d82d4ff0SYann Gautier bool initialize_pmic_i2c(void) 12423684d0eSYann Gautier { 12523684d0eSYann Gautier int ret; 12623684d0eSYann Gautier struct dt_node_info i2c_info; 127d82d4ff0SYann Gautier struct i2c_handle_s *i2c = &i2c_handle; 128d82d4ff0SYann Gautier struct stm32_i2c_init_s i2c_init; 12923684d0eSYann Gautier 130d82d4ff0SYann Gautier ret = dt_pmic_i2c_config(&i2c_info, &i2c_init); 131d82d4ff0SYann Gautier if (ret < 0) { 132d82d4ff0SYann Gautier ERROR("I2C configuration failed %d\n", ret); 13323684d0eSYann Gautier panic(); 13423684d0eSYann Gautier } 13523684d0eSYann Gautier 136d82d4ff0SYann Gautier if (ret != 0) { 137d82d4ff0SYann Gautier return false; 13823684d0eSYann Gautier } 13923684d0eSYann Gautier 14023684d0eSYann Gautier /* Initialize PMIC I2C */ 141d82d4ff0SYann Gautier i2c->i2c_base_addr = i2c_info.base; 142d82d4ff0SYann Gautier i2c->dt_status = i2c_info.status; 143d82d4ff0SYann Gautier i2c->clock = i2c_info.clock; 14442822844SBenjamin Gaignard i2c->i2c_state = I2C_STATE_RESET; 145d82d4ff0SYann Gautier i2c_init.own_address1 = pmic_i2c_addr; 146d82d4ff0SYann Gautier i2c_init.addressing_mode = I2C_ADDRESSINGMODE_7BIT; 147d82d4ff0SYann Gautier i2c_init.dual_address_mode = I2C_DUALADDRESS_DISABLE; 148d82d4ff0SYann Gautier i2c_init.own_address2 = 0; 149d82d4ff0SYann Gautier i2c_init.own_address2_masks = I2C_OAR2_OA2NOMASK; 150d82d4ff0SYann Gautier i2c_init.general_call_mode = I2C_GENERALCALL_DISABLE; 151d82d4ff0SYann Gautier i2c_init.no_stretch_mode = I2C_NOSTRETCH_DISABLE; 152d82d4ff0SYann Gautier i2c_init.analog_filter = 1; 153d82d4ff0SYann Gautier i2c_init.digital_filter_coef = 0; 15423684d0eSYann Gautier 155d82d4ff0SYann Gautier ret = stm32_i2c_init(i2c, &i2c_init); 15623684d0eSYann Gautier if (ret != 0) { 15723684d0eSYann Gautier ERROR("Cannot initialize I2C %x (%d)\n", 158d82d4ff0SYann Gautier i2c->i2c_base_addr, ret); 15923684d0eSYann Gautier panic(); 16023684d0eSYann Gautier } 16123684d0eSYann Gautier 162d82d4ff0SYann Gautier if (!stm32_i2c_is_device_ready(i2c, pmic_i2c_addr, 1, 163d82d4ff0SYann Gautier I2C_TIMEOUT_BUSY_MS)) { 164d82d4ff0SYann Gautier ERROR("I2C device not ready\n"); 16523684d0eSYann Gautier panic(); 16623684d0eSYann Gautier } 16723684d0eSYann Gautier 168d82d4ff0SYann Gautier stpmic1_bind_i2c(i2c, (uint16_t)pmic_i2c_addr); 16923684d0eSYann Gautier 170d82d4ff0SYann Gautier return true; 17123684d0eSYann Gautier } 17223684d0eSYann Gautier 173f564d439SEtienne Carriere static void register_pmic_shared_peripherals(void) 174f564d439SEtienne Carriere { 175f564d439SEtienne Carriere uintptr_t i2c_base = i2c_handle.i2c_base_addr; 176f564d439SEtienne Carriere 177f564d439SEtienne Carriere if (dt_pmic_is_secure()) { 178f564d439SEtienne Carriere stm32mp_register_secure_periph_iomem(i2c_base); 179f564d439SEtienne Carriere } else { 180f564d439SEtienne Carriere if (i2c_base != 0U) { 181f564d439SEtienne Carriere stm32mp_register_non_secure_periph_iomem(i2c_base); 182f564d439SEtienne Carriere } 183f564d439SEtienne Carriere } 184f564d439SEtienne Carriere } 185f564d439SEtienne Carriere 18623684d0eSYann Gautier void initialize_pmic(void) 18723684d0eSYann Gautier { 188d82d4ff0SYann Gautier if (!initialize_pmic_i2c()) { 189d82d4ff0SYann Gautier VERBOSE("No PMIC\n"); 190d82d4ff0SYann Gautier return; 191d82d4ff0SYann Gautier } 19223684d0eSYann Gautier 193f564d439SEtienne Carriere register_pmic_shared_peripherals(); 194f564d439SEtienne Carriere 19585fb175bSYann Gautier if (register_pmic() < 0) { 196ae7792e0SNicolas Le Bayon panic(); 19785fb175bSYann Gautier } 19885fb175bSYann Gautier 19985fb175bSYann Gautier if (stpmic1_powerctrl_on() < 0) { 20085fb175bSYann Gautier panic(); 20185fb175bSYann Gautier } 20285fb175bSYann Gautier 203ae7792e0SNicolas Le Bayon } 204ae7792e0SNicolas Le Bayon 205ae7792e0SNicolas Le Bayon #if DEBUG 206ae7792e0SNicolas Le Bayon void print_pmic_info_and_debug(void) 207ae7792e0SNicolas Le Bayon { 208ae7792e0SNicolas Le Bayon unsigned long pmic_version; 209ae7792e0SNicolas Le Bayon 210d82d4ff0SYann Gautier if (stpmic1_get_version(&pmic_version) != 0) { 211d82d4ff0SYann Gautier ERROR("Failed to access PMIC\n"); 21223684d0eSYann Gautier panic(); 21323684d0eSYann Gautier } 21423684d0eSYann Gautier 215d82d4ff0SYann Gautier INFO("PMIC version = 0x%02lx\n", pmic_version); 21623684d0eSYann Gautier } 217ae7792e0SNicolas Le Bayon #endif 21823684d0eSYann Gautier 21923684d0eSYann Gautier int pmic_ddr_power_init(enum ddr_type ddr_type) 22023684d0eSYann Gautier { 22123684d0eSYann Gautier int status; 2220ba71ac9SPascal Paillet uint16_t buck3_min_mv; 223111a384cSYann Gautier struct rdev *buck2, *buck3, *vref; 224111a384cSYann Gautier struct rdev *ldo3 __unused; 2250ba71ac9SPascal Paillet 2260ba71ac9SPascal Paillet buck2 = regulator_get_by_name("buck2"); 2270ba71ac9SPascal Paillet if (buck2 == NULL) { 2280ba71ac9SPascal Paillet return -ENOENT; 2290ba71ac9SPascal Paillet } 2300ba71ac9SPascal Paillet 231111a384cSYann Gautier #if STM32MP15 2320ba71ac9SPascal Paillet ldo3 = regulator_get_by_name("ldo3"); 2330ba71ac9SPascal Paillet if (ldo3 == NULL) { 2340ba71ac9SPascal Paillet return -ENOENT; 2350ba71ac9SPascal Paillet } 236111a384cSYann Gautier #endif 2370ba71ac9SPascal Paillet 2380ba71ac9SPascal Paillet vref = regulator_get_by_name("vref_ddr"); 2390ba71ac9SPascal Paillet if (vref == NULL) { 2400ba71ac9SPascal Paillet return -ENOENT; 2410ba71ac9SPascal Paillet } 24223684d0eSYann Gautier 24323684d0eSYann Gautier switch (ddr_type) { 24423684d0eSYann Gautier case STM32MP_DDR3: 245111a384cSYann Gautier #if STM32MP15 2460ba71ac9SPascal Paillet status = regulator_set_flag(ldo3, REGUL_SINK_SOURCE); 24723684d0eSYann Gautier if (status != 0) { 24823684d0eSYann Gautier return status; 24923684d0eSYann Gautier } 250111a384cSYann Gautier #endif 25123684d0eSYann Gautier 2520ba71ac9SPascal Paillet status = regulator_set_min_voltage(buck2); 25323684d0eSYann Gautier if (status != 0) { 25423684d0eSYann Gautier return status; 25523684d0eSYann Gautier } 25623684d0eSYann Gautier 2570ba71ac9SPascal Paillet status = regulator_enable(buck2); 25823684d0eSYann Gautier if (status != 0) { 25923684d0eSYann Gautier return status; 26023684d0eSYann Gautier } 26123684d0eSYann Gautier 2620ba71ac9SPascal Paillet status = regulator_enable(vref); 26323684d0eSYann Gautier if (status != 0) { 26423684d0eSYann Gautier return status; 26523684d0eSYann Gautier } 26623684d0eSYann Gautier 267111a384cSYann Gautier #if STM32MP15 2680ba71ac9SPascal Paillet status = regulator_enable(ldo3); 26923684d0eSYann Gautier if (status != 0) { 27023684d0eSYann Gautier return status; 27123684d0eSYann Gautier } 272111a384cSYann Gautier #endif 27323684d0eSYann Gautier break; 27423684d0eSYann Gautier 27523684d0eSYann Gautier case STM32MP_LPDDR2: 2764b549b21SYann Gautier case STM32MP_LPDDR3: 27723684d0eSYann Gautier /* 27823684d0eSYann Gautier * Set LDO3 to 1.8V 27923684d0eSYann Gautier * Set LDO3 to bypass mode if BUCK3 = 1.8V 28023684d0eSYann Gautier * Set LDO3 to normal mode if BUCK3 != 1.8V 28123684d0eSYann Gautier */ 2820ba71ac9SPascal Paillet buck3 = regulator_get_by_name("buck3"); 2830ba71ac9SPascal Paillet if (buck3 == NULL) { 2840ba71ac9SPascal Paillet return -ENOENT; 2850ba71ac9SPascal Paillet } 2860ba71ac9SPascal Paillet 2870ba71ac9SPascal Paillet regulator_get_range(buck3, &buck3_min_mv, NULL); 2880ba71ac9SPascal Paillet 289111a384cSYann Gautier #if STM32MP15 2900ba71ac9SPascal Paillet if (buck3_min_mv != 1800) { 2910ba71ac9SPascal Paillet status = regulator_set_min_voltage(ldo3); 2920ba71ac9SPascal Paillet if (status != 0) { 2930ba71ac9SPascal Paillet return status; 2940ba71ac9SPascal Paillet } 2950ba71ac9SPascal Paillet } else { 2960ba71ac9SPascal Paillet status = regulator_set_flag(ldo3, REGUL_ENABLE_BYPASS); 2970ba71ac9SPascal Paillet if (status != 0) { 2980ba71ac9SPascal Paillet return status; 2990ba71ac9SPascal Paillet } 3000ba71ac9SPascal Paillet } 301111a384cSYann Gautier #endif 3020ba71ac9SPascal Paillet 3030ba71ac9SPascal Paillet status = regulator_set_min_voltage(buck2); 30423684d0eSYann Gautier if (status != 0) { 30523684d0eSYann Gautier return status; 30623684d0eSYann Gautier } 30723684d0eSYann Gautier 308111a384cSYann Gautier #if STM32MP15 3090ba71ac9SPascal Paillet status = regulator_enable(ldo3); 31023684d0eSYann Gautier if (status != 0) { 31123684d0eSYann Gautier return status; 31223684d0eSYann Gautier } 313111a384cSYann Gautier #endif 31423684d0eSYann Gautier 3150ba71ac9SPascal Paillet status = regulator_enable(buck2); 31623684d0eSYann Gautier if (status != 0) { 31723684d0eSYann Gautier return status; 31823684d0eSYann Gautier } 31923684d0eSYann Gautier 3200ba71ac9SPascal Paillet status = regulator_enable(vref); 32123684d0eSYann Gautier if (status != 0) { 32223684d0eSYann Gautier return status; 32323684d0eSYann Gautier } 32423684d0eSYann Gautier break; 32523684d0eSYann Gautier 32623684d0eSYann Gautier default: 32723684d0eSYann Gautier break; 32823684d0eSYann Gautier }; 32923684d0eSYann Gautier 33023684d0eSYann Gautier return 0; 33123684d0eSYann Gautier } 33285fb175bSYann Gautier 3335278ec3fSYann Gautier int pmic_voltages_init(void) 3345278ec3fSYann Gautier { 3355278ec3fSYann Gautier #if STM32MP13 3365278ec3fSYann Gautier struct rdev *buck1, *buck4; 3375278ec3fSYann Gautier int status; 3385278ec3fSYann Gautier 3395278ec3fSYann Gautier buck1 = regulator_get_by_name("buck1"); 3405278ec3fSYann Gautier if (buck1 == NULL) { 3415278ec3fSYann Gautier return -ENOENT; 3425278ec3fSYann Gautier } 3435278ec3fSYann Gautier 3445278ec3fSYann Gautier buck4 = regulator_get_by_name("buck4"); 3455278ec3fSYann Gautier if (buck4 == NULL) { 3465278ec3fSYann Gautier return -ENOENT; 3475278ec3fSYann Gautier } 3485278ec3fSYann Gautier 3495278ec3fSYann Gautier status = regulator_set_min_voltage(buck1); 3505278ec3fSYann Gautier if (status != 0) { 3515278ec3fSYann Gautier return status; 3525278ec3fSYann Gautier } 3535278ec3fSYann Gautier 3545278ec3fSYann Gautier status = regulator_set_min_voltage(buck4); 3555278ec3fSYann Gautier if (status != 0) { 3565278ec3fSYann Gautier return status; 3575278ec3fSYann Gautier } 3585278ec3fSYann Gautier #endif 3595278ec3fSYann Gautier 3605278ec3fSYann Gautier return 0; 3615278ec3fSYann Gautier } 3625278ec3fSYann Gautier 36385fb175bSYann Gautier enum { 36485fb175bSYann Gautier STPMIC1_BUCK1 = 0, 36585fb175bSYann Gautier STPMIC1_BUCK2, 36685fb175bSYann Gautier STPMIC1_BUCK3, 36785fb175bSYann Gautier STPMIC1_BUCK4, 36885fb175bSYann Gautier STPMIC1_LDO1, 36985fb175bSYann Gautier STPMIC1_LDO2, 37085fb175bSYann Gautier STPMIC1_LDO3, 37185fb175bSYann Gautier STPMIC1_LDO4, 37285fb175bSYann Gautier STPMIC1_LDO5, 37385fb175bSYann Gautier STPMIC1_LDO6, 37485fb175bSYann Gautier STPMIC1_VREF_DDR, 37585fb175bSYann Gautier STPMIC1_BOOST, 37685fb175bSYann Gautier STPMIC1_VBUS_OTG, 37785fb175bSYann Gautier STPMIC1_SW_OUT, 37885fb175bSYann Gautier }; 37985fb175bSYann Gautier 38085fb175bSYann Gautier static int pmic_set_state(const struct regul_description *desc, bool enable) 38185fb175bSYann Gautier { 38247065ffeSYann Gautier VERBOSE("%s: set state to %d\n", desc->node_name, enable); 38385fb175bSYann Gautier 38485fb175bSYann Gautier if (enable == STATE_ENABLE) { 38585fb175bSYann Gautier return stpmic1_regulator_enable(desc->node_name); 38685fb175bSYann Gautier } else { 38785fb175bSYann Gautier return stpmic1_regulator_disable(desc->node_name); 38885fb175bSYann Gautier } 38985fb175bSYann Gautier } 39085fb175bSYann Gautier 39185fb175bSYann Gautier static int pmic_get_state(const struct regul_description *desc) 39285fb175bSYann Gautier { 39385fb175bSYann Gautier VERBOSE("%s: get state\n", desc->node_name); 39485fb175bSYann Gautier 39585fb175bSYann Gautier return stpmic1_is_regulator_enabled(desc->node_name); 39685fb175bSYann Gautier } 39785fb175bSYann Gautier 39885fb175bSYann Gautier static int pmic_get_voltage(const struct regul_description *desc) 39985fb175bSYann Gautier { 40085fb175bSYann Gautier VERBOSE("%s: get volt\n", desc->node_name); 40185fb175bSYann Gautier 40285fb175bSYann Gautier return stpmic1_regulator_voltage_get(desc->node_name); 40385fb175bSYann Gautier } 40485fb175bSYann Gautier 40585fb175bSYann Gautier static int pmic_set_voltage(const struct regul_description *desc, uint16_t mv) 40685fb175bSYann Gautier { 40785fb175bSYann Gautier VERBOSE("%s: get volt\n", desc->node_name); 40885fb175bSYann Gautier 40985fb175bSYann Gautier return stpmic1_regulator_voltage_set(desc->node_name, mv); 41085fb175bSYann Gautier } 41185fb175bSYann Gautier 41285fb175bSYann Gautier static int pmic_list_voltages(const struct regul_description *desc, 41385fb175bSYann Gautier const uint16_t **levels, size_t *count) 41485fb175bSYann Gautier { 41585fb175bSYann Gautier VERBOSE("%s: list volt\n", desc->node_name); 41685fb175bSYann Gautier 41785fb175bSYann Gautier return stpmic1_regulator_levels_mv(desc->node_name, levels, count); 41885fb175bSYann Gautier } 41985fb175bSYann Gautier 42085fb175bSYann Gautier static int pmic_set_flag(const struct regul_description *desc, uint16_t flag) 42185fb175bSYann Gautier { 42285fb175bSYann Gautier VERBOSE("%s: set_flag 0x%x\n", desc->node_name, flag); 42385fb175bSYann Gautier 42485fb175bSYann Gautier switch (flag) { 42585fb175bSYann Gautier case REGUL_OCP: 42685fb175bSYann Gautier return stpmic1_regulator_icc_set(desc->node_name); 42785fb175bSYann Gautier 42885fb175bSYann Gautier case REGUL_ACTIVE_DISCHARGE: 42985fb175bSYann Gautier return stpmic1_active_discharge_mode_set(desc->node_name); 43085fb175bSYann Gautier 43185fb175bSYann Gautier case REGUL_PULL_DOWN: 43285fb175bSYann Gautier return stpmic1_regulator_pull_down_set(desc->node_name); 43385fb175bSYann Gautier 43485fb175bSYann Gautier case REGUL_MASK_RESET: 43585fb175bSYann Gautier return stpmic1_regulator_mask_reset_set(desc->node_name); 43685fb175bSYann Gautier 43785fb175bSYann Gautier case REGUL_SINK_SOURCE: 43885fb175bSYann Gautier return stpmic1_regulator_sink_mode_set(desc->node_name); 43985fb175bSYann Gautier 44085fb175bSYann Gautier case REGUL_ENABLE_BYPASS: 44185fb175bSYann Gautier return stpmic1_regulator_bypass_mode_set(desc->node_name); 44285fb175bSYann Gautier 44385fb175bSYann Gautier default: 44485fb175bSYann Gautier return -EINVAL; 44585fb175bSYann Gautier } 44685fb175bSYann Gautier } 44785fb175bSYann Gautier 44857e60183SYann Gautier static const struct regul_ops pmic_ops = { 44985fb175bSYann Gautier .set_state = pmic_set_state, 45085fb175bSYann Gautier .get_state = pmic_get_state, 45185fb175bSYann Gautier .set_voltage = pmic_set_voltage, 45285fb175bSYann Gautier .get_voltage = pmic_get_voltage, 45385fb175bSYann Gautier .list_voltages = pmic_list_voltages, 45485fb175bSYann Gautier .set_flag = pmic_set_flag, 45585fb175bSYann Gautier }; 45685fb175bSYann Gautier 45785fb175bSYann Gautier #define DEFINE_REGU(name) { \ 458be7195d0SYann Gautier .node_name = (name), \ 45985fb175bSYann Gautier .ops = &pmic_ops, \ 46085fb175bSYann Gautier .driver_data = NULL, \ 46185fb175bSYann Gautier .enable_ramp_delay = 1000, \ 46285fb175bSYann Gautier } 46385fb175bSYann Gautier 464*3cebeec2SYann Gautier static const struct regul_description pmic_regs[NB_REG] = { 46585fb175bSYann Gautier [STPMIC1_BUCK1] = DEFINE_REGU("buck1"), 46685fb175bSYann Gautier [STPMIC1_BUCK2] = DEFINE_REGU("buck2"), 46785fb175bSYann Gautier [STPMIC1_BUCK3] = DEFINE_REGU("buck3"), 46885fb175bSYann Gautier [STPMIC1_BUCK4] = DEFINE_REGU("buck4"), 46985fb175bSYann Gautier [STPMIC1_LDO1] = DEFINE_REGU("ldo1"), 47085fb175bSYann Gautier [STPMIC1_LDO2] = DEFINE_REGU("ldo2"), 47185fb175bSYann Gautier [STPMIC1_LDO3] = DEFINE_REGU("ldo3"), 47285fb175bSYann Gautier [STPMIC1_LDO4] = DEFINE_REGU("ldo4"), 47385fb175bSYann Gautier [STPMIC1_LDO5] = DEFINE_REGU("ldo5"), 47485fb175bSYann Gautier [STPMIC1_LDO6] = DEFINE_REGU("ldo6"), 47585fb175bSYann Gautier [STPMIC1_VREF_DDR] = DEFINE_REGU("vref_ddr"), 47685fb175bSYann Gautier [STPMIC1_BOOST] = DEFINE_REGU("boost"), 47785fb175bSYann Gautier [STPMIC1_VBUS_OTG] = DEFINE_REGU("pwr_sw1"), 47885fb175bSYann Gautier [STPMIC1_SW_OUT] = DEFINE_REGU("pwr_sw2"), 47985fb175bSYann Gautier }; 48085fb175bSYann Gautier 48185fb175bSYann Gautier static int register_pmic(void) 48285fb175bSYann Gautier { 48385fb175bSYann Gautier void *fdt; 48485fb175bSYann Gautier int pmic_node, regulators_node, subnode; 48585fb175bSYann Gautier 48685fb175bSYann Gautier VERBOSE("Register pmic\n"); 48785fb175bSYann Gautier 48885fb175bSYann Gautier if (fdt_get_address(&fdt) == 0) { 48985fb175bSYann Gautier return -FDT_ERR_NOTFOUND; 49085fb175bSYann Gautier } 49185fb175bSYann Gautier 49285fb175bSYann Gautier pmic_node = dt_get_pmic_node(fdt); 49385fb175bSYann Gautier if (pmic_node < 0) { 49485fb175bSYann Gautier return pmic_node; 49585fb175bSYann Gautier } 49685fb175bSYann Gautier 49785fb175bSYann Gautier regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators"); 49885fb175bSYann Gautier if (regulators_node < 0) { 49985fb175bSYann Gautier return -ENOENT; 50085fb175bSYann Gautier } 50185fb175bSYann Gautier 50285fb175bSYann Gautier fdt_for_each_subnode(subnode, fdt, regulators_node) { 50385fb175bSYann Gautier const char *reg_name = fdt_get_name(fdt, subnode, NULL); 50485fb175bSYann Gautier const struct regul_description *desc; 50585fb175bSYann Gautier unsigned int i; 50685fb175bSYann Gautier int ret; 50785fb175bSYann Gautier 508*3cebeec2SYann Gautier for (i = 0U; i < NB_REG; i++) { 50985fb175bSYann Gautier desc = &pmic_regs[i]; 51085fb175bSYann Gautier if (strcmp(desc->node_name, reg_name) == 0) { 51185fb175bSYann Gautier break; 51285fb175bSYann Gautier } 51385fb175bSYann Gautier } 51485fb175bSYann Gautier assert(i < NB_REG); 51585fb175bSYann Gautier 51685fb175bSYann Gautier ret = regulator_register(desc, subnode); 51785fb175bSYann Gautier if (ret != 0) { 51885fb175bSYann Gautier WARN("%s:%d failed to register %s\n", __func__, 51985fb175bSYann Gautier __LINE__, reg_name); 52085fb175bSYann Gautier return ret; 52185fb175bSYann Gautier } 52285fb175bSYann Gautier } 52385fb175bSYann Gautier 52485fb175bSYann Gautier return 0; 52585fb175bSYann Gautier } 526