123684d0eSYann Gautier /* 242822844SBenjamin Gaignard * Copyright (c) 2017-2021, 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 2323684d0eSYann Gautier 2423684d0eSYann Gautier static struct i2c_handle_s i2c_handle; 2523684d0eSYann Gautier static uint32_t pmic_i2c_addr; 2623684d0eSYann Gautier 2785fb175bSYann Gautier static int register_pmic(void); 2885fb175bSYann Gautier 2923684d0eSYann Gautier static int dt_get_pmic_node(void *fdt) 3023684d0eSYann Gautier { 31c77c7d9eSNicolas Le Bayon static int node = -FDT_ERR_BADOFFSET; 32c77c7d9eSNicolas Le Bayon 33c77c7d9eSNicolas Le Bayon if (node == -FDT_ERR_BADOFFSET) { 34c77c7d9eSNicolas Le Bayon node = fdt_node_offset_by_compatible(fdt, -1, "st,stpmic1"); 35c77c7d9eSNicolas Le Bayon } 36c77c7d9eSNicolas Le Bayon 37c77c7d9eSNicolas Le Bayon return node; 3823684d0eSYann Gautier } 3923684d0eSYann Gautier 40d82d4ff0SYann Gautier int dt_pmic_status(void) 4123684d0eSYann Gautier { 42c77c7d9eSNicolas Le Bayon static int status = -FDT_ERR_BADVALUE; 4323684d0eSYann Gautier int node; 4423684d0eSYann Gautier void *fdt; 4523684d0eSYann Gautier 46c77c7d9eSNicolas Le Bayon if (status != -FDT_ERR_BADVALUE) { 47c77c7d9eSNicolas Le Bayon return status; 48c77c7d9eSNicolas Le Bayon } 49c77c7d9eSNicolas Le Bayon 5023684d0eSYann Gautier if (fdt_get_address(&fdt) == 0) { 51d82d4ff0SYann Gautier return -ENOENT; 5223684d0eSYann Gautier } 5323684d0eSYann Gautier 5423684d0eSYann Gautier node = dt_get_pmic_node(fdt); 55d82d4ff0SYann Gautier if (node <= 0) { 56c77c7d9eSNicolas Le Bayon status = -FDT_ERR_NOTFOUND; 57c77c7d9eSNicolas Le Bayon 58c77c7d9eSNicolas Le Bayon return status; 5923684d0eSYann Gautier } 6023684d0eSYann Gautier 61c77c7d9eSNicolas Le Bayon status = (int)fdt_get_status(node); 62c77c7d9eSNicolas Le Bayon 63c77c7d9eSNicolas Le Bayon return status; 6423684d0eSYann Gautier } 6523684d0eSYann Gautier 66f564d439SEtienne Carriere static bool dt_pmic_is_secure(void) 67f564d439SEtienne Carriere { 68f564d439SEtienne Carriere int status = dt_pmic_status(); 69f564d439SEtienne Carriere 70f564d439SEtienne Carriere return (status >= 0) && 71f564d439SEtienne Carriere (status == DT_SECURE) && 72f564d439SEtienne Carriere (i2c_handle.dt_status == DT_SECURE); 73f564d439SEtienne Carriere } 74f564d439SEtienne Carriere 75d82d4ff0SYann Gautier /* 76d82d4ff0SYann Gautier * Get PMIC and its I2C bus configuration from the device tree. 77c77c7d9eSNicolas Le Bayon * Return 0 on success, negative on error, 1 if no PMIC node is defined. 78d82d4ff0SYann Gautier */ 79d82d4ff0SYann Gautier static int dt_pmic_i2c_config(struct dt_node_info *i2c_info, 80d82d4ff0SYann Gautier struct stm32_i2c_init_s *init) 8123684d0eSYann Gautier { 82c77c7d9eSNicolas Le Bayon static int i2c_node = -FDT_ERR_NOTFOUND; 8323684d0eSYann Gautier void *fdt; 8423684d0eSYann Gautier 8523684d0eSYann Gautier if (fdt_get_address(&fdt) == 0) { 86c77c7d9eSNicolas Le Bayon return -FDT_ERR_NOTFOUND; 8723684d0eSYann Gautier } 8823684d0eSYann Gautier 89c77c7d9eSNicolas Le Bayon if (i2c_node == -FDT_ERR_NOTFOUND) { 90c77c7d9eSNicolas Le Bayon int pmic_node; 91c77c7d9eSNicolas Le Bayon const fdt32_t *cuint; 92c77c7d9eSNicolas Le Bayon 9323684d0eSYann Gautier pmic_node = dt_get_pmic_node(fdt); 9423684d0eSYann Gautier if (pmic_node < 0) { 95c77c7d9eSNicolas Le Bayon return PMIC_NODE_NOT_FOUND; 9623684d0eSYann Gautier } 9723684d0eSYann Gautier 9823684d0eSYann Gautier cuint = fdt_getprop(fdt, pmic_node, "reg", NULL); 9923684d0eSYann Gautier if (cuint == NULL) { 10023684d0eSYann Gautier return -FDT_ERR_NOTFOUND; 10123684d0eSYann Gautier } 10223684d0eSYann Gautier 10323684d0eSYann Gautier pmic_i2c_addr = fdt32_to_cpu(*cuint) << 1; 10423684d0eSYann Gautier if (pmic_i2c_addr > UINT16_MAX) { 105c77c7d9eSNicolas Le Bayon return -FDT_ERR_BADVALUE; 10623684d0eSYann Gautier } 10723684d0eSYann Gautier 10823684d0eSYann Gautier i2c_node = fdt_parent_offset(fdt, pmic_node); 10923684d0eSYann Gautier if (i2c_node < 0) { 11023684d0eSYann Gautier return -FDT_ERR_NOTFOUND; 11123684d0eSYann Gautier } 112c77c7d9eSNicolas Le Bayon } 11323684d0eSYann Gautier 11423684d0eSYann Gautier dt_fill_device_info(i2c_info, i2c_node); 11523684d0eSYann Gautier if (i2c_info->base == 0U) { 11623684d0eSYann Gautier return -FDT_ERR_NOTFOUND; 11723684d0eSYann Gautier } 11823684d0eSYann Gautier 119d82d4ff0SYann Gautier return stm32_i2c_get_setup_from_fdt(fdt, i2c_node, init); 12023684d0eSYann Gautier } 12123684d0eSYann Gautier 122d82d4ff0SYann Gautier bool initialize_pmic_i2c(void) 12323684d0eSYann Gautier { 12423684d0eSYann Gautier int ret; 12523684d0eSYann Gautier struct dt_node_info i2c_info; 126d82d4ff0SYann Gautier struct i2c_handle_s *i2c = &i2c_handle; 127d82d4ff0SYann Gautier struct stm32_i2c_init_s i2c_init; 12823684d0eSYann Gautier 129d82d4ff0SYann Gautier ret = dt_pmic_i2c_config(&i2c_info, &i2c_init); 130d82d4ff0SYann Gautier if (ret < 0) { 131d82d4ff0SYann Gautier ERROR("I2C configuration failed %d\n", ret); 13223684d0eSYann Gautier panic(); 13323684d0eSYann Gautier } 13423684d0eSYann Gautier 135d82d4ff0SYann Gautier if (ret != 0) { 136d82d4ff0SYann Gautier return false; 13723684d0eSYann Gautier } 13823684d0eSYann Gautier 13923684d0eSYann Gautier /* Initialize PMIC I2C */ 140d82d4ff0SYann Gautier i2c->i2c_base_addr = i2c_info.base; 141d82d4ff0SYann Gautier i2c->dt_status = i2c_info.status; 142d82d4ff0SYann Gautier i2c->clock = i2c_info.clock; 14342822844SBenjamin Gaignard i2c->i2c_state = I2C_STATE_RESET; 144d82d4ff0SYann Gautier i2c_init.own_address1 = pmic_i2c_addr; 145d82d4ff0SYann Gautier i2c_init.addressing_mode = I2C_ADDRESSINGMODE_7BIT; 146d82d4ff0SYann Gautier i2c_init.dual_address_mode = I2C_DUALADDRESS_DISABLE; 147d82d4ff0SYann Gautier i2c_init.own_address2 = 0; 148d82d4ff0SYann Gautier i2c_init.own_address2_masks = I2C_OAR2_OA2NOMASK; 149d82d4ff0SYann Gautier i2c_init.general_call_mode = I2C_GENERALCALL_DISABLE; 150d82d4ff0SYann Gautier i2c_init.no_stretch_mode = I2C_NOSTRETCH_DISABLE; 151d82d4ff0SYann Gautier i2c_init.analog_filter = 1; 152d82d4ff0SYann Gautier i2c_init.digital_filter_coef = 0; 15323684d0eSYann Gautier 154d82d4ff0SYann Gautier ret = stm32_i2c_init(i2c, &i2c_init); 15523684d0eSYann Gautier if (ret != 0) { 15623684d0eSYann Gautier ERROR("Cannot initialize I2C %x (%d)\n", 157d82d4ff0SYann Gautier i2c->i2c_base_addr, ret); 15823684d0eSYann Gautier panic(); 15923684d0eSYann Gautier } 16023684d0eSYann Gautier 161d82d4ff0SYann Gautier if (!stm32_i2c_is_device_ready(i2c, pmic_i2c_addr, 1, 162d82d4ff0SYann Gautier I2C_TIMEOUT_BUSY_MS)) { 163d82d4ff0SYann Gautier ERROR("I2C device not ready\n"); 16423684d0eSYann Gautier panic(); 16523684d0eSYann Gautier } 16623684d0eSYann Gautier 167d82d4ff0SYann Gautier stpmic1_bind_i2c(i2c, (uint16_t)pmic_i2c_addr); 16823684d0eSYann Gautier 169d82d4ff0SYann Gautier return true; 17023684d0eSYann Gautier } 17123684d0eSYann Gautier 172f564d439SEtienne Carriere static void register_pmic_shared_peripherals(void) 173f564d439SEtienne Carriere { 174f564d439SEtienne Carriere uintptr_t i2c_base = i2c_handle.i2c_base_addr; 175f564d439SEtienne Carriere 176f564d439SEtienne Carriere if (dt_pmic_is_secure()) { 177f564d439SEtienne Carriere stm32mp_register_secure_periph_iomem(i2c_base); 178f564d439SEtienne Carriere } else { 179f564d439SEtienne Carriere if (i2c_base != 0U) { 180f564d439SEtienne Carriere stm32mp_register_non_secure_periph_iomem(i2c_base); 181f564d439SEtienne Carriere } 182f564d439SEtienne Carriere } 183f564d439SEtienne Carriere } 184f564d439SEtienne Carriere 18523684d0eSYann Gautier void initialize_pmic(void) 18623684d0eSYann Gautier { 187d82d4ff0SYann Gautier if (!initialize_pmic_i2c()) { 188d82d4ff0SYann Gautier VERBOSE("No PMIC\n"); 189d82d4ff0SYann Gautier return; 190d82d4ff0SYann Gautier } 19123684d0eSYann Gautier 192f564d439SEtienne Carriere register_pmic_shared_peripherals(); 193f564d439SEtienne Carriere 19485fb175bSYann Gautier if (register_pmic() < 0) { 195ae7792e0SNicolas Le Bayon panic(); 19685fb175bSYann Gautier } 19785fb175bSYann Gautier 19885fb175bSYann Gautier if (stpmic1_powerctrl_on() < 0) { 19985fb175bSYann Gautier panic(); 20085fb175bSYann Gautier } 20185fb175bSYann Gautier 202ae7792e0SNicolas Le Bayon } 203ae7792e0SNicolas Le Bayon 204ae7792e0SNicolas Le Bayon #if DEBUG 205ae7792e0SNicolas Le Bayon void print_pmic_info_and_debug(void) 206ae7792e0SNicolas Le Bayon { 207ae7792e0SNicolas Le Bayon unsigned long pmic_version; 208ae7792e0SNicolas Le Bayon 209d82d4ff0SYann Gautier if (stpmic1_get_version(&pmic_version) != 0) { 210d82d4ff0SYann Gautier ERROR("Failed to access PMIC\n"); 21123684d0eSYann Gautier panic(); 21223684d0eSYann Gautier } 21323684d0eSYann Gautier 214d82d4ff0SYann Gautier INFO("PMIC version = 0x%02lx\n", pmic_version); 21523684d0eSYann Gautier } 216ae7792e0SNicolas Le Bayon #endif 21723684d0eSYann Gautier 21823684d0eSYann Gautier int pmic_ddr_power_init(enum ddr_type ddr_type) 21923684d0eSYann Gautier { 22023684d0eSYann Gautier int status; 221*0ba71ac9SPascal Paillet uint16_t buck3_min_mv; 222*0ba71ac9SPascal Paillet struct rdev *buck2, *buck3, *ldo3, *vref; 223*0ba71ac9SPascal Paillet 224*0ba71ac9SPascal Paillet buck2 = regulator_get_by_name("buck2"); 225*0ba71ac9SPascal Paillet if (buck2 == NULL) { 226*0ba71ac9SPascal Paillet return -ENOENT; 227*0ba71ac9SPascal Paillet } 228*0ba71ac9SPascal Paillet 229*0ba71ac9SPascal Paillet ldo3 = regulator_get_by_name("ldo3"); 230*0ba71ac9SPascal Paillet if (ldo3 == NULL) { 231*0ba71ac9SPascal Paillet return -ENOENT; 232*0ba71ac9SPascal Paillet } 233*0ba71ac9SPascal Paillet 234*0ba71ac9SPascal Paillet vref = regulator_get_by_name("vref_ddr"); 235*0ba71ac9SPascal Paillet if (vref == NULL) { 236*0ba71ac9SPascal Paillet return -ENOENT; 237*0ba71ac9SPascal Paillet } 23823684d0eSYann Gautier 23923684d0eSYann Gautier switch (ddr_type) { 24023684d0eSYann Gautier case STM32MP_DDR3: 241*0ba71ac9SPascal Paillet status = regulator_set_flag(ldo3, REGUL_SINK_SOURCE); 24223684d0eSYann Gautier if (status != 0) { 24323684d0eSYann Gautier return status; 24423684d0eSYann Gautier } 24523684d0eSYann Gautier 246*0ba71ac9SPascal Paillet status = regulator_set_min_voltage(buck2); 24723684d0eSYann Gautier if (status != 0) { 24823684d0eSYann Gautier return status; 24923684d0eSYann Gautier } 25023684d0eSYann Gautier 251*0ba71ac9SPascal Paillet status = regulator_enable(buck2); 25223684d0eSYann Gautier if (status != 0) { 25323684d0eSYann Gautier return status; 25423684d0eSYann Gautier } 25523684d0eSYann Gautier 256*0ba71ac9SPascal Paillet status = regulator_enable(vref); 25723684d0eSYann Gautier if (status != 0) { 25823684d0eSYann Gautier return status; 25923684d0eSYann Gautier } 26023684d0eSYann Gautier 261*0ba71ac9SPascal Paillet status = regulator_enable(ldo3); 26223684d0eSYann Gautier if (status != 0) { 26323684d0eSYann Gautier return status; 26423684d0eSYann Gautier } 26523684d0eSYann Gautier break; 26623684d0eSYann Gautier 26723684d0eSYann Gautier case STM32MP_LPDDR2: 2684b549b21SYann Gautier case STM32MP_LPDDR3: 26923684d0eSYann Gautier /* 27023684d0eSYann Gautier * Set LDO3 to 1.8V 27123684d0eSYann Gautier * Set LDO3 to bypass mode if BUCK3 = 1.8V 27223684d0eSYann Gautier * Set LDO3 to normal mode if BUCK3 != 1.8V 27323684d0eSYann Gautier */ 274*0ba71ac9SPascal Paillet buck3 = regulator_get_by_name("buck3"); 275*0ba71ac9SPascal Paillet if (buck3 == NULL) { 276*0ba71ac9SPascal Paillet return -ENOENT; 277*0ba71ac9SPascal Paillet } 278*0ba71ac9SPascal Paillet 279*0ba71ac9SPascal Paillet regulator_get_range(buck3, &buck3_min_mv, NULL); 280*0ba71ac9SPascal Paillet 281*0ba71ac9SPascal Paillet if (buck3_min_mv != 1800) { 282*0ba71ac9SPascal Paillet status = regulator_set_min_voltage(ldo3); 283*0ba71ac9SPascal Paillet if (status != 0) { 284*0ba71ac9SPascal Paillet return status; 285*0ba71ac9SPascal Paillet } 286*0ba71ac9SPascal Paillet } else { 287*0ba71ac9SPascal Paillet status = regulator_set_flag(ldo3, REGUL_ENABLE_BYPASS); 288*0ba71ac9SPascal Paillet if (status != 0) { 289*0ba71ac9SPascal Paillet return status; 290*0ba71ac9SPascal Paillet } 291*0ba71ac9SPascal Paillet } 292*0ba71ac9SPascal Paillet 293*0ba71ac9SPascal Paillet status = regulator_set_min_voltage(buck2); 29423684d0eSYann Gautier if (status != 0) { 29523684d0eSYann Gautier return status; 29623684d0eSYann Gautier } 29723684d0eSYann Gautier 298*0ba71ac9SPascal Paillet status = regulator_enable(ldo3); 29923684d0eSYann Gautier if (status != 0) { 30023684d0eSYann Gautier return status; 30123684d0eSYann Gautier } 30223684d0eSYann Gautier 303*0ba71ac9SPascal Paillet status = regulator_enable(buck2); 30423684d0eSYann Gautier if (status != 0) { 30523684d0eSYann Gautier return status; 30623684d0eSYann Gautier } 30723684d0eSYann Gautier 308*0ba71ac9SPascal Paillet status = regulator_enable(vref); 30923684d0eSYann Gautier if (status != 0) { 31023684d0eSYann Gautier return status; 31123684d0eSYann Gautier } 31223684d0eSYann Gautier break; 31323684d0eSYann Gautier 31423684d0eSYann Gautier default: 31523684d0eSYann Gautier break; 31623684d0eSYann Gautier }; 31723684d0eSYann Gautier 31823684d0eSYann Gautier return 0; 31923684d0eSYann Gautier } 32085fb175bSYann Gautier 32185fb175bSYann Gautier enum { 32285fb175bSYann Gautier STPMIC1_BUCK1 = 0, 32385fb175bSYann Gautier STPMIC1_BUCK2, 32485fb175bSYann Gautier STPMIC1_BUCK3, 32585fb175bSYann Gautier STPMIC1_BUCK4, 32685fb175bSYann Gautier STPMIC1_LDO1, 32785fb175bSYann Gautier STPMIC1_LDO2, 32885fb175bSYann Gautier STPMIC1_LDO3, 32985fb175bSYann Gautier STPMIC1_LDO4, 33085fb175bSYann Gautier STPMIC1_LDO5, 33185fb175bSYann Gautier STPMIC1_LDO6, 33285fb175bSYann Gautier STPMIC1_VREF_DDR, 33385fb175bSYann Gautier STPMIC1_BOOST, 33485fb175bSYann Gautier STPMIC1_VBUS_OTG, 33585fb175bSYann Gautier STPMIC1_SW_OUT, 33685fb175bSYann Gautier }; 33785fb175bSYann Gautier 33885fb175bSYann Gautier static int pmic_set_state(const struct regul_description *desc, bool enable) 33985fb175bSYann Gautier { 34085fb175bSYann Gautier VERBOSE("%s: set state to %u\n", desc->node_name, enable); 34185fb175bSYann Gautier 34285fb175bSYann Gautier if (enable == STATE_ENABLE) { 34385fb175bSYann Gautier return stpmic1_regulator_enable(desc->node_name); 34485fb175bSYann Gautier } else { 34585fb175bSYann Gautier return stpmic1_regulator_disable(desc->node_name); 34685fb175bSYann Gautier } 34785fb175bSYann Gautier } 34885fb175bSYann Gautier 34985fb175bSYann Gautier static int pmic_get_state(const struct regul_description *desc) 35085fb175bSYann Gautier { 35185fb175bSYann Gautier VERBOSE("%s: get state\n", desc->node_name); 35285fb175bSYann Gautier 35385fb175bSYann Gautier return stpmic1_is_regulator_enabled(desc->node_name); 35485fb175bSYann Gautier } 35585fb175bSYann Gautier 35685fb175bSYann Gautier static int pmic_get_voltage(const struct regul_description *desc) 35785fb175bSYann Gautier { 35885fb175bSYann Gautier VERBOSE("%s: get volt\n", desc->node_name); 35985fb175bSYann Gautier 36085fb175bSYann Gautier return stpmic1_regulator_voltage_get(desc->node_name); 36185fb175bSYann Gautier } 36285fb175bSYann Gautier 36385fb175bSYann Gautier static int pmic_set_voltage(const struct regul_description *desc, uint16_t mv) 36485fb175bSYann Gautier { 36585fb175bSYann Gautier VERBOSE("%s: get volt\n", desc->node_name); 36685fb175bSYann Gautier 36785fb175bSYann Gautier return stpmic1_regulator_voltage_set(desc->node_name, mv); 36885fb175bSYann Gautier } 36985fb175bSYann Gautier 37085fb175bSYann Gautier static int pmic_list_voltages(const struct regul_description *desc, 37185fb175bSYann Gautier const uint16_t **levels, size_t *count) 37285fb175bSYann Gautier { 37385fb175bSYann Gautier VERBOSE("%s: list volt\n", desc->node_name); 37485fb175bSYann Gautier 37585fb175bSYann Gautier return stpmic1_regulator_levels_mv(desc->node_name, levels, count); 37685fb175bSYann Gautier } 37785fb175bSYann Gautier 37885fb175bSYann Gautier static int pmic_set_flag(const struct regul_description *desc, uint16_t flag) 37985fb175bSYann Gautier { 38085fb175bSYann Gautier VERBOSE("%s: set_flag 0x%x\n", desc->node_name, flag); 38185fb175bSYann Gautier 38285fb175bSYann Gautier switch (flag) { 38385fb175bSYann Gautier case REGUL_OCP: 38485fb175bSYann Gautier return stpmic1_regulator_icc_set(desc->node_name); 38585fb175bSYann Gautier 38685fb175bSYann Gautier case REGUL_ACTIVE_DISCHARGE: 38785fb175bSYann Gautier return stpmic1_active_discharge_mode_set(desc->node_name); 38885fb175bSYann Gautier 38985fb175bSYann Gautier case REGUL_PULL_DOWN: 39085fb175bSYann Gautier return stpmic1_regulator_pull_down_set(desc->node_name); 39185fb175bSYann Gautier 39285fb175bSYann Gautier case REGUL_MASK_RESET: 39385fb175bSYann Gautier return stpmic1_regulator_mask_reset_set(desc->node_name); 39485fb175bSYann Gautier 39585fb175bSYann Gautier case REGUL_SINK_SOURCE: 39685fb175bSYann Gautier return stpmic1_regulator_sink_mode_set(desc->node_name); 39785fb175bSYann Gautier 39885fb175bSYann Gautier case REGUL_ENABLE_BYPASS: 39985fb175bSYann Gautier return stpmic1_regulator_bypass_mode_set(desc->node_name); 40085fb175bSYann Gautier 40185fb175bSYann Gautier default: 40285fb175bSYann Gautier return -EINVAL; 40385fb175bSYann Gautier } 40485fb175bSYann Gautier } 40585fb175bSYann Gautier 40685fb175bSYann Gautier struct regul_ops pmic_ops = { 40785fb175bSYann Gautier .set_state = pmic_set_state, 40885fb175bSYann Gautier .get_state = pmic_get_state, 40985fb175bSYann Gautier .set_voltage = pmic_set_voltage, 41085fb175bSYann Gautier .get_voltage = pmic_get_voltage, 41185fb175bSYann Gautier .list_voltages = pmic_list_voltages, 41285fb175bSYann Gautier .set_flag = pmic_set_flag, 41385fb175bSYann Gautier }; 41485fb175bSYann Gautier 41585fb175bSYann Gautier #define DEFINE_REGU(name) { \ 41685fb175bSYann Gautier .node_name = name, \ 41785fb175bSYann Gautier .ops = &pmic_ops, \ 41885fb175bSYann Gautier .driver_data = NULL, \ 41985fb175bSYann Gautier .enable_ramp_delay = 1000, \ 42085fb175bSYann Gautier } 42185fb175bSYann Gautier 42285fb175bSYann Gautier static const struct regul_description pmic_regs[] = { 42385fb175bSYann Gautier [STPMIC1_BUCK1] = DEFINE_REGU("buck1"), 42485fb175bSYann Gautier [STPMIC1_BUCK2] = DEFINE_REGU("buck2"), 42585fb175bSYann Gautier [STPMIC1_BUCK3] = DEFINE_REGU("buck3"), 42685fb175bSYann Gautier [STPMIC1_BUCK4] = DEFINE_REGU("buck4"), 42785fb175bSYann Gautier [STPMIC1_LDO1] = DEFINE_REGU("ldo1"), 42885fb175bSYann Gautier [STPMIC1_LDO2] = DEFINE_REGU("ldo2"), 42985fb175bSYann Gautier [STPMIC1_LDO3] = DEFINE_REGU("ldo3"), 43085fb175bSYann Gautier [STPMIC1_LDO4] = DEFINE_REGU("ldo4"), 43185fb175bSYann Gautier [STPMIC1_LDO5] = DEFINE_REGU("ldo5"), 43285fb175bSYann Gautier [STPMIC1_LDO6] = DEFINE_REGU("ldo6"), 43385fb175bSYann Gautier [STPMIC1_VREF_DDR] = DEFINE_REGU("vref_ddr"), 43485fb175bSYann Gautier [STPMIC1_BOOST] = DEFINE_REGU("boost"), 43585fb175bSYann Gautier [STPMIC1_VBUS_OTG] = DEFINE_REGU("pwr_sw1"), 43685fb175bSYann Gautier [STPMIC1_SW_OUT] = DEFINE_REGU("pwr_sw2"), 43785fb175bSYann Gautier }; 43885fb175bSYann Gautier 43985fb175bSYann Gautier #define NB_REG ARRAY_SIZE(pmic_regs) 44085fb175bSYann Gautier 44185fb175bSYann Gautier static int register_pmic(void) 44285fb175bSYann Gautier { 44385fb175bSYann Gautier void *fdt; 44485fb175bSYann Gautier int pmic_node, regulators_node, subnode; 44585fb175bSYann Gautier 44685fb175bSYann Gautier VERBOSE("Register pmic\n"); 44785fb175bSYann Gautier 44885fb175bSYann Gautier if (fdt_get_address(&fdt) == 0) { 44985fb175bSYann Gautier return -FDT_ERR_NOTFOUND; 45085fb175bSYann Gautier } 45185fb175bSYann Gautier 45285fb175bSYann Gautier pmic_node = dt_get_pmic_node(fdt); 45385fb175bSYann Gautier if (pmic_node < 0) { 45485fb175bSYann Gautier return pmic_node; 45585fb175bSYann Gautier } 45685fb175bSYann Gautier 45785fb175bSYann Gautier regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators"); 45885fb175bSYann Gautier if (regulators_node < 0) { 45985fb175bSYann Gautier return -ENOENT; 46085fb175bSYann Gautier } 46185fb175bSYann Gautier 46285fb175bSYann Gautier fdt_for_each_subnode(subnode, fdt, regulators_node) { 46385fb175bSYann Gautier const char *reg_name = fdt_get_name(fdt, subnode, NULL); 46485fb175bSYann Gautier const struct regul_description *desc; 46585fb175bSYann Gautier unsigned int i; 46685fb175bSYann Gautier int ret; 46785fb175bSYann Gautier 46885fb175bSYann Gautier for (i = 0; i < NB_REG; i++) { 46985fb175bSYann Gautier desc = &pmic_regs[i]; 47085fb175bSYann Gautier if (strcmp(desc->node_name, reg_name) == 0) { 47185fb175bSYann Gautier break; 47285fb175bSYann Gautier } 47385fb175bSYann Gautier } 47485fb175bSYann Gautier assert(i < NB_REG); 47585fb175bSYann Gautier 47685fb175bSYann Gautier ret = regulator_register(desc, subnode); 47785fb175bSYann Gautier if (ret != 0) { 47885fb175bSYann Gautier WARN("%s:%d failed to register %s\n", __func__, 47985fb175bSYann Gautier __LINE__, reg_name); 48085fb175bSYann Gautier return ret; 48185fb175bSYann Gautier } 48285fb175bSYann Gautier } 48385fb175bSYann Gautier 48485fb175bSYann Gautier return 0; 48585fb175bSYann Gautier } 486