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 7*85fb175bSYann Gautier #include <assert.h> 823684d0eSYann Gautier #include <errno.h> 923684d0eSYann Gautier 1023684d0eSYann Gautier #include <common/debug.h> 1123684d0eSYann Gautier #include <drivers/delay_timer.h> 12*85fb175bSYann 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 #define STPMIC1_LDO12356_OUTPUT_MASK (uint8_t)(GENMASK(6, 2)) 2423684d0eSYann Gautier #define STPMIC1_LDO12356_OUTPUT_SHIFT 2 2523684d0eSYann Gautier #define STPMIC1_LDO3_MODE (uint8_t)(BIT(7)) 2623684d0eSYann Gautier #define STPMIC1_LDO3_DDR_SEL 31U 2723684d0eSYann Gautier #define STPMIC1_LDO3_1800000 (9U << STPMIC1_LDO12356_OUTPUT_SHIFT) 2823684d0eSYann Gautier 2923684d0eSYann Gautier #define STPMIC1_BUCK_OUTPUT_SHIFT 2 3023684d0eSYann Gautier #define STPMIC1_BUCK3_1V8 (39U << STPMIC1_BUCK_OUTPUT_SHIFT) 3123684d0eSYann Gautier 3223684d0eSYann Gautier #define STPMIC1_DEFAULT_START_UP_DELAY_MS 1 3323684d0eSYann Gautier 3423684d0eSYann Gautier static struct i2c_handle_s i2c_handle; 3523684d0eSYann Gautier static uint32_t pmic_i2c_addr; 3623684d0eSYann Gautier 37*85fb175bSYann Gautier static int register_pmic(void); 38*85fb175bSYann Gautier 3923684d0eSYann Gautier static int dt_get_pmic_node(void *fdt) 4023684d0eSYann Gautier { 41c77c7d9eSNicolas Le Bayon static int node = -FDT_ERR_BADOFFSET; 42c77c7d9eSNicolas Le Bayon 43c77c7d9eSNicolas Le Bayon if (node == -FDT_ERR_BADOFFSET) { 44c77c7d9eSNicolas Le Bayon node = fdt_node_offset_by_compatible(fdt, -1, "st,stpmic1"); 45c77c7d9eSNicolas Le Bayon } 46c77c7d9eSNicolas Le Bayon 47c77c7d9eSNicolas Le Bayon return node; 4823684d0eSYann Gautier } 4923684d0eSYann Gautier 50d82d4ff0SYann Gautier int dt_pmic_status(void) 5123684d0eSYann Gautier { 52c77c7d9eSNicolas Le Bayon static int status = -FDT_ERR_BADVALUE; 5323684d0eSYann Gautier int node; 5423684d0eSYann Gautier void *fdt; 5523684d0eSYann Gautier 56c77c7d9eSNicolas Le Bayon if (status != -FDT_ERR_BADVALUE) { 57c77c7d9eSNicolas Le Bayon return status; 58c77c7d9eSNicolas Le Bayon } 59c77c7d9eSNicolas Le Bayon 6023684d0eSYann Gautier if (fdt_get_address(&fdt) == 0) { 61d82d4ff0SYann Gautier return -ENOENT; 6223684d0eSYann Gautier } 6323684d0eSYann Gautier 6423684d0eSYann Gautier node = dt_get_pmic_node(fdt); 65d82d4ff0SYann Gautier if (node <= 0) { 66c77c7d9eSNicolas Le Bayon status = -FDT_ERR_NOTFOUND; 67c77c7d9eSNicolas Le Bayon 68c77c7d9eSNicolas Le Bayon return status; 6923684d0eSYann Gautier } 7023684d0eSYann Gautier 71c77c7d9eSNicolas Le Bayon status = (int)fdt_get_status(node); 72c77c7d9eSNicolas Le Bayon 73c77c7d9eSNicolas Le Bayon return status; 7423684d0eSYann Gautier } 7523684d0eSYann Gautier 76f564d439SEtienne Carriere static bool dt_pmic_is_secure(void) 77f564d439SEtienne Carriere { 78f564d439SEtienne Carriere int status = dt_pmic_status(); 79f564d439SEtienne Carriere 80f564d439SEtienne Carriere return (status >= 0) && 81f564d439SEtienne Carriere (status == DT_SECURE) && 82f564d439SEtienne Carriere (i2c_handle.dt_status == DT_SECURE); 83f564d439SEtienne Carriere } 84f564d439SEtienne Carriere 85d82d4ff0SYann Gautier /* 86d82d4ff0SYann Gautier * Get PMIC and its I2C bus configuration from the device tree. 87c77c7d9eSNicolas Le Bayon * Return 0 on success, negative on error, 1 if no PMIC node is defined. 88d82d4ff0SYann Gautier */ 89d82d4ff0SYann Gautier static int dt_pmic_i2c_config(struct dt_node_info *i2c_info, 90d82d4ff0SYann Gautier struct stm32_i2c_init_s *init) 9123684d0eSYann Gautier { 92c77c7d9eSNicolas Le Bayon static int i2c_node = -FDT_ERR_NOTFOUND; 9323684d0eSYann Gautier void *fdt; 9423684d0eSYann Gautier 9523684d0eSYann Gautier if (fdt_get_address(&fdt) == 0) { 96c77c7d9eSNicolas Le Bayon return -FDT_ERR_NOTFOUND; 9723684d0eSYann Gautier } 9823684d0eSYann Gautier 99c77c7d9eSNicolas Le Bayon if (i2c_node == -FDT_ERR_NOTFOUND) { 100c77c7d9eSNicolas Le Bayon int pmic_node; 101c77c7d9eSNicolas Le Bayon const fdt32_t *cuint; 102c77c7d9eSNicolas Le Bayon 10323684d0eSYann Gautier pmic_node = dt_get_pmic_node(fdt); 10423684d0eSYann Gautier if (pmic_node < 0) { 105c77c7d9eSNicolas Le Bayon return PMIC_NODE_NOT_FOUND; 10623684d0eSYann Gautier } 10723684d0eSYann Gautier 10823684d0eSYann Gautier cuint = fdt_getprop(fdt, pmic_node, "reg", NULL); 10923684d0eSYann Gautier if (cuint == NULL) { 11023684d0eSYann Gautier return -FDT_ERR_NOTFOUND; 11123684d0eSYann Gautier } 11223684d0eSYann Gautier 11323684d0eSYann Gautier pmic_i2c_addr = fdt32_to_cpu(*cuint) << 1; 11423684d0eSYann Gautier if (pmic_i2c_addr > UINT16_MAX) { 115c77c7d9eSNicolas Le Bayon return -FDT_ERR_BADVALUE; 11623684d0eSYann Gautier } 11723684d0eSYann Gautier 11823684d0eSYann Gautier i2c_node = fdt_parent_offset(fdt, pmic_node); 11923684d0eSYann Gautier if (i2c_node < 0) { 12023684d0eSYann Gautier return -FDT_ERR_NOTFOUND; 12123684d0eSYann Gautier } 122c77c7d9eSNicolas Le Bayon } 12323684d0eSYann Gautier 12423684d0eSYann Gautier dt_fill_device_info(i2c_info, i2c_node); 12523684d0eSYann Gautier if (i2c_info->base == 0U) { 12623684d0eSYann Gautier return -FDT_ERR_NOTFOUND; 12723684d0eSYann Gautier } 12823684d0eSYann Gautier 129d82d4ff0SYann Gautier return stm32_i2c_get_setup_from_fdt(fdt, i2c_node, init); 13023684d0eSYann Gautier } 13123684d0eSYann Gautier 132d82d4ff0SYann Gautier bool initialize_pmic_i2c(void) 13323684d0eSYann Gautier { 13423684d0eSYann Gautier int ret; 13523684d0eSYann Gautier struct dt_node_info i2c_info; 136d82d4ff0SYann Gautier struct i2c_handle_s *i2c = &i2c_handle; 137d82d4ff0SYann Gautier struct stm32_i2c_init_s i2c_init; 13823684d0eSYann Gautier 139d82d4ff0SYann Gautier ret = dt_pmic_i2c_config(&i2c_info, &i2c_init); 140d82d4ff0SYann Gautier if (ret < 0) { 141d82d4ff0SYann Gautier ERROR("I2C configuration failed %d\n", ret); 14223684d0eSYann Gautier panic(); 14323684d0eSYann Gautier } 14423684d0eSYann Gautier 145d82d4ff0SYann Gautier if (ret != 0) { 146d82d4ff0SYann Gautier return false; 14723684d0eSYann Gautier } 14823684d0eSYann Gautier 14923684d0eSYann Gautier /* Initialize PMIC I2C */ 150d82d4ff0SYann Gautier i2c->i2c_base_addr = i2c_info.base; 151d82d4ff0SYann Gautier i2c->dt_status = i2c_info.status; 152d82d4ff0SYann Gautier i2c->clock = i2c_info.clock; 15342822844SBenjamin Gaignard i2c->i2c_state = I2C_STATE_RESET; 154d82d4ff0SYann Gautier i2c_init.own_address1 = pmic_i2c_addr; 155d82d4ff0SYann Gautier i2c_init.addressing_mode = I2C_ADDRESSINGMODE_7BIT; 156d82d4ff0SYann Gautier i2c_init.dual_address_mode = I2C_DUALADDRESS_DISABLE; 157d82d4ff0SYann Gautier i2c_init.own_address2 = 0; 158d82d4ff0SYann Gautier i2c_init.own_address2_masks = I2C_OAR2_OA2NOMASK; 159d82d4ff0SYann Gautier i2c_init.general_call_mode = I2C_GENERALCALL_DISABLE; 160d82d4ff0SYann Gautier i2c_init.no_stretch_mode = I2C_NOSTRETCH_DISABLE; 161d82d4ff0SYann Gautier i2c_init.analog_filter = 1; 162d82d4ff0SYann Gautier i2c_init.digital_filter_coef = 0; 16323684d0eSYann Gautier 164d82d4ff0SYann Gautier ret = stm32_i2c_init(i2c, &i2c_init); 16523684d0eSYann Gautier if (ret != 0) { 16623684d0eSYann Gautier ERROR("Cannot initialize I2C %x (%d)\n", 167d82d4ff0SYann Gautier i2c->i2c_base_addr, ret); 16823684d0eSYann Gautier panic(); 16923684d0eSYann Gautier } 17023684d0eSYann Gautier 171d82d4ff0SYann Gautier if (!stm32_i2c_is_device_ready(i2c, pmic_i2c_addr, 1, 172d82d4ff0SYann Gautier I2C_TIMEOUT_BUSY_MS)) { 173d82d4ff0SYann Gautier ERROR("I2C device not ready\n"); 17423684d0eSYann Gautier panic(); 17523684d0eSYann Gautier } 17623684d0eSYann Gautier 177d82d4ff0SYann Gautier stpmic1_bind_i2c(i2c, (uint16_t)pmic_i2c_addr); 17823684d0eSYann Gautier 179d82d4ff0SYann Gautier return true; 18023684d0eSYann Gautier } 18123684d0eSYann Gautier 182f564d439SEtienne Carriere static void register_pmic_shared_peripherals(void) 183f564d439SEtienne Carriere { 184f564d439SEtienne Carriere uintptr_t i2c_base = i2c_handle.i2c_base_addr; 185f564d439SEtienne Carriere 186f564d439SEtienne Carriere if (dt_pmic_is_secure()) { 187f564d439SEtienne Carriere stm32mp_register_secure_periph_iomem(i2c_base); 188f564d439SEtienne Carriere } else { 189f564d439SEtienne Carriere if (i2c_base != 0U) { 190f564d439SEtienne Carriere stm32mp_register_non_secure_periph_iomem(i2c_base); 191f564d439SEtienne Carriere } 192f564d439SEtienne Carriere } 193f564d439SEtienne Carriere } 194f564d439SEtienne Carriere 19523684d0eSYann Gautier void initialize_pmic(void) 19623684d0eSYann Gautier { 197d82d4ff0SYann Gautier if (!initialize_pmic_i2c()) { 198d82d4ff0SYann Gautier VERBOSE("No PMIC\n"); 199d82d4ff0SYann Gautier return; 200d82d4ff0SYann Gautier } 20123684d0eSYann Gautier 202f564d439SEtienne Carriere register_pmic_shared_peripherals(); 203f564d439SEtienne Carriere 204*85fb175bSYann Gautier if (register_pmic() < 0) { 205ae7792e0SNicolas Le Bayon panic(); 206*85fb175bSYann Gautier } 207*85fb175bSYann Gautier 208*85fb175bSYann Gautier if (stpmic1_powerctrl_on() < 0) { 209*85fb175bSYann Gautier panic(); 210*85fb175bSYann Gautier } 211*85fb175bSYann Gautier 212ae7792e0SNicolas Le Bayon } 213ae7792e0SNicolas Le Bayon 214ae7792e0SNicolas Le Bayon #if DEBUG 215ae7792e0SNicolas Le Bayon void print_pmic_info_and_debug(void) 216ae7792e0SNicolas Le Bayon { 217ae7792e0SNicolas Le Bayon unsigned long pmic_version; 218ae7792e0SNicolas Le Bayon 219d82d4ff0SYann Gautier if (stpmic1_get_version(&pmic_version) != 0) { 220d82d4ff0SYann Gautier ERROR("Failed to access PMIC\n"); 22123684d0eSYann Gautier panic(); 22223684d0eSYann Gautier } 22323684d0eSYann Gautier 224d82d4ff0SYann Gautier INFO("PMIC version = 0x%02lx\n", pmic_version); 22523684d0eSYann Gautier } 226ae7792e0SNicolas Le Bayon #endif 22723684d0eSYann Gautier 22823684d0eSYann Gautier int pmic_ddr_power_init(enum ddr_type ddr_type) 22923684d0eSYann Gautier { 23023684d0eSYann Gautier bool buck3_at_1v8 = false; 23123684d0eSYann Gautier uint8_t read_val; 23223684d0eSYann Gautier int status; 23323684d0eSYann Gautier 23423684d0eSYann Gautier switch (ddr_type) { 23523684d0eSYann Gautier case STM32MP_DDR3: 23623684d0eSYann Gautier /* Set LDO3 to sync mode */ 23723684d0eSYann Gautier status = stpmic1_register_read(LDO3_CONTROL_REG, &read_val); 23823684d0eSYann Gautier if (status != 0) { 23923684d0eSYann Gautier return status; 24023684d0eSYann Gautier } 24123684d0eSYann Gautier 24223684d0eSYann Gautier read_val &= ~STPMIC1_LDO3_MODE; 24323684d0eSYann Gautier read_val &= ~STPMIC1_LDO12356_OUTPUT_MASK; 24423684d0eSYann Gautier read_val |= STPMIC1_LDO3_DDR_SEL << 24523684d0eSYann Gautier STPMIC1_LDO12356_OUTPUT_SHIFT; 24623684d0eSYann Gautier 24723684d0eSYann Gautier status = stpmic1_register_write(LDO3_CONTROL_REG, read_val); 24823684d0eSYann Gautier if (status != 0) { 24923684d0eSYann Gautier return status; 25023684d0eSYann Gautier } 25123684d0eSYann Gautier 25223684d0eSYann Gautier status = stpmic1_regulator_voltage_set("buck2", 1350); 25323684d0eSYann Gautier if (status != 0) { 25423684d0eSYann Gautier return status; 25523684d0eSYann Gautier } 25623684d0eSYann Gautier 25723684d0eSYann Gautier status = stpmic1_regulator_enable("buck2"); 25823684d0eSYann Gautier if (status != 0) { 25923684d0eSYann Gautier return status; 26023684d0eSYann Gautier } 26123684d0eSYann Gautier 26223684d0eSYann Gautier mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); 26323684d0eSYann Gautier 26423684d0eSYann Gautier status = stpmic1_regulator_enable("vref_ddr"); 26523684d0eSYann Gautier if (status != 0) { 26623684d0eSYann Gautier return status; 26723684d0eSYann Gautier } 26823684d0eSYann Gautier 26923684d0eSYann Gautier mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); 27023684d0eSYann Gautier 27123684d0eSYann Gautier status = stpmic1_regulator_enable("ldo3"); 27223684d0eSYann Gautier if (status != 0) { 27323684d0eSYann Gautier return status; 27423684d0eSYann Gautier } 27523684d0eSYann Gautier 27623684d0eSYann Gautier mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); 27723684d0eSYann Gautier break; 27823684d0eSYann Gautier 27923684d0eSYann Gautier case STM32MP_LPDDR2: 2804b549b21SYann Gautier case STM32MP_LPDDR3: 28123684d0eSYann Gautier /* 28223684d0eSYann Gautier * Set LDO3 to 1.8V 28323684d0eSYann Gautier * Set LDO3 to bypass mode if BUCK3 = 1.8V 28423684d0eSYann Gautier * Set LDO3 to normal mode if BUCK3 != 1.8V 28523684d0eSYann Gautier */ 28623684d0eSYann Gautier status = stpmic1_register_read(BUCK3_CONTROL_REG, &read_val); 28723684d0eSYann Gautier if (status != 0) { 28823684d0eSYann Gautier return status; 28923684d0eSYann Gautier } 29023684d0eSYann Gautier 29123684d0eSYann Gautier if ((read_val & STPMIC1_BUCK3_1V8) == STPMIC1_BUCK3_1V8) { 29223684d0eSYann Gautier buck3_at_1v8 = true; 29323684d0eSYann Gautier } 29423684d0eSYann Gautier 29523684d0eSYann Gautier status = stpmic1_register_read(LDO3_CONTROL_REG, &read_val); 29623684d0eSYann Gautier if (status != 0) { 29723684d0eSYann Gautier return status; 29823684d0eSYann Gautier } 29923684d0eSYann Gautier 30023684d0eSYann Gautier read_val &= ~STPMIC1_LDO3_MODE; 30123684d0eSYann Gautier read_val &= ~STPMIC1_LDO12356_OUTPUT_MASK; 30223684d0eSYann Gautier read_val |= STPMIC1_LDO3_1800000; 30323684d0eSYann Gautier if (buck3_at_1v8) { 30423684d0eSYann Gautier read_val |= STPMIC1_LDO3_MODE; 30523684d0eSYann Gautier } 30623684d0eSYann Gautier 30723684d0eSYann Gautier status = stpmic1_register_write(LDO3_CONTROL_REG, read_val); 30823684d0eSYann Gautier if (status != 0) { 30923684d0eSYann Gautier return status; 31023684d0eSYann Gautier } 31123684d0eSYann Gautier 31223684d0eSYann Gautier status = stpmic1_regulator_voltage_set("buck2", 1200); 31323684d0eSYann Gautier if (status != 0) { 31423684d0eSYann Gautier return status; 31523684d0eSYann Gautier } 31623684d0eSYann Gautier 31723684d0eSYann Gautier status = stpmic1_regulator_enable("ldo3"); 31823684d0eSYann Gautier if (status != 0) { 31923684d0eSYann Gautier return status; 32023684d0eSYann Gautier } 32123684d0eSYann Gautier 32223684d0eSYann Gautier mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); 32323684d0eSYann Gautier 32423684d0eSYann Gautier status = stpmic1_regulator_enable("buck2"); 32523684d0eSYann Gautier if (status != 0) { 32623684d0eSYann Gautier return status; 32723684d0eSYann Gautier } 32823684d0eSYann Gautier 32923684d0eSYann Gautier mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); 33023684d0eSYann Gautier 33123684d0eSYann Gautier status = stpmic1_regulator_enable("vref_ddr"); 33223684d0eSYann Gautier if (status != 0) { 33323684d0eSYann Gautier return status; 33423684d0eSYann Gautier } 33523684d0eSYann Gautier 33623684d0eSYann Gautier mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); 33723684d0eSYann Gautier break; 33823684d0eSYann Gautier 33923684d0eSYann Gautier default: 34023684d0eSYann Gautier break; 34123684d0eSYann Gautier }; 34223684d0eSYann Gautier 34323684d0eSYann Gautier return 0; 34423684d0eSYann Gautier } 345*85fb175bSYann Gautier 346*85fb175bSYann Gautier enum { 347*85fb175bSYann Gautier STPMIC1_BUCK1 = 0, 348*85fb175bSYann Gautier STPMIC1_BUCK2, 349*85fb175bSYann Gautier STPMIC1_BUCK3, 350*85fb175bSYann Gautier STPMIC1_BUCK4, 351*85fb175bSYann Gautier STPMIC1_LDO1, 352*85fb175bSYann Gautier STPMIC1_LDO2, 353*85fb175bSYann Gautier STPMIC1_LDO3, 354*85fb175bSYann Gautier STPMIC1_LDO4, 355*85fb175bSYann Gautier STPMIC1_LDO5, 356*85fb175bSYann Gautier STPMIC1_LDO6, 357*85fb175bSYann Gautier STPMIC1_VREF_DDR, 358*85fb175bSYann Gautier STPMIC1_BOOST, 359*85fb175bSYann Gautier STPMIC1_VBUS_OTG, 360*85fb175bSYann Gautier STPMIC1_SW_OUT, 361*85fb175bSYann Gautier }; 362*85fb175bSYann Gautier 363*85fb175bSYann Gautier static int pmic_set_state(const struct regul_description *desc, bool enable) 364*85fb175bSYann Gautier { 365*85fb175bSYann Gautier VERBOSE("%s: set state to %u\n", desc->node_name, enable); 366*85fb175bSYann Gautier 367*85fb175bSYann Gautier if (enable == STATE_ENABLE) { 368*85fb175bSYann Gautier return stpmic1_regulator_enable(desc->node_name); 369*85fb175bSYann Gautier } else { 370*85fb175bSYann Gautier return stpmic1_regulator_disable(desc->node_name); 371*85fb175bSYann Gautier } 372*85fb175bSYann Gautier } 373*85fb175bSYann Gautier 374*85fb175bSYann Gautier static int pmic_get_state(const struct regul_description *desc) 375*85fb175bSYann Gautier { 376*85fb175bSYann Gautier VERBOSE("%s: get state\n", desc->node_name); 377*85fb175bSYann Gautier 378*85fb175bSYann Gautier return stpmic1_is_regulator_enabled(desc->node_name); 379*85fb175bSYann Gautier } 380*85fb175bSYann Gautier 381*85fb175bSYann Gautier static int pmic_get_voltage(const struct regul_description *desc) 382*85fb175bSYann Gautier { 383*85fb175bSYann Gautier VERBOSE("%s: get volt\n", desc->node_name); 384*85fb175bSYann Gautier 385*85fb175bSYann Gautier return stpmic1_regulator_voltage_get(desc->node_name); 386*85fb175bSYann Gautier } 387*85fb175bSYann Gautier 388*85fb175bSYann Gautier static int pmic_set_voltage(const struct regul_description *desc, uint16_t mv) 389*85fb175bSYann Gautier { 390*85fb175bSYann Gautier VERBOSE("%s: get volt\n", desc->node_name); 391*85fb175bSYann Gautier 392*85fb175bSYann Gautier return stpmic1_regulator_voltage_set(desc->node_name, mv); 393*85fb175bSYann Gautier } 394*85fb175bSYann Gautier 395*85fb175bSYann Gautier static int pmic_list_voltages(const struct regul_description *desc, 396*85fb175bSYann Gautier const uint16_t **levels, size_t *count) 397*85fb175bSYann Gautier { 398*85fb175bSYann Gautier VERBOSE("%s: list volt\n", desc->node_name); 399*85fb175bSYann Gautier 400*85fb175bSYann Gautier return stpmic1_regulator_levels_mv(desc->node_name, levels, count); 401*85fb175bSYann Gautier } 402*85fb175bSYann Gautier 403*85fb175bSYann Gautier static int pmic_set_flag(const struct regul_description *desc, uint16_t flag) 404*85fb175bSYann Gautier { 405*85fb175bSYann Gautier VERBOSE("%s: set_flag 0x%x\n", desc->node_name, flag); 406*85fb175bSYann Gautier 407*85fb175bSYann Gautier switch (flag) { 408*85fb175bSYann Gautier case REGUL_OCP: 409*85fb175bSYann Gautier return stpmic1_regulator_icc_set(desc->node_name); 410*85fb175bSYann Gautier 411*85fb175bSYann Gautier case REGUL_ACTIVE_DISCHARGE: 412*85fb175bSYann Gautier return stpmic1_active_discharge_mode_set(desc->node_name); 413*85fb175bSYann Gautier 414*85fb175bSYann Gautier case REGUL_PULL_DOWN: 415*85fb175bSYann Gautier return stpmic1_regulator_pull_down_set(desc->node_name); 416*85fb175bSYann Gautier 417*85fb175bSYann Gautier case REGUL_MASK_RESET: 418*85fb175bSYann Gautier return stpmic1_regulator_mask_reset_set(desc->node_name); 419*85fb175bSYann Gautier 420*85fb175bSYann Gautier case REGUL_SINK_SOURCE: 421*85fb175bSYann Gautier return stpmic1_regulator_sink_mode_set(desc->node_name); 422*85fb175bSYann Gautier 423*85fb175bSYann Gautier case REGUL_ENABLE_BYPASS: 424*85fb175bSYann Gautier return stpmic1_regulator_bypass_mode_set(desc->node_name); 425*85fb175bSYann Gautier 426*85fb175bSYann Gautier default: 427*85fb175bSYann Gautier return -EINVAL; 428*85fb175bSYann Gautier } 429*85fb175bSYann Gautier } 430*85fb175bSYann Gautier 431*85fb175bSYann Gautier struct regul_ops pmic_ops = { 432*85fb175bSYann Gautier .set_state = pmic_set_state, 433*85fb175bSYann Gautier .get_state = pmic_get_state, 434*85fb175bSYann Gautier .set_voltage = pmic_set_voltage, 435*85fb175bSYann Gautier .get_voltage = pmic_get_voltage, 436*85fb175bSYann Gautier .list_voltages = pmic_list_voltages, 437*85fb175bSYann Gautier .set_flag = pmic_set_flag, 438*85fb175bSYann Gautier }; 439*85fb175bSYann Gautier 440*85fb175bSYann Gautier #define DEFINE_REGU(name) { \ 441*85fb175bSYann Gautier .node_name = name, \ 442*85fb175bSYann Gautier .ops = &pmic_ops, \ 443*85fb175bSYann Gautier .driver_data = NULL, \ 444*85fb175bSYann Gautier .enable_ramp_delay = 1000, \ 445*85fb175bSYann Gautier } 446*85fb175bSYann Gautier 447*85fb175bSYann Gautier static const struct regul_description pmic_regs[] = { 448*85fb175bSYann Gautier [STPMIC1_BUCK1] = DEFINE_REGU("buck1"), 449*85fb175bSYann Gautier [STPMIC1_BUCK2] = DEFINE_REGU("buck2"), 450*85fb175bSYann Gautier [STPMIC1_BUCK3] = DEFINE_REGU("buck3"), 451*85fb175bSYann Gautier [STPMIC1_BUCK4] = DEFINE_REGU("buck4"), 452*85fb175bSYann Gautier [STPMIC1_LDO1] = DEFINE_REGU("ldo1"), 453*85fb175bSYann Gautier [STPMIC1_LDO2] = DEFINE_REGU("ldo2"), 454*85fb175bSYann Gautier [STPMIC1_LDO3] = DEFINE_REGU("ldo3"), 455*85fb175bSYann Gautier [STPMIC1_LDO4] = DEFINE_REGU("ldo4"), 456*85fb175bSYann Gautier [STPMIC1_LDO5] = DEFINE_REGU("ldo5"), 457*85fb175bSYann Gautier [STPMIC1_LDO6] = DEFINE_REGU("ldo6"), 458*85fb175bSYann Gautier [STPMIC1_VREF_DDR] = DEFINE_REGU("vref_ddr"), 459*85fb175bSYann Gautier [STPMIC1_BOOST] = DEFINE_REGU("boost"), 460*85fb175bSYann Gautier [STPMIC1_VBUS_OTG] = DEFINE_REGU("pwr_sw1"), 461*85fb175bSYann Gautier [STPMIC1_SW_OUT] = DEFINE_REGU("pwr_sw2"), 462*85fb175bSYann Gautier }; 463*85fb175bSYann Gautier 464*85fb175bSYann Gautier #define NB_REG ARRAY_SIZE(pmic_regs) 465*85fb175bSYann Gautier 466*85fb175bSYann Gautier static int register_pmic(void) 467*85fb175bSYann Gautier { 468*85fb175bSYann Gautier void *fdt; 469*85fb175bSYann Gautier int pmic_node, regulators_node, subnode; 470*85fb175bSYann Gautier 471*85fb175bSYann Gautier VERBOSE("Register pmic\n"); 472*85fb175bSYann Gautier 473*85fb175bSYann Gautier if (fdt_get_address(&fdt) == 0) { 474*85fb175bSYann Gautier return -FDT_ERR_NOTFOUND; 475*85fb175bSYann Gautier } 476*85fb175bSYann Gautier 477*85fb175bSYann Gautier pmic_node = dt_get_pmic_node(fdt); 478*85fb175bSYann Gautier if (pmic_node < 0) { 479*85fb175bSYann Gautier return pmic_node; 480*85fb175bSYann Gautier } 481*85fb175bSYann Gautier 482*85fb175bSYann Gautier regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators"); 483*85fb175bSYann Gautier if (regulators_node < 0) { 484*85fb175bSYann Gautier return -ENOENT; 485*85fb175bSYann Gautier } 486*85fb175bSYann Gautier 487*85fb175bSYann Gautier fdt_for_each_subnode(subnode, fdt, regulators_node) { 488*85fb175bSYann Gautier const char *reg_name = fdt_get_name(fdt, subnode, NULL); 489*85fb175bSYann Gautier const struct regul_description *desc; 490*85fb175bSYann Gautier unsigned int i; 491*85fb175bSYann Gautier int ret; 492*85fb175bSYann Gautier 493*85fb175bSYann Gautier for (i = 0; i < NB_REG; i++) { 494*85fb175bSYann Gautier desc = &pmic_regs[i]; 495*85fb175bSYann Gautier if (strcmp(desc->node_name, reg_name) == 0) { 496*85fb175bSYann Gautier break; 497*85fb175bSYann Gautier } 498*85fb175bSYann Gautier } 499*85fb175bSYann Gautier assert(i < NB_REG); 500*85fb175bSYann Gautier 501*85fb175bSYann Gautier ret = regulator_register(desc, subnode); 502*85fb175bSYann Gautier if (ret != 0) { 503*85fb175bSYann Gautier WARN("%s:%d failed to register %s\n", __func__, 504*85fb175bSYann Gautier __LINE__, reg_name); 505*85fb175bSYann Gautier return ret; 506*85fb175bSYann Gautier } 507*85fb175bSYann Gautier } 508*85fb175bSYann Gautier 509*85fb175bSYann Gautier return 0; 510*85fb175bSYann Gautier } 511