18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * tps65910.c -- TI tps65910 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright 2010 Texas Instruments Inc. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Author: Graeme Gregory <gg@slimlogic.co.uk> 88c2ecf20Sopenharmony_ci * Author: Jorge Eduardo Candelaria <jedu@slimlogic.co.uk> 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/kernel.h> 128c2ecf20Sopenharmony_ci#include <linux/module.h> 138c2ecf20Sopenharmony_ci#include <linux/init.h> 148c2ecf20Sopenharmony_ci#include <linux/err.h> 158c2ecf20Sopenharmony_ci#include <linux/of.h> 168c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 178c2ecf20Sopenharmony_ci#include <linux/regulator/driver.h> 188c2ecf20Sopenharmony_ci#include <linux/regulator/machine.h> 198c2ecf20Sopenharmony_ci#include <linux/slab.h> 208c2ecf20Sopenharmony_ci#include <linux/gpio.h> 218c2ecf20Sopenharmony_ci#include <linux/mfd/tps65910.h> 228c2ecf20Sopenharmony_ci#include <linux/regulator/of_regulator.h> 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#define TPS65910_SUPPLY_STATE_ENABLED 0x1 258c2ecf20Sopenharmony_ci#define EXT_SLEEP_CONTROL (TPS65910_SLEEP_CONTROL_EXT_INPUT_EN1 | \ 268c2ecf20Sopenharmony_ci TPS65910_SLEEP_CONTROL_EXT_INPUT_EN2 | \ 278c2ecf20Sopenharmony_ci TPS65910_SLEEP_CONTROL_EXT_INPUT_EN3 | \ 288c2ecf20Sopenharmony_ci TPS65911_SLEEP_CONTROL_EXT_INPUT_SLEEP) 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci/* supported VIO voltages in microvolts */ 318c2ecf20Sopenharmony_cistatic const unsigned int VIO_VSEL_table[] = { 328c2ecf20Sopenharmony_ci 1500000, 1800000, 2500000, 3300000, 338c2ecf20Sopenharmony_ci}; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci/* VSEL tables for TPS65910 specific LDOs and dcdc's */ 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci/* supported VRTC voltages in microvolts */ 388c2ecf20Sopenharmony_cistatic const unsigned int VRTC_VSEL_table[] = { 398c2ecf20Sopenharmony_ci 1800000, 408c2ecf20Sopenharmony_ci}; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci/* supported VDD3 voltages in microvolts */ 438c2ecf20Sopenharmony_cistatic const unsigned int VDD3_VSEL_table[] = { 448c2ecf20Sopenharmony_ci 5000000, 458c2ecf20Sopenharmony_ci}; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci/* supported VDIG1 voltages in microvolts */ 488c2ecf20Sopenharmony_cistatic const unsigned int VDIG1_VSEL_table[] = { 498c2ecf20Sopenharmony_ci 1200000, 1500000, 1800000, 2700000, 508c2ecf20Sopenharmony_ci}; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci/* supported VDIG2 voltages in microvolts */ 538c2ecf20Sopenharmony_cistatic const unsigned int VDIG2_VSEL_table[] = { 548c2ecf20Sopenharmony_ci 1000000, 1100000, 1200000, 1800000, 558c2ecf20Sopenharmony_ci}; 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci/* supported VPLL voltages in microvolts */ 588c2ecf20Sopenharmony_cistatic const unsigned int VPLL_VSEL_table[] = { 598c2ecf20Sopenharmony_ci 1000000, 1100000, 1800000, 2500000, 608c2ecf20Sopenharmony_ci}; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci/* supported VDAC voltages in microvolts */ 638c2ecf20Sopenharmony_cistatic const unsigned int VDAC_VSEL_table[] = { 648c2ecf20Sopenharmony_ci 1800000, 2600000, 2800000, 2850000, 658c2ecf20Sopenharmony_ci}; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci/* supported VAUX1 voltages in microvolts */ 688c2ecf20Sopenharmony_cistatic const unsigned int VAUX1_VSEL_table[] = { 698c2ecf20Sopenharmony_ci 1800000, 2500000, 2800000, 2850000, 708c2ecf20Sopenharmony_ci}; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci/* supported VAUX2 voltages in microvolts */ 738c2ecf20Sopenharmony_cistatic const unsigned int VAUX2_VSEL_table[] = { 748c2ecf20Sopenharmony_ci 1800000, 2800000, 2900000, 3300000, 758c2ecf20Sopenharmony_ci}; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci/* supported VAUX33 voltages in microvolts */ 788c2ecf20Sopenharmony_cistatic const unsigned int VAUX33_VSEL_table[] = { 798c2ecf20Sopenharmony_ci 1800000, 2000000, 2800000, 3300000, 808c2ecf20Sopenharmony_ci}; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci/* supported VMMC voltages in microvolts */ 838c2ecf20Sopenharmony_cistatic const unsigned int VMMC_VSEL_table[] = { 848c2ecf20Sopenharmony_ci 1800000, 2800000, 3000000, 3300000, 858c2ecf20Sopenharmony_ci}; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci/* supported BBCH voltages in microvolts */ 888c2ecf20Sopenharmony_cistatic const unsigned int VBB_VSEL_table[] = { 898c2ecf20Sopenharmony_ci 3000000, 2520000, 3150000, 5000000, 908c2ecf20Sopenharmony_ci}; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_cistruct tps_info { 938c2ecf20Sopenharmony_ci const char *name; 948c2ecf20Sopenharmony_ci const char *vin_name; 958c2ecf20Sopenharmony_ci u8 n_voltages; 968c2ecf20Sopenharmony_ci const unsigned int *voltage_table; 978c2ecf20Sopenharmony_ci int enable_time_us; 988c2ecf20Sopenharmony_ci}; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_cistatic struct tps_info tps65910_regs[] = { 1018c2ecf20Sopenharmony_ci { 1028c2ecf20Sopenharmony_ci .name = "vrtc", 1038c2ecf20Sopenharmony_ci .vin_name = "vcc7", 1048c2ecf20Sopenharmony_ci .n_voltages = ARRAY_SIZE(VRTC_VSEL_table), 1058c2ecf20Sopenharmony_ci .voltage_table = VRTC_VSEL_table, 1068c2ecf20Sopenharmony_ci .enable_time_us = 2200, 1078c2ecf20Sopenharmony_ci }, 1088c2ecf20Sopenharmony_ci { 1098c2ecf20Sopenharmony_ci .name = "vio", 1108c2ecf20Sopenharmony_ci .vin_name = "vccio", 1118c2ecf20Sopenharmony_ci .n_voltages = ARRAY_SIZE(VIO_VSEL_table), 1128c2ecf20Sopenharmony_ci .voltage_table = VIO_VSEL_table, 1138c2ecf20Sopenharmony_ci .enable_time_us = 350, 1148c2ecf20Sopenharmony_ci }, 1158c2ecf20Sopenharmony_ci { 1168c2ecf20Sopenharmony_ci .name = "vdd1", 1178c2ecf20Sopenharmony_ci .vin_name = "vcc1", 1188c2ecf20Sopenharmony_ci .enable_time_us = 350, 1198c2ecf20Sopenharmony_ci }, 1208c2ecf20Sopenharmony_ci { 1218c2ecf20Sopenharmony_ci .name = "vdd2", 1228c2ecf20Sopenharmony_ci .vin_name = "vcc2", 1238c2ecf20Sopenharmony_ci .enable_time_us = 350, 1248c2ecf20Sopenharmony_ci }, 1258c2ecf20Sopenharmony_ci { 1268c2ecf20Sopenharmony_ci .name = "vdd3", 1278c2ecf20Sopenharmony_ci .n_voltages = ARRAY_SIZE(VDD3_VSEL_table), 1288c2ecf20Sopenharmony_ci .voltage_table = VDD3_VSEL_table, 1298c2ecf20Sopenharmony_ci .enable_time_us = 200, 1308c2ecf20Sopenharmony_ci }, 1318c2ecf20Sopenharmony_ci { 1328c2ecf20Sopenharmony_ci .name = "vdig1", 1338c2ecf20Sopenharmony_ci .vin_name = "vcc6", 1348c2ecf20Sopenharmony_ci .n_voltages = ARRAY_SIZE(VDIG1_VSEL_table), 1358c2ecf20Sopenharmony_ci .voltage_table = VDIG1_VSEL_table, 1368c2ecf20Sopenharmony_ci .enable_time_us = 100, 1378c2ecf20Sopenharmony_ci }, 1388c2ecf20Sopenharmony_ci { 1398c2ecf20Sopenharmony_ci .name = "vdig2", 1408c2ecf20Sopenharmony_ci .vin_name = "vcc6", 1418c2ecf20Sopenharmony_ci .n_voltages = ARRAY_SIZE(VDIG2_VSEL_table), 1428c2ecf20Sopenharmony_ci .voltage_table = VDIG2_VSEL_table, 1438c2ecf20Sopenharmony_ci .enable_time_us = 100, 1448c2ecf20Sopenharmony_ci }, 1458c2ecf20Sopenharmony_ci { 1468c2ecf20Sopenharmony_ci .name = "vpll", 1478c2ecf20Sopenharmony_ci .vin_name = "vcc5", 1488c2ecf20Sopenharmony_ci .n_voltages = ARRAY_SIZE(VPLL_VSEL_table), 1498c2ecf20Sopenharmony_ci .voltage_table = VPLL_VSEL_table, 1508c2ecf20Sopenharmony_ci .enable_time_us = 100, 1518c2ecf20Sopenharmony_ci }, 1528c2ecf20Sopenharmony_ci { 1538c2ecf20Sopenharmony_ci .name = "vdac", 1548c2ecf20Sopenharmony_ci .vin_name = "vcc5", 1558c2ecf20Sopenharmony_ci .n_voltages = ARRAY_SIZE(VDAC_VSEL_table), 1568c2ecf20Sopenharmony_ci .voltage_table = VDAC_VSEL_table, 1578c2ecf20Sopenharmony_ci .enable_time_us = 100, 1588c2ecf20Sopenharmony_ci }, 1598c2ecf20Sopenharmony_ci { 1608c2ecf20Sopenharmony_ci .name = "vaux1", 1618c2ecf20Sopenharmony_ci .vin_name = "vcc4", 1628c2ecf20Sopenharmony_ci .n_voltages = ARRAY_SIZE(VAUX1_VSEL_table), 1638c2ecf20Sopenharmony_ci .voltage_table = VAUX1_VSEL_table, 1648c2ecf20Sopenharmony_ci .enable_time_us = 100, 1658c2ecf20Sopenharmony_ci }, 1668c2ecf20Sopenharmony_ci { 1678c2ecf20Sopenharmony_ci .name = "vaux2", 1688c2ecf20Sopenharmony_ci .vin_name = "vcc4", 1698c2ecf20Sopenharmony_ci .n_voltages = ARRAY_SIZE(VAUX2_VSEL_table), 1708c2ecf20Sopenharmony_ci .voltage_table = VAUX2_VSEL_table, 1718c2ecf20Sopenharmony_ci .enable_time_us = 100, 1728c2ecf20Sopenharmony_ci }, 1738c2ecf20Sopenharmony_ci { 1748c2ecf20Sopenharmony_ci .name = "vaux33", 1758c2ecf20Sopenharmony_ci .vin_name = "vcc3", 1768c2ecf20Sopenharmony_ci .n_voltages = ARRAY_SIZE(VAUX33_VSEL_table), 1778c2ecf20Sopenharmony_ci .voltage_table = VAUX33_VSEL_table, 1788c2ecf20Sopenharmony_ci .enable_time_us = 100, 1798c2ecf20Sopenharmony_ci }, 1808c2ecf20Sopenharmony_ci { 1818c2ecf20Sopenharmony_ci .name = "vmmc", 1828c2ecf20Sopenharmony_ci .vin_name = "vcc3", 1838c2ecf20Sopenharmony_ci .n_voltages = ARRAY_SIZE(VMMC_VSEL_table), 1848c2ecf20Sopenharmony_ci .voltage_table = VMMC_VSEL_table, 1858c2ecf20Sopenharmony_ci .enable_time_us = 100, 1868c2ecf20Sopenharmony_ci }, 1878c2ecf20Sopenharmony_ci { 1888c2ecf20Sopenharmony_ci .name = "vbb", 1898c2ecf20Sopenharmony_ci .vin_name = "vcc7", 1908c2ecf20Sopenharmony_ci .n_voltages = ARRAY_SIZE(VBB_VSEL_table), 1918c2ecf20Sopenharmony_ci .voltage_table = VBB_VSEL_table, 1928c2ecf20Sopenharmony_ci }, 1938c2ecf20Sopenharmony_ci}; 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_cistatic struct tps_info tps65911_regs[] = { 1968c2ecf20Sopenharmony_ci { 1978c2ecf20Sopenharmony_ci .name = "vrtc", 1988c2ecf20Sopenharmony_ci .vin_name = "vcc7", 1998c2ecf20Sopenharmony_ci .enable_time_us = 2200, 2008c2ecf20Sopenharmony_ci }, 2018c2ecf20Sopenharmony_ci { 2028c2ecf20Sopenharmony_ci .name = "vio", 2038c2ecf20Sopenharmony_ci .vin_name = "vccio", 2048c2ecf20Sopenharmony_ci .n_voltages = ARRAY_SIZE(VIO_VSEL_table), 2058c2ecf20Sopenharmony_ci .voltage_table = VIO_VSEL_table, 2068c2ecf20Sopenharmony_ci .enable_time_us = 350, 2078c2ecf20Sopenharmony_ci }, 2088c2ecf20Sopenharmony_ci { 2098c2ecf20Sopenharmony_ci .name = "vdd1", 2108c2ecf20Sopenharmony_ci .vin_name = "vcc1", 2118c2ecf20Sopenharmony_ci .n_voltages = 0x4C, 2128c2ecf20Sopenharmony_ci .enable_time_us = 350, 2138c2ecf20Sopenharmony_ci }, 2148c2ecf20Sopenharmony_ci { 2158c2ecf20Sopenharmony_ci .name = "vdd2", 2168c2ecf20Sopenharmony_ci .vin_name = "vcc2", 2178c2ecf20Sopenharmony_ci .n_voltages = 0x4C, 2188c2ecf20Sopenharmony_ci .enable_time_us = 350, 2198c2ecf20Sopenharmony_ci }, 2208c2ecf20Sopenharmony_ci { 2218c2ecf20Sopenharmony_ci .name = "vddctrl", 2228c2ecf20Sopenharmony_ci .n_voltages = 0x44, 2238c2ecf20Sopenharmony_ci .enable_time_us = 900, 2248c2ecf20Sopenharmony_ci }, 2258c2ecf20Sopenharmony_ci { 2268c2ecf20Sopenharmony_ci .name = "ldo1", 2278c2ecf20Sopenharmony_ci .vin_name = "vcc6", 2288c2ecf20Sopenharmony_ci .n_voltages = 0x33, 2298c2ecf20Sopenharmony_ci .enable_time_us = 420, 2308c2ecf20Sopenharmony_ci }, 2318c2ecf20Sopenharmony_ci { 2328c2ecf20Sopenharmony_ci .name = "ldo2", 2338c2ecf20Sopenharmony_ci .vin_name = "vcc6", 2348c2ecf20Sopenharmony_ci .n_voltages = 0x33, 2358c2ecf20Sopenharmony_ci .enable_time_us = 420, 2368c2ecf20Sopenharmony_ci }, 2378c2ecf20Sopenharmony_ci { 2388c2ecf20Sopenharmony_ci .name = "ldo3", 2398c2ecf20Sopenharmony_ci .vin_name = "vcc5", 2408c2ecf20Sopenharmony_ci .n_voltages = 0x1A, 2418c2ecf20Sopenharmony_ci .enable_time_us = 230, 2428c2ecf20Sopenharmony_ci }, 2438c2ecf20Sopenharmony_ci { 2448c2ecf20Sopenharmony_ci .name = "ldo4", 2458c2ecf20Sopenharmony_ci .vin_name = "vcc5", 2468c2ecf20Sopenharmony_ci .n_voltages = 0x33, 2478c2ecf20Sopenharmony_ci .enable_time_us = 230, 2488c2ecf20Sopenharmony_ci }, 2498c2ecf20Sopenharmony_ci { 2508c2ecf20Sopenharmony_ci .name = "ldo5", 2518c2ecf20Sopenharmony_ci .vin_name = "vcc4", 2528c2ecf20Sopenharmony_ci .n_voltages = 0x1A, 2538c2ecf20Sopenharmony_ci .enable_time_us = 230, 2548c2ecf20Sopenharmony_ci }, 2558c2ecf20Sopenharmony_ci { 2568c2ecf20Sopenharmony_ci .name = "ldo6", 2578c2ecf20Sopenharmony_ci .vin_name = "vcc3", 2588c2ecf20Sopenharmony_ci .n_voltages = 0x1A, 2598c2ecf20Sopenharmony_ci .enable_time_us = 230, 2608c2ecf20Sopenharmony_ci }, 2618c2ecf20Sopenharmony_ci { 2628c2ecf20Sopenharmony_ci .name = "ldo7", 2638c2ecf20Sopenharmony_ci .vin_name = "vcc3", 2648c2ecf20Sopenharmony_ci .n_voltages = 0x1A, 2658c2ecf20Sopenharmony_ci .enable_time_us = 230, 2668c2ecf20Sopenharmony_ci }, 2678c2ecf20Sopenharmony_ci { 2688c2ecf20Sopenharmony_ci .name = "ldo8", 2698c2ecf20Sopenharmony_ci .vin_name = "vcc3", 2708c2ecf20Sopenharmony_ci .n_voltages = 0x1A, 2718c2ecf20Sopenharmony_ci .enable_time_us = 230, 2728c2ecf20Sopenharmony_ci }, 2738c2ecf20Sopenharmony_ci}; 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci#define EXT_CONTROL_REG_BITS(id, regs_offs, bits) (((regs_offs) << 8) | (bits)) 2768c2ecf20Sopenharmony_cistatic unsigned int tps65910_ext_sleep_control[] = { 2778c2ecf20Sopenharmony_ci 0, 2788c2ecf20Sopenharmony_ci EXT_CONTROL_REG_BITS(VIO, 1, 0), 2798c2ecf20Sopenharmony_ci EXT_CONTROL_REG_BITS(VDD1, 1, 1), 2808c2ecf20Sopenharmony_ci EXT_CONTROL_REG_BITS(VDD2, 1, 2), 2818c2ecf20Sopenharmony_ci EXT_CONTROL_REG_BITS(VDD3, 1, 3), 2828c2ecf20Sopenharmony_ci EXT_CONTROL_REG_BITS(VDIG1, 0, 1), 2838c2ecf20Sopenharmony_ci EXT_CONTROL_REG_BITS(VDIG2, 0, 2), 2848c2ecf20Sopenharmony_ci EXT_CONTROL_REG_BITS(VPLL, 0, 6), 2858c2ecf20Sopenharmony_ci EXT_CONTROL_REG_BITS(VDAC, 0, 7), 2868c2ecf20Sopenharmony_ci EXT_CONTROL_REG_BITS(VAUX1, 0, 3), 2878c2ecf20Sopenharmony_ci EXT_CONTROL_REG_BITS(VAUX2, 0, 4), 2888c2ecf20Sopenharmony_ci EXT_CONTROL_REG_BITS(VAUX33, 0, 5), 2898c2ecf20Sopenharmony_ci EXT_CONTROL_REG_BITS(VMMC, 0, 0), 2908c2ecf20Sopenharmony_ci}; 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_cistatic unsigned int tps65911_ext_sleep_control[] = { 2938c2ecf20Sopenharmony_ci 0, 2948c2ecf20Sopenharmony_ci EXT_CONTROL_REG_BITS(VIO, 1, 0), 2958c2ecf20Sopenharmony_ci EXT_CONTROL_REG_BITS(VDD1, 1, 1), 2968c2ecf20Sopenharmony_ci EXT_CONTROL_REG_BITS(VDD2, 1, 2), 2978c2ecf20Sopenharmony_ci EXT_CONTROL_REG_BITS(VDDCTRL, 1, 3), 2988c2ecf20Sopenharmony_ci EXT_CONTROL_REG_BITS(LDO1, 0, 1), 2998c2ecf20Sopenharmony_ci EXT_CONTROL_REG_BITS(LDO2, 0, 2), 3008c2ecf20Sopenharmony_ci EXT_CONTROL_REG_BITS(LDO3, 0, 7), 3018c2ecf20Sopenharmony_ci EXT_CONTROL_REG_BITS(LDO4, 0, 6), 3028c2ecf20Sopenharmony_ci EXT_CONTROL_REG_BITS(LDO5, 0, 3), 3038c2ecf20Sopenharmony_ci EXT_CONTROL_REG_BITS(LDO6, 0, 0), 3048c2ecf20Sopenharmony_ci EXT_CONTROL_REG_BITS(LDO7, 0, 5), 3058c2ecf20Sopenharmony_ci EXT_CONTROL_REG_BITS(LDO8, 0, 4), 3068c2ecf20Sopenharmony_ci}; 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_cistruct tps65910_reg { 3098c2ecf20Sopenharmony_ci struct regulator_desc *desc; 3108c2ecf20Sopenharmony_ci struct tps65910 *mfd; 3118c2ecf20Sopenharmony_ci struct regulator_dev **rdev; 3128c2ecf20Sopenharmony_ci struct tps_info **info; 3138c2ecf20Sopenharmony_ci int num_regulators; 3148c2ecf20Sopenharmony_ci int mode; 3158c2ecf20Sopenharmony_ci int (*get_ctrl_reg)(int); 3168c2ecf20Sopenharmony_ci unsigned int *ext_sleep_control; 3178c2ecf20Sopenharmony_ci unsigned int board_ext_control[TPS65910_NUM_REGS]; 3188c2ecf20Sopenharmony_ci}; 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_cistatic int tps65910_get_ctrl_register(int id) 3218c2ecf20Sopenharmony_ci{ 3228c2ecf20Sopenharmony_ci switch (id) { 3238c2ecf20Sopenharmony_ci case TPS65910_REG_VRTC: 3248c2ecf20Sopenharmony_ci return TPS65910_VRTC; 3258c2ecf20Sopenharmony_ci case TPS65910_REG_VIO: 3268c2ecf20Sopenharmony_ci return TPS65910_VIO; 3278c2ecf20Sopenharmony_ci case TPS65910_REG_VDD1: 3288c2ecf20Sopenharmony_ci return TPS65910_VDD1; 3298c2ecf20Sopenharmony_ci case TPS65910_REG_VDD2: 3308c2ecf20Sopenharmony_ci return TPS65910_VDD2; 3318c2ecf20Sopenharmony_ci case TPS65910_REG_VDD3: 3328c2ecf20Sopenharmony_ci return TPS65910_VDD3; 3338c2ecf20Sopenharmony_ci case TPS65910_REG_VDIG1: 3348c2ecf20Sopenharmony_ci return TPS65910_VDIG1; 3358c2ecf20Sopenharmony_ci case TPS65910_REG_VDIG2: 3368c2ecf20Sopenharmony_ci return TPS65910_VDIG2; 3378c2ecf20Sopenharmony_ci case TPS65910_REG_VPLL: 3388c2ecf20Sopenharmony_ci return TPS65910_VPLL; 3398c2ecf20Sopenharmony_ci case TPS65910_REG_VDAC: 3408c2ecf20Sopenharmony_ci return TPS65910_VDAC; 3418c2ecf20Sopenharmony_ci case TPS65910_REG_VAUX1: 3428c2ecf20Sopenharmony_ci return TPS65910_VAUX1; 3438c2ecf20Sopenharmony_ci case TPS65910_REG_VAUX2: 3448c2ecf20Sopenharmony_ci return TPS65910_VAUX2; 3458c2ecf20Sopenharmony_ci case TPS65910_REG_VAUX33: 3468c2ecf20Sopenharmony_ci return TPS65910_VAUX33; 3478c2ecf20Sopenharmony_ci case TPS65910_REG_VMMC: 3488c2ecf20Sopenharmony_ci return TPS65910_VMMC; 3498c2ecf20Sopenharmony_ci case TPS65910_REG_VBB: 3508c2ecf20Sopenharmony_ci return TPS65910_BBCH; 3518c2ecf20Sopenharmony_ci default: 3528c2ecf20Sopenharmony_ci return -EINVAL; 3538c2ecf20Sopenharmony_ci } 3548c2ecf20Sopenharmony_ci} 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_cistatic int tps65911_get_ctrl_register(int id) 3578c2ecf20Sopenharmony_ci{ 3588c2ecf20Sopenharmony_ci switch (id) { 3598c2ecf20Sopenharmony_ci case TPS65910_REG_VRTC: 3608c2ecf20Sopenharmony_ci return TPS65910_VRTC; 3618c2ecf20Sopenharmony_ci case TPS65910_REG_VIO: 3628c2ecf20Sopenharmony_ci return TPS65910_VIO; 3638c2ecf20Sopenharmony_ci case TPS65910_REG_VDD1: 3648c2ecf20Sopenharmony_ci return TPS65910_VDD1; 3658c2ecf20Sopenharmony_ci case TPS65910_REG_VDD2: 3668c2ecf20Sopenharmony_ci return TPS65910_VDD2; 3678c2ecf20Sopenharmony_ci case TPS65911_REG_VDDCTRL: 3688c2ecf20Sopenharmony_ci return TPS65911_VDDCTRL; 3698c2ecf20Sopenharmony_ci case TPS65911_REG_LDO1: 3708c2ecf20Sopenharmony_ci return TPS65911_LDO1; 3718c2ecf20Sopenharmony_ci case TPS65911_REG_LDO2: 3728c2ecf20Sopenharmony_ci return TPS65911_LDO2; 3738c2ecf20Sopenharmony_ci case TPS65911_REG_LDO3: 3748c2ecf20Sopenharmony_ci return TPS65911_LDO3; 3758c2ecf20Sopenharmony_ci case TPS65911_REG_LDO4: 3768c2ecf20Sopenharmony_ci return TPS65911_LDO4; 3778c2ecf20Sopenharmony_ci case TPS65911_REG_LDO5: 3788c2ecf20Sopenharmony_ci return TPS65911_LDO5; 3798c2ecf20Sopenharmony_ci case TPS65911_REG_LDO6: 3808c2ecf20Sopenharmony_ci return TPS65911_LDO6; 3818c2ecf20Sopenharmony_ci case TPS65911_REG_LDO7: 3828c2ecf20Sopenharmony_ci return TPS65911_LDO7; 3838c2ecf20Sopenharmony_ci case TPS65911_REG_LDO8: 3848c2ecf20Sopenharmony_ci return TPS65911_LDO8; 3858c2ecf20Sopenharmony_ci default: 3868c2ecf20Sopenharmony_ci return -EINVAL; 3878c2ecf20Sopenharmony_ci } 3888c2ecf20Sopenharmony_ci} 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_cistatic int tps65910_set_mode(struct regulator_dev *dev, unsigned int mode) 3918c2ecf20Sopenharmony_ci{ 3928c2ecf20Sopenharmony_ci struct tps65910_reg *pmic = rdev_get_drvdata(dev); 3938c2ecf20Sopenharmony_ci struct regmap *regmap = rdev_get_regmap(dev); 3948c2ecf20Sopenharmony_ci int reg, id = rdev_get_id(dev); 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci reg = pmic->get_ctrl_reg(id); 3978c2ecf20Sopenharmony_ci if (reg < 0) 3988c2ecf20Sopenharmony_ci return reg; 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci switch (mode) { 4018c2ecf20Sopenharmony_ci case REGULATOR_MODE_NORMAL: 4028c2ecf20Sopenharmony_ci return regmap_update_bits(regmap, reg, 4038c2ecf20Sopenharmony_ci LDO_ST_MODE_BIT | LDO_ST_ON_BIT, 4048c2ecf20Sopenharmony_ci LDO_ST_ON_BIT); 4058c2ecf20Sopenharmony_ci case REGULATOR_MODE_IDLE: 4068c2ecf20Sopenharmony_ci return regmap_set_bits(regmap, reg, 4078c2ecf20Sopenharmony_ci LDO_ST_ON_BIT | LDO_ST_MODE_BIT); 4088c2ecf20Sopenharmony_ci case REGULATOR_MODE_STANDBY: 4098c2ecf20Sopenharmony_ci return regmap_clear_bits(regmap, reg, LDO_ST_ON_BIT); 4108c2ecf20Sopenharmony_ci } 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci return -EINVAL; 4138c2ecf20Sopenharmony_ci} 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_cistatic unsigned int tps65910_get_mode(struct regulator_dev *dev) 4168c2ecf20Sopenharmony_ci{ 4178c2ecf20Sopenharmony_ci struct tps65910_reg *pmic = rdev_get_drvdata(dev); 4188c2ecf20Sopenharmony_ci struct regmap *regmap = rdev_get_regmap(dev); 4198c2ecf20Sopenharmony_ci int ret, reg, value, id = rdev_get_id(dev); 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci reg = pmic->get_ctrl_reg(id); 4228c2ecf20Sopenharmony_ci if (reg < 0) 4238c2ecf20Sopenharmony_ci return reg; 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci ret = regmap_read(regmap, reg, &value); 4268c2ecf20Sopenharmony_ci if (ret < 0) 4278c2ecf20Sopenharmony_ci return ret; 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci if (!(value & LDO_ST_ON_BIT)) 4308c2ecf20Sopenharmony_ci return REGULATOR_MODE_STANDBY; 4318c2ecf20Sopenharmony_ci else if (value & LDO_ST_MODE_BIT) 4328c2ecf20Sopenharmony_ci return REGULATOR_MODE_IDLE; 4338c2ecf20Sopenharmony_ci else 4348c2ecf20Sopenharmony_ci return REGULATOR_MODE_NORMAL; 4358c2ecf20Sopenharmony_ci} 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_cistatic int tps65910_get_voltage_dcdc_sel(struct regulator_dev *dev) 4388c2ecf20Sopenharmony_ci{ 4398c2ecf20Sopenharmony_ci struct regmap *regmap = rdev_get_regmap(dev); 4408c2ecf20Sopenharmony_ci int ret, id = rdev_get_id(dev); 4418c2ecf20Sopenharmony_ci int opvsel = 0, srvsel = 0, vselmax = 0, mult = 0, sr = 0; 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci switch (id) { 4448c2ecf20Sopenharmony_ci case TPS65910_REG_VDD1: 4458c2ecf20Sopenharmony_ci ret = regmap_read(regmap, TPS65910_VDD1_OP, &opvsel); 4468c2ecf20Sopenharmony_ci if (ret < 0) 4478c2ecf20Sopenharmony_ci return ret; 4488c2ecf20Sopenharmony_ci ret = regmap_read(regmap, TPS65910_VDD1, &mult); 4498c2ecf20Sopenharmony_ci if (ret < 0) 4508c2ecf20Sopenharmony_ci return ret; 4518c2ecf20Sopenharmony_ci mult = (mult & VDD1_VGAIN_SEL_MASK) >> VDD1_VGAIN_SEL_SHIFT; 4528c2ecf20Sopenharmony_ci ret = regmap_read(regmap, TPS65910_VDD1_SR, &srvsel); 4538c2ecf20Sopenharmony_ci if (ret < 0) 4548c2ecf20Sopenharmony_ci return ret; 4558c2ecf20Sopenharmony_ci sr = opvsel & VDD1_OP_CMD_MASK; 4568c2ecf20Sopenharmony_ci opvsel &= VDD1_OP_SEL_MASK; 4578c2ecf20Sopenharmony_ci srvsel &= VDD1_SR_SEL_MASK; 4588c2ecf20Sopenharmony_ci vselmax = 75; 4598c2ecf20Sopenharmony_ci break; 4608c2ecf20Sopenharmony_ci case TPS65910_REG_VDD2: 4618c2ecf20Sopenharmony_ci ret = regmap_read(regmap, TPS65910_VDD2_OP, &opvsel); 4628c2ecf20Sopenharmony_ci if (ret < 0) 4638c2ecf20Sopenharmony_ci return ret; 4648c2ecf20Sopenharmony_ci ret = regmap_read(regmap, TPS65910_VDD2, &mult); 4658c2ecf20Sopenharmony_ci if (ret < 0) 4668c2ecf20Sopenharmony_ci return ret; 4678c2ecf20Sopenharmony_ci mult = (mult & VDD2_VGAIN_SEL_MASK) >> VDD2_VGAIN_SEL_SHIFT; 4688c2ecf20Sopenharmony_ci ret = regmap_read(regmap, TPS65910_VDD2_SR, &srvsel); 4698c2ecf20Sopenharmony_ci if (ret < 0) 4708c2ecf20Sopenharmony_ci return ret; 4718c2ecf20Sopenharmony_ci sr = opvsel & VDD2_OP_CMD_MASK; 4728c2ecf20Sopenharmony_ci opvsel &= VDD2_OP_SEL_MASK; 4738c2ecf20Sopenharmony_ci srvsel &= VDD2_SR_SEL_MASK; 4748c2ecf20Sopenharmony_ci vselmax = 75; 4758c2ecf20Sopenharmony_ci break; 4768c2ecf20Sopenharmony_ci case TPS65911_REG_VDDCTRL: 4778c2ecf20Sopenharmony_ci ret = regmap_read(regmap, TPS65911_VDDCTRL_OP, &opvsel); 4788c2ecf20Sopenharmony_ci if (ret < 0) 4798c2ecf20Sopenharmony_ci return ret; 4808c2ecf20Sopenharmony_ci ret = regmap_read(regmap, TPS65911_VDDCTRL_SR, &srvsel); 4818c2ecf20Sopenharmony_ci if (ret < 0) 4828c2ecf20Sopenharmony_ci return ret; 4838c2ecf20Sopenharmony_ci sr = opvsel & VDDCTRL_OP_CMD_MASK; 4848c2ecf20Sopenharmony_ci opvsel &= VDDCTRL_OP_SEL_MASK; 4858c2ecf20Sopenharmony_ci srvsel &= VDDCTRL_SR_SEL_MASK; 4868c2ecf20Sopenharmony_ci vselmax = 64; 4878c2ecf20Sopenharmony_ci break; 4888c2ecf20Sopenharmony_ci } 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ci /* multiplier 0 == 1 but 2,3 normal */ 4918c2ecf20Sopenharmony_ci if (!mult) 4928c2ecf20Sopenharmony_ci mult = 1; 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_ci if (sr) { 4958c2ecf20Sopenharmony_ci /* normalise to valid range */ 4968c2ecf20Sopenharmony_ci if (srvsel < 3) 4978c2ecf20Sopenharmony_ci srvsel = 3; 4988c2ecf20Sopenharmony_ci if (srvsel > vselmax) 4998c2ecf20Sopenharmony_ci srvsel = vselmax; 5008c2ecf20Sopenharmony_ci return srvsel - 3; 5018c2ecf20Sopenharmony_ci } else { 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci /* normalise to valid range*/ 5048c2ecf20Sopenharmony_ci if (opvsel < 3) 5058c2ecf20Sopenharmony_ci opvsel = 3; 5068c2ecf20Sopenharmony_ci if (opvsel > vselmax) 5078c2ecf20Sopenharmony_ci opvsel = vselmax; 5088c2ecf20Sopenharmony_ci return opvsel - 3; 5098c2ecf20Sopenharmony_ci } 5108c2ecf20Sopenharmony_ci return -EINVAL; 5118c2ecf20Sopenharmony_ci} 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_cistatic int tps65910_get_voltage_sel(struct regulator_dev *dev) 5148c2ecf20Sopenharmony_ci{ 5158c2ecf20Sopenharmony_ci struct tps65910_reg *pmic = rdev_get_drvdata(dev); 5168c2ecf20Sopenharmony_ci struct regmap *regmap = rdev_get_regmap(dev); 5178c2ecf20Sopenharmony_ci int ret, reg, value, id = rdev_get_id(dev); 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_ci reg = pmic->get_ctrl_reg(id); 5208c2ecf20Sopenharmony_ci if (reg < 0) 5218c2ecf20Sopenharmony_ci return reg; 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ci ret = regmap_read(regmap, reg, &value); 5248c2ecf20Sopenharmony_ci if (ret < 0) 5258c2ecf20Sopenharmony_ci return ret; 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci switch (id) { 5288c2ecf20Sopenharmony_ci case TPS65910_REG_VIO: 5298c2ecf20Sopenharmony_ci case TPS65910_REG_VDIG1: 5308c2ecf20Sopenharmony_ci case TPS65910_REG_VDIG2: 5318c2ecf20Sopenharmony_ci case TPS65910_REG_VPLL: 5328c2ecf20Sopenharmony_ci case TPS65910_REG_VDAC: 5338c2ecf20Sopenharmony_ci case TPS65910_REG_VAUX1: 5348c2ecf20Sopenharmony_ci case TPS65910_REG_VAUX2: 5358c2ecf20Sopenharmony_ci case TPS65910_REG_VAUX33: 5368c2ecf20Sopenharmony_ci case TPS65910_REG_VMMC: 5378c2ecf20Sopenharmony_ci value &= LDO_SEL_MASK; 5388c2ecf20Sopenharmony_ci value >>= LDO_SEL_SHIFT; 5398c2ecf20Sopenharmony_ci break; 5408c2ecf20Sopenharmony_ci case TPS65910_REG_VBB: 5418c2ecf20Sopenharmony_ci value &= BBCH_BBSEL_MASK; 5428c2ecf20Sopenharmony_ci value >>= BBCH_BBSEL_SHIFT; 5438c2ecf20Sopenharmony_ci break; 5448c2ecf20Sopenharmony_ci default: 5458c2ecf20Sopenharmony_ci return -EINVAL; 5468c2ecf20Sopenharmony_ci } 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci return value; 5498c2ecf20Sopenharmony_ci} 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_cistatic int tps65910_get_voltage_vdd3(struct regulator_dev *dev) 5528c2ecf20Sopenharmony_ci{ 5538c2ecf20Sopenharmony_ci return dev->desc->volt_table[0]; 5548c2ecf20Sopenharmony_ci} 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_cistatic int tps65911_get_voltage_sel(struct regulator_dev *dev) 5578c2ecf20Sopenharmony_ci{ 5588c2ecf20Sopenharmony_ci struct tps65910_reg *pmic = rdev_get_drvdata(dev); 5598c2ecf20Sopenharmony_ci struct regmap *regmap = rdev_get_regmap(dev); 5608c2ecf20Sopenharmony_ci int ret, id = rdev_get_id(dev); 5618c2ecf20Sopenharmony_ci unsigned int value, reg; 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci reg = pmic->get_ctrl_reg(id); 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci ret = regmap_read(regmap, reg, &value); 5668c2ecf20Sopenharmony_ci if (ret < 0) 5678c2ecf20Sopenharmony_ci return ret; 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci switch (id) { 5708c2ecf20Sopenharmony_ci case TPS65911_REG_LDO1: 5718c2ecf20Sopenharmony_ci case TPS65911_REG_LDO2: 5728c2ecf20Sopenharmony_ci case TPS65911_REG_LDO4: 5738c2ecf20Sopenharmony_ci value &= LDO1_SEL_MASK; 5748c2ecf20Sopenharmony_ci value >>= LDO_SEL_SHIFT; 5758c2ecf20Sopenharmony_ci break; 5768c2ecf20Sopenharmony_ci case TPS65911_REG_LDO3: 5778c2ecf20Sopenharmony_ci case TPS65911_REG_LDO5: 5788c2ecf20Sopenharmony_ci case TPS65911_REG_LDO6: 5798c2ecf20Sopenharmony_ci case TPS65911_REG_LDO7: 5808c2ecf20Sopenharmony_ci case TPS65911_REG_LDO8: 5818c2ecf20Sopenharmony_ci value &= LDO3_SEL_MASK; 5828c2ecf20Sopenharmony_ci value >>= LDO_SEL_SHIFT; 5838c2ecf20Sopenharmony_ci break; 5848c2ecf20Sopenharmony_ci case TPS65910_REG_VIO: 5858c2ecf20Sopenharmony_ci value &= LDO_SEL_MASK; 5868c2ecf20Sopenharmony_ci value >>= LDO_SEL_SHIFT; 5878c2ecf20Sopenharmony_ci break; 5888c2ecf20Sopenharmony_ci default: 5898c2ecf20Sopenharmony_ci return -EINVAL; 5908c2ecf20Sopenharmony_ci } 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_ci return value; 5938c2ecf20Sopenharmony_ci} 5948c2ecf20Sopenharmony_ci 5958c2ecf20Sopenharmony_cistatic int tps65910_set_voltage_dcdc_sel(struct regulator_dev *dev, 5968c2ecf20Sopenharmony_ci unsigned selector) 5978c2ecf20Sopenharmony_ci{ 5988c2ecf20Sopenharmony_ci struct regmap *regmap = rdev_get_regmap(dev); 5998c2ecf20Sopenharmony_ci int id = rdev_get_id(dev), vsel; 6008c2ecf20Sopenharmony_ci int dcdc_mult = 0; 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_ci switch (id) { 6038c2ecf20Sopenharmony_ci case TPS65910_REG_VDD1: 6048c2ecf20Sopenharmony_ci dcdc_mult = (selector / VDD1_2_NUM_VOLT_FINE) + 1; 6058c2ecf20Sopenharmony_ci if (dcdc_mult == 1) 6068c2ecf20Sopenharmony_ci dcdc_mult--; 6078c2ecf20Sopenharmony_ci vsel = (selector % VDD1_2_NUM_VOLT_FINE) + 3; 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci regmap_update_bits(regmap, TPS65910_VDD1, VDD1_VGAIN_SEL_MASK, 6108c2ecf20Sopenharmony_ci dcdc_mult << VDD1_VGAIN_SEL_SHIFT); 6118c2ecf20Sopenharmony_ci regmap_write(regmap, TPS65910_VDD1_OP, vsel); 6128c2ecf20Sopenharmony_ci break; 6138c2ecf20Sopenharmony_ci case TPS65910_REG_VDD2: 6148c2ecf20Sopenharmony_ci dcdc_mult = (selector / VDD1_2_NUM_VOLT_FINE) + 1; 6158c2ecf20Sopenharmony_ci if (dcdc_mult == 1) 6168c2ecf20Sopenharmony_ci dcdc_mult--; 6178c2ecf20Sopenharmony_ci vsel = (selector % VDD1_2_NUM_VOLT_FINE) + 3; 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci regmap_update_bits(regmap, TPS65910_VDD2, VDD1_VGAIN_SEL_MASK, 6208c2ecf20Sopenharmony_ci dcdc_mult << VDD2_VGAIN_SEL_SHIFT); 6218c2ecf20Sopenharmony_ci regmap_write(regmap, TPS65910_VDD2_OP, vsel); 6228c2ecf20Sopenharmony_ci break; 6238c2ecf20Sopenharmony_ci case TPS65911_REG_VDDCTRL: 6248c2ecf20Sopenharmony_ci vsel = selector + 3; 6258c2ecf20Sopenharmony_ci regmap_write(regmap, TPS65911_VDDCTRL_OP, vsel); 6268c2ecf20Sopenharmony_ci break; 6278c2ecf20Sopenharmony_ci } 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_ci return 0; 6308c2ecf20Sopenharmony_ci} 6318c2ecf20Sopenharmony_ci 6328c2ecf20Sopenharmony_cistatic int tps65910_set_voltage_sel(struct regulator_dev *dev, 6338c2ecf20Sopenharmony_ci unsigned selector) 6348c2ecf20Sopenharmony_ci{ 6358c2ecf20Sopenharmony_ci struct tps65910_reg *pmic = rdev_get_drvdata(dev); 6368c2ecf20Sopenharmony_ci struct regmap *regmap = rdev_get_regmap(dev); 6378c2ecf20Sopenharmony_ci int reg, id = rdev_get_id(dev); 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci reg = pmic->get_ctrl_reg(id); 6408c2ecf20Sopenharmony_ci if (reg < 0) 6418c2ecf20Sopenharmony_ci return reg; 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ci switch (id) { 6448c2ecf20Sopenharmony_ci case TPS65910_REG_VIO: 6458c2ecf20Sopenharmony_ci case TPS65910_REG_VDIG1: 6468c2ecf20Sopenharmony_ci case TPS65910_REG_VDIG2: 6478c2ecf20Sopenharmony_ci case TPS65910_REG_VPLL: 6488c2ecf20Sopenharmony_ci case TPS65910_REG_VDAC: 6498c2ecf20Sopenharmony_ci case TPS65910_REG_VAUX1: 6508c2ecf20Sopenharmony_ci case TPS65910_REG_VAUX2: 6518c2ecf20Sopenharmony_ci case TPS65910_REG_VAUX33: 6528c2ecf20Sopenharmony_ci case TPS65910_REG_VMMC: 6538c2ecf20Sopenharmony_ci return regmap_update_bits(regmap, reg, LDO_SEL_MASK, 6548c2ecf20Sopenharmony_ci selector << LDO_SEL_SHIFT); 6558c2ecf20Sopenharmony_ci case TPS65910_REG_VBB: 6568c2ecf20Sopenharmony_ci return regmap_update_bits(regmap, reg, BBCH_BBSEL_MASK, 6578c2ecf20Sopenharmony_ci selector << BBCH_BBSEL_SHIFT); 6588c2ecf20Sopenharmony_ci } 6598c2ecf20Sopenharmony_ci 6608c2ecf20Sopenharmony_ci return -EINVAL; 6618c2ecf20Sopenharmony_ci} 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_cistatic int tps65911_set_voltage_sel(struct regulator_dev *dev, 6648c2ecf20Sopenharmony_ci unsigned selector) 6658c2ecf20Sopenharmony_ci{ 6668c2ecf20Sopenharmony_ci struct tps65910_reg *pmic = rdev_get_drvdata(dev); 6678c2ecf20Sopenharmony_ci struct regmap *regmap = rdev_get_regmap(dev); 6688c2ecf20Sopenharmony_ci int reg, id = rdev_get_id(dev); 6698c2ecf20Sopenharmony_ci 6708c2ecf20Sopenharmony_ci reg = pmic->get_ctrl_reg(id); 6718c2ecf20Sopenharmony_ci if (reg < 0) 6728c2ecf20Sopenharmony_ci return reg; 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci switch (id) { 6758c2ecf20Sopenharmony_ci case TPS65911_REG_LDO1: 6768c2ecf20Sopenharmony_ci case TPS65911_REG_LDO2: 6778c2ecf20Sopenharmony_ci case TPS65911_REG_LDO4: 6788c2ecf20Sopenharmony_ci return regmap_update_bits(regmap, reg, LDO1_SEL_MASK, 6798c2ecf20Sopenharmony_ci selector << LDO_SEL_SHIFT); 6808c2ecf20Sopenharmony_ci case TPS65911_REG_LDO3: 6818c2ecf20Sopenharmony_ci case TPS65911_REG_LDO5: 6828c2ecf20Sopenharmony_ci case TPS65911_REG_LDO6: 6838c2ecf20Sopenharmony_ci case TPS65911_REG_LDO7: 6848c2ecf20Sopenharmony_ci case TPS65911_REG_LDO8: 6858c2ecf20Sopenharmony_ci return regmap_update_bits(regmap, reg, LDO3_SEL_MASK, 6868c2ecf20Sopenharmony_ci selector << LDO_SEL_SHIFT); 6878c2ecf20Sopenharmony_ci case TPS65910_REG_VIO: 6888c2ecf20Sopenharmony_ci return regmap_update_bits(regmap, reg, LDO_SEL_MASK, 6898c2ecf20Sopenharmony_ci selector << LDO_SEL_SHIFT); 6908c2ecf20Sopenharmony_ci case TPS65910_REG_VBB: 6918c2ecf20Sopenharmony_ci return regmap_update_bits(regmap, reg, BBCH_BBSEL_MASK, 6928c2ecf20Sopenharmony_ci selector << BBCH_BBSEL_SHIFT); 6938c2ecf20Sopenharmony_ci } 6948c2ecf20Sopenharmony_ci 6958c2ecf20Sopenharmony_ci return -EINVAL; 6968c2ecf20Sopenharmony_ci} 6978c2ecf20Sopenharmony_ci 6988c2ecf20Sopenharmony_ci 6998c2ecf20Sopenharmony_cistatic int tps65910_list_voltage_dcdc(struct regulator_dev *dev, 7008c2ecf20Sopenharmony_ci unsigned selector) 7018c2ecf20Sopenharmony_ci{ 7028c2ecf20Sopenharmony_ci int volt, mult = 1, id = rdev_get_id(dev); 7038c2ecf20Sopenharmony_ci 7048c2ecf20Sopenharmony_ci switch (id) { 7058c2ecf20Sopenharmony_ci case TPS65910_REG_VDD1: 7068c2ecf20Sopenharmony_ci case TPS65910_REG_VDD2: 7078c2ecf20Sopenharmony_ci mult = (selector / VDD1_2_NUM_VOLT_FINE) + 1; 7088c2ecf20Sopenharmony_ci volt = VDD1_2_MIN_VOLT + 7098c2ecf20Sopenharmony_ci (selector % VDD1_2_NUM_VOLT_FINE) * VDD1_2_OFFSET; 7108c2ecf20Sopenharmony_ci break; 7118c2ecf20Sopenharmony_ci case TPS65911_REG_VDDCTRL: 7128c2ecf20Sopenharmony_ci volt = VDDCTRL_MIN_VOLT + (selector * VDDCTRL_OFFSET); 7138c2ecf20Sopenharmony_ci break; 7148c2ecf20Sopenharmony_ci default: 7158c2ecf20Sopenharmony_ci BUG(); 7168c2ecf20Sopenharmony_ci return -EINVAL; 7178c2ecf20Sopenharmony_ci } 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci return volt * 100 * mult; 7208c2ecf20Sopenharmony_ci} 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_cistatic int tps65911_list_voltage(struct regulator_dev *dev, unsigned selector) 7238c2ecf20Sopenharmony_ci{ 7248c2ecf20Sopenharmony_ci struct tps65910_reg *pmic = rdev_get_drvdata(dev); 7258c2ecf20Sopenharmony_ci int step_mv = 0, id = rdev_get_id(dev); 7268c2ecf20Sopenharmony_ci 7278c2ecf20Sopenharmony_ci switch (id) { 7288c2ecf20Sopenharmony_ci case TPS65911_REG_LDO1: 7298c2ecf20Sopenharmony_ci case TPS65911_REG_LDO2: 7308c2ecf20Sopenharmony_ci case TPS65911_REG_LDO4: 7318c2ecf20Sopenharmony_ci /* The first 5 values of the selector correspond to 1V */ 7328c2ecf20Sopenharmony_ci if (selector < 5) 7338c2ecf20Sopenharmony_ci selector = 0; 7348c2ecf20Sopenharmony_ci else 7358c2ecf20Sopenharmony_ci selector -= 4; 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_ci step_mv = 50; 7388c2ecf20Sopenharmony_ci break; 7398c2ecf20Sopenharmony_ci case TPS65911_REG_LDO3: 7408c2ecf20Sopenharmony_ci case TPS65911_REG_LDO5: 7418c2ecf20Sopenharmony_ci case TPS65911_REG_LDO6: 7428c2ecf20Sopenharmony_ci case TPS65911_REG_LDO7: 7438c2ecf20Sopenharmony_ci case TPS65911_REG_LDO8: 7448c2ecf20Sopenharmony_ci /* The first 3 values of the selector correspond to 1V */ 7458c2ecf20Sopenharmony_ci if (selector < 3) 7468c2ecf20Sopenharmony_ci selector = 0; 7478c2ecf20Sopenharmony_ci else 7488c2ecf20Sopenharmony_ci selector -= 2; 7498c2ecf20Sopenharmony_ci 7508c2ecf20Sopenharmony_ci step_mv = 100; 7518c2ecf20Sopenharmony_ci break; 7528c2ecf20Sopenharmony_ci case TPS65910_REG_VIO: 7538c2ecf20Sopenharmony_ci return pmic->info[id]->voltage_table[selector]; 7548c2ecf20Sopenharmony_ci default: 7558c2ecf20Sopenharmony_ci return -EINVAL; 7568c2ecf20Sopenharmony_ci } 7578c2ecf20Sopenharmony_ci 7588c2ecf20Sopenharmony_ci return (LDO_MIN_VOLT + selector * step_mv) * 1000; 7598c2ecf20Sopenharmony_ci} 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci/* Regulator ops (except VRTC) */ 7628c2ecf20Sopenharmony_cistatic const struct regulator_ops tps65910_ops_dcdc = { 7638c2ecf20Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 7648c2ecf20Sopenharmony_ci .enable = regulator_enable_regmap, 7658c2ecf20Sopenharmony_ci .disable = regulator_disable_regmap, 7668c2ecf20Sopenharmony_ci .set_mode = tps65910_set_mode, 7678c2ecf20Sopenharmony_ci .get_mode = tps65910_get_mode, 7688c2ecf20Sopenharmony_ci .get_voltage_sel = tps65910_get_voltage_dcdc_sel, 7698c2ecf20Sopenharmony_ci .set_voltage_sel = tps65910_set_voltage_dcdc_sel, 7708c2ecf20Sopenharmony_ci .set_voltage_time_sel = regulator_set_voltage_time_sel, 7718c2ecf20Sopenharmony_ci .list_voltage = tps65910_list_voltage_dcdc, 7728c2ecf20Sopenharmony_ci .map_voltage = regulator_map_voltage_ascend, 7738c2ecf20Sopenharmony_ci}; 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_cistatic const struct regulator_ops tps65910_ops_vdd3 = { 7768c2ecf20Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 7778c2ecf20Sopenharmony_ci .enable = regulator_enable_regmap, 7788c2ecf20Sopenharmony_ci .disable = regulator_disable_regmap, 7798c2ecf20Sopenharmony_ci .set_mode = tps65910_set_mode, 7808c2ecf20Sopenharmony_ci .get_mode = tps65910_get_mode, 7818c2ecf20Sopenharmony_ci .get_voltage = tps65910_get_voltage_vdd3, 7828c2ecf20Sopenharmony_ci .list_voltage = regulator_list_voltage_table, 7838c2ecf20Sopenharmony_ci .map_voltage = regulator_map_voltage_ascend, 7848c2ecf20Sopenharmony_ci}; 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_cistatic const struct regulator_ops tps65910_ops_vbb = { 7878c2ecf20Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 7888c2ecf20Sopenharmony_ci .enable = regulator_enable_regmap, 7898c2ecf20Sopenharmony_ci .disable = regulator_disable_regmap, 7908c2ecf20Sopenharmony_ci .set_mode = tps65910_set_mode, 7918c2ecf20Sopenharmony_ci .get_mode = tps65910_get_mode, 7928c2ecf20Sopenharmony_ci .get_voltage_sel = tps65910_get_voltage_sel, 7938c2ecf20Sopenharmony_ci .set_voltage_sel = tps65910_set_voltage_sel, 7948c2ecf20Sopenharmony_ci .list_voltage = regulator_list_voltage_table, 7958c2ecf20Sopenharmony_ci .map_voltage = regulator_map_voltage_iterate, 7968c2ecf20Sopenharmony_ci}; 7978c2ecf20Sopenharmony_ci 7988c2ecf20Sopenharmony_cistatic const struct regulator_ops tps65910_ops = { 7998c2ecf20Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 8008c2ecf20Sopenharmony_ci .enable = regulator_enable_regmap, 8018c2ecf20Sopenharmony_ci .disable = regulator_disable_regmap, 8028c2ecf20Sopenharmony_ci .set_mode = tps65910_set_mode, 8038c2ecf20Sopenharmony_ci .get_mode = tps65910_get_mode, 8048c2ecf20Sopenharmony_ci .get_voltage_sel = tps65910_get_voltage_sel, 8058c2ecf20Sopenharmony_ci .set_voltage_sel = tps65910_set_voltage_sel, 8068c2ecf20Sopenharmony_ci .list_voltage = regulator_list_voltage_table, 8078c2ecf20Sopenharmony_ci .map_voltage = regulator_map_voltage_ascend, 8088c2ecf20Sopenharmony_ci}; 8098c2ecf20Sopenharmony_ci 8108c2ecf20Sopenharmony_cistatic const struct regulator_ops tps65911_ops = { 8118c2ecf20Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 8128c2ecf20Sopenharmony_ci .enable = regulator_enable_regmap, 8138c2ecf20Sopenharmony_ci .disable = regulator_disable_regmap, 8148c2ecf20Sopenharmony_ci .set_mode = tps65910_set_mode, 8158c2ecf20Sopenharmony_ci .get_mode = tps65910_get_mode, 8168c2ecf20Sopenharmony_ci .get_voltage_sel = tps65911_get_voltage_sel, 8178c2ecf20Sopenharmony_ci .set_voltage_sel = tps65911_set_voltage_sel, 8188c2ecf20Sopenharmony_ci .list_voltage = tps65911_list_voltage, 8198c2ecf20Sopenharmony_ci .map_voltage = regulator_map_voltage_ascend, 8208c2ecf20Sopenharmony_ci}; 8218c2ecf20Sopenharmony_ci 8228c2ecf20Sopenharmony_cistatic int tps65910_set_ext_sleep_config(struct tps65910_reg *pmic, 8238c2ecf20Sopenharmony_ci int id, int ext_sleep_config) 8248c2ecf20Sopenharmony_ci{ 8258c2ecf20Sopenharmony_ci struct tps65910 *mfd = pmic->mfd; 8268c2ecf20Sopenharmony_ci u8 regoffs = (pmic->ext_sleep_control[id] >> 8) & 0xFF; 8278c2ecf20Sopenharmony_ci u8 bit_pos = (1 << pmic->ext_sleep_control[id] & 0xFF); 8288c2ecf20Sopenharmony_ci int ret; 8298c2ecf20Sopenharmony_ci 8308c2ecf20Sopenharmony_ci /* 8318c2ecf20Sopenharmony_ci * Regulator can not be control from multiple external input EN1, EN2 8328c2ecf20Sopenharmony_ci * and EN3 together. 8338c2ecf20Sopenharmony_ci */ 8348c2ecf20Sopenharmony_ci if (ext_sleep_config & EXT_SLEEP_CONTROL) { 8358c2ecf20Sopenharmony_ci int en_count; 8368c2ecf20Sopenharmony_ci en_count = ((ext_sleep_config & 8378c2ecf20Sopenharmony_ci TPS65910_SLEEP_CONTROL_EXT_INPUT_EN1) != 0); 8388c2ecf20Sopenharmony_ci en_count += ((ext_sleep_config & 8398c2ecf20Sopenharmony_ci TPS65910_SLEEP_CONTROL_EXT_INPUT_EN2) != 0); 8408c2ecf20Sopenharmony_ci en_count += ((ext_sleep_config & 8418c2ecf20Sopenharmony_ci TPS65910_SLEEP_CONTROL_EXT_INPUT_EN3) != 0); 8428c2ecf20Sopenharmony_ci en_count += ((ext_sleep_config & 8438c2ecf20Sopenharmony_ci TPS65911_SLEEP_CONTROL_EXT_INPUT_SLEEP) != 0); 8448c2ecf20Sopenharmony_ci if (en_count > 1) { 8458c2ecf20Sopenharmony_ci dev_err(mfd->dev, 8468c2ecf20Sopenharmony_ci "External sleep control flag is not proper\n"); 8478c2ecf20Sopenharmony_ci return -EINVAL; 8488c2ecf20Sopenharmony_ci } 8498c2ecf20Sopenharmony_ci } 8508c2ecf20Sopenharmony_ci 8518c2ecf20Sopenharmony_ci pmic->board_ext_control[id] = ext_sleep_config; 8528c2ecf20Sopenharmony_ci 8538c2ecf20Sopenharmony_ci /* External EN1 control */ 8548c2ecf20Sopenharmony_ci if (ext_sleep_config & TPS65910_SLEEP_CONTROL_EXT_INPUT_EN1) 8558c2ecf20Sopenharmony_ci ret = regmap_set_bits(mfd->regmap, 8568c2ecf20Sopenharmony_ci TPS65910_EN1_LDO_ASS + regoffs, bit_pos); 8578c2ecf20Sopenharmony_ci else 8588c2ecf20Sopenharmony_ci ret = regmap_clear_bits(mfd->regmap, 8598c2ecf20Sopenharmony_ci TPS65910_EN1_LDO_ASS + regoffs, bit_pos); 8608c2ecf20Sopenharmony_ci if (ret < 0) { 8618c2ecf20Sopenharmony_ci dev_err(mfd->dev, 8628c2ecf20Sopenharmony_ci "Error in configuring external control EN1\n"); 8638c2ecf20Sopenharmony_ci return ret; 8648c2ecf20Sopenharmony_ci } 8658c2ecf20Sopenharmony_ci 8668c2ecf20Sopenharmony_ci /* External EN2 control */ 8678c2ecf20Sopenharmony_ci if (ext_sleep_config & TPS65910_SLEEP_CONTROL_EXT_INPUT_EN2) 8688c2ecf20Sopenharmony_ci ret = regmap_set_bits(mfd->regmap, 8698c2ecf20Sopenharmony_ci TPS65910_EN2_LDO_ASS + regoffs, bit_pos); 8708c2ecf20Sopenharmony_ci else 8718c2ecf20Sopenharmony_ci ret = regmap_clear_bits(mfd->regmap, 8728c2ecf20Sopenharmony_ci TPS65910_EN2_LDO_ASS + regoffs, bit_pos); 8738c2ecf20Sopenharmony_ci if (ret < 0) { 8748c2ecf20Sopenharmony_ci dev_err(mfd->dev, 8758c2ecf20Sopenharmony_ci "Error in configuring external control EN2\n"); 8768c2ecf20Sopenharmony_ci return ret; 8778c2ecf20Sopenharmony_ci } 8788c2ecf20Sopenharmony_ci 8798c2ecf20Sopenharmony_ci /* External EN3 control for TPS65910 LDO only */ 8808c2ecf20Sopenharmony_ci if ((tps65910_chip_id(mfd) == TPS65910) && 8818c2ecf20Sopenharmony_ci (id >= TPS65910_REG_VDIG1)) { 8828c2ecf20Sopenharmony_ci if (ext_sleep_config & TPS65910_SLEEP_CONTROL_EXT_INPUT_EN3) 8838c2ecf20Sopenharmony_ci ret = regmap_set_bits(mfd->regmap, 8848c2ecf20Sopenharmony_ci TPS65910_EN3_LDO_ASS + regoffs, bit_pos); 8858c2ecf20Sopenharmony_ci else 8868c2ecf20Sopenharmony_ci ret = regmap_clear_bits(mfd->regmap, 8878c2ecf20Sopenharmony_ci TPS65910_EN3_LDO_ASS + regoffs, bit_pos); 8888c2ecf20Sopenharmony_ci if (ret < 0) { 8898c2ecf20Sopenharmony_ci dev_err(mfd->dev, 8908c2ecf20Sopenharmony_ci "Error in configuring external control EN3\n"); 8918c2ecf20Sopenharmony_ci return ret; 8928c2ecf20Sopenharmony_ci } 8938c2ecf20Sopenharmony_ci } 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_ci /* Return if no external control is selected */ 8968c2ecf20Sopenharmony_ci if (!(ext_sleep_config & EXT_SLEEP_CONTROL)) { 8978c2ecf20Sopenharmony_ci /* Clear all sleep controls */ 8988c2ecf20Sopenharmony_ci ret = regmap_clear_bits(mfd->regmap, 8998c2ecf20Sopenharmony_ci TPS65910_SLEEP_KEEP_LDO_ON + regoffs, bit_pos); 9008c2ecf20Sopenharmony_ci if (!ret) 9018c2ecf20Sopenharmony_ci ret = regmap_clear_bits(mfd->regmap, 9028c2ecf20Sopenharmony_ci TPS65910_SLEEP_SET_LDO_OFF + regoffs, bit_pos); 9038c2ecf20Sopenharmony_ci if (ret < 0) 9048c2ecf20Sopenharmony_ci dev_err(mfd->dev, 9058c2ecf20Sopenharmony_ci "Error in configuring SLEEP register\n"); 9068c2ecf20Sopenharmony_ci return ret; 9078c2ecf20Sopenharmony_ci } 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_ci /* 9108c2ecf20Sopenharmony_ci * For regulator that has separate operational and sleep register make 9118c2ecf20Sopenharmony_ci * sure that operational is used and clear sleep register to turn 9128c2ecf20Sopenharmony_ci * regulator off when external control is inactive 9138c2ecf20Sopenharmony_ci */ 9148c2ecf20Sopenharmony_ci if ((id == TPS65910_REG_VDD1) || 9158c2ecf20Sopenharmony_ci (id == TPS65910_REG_VDD2) || 9168c2ecf20Sopenharmony_ci ((id == TPS65911_REG_VDDCTRL) && 9178c2ecf20Sopenharmony_ci (tps65910_chip_id(mfd) == TPS65911))) { 9188c2ecf20Sopenharmony_ci int op_reg_add = pmic->get_ctrl_reg(id) + 1; 9198c2ecf20Sopenharmony_ci int sr_reg_add = pmic->get_ctrl_reg(id) + 2; 9208c2ecf20Sopenharmony_ci int opvsel, srvsel; 9218c2ecf20Sopenharmony_ci 9228c2ecf20Sopenharmony_ci ret = regmap_read(mfd->regmap, op_reg_add, &opvsel); 9238c2ecf20Sopenharmony_ci if (ret < 0) 9248c2ecf20Sopenharmony_ci return ret; 9258c2ecf20Sopenharmony_ci ret = regmap_read(mfd->regmap, sr_reg_add, &srvsel); 9268c2ecf20Sopenharmony_ci if (ret < 0) 9278c2ecf20Sopenharmony_ci return ret; 9288c2ecf20Sopenharmony_ci 9298c2ecf20Sopenharmony_ci if (opvsel & VDD1_OP_CMD_MASK) { 9308c2ecf20Sopenharmony_ci u8 reg_val = srvsel & VDD1_OP_SEL_MASK; 9318c2ecf20Sopenharmony_ci 9328c2ecf20Sopenharmony_ci ret = regmap_write(mfd->regmap, op_reg_add, reg_val); 9338c2ecf20Sopenharmony_ci if (ret < 0) { 9348c2ecf20Sopenharmony_ci dev_err(mfd->dev, 9358c2ecf20Sopenharmony_ci "Error in configuring op register\n"); 9368c2ecf20Sopenharmony_ci return ret; 9378c2ecf20Sopenharmony_ci } 9388c2ecf20Sopenharmony_ci } 9398c2ecf20Sopenharmony_ci ret = regmap_write(mfd->regmap, sr_reg_add, 0); 9408c2ecf20Sopenharmony_ci if (ret < 0) { 9418c2ecf20Sopenharmony_ci dev_err(mfd->dev, "Error in setting sr register\n"); 9428c2ecf20Sopenharmony_ci return ret; 9438c2ecf20Sopenharmony_ci } 9448c2ecf20Sopenharmony_ci } 9458c2ecf20Sopenharmony_ci 9468c2ecf20Sopenharmony_ci ret = regmap_clear_bits(mfd->regmap, 9478c2ecf20Sopenharmony_ci TPS65910_SLEEP_KEEP_LDO_ON + regoffs, bit_pos); 9488c2ecf20Sopenharmony_ci if (!ret) { 9498c2ecf20Sopenharmony_ci if (ext_sleep_config & TPS65911_SLEEP_CONTROL_EXT_INPUT_SLEEP) 9508c2ecf20Sopenharmony_ci ret = regmap_set_bits(mfd->regmap, 9518c2ecf20Sopenharmony_ci TPS65910_SLEEP_SET_LDO_OFF + regoffs, bit_pos); 9528c2ecf20Sopenharmony_ci else 9538c2ecf20Sopenharmony_ci ret = regmap_clear_bits(mfd->regmap, 9548c2ecf20Sopenharmony_ci TPS65910_SLEEP_SET_LDO_OFF + regoffs, bit_pos); 9558c2ecf20Sopenharmony_ci } 9568c2ecf20Sopenharmony_ci if (ret < 0) 9578c2ecf20Sopenharmony_ci dev_err(mfd->dev, 9588c2ecf20Sopenharmony_ci "Error in configuring SLEEP register\n"); 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_ci return ret; 9618c2ecf20Sopenharmony_ci} 9628c2ecf20Sopenharmony_ci 9638c2ecf20Sopenharmony_ci#ifdef CONFIG_OF 9648c2ecf20Sopenharmony_ci 9658c2ecf20Sopenharmony_cistatic struct of_regulator_match tps65910_matches[] = { 9668c2ecf20Sopenharmony_ci { .name = "vrtc", .driver_data = (void *) &tps65910_regs[0] }, 9678c2ecf20Sopenharmony_ci { .name = "vio", .driver_data = (void *) &tps65910_regs[1] }, 9688c2ecf20Sopenharmony_ci { .name = "vdd1", .driver_data = (void *) &tps65910_regs[2] }, 9698c2ecf20Sopenharmony_ci { .name = "vdd2", .driver_data = (void *) &tps65910_regs[3] }, 9708c2ecf20Sopenharmony_ci { .name = "vdd3", .driver_data = (void *) &tps65910_regs[4] }, 9718c2ecf20Sopenharmony_ci { .name = "vdig1", .driver_data = (void *) &tps65910_regs[5] }, 9728c2ecf20Sopenharmony_ci { .name = "vdig2", .driver_data = (void *) &tps65910_regs[6] }, 9738c2ecf20Sopenharmony_ci { .name = "vpll", .driver_data = (void *) &tps65910_regs[7] }, 9748c2ecf20Sopenharmony_ci { .name = "vdac", .driver_data = (void *) &tps65910_regs[8] }, 9758c2ecf20Sopenharmony_ci { .name = "vaux1", .driver_data = (void *) &tps65910_regs[9] }, 9768c2ecf20Sopenharmony_ci { .name = "vaux2", .driver_data = (void *) &tps65910_regs[10] }, 9778c2ecf20Sopenharmony_ci { .name = "vaux33", .driver_data = (void *) &tps65910_regs[11] }, 9788c2ecf20Sopenharmony_ci { .name = "vmmc", .driver_data = (void *) &tps65910_regs[12] }, 9798c2ecf20Sopenharmony_ci { .name = "vbb", .driver_data = (void *) &tps65910_regs[13] }, 9808c2ecf20Sopenharmony_ci}; 9818c2ecf20Sopenharmony_ci 9828c2ecf20Sopenharmony_cistatic struct of_regulator_match tps65911_matches[] = { 9838c2ecf20Sopenharmony_ci { .name = "vrtc", .driver_data = (void *) &tps65911_regs[0] }, 9848c2ecf20Sopenharmony_ci { .name = "vio", .driver_data = (void *) &tps65911_regs[1] }, 9858c2ecf20Sopenharmony_ci { .name = "vdd1", .driver_data = (void *) &tps65911_regs[2] }, 9868c2ecf20Sopenharmony_ci { .name = "vdd2", .driver_data = (void *) &tps65911_regs[3] }, 9878c2ecf20Sopenharmony_ci { .name = "vddctrl", .driver_data = (void *) &tps65911_regs[4] }, 9888c2ecf20Sopenharmony_ci { .name = "ldo1", .driver_data = (void *) &tps65911_regs[5] }, 9898c2ecf20Sopenharmony_ci { .name = "ldo2", .driver_data = (void *) &tps65911_regs[6] }, 9908c2ecf20Sopenharmony_ci { .name = "ldo3", .driver_data = (void *) &tps65911_regs[7] }, 9918c2ecf20Sopenharmony_ci { .name = "ldo4", .driver_data = (void *) &tps65911_regs[8] }, 9928c2ecf20Sopenharmony_ci { .name = "ldo5", .driver_data = (void *) &tps65911_regs[9] }, 9938c2ecf20Sopenharmony_ci { .name = "ldo6", .driver_data = (void *) &tps65911_regs[10] }, 9948c2ecf20Sopenharmony_ci { .name = "ldo7", .driver_data = (void *) &tps65911_regs[11] }, 9958c2ecf20Sopenharmony_ci { .name = "ldo8", .driver_data = (void *) &tps65911_regs[12] }, 9968c2ecf20Sopenharmony_ci}; 9978c2ecf20Sopenharmony_ci 9988c2ecf20Sopenharmony_cistatic struct tps65910_board *tps65910_parse_dt_reg_data( 9998c2ecf20Sopenharmony_ci struct platform_device *pdev, 10008c2ecf20Sopenharmony_ci struct of_regulator_match **tps65910_reg_matches) 10018c2ecf20Sopenharmony_ci{ 10028c2ecf20Sopenharmony_ci struct tps65910_board *pmic_plat_data; 10038c2ecf20Sopenharmony_ci struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent); 10048c2ecf20Sopenharmony_ci struct device_node *np, *regulators; 10058c2ecf20Sopenharmony_ci struct of_regulator_match *matches; 10068c2ecf20Sopenharmony_ci unsigned int prop; 10078c2ecf20Sopenharmony_ci int idx = 0, ret, count; 10088c2ecf20Sopenharmony_ci 10098c2ecf20Sopenharmony_ci pmic_plat_data = devm_kzalloc(&pdev->dev, sizeof(*pmic_plat_data), 10108c2ecf20Sopenharmony_ci GFP_KERNEL); 10118c2ecf20Sopenharmony_ci if (!pmic_plat_data) 10128c2ecf20Sopenharmony_ci return NULL; 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_ci np = pdev->dev.parent->of_node; 10158c2ecf20Sopenharmony_ci regulators = of_get_child_by_name(np, "regulators"); 10168c2ecf20Sopenharmony_ci if (!regulators) { 10178c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "regulator node not found\n"); 10188c2ecf20Sopenharmony_ci return NULL; 10198c2ecf20Sopenharmony_ci } 10208c2ecf20Sopenharmony_ci 10218c2ecf20Sopenharmony_ci switch (tps65910_chip_id(tps65910)) { 10228c2ecf20Sopenharmony_ci case TPS65910: 10238c2ecf20Sopenharmony_ci count = ARRAY_SIZE(tps65910_matches); 10248c2ecf20Sopenharmony_ci matches = tps65910_matches; 10258c2ecf20Sopenharmony_ci break; 10268c2ecf20Sopenharmony_ci case TPS65911: 10278c2ecf20Sopenharmony_ci count = ARRAY_SIZE(tps65911_matches); 10288c2ecf20Sopenharmony_ci matches = tps65911_matches; 10298c2ecf20Sopenharmony_ci break; 10308c2ecf20Sopenharmony_ci default: 10318c2ecf20Sopenharmony_ci of_node_put(regulators); 10328c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Invalid tps chip version\n"); 10338c2ecf20Sopenharmony_ci return NULL; 10348c2ecf20Sopenharmony_ci } 10358c2ecf20Sopenharmony_ci 10368c2ecf20Sopenharmony_ci ret = of_regulator_match(&pdev->dev, regulators, matches, count); 10378c2ecf20Sopenharmony_ci of_node_put(regulators); 10388c2ecf20Sopenharmony_ci if (ret < 0) { 10398c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Error parsing regulator init data: %d\n", 10408c2ecf20Sopenharmony_ci ret); 10418c2ecf20Sopenharmony_ci return NULL; 10428c2ecf20Sopenharmony_ci } 10438c2ecf20Sopenharmony_ci 10448c2ecf20Sopenharmony_ci *tps65910_reg_matches = matches; 10458c2ecf20Sopenharmony_ci 10468c2ecf20Sopenharmony_ci for (idx = 0; idx < count; idx++) { 10478c2ecf20Sopenharmony_ci if (!matches[idx].of_node) 10488c2ecf20Sopenharmony_ci continue; 10498c2ecf20Sopenharmony_ci 10508c2ecf20Sopenharmony_ci pmic_plat_data->tps65910_pmic_init_data[idx] = 10518c2ecf20Sopenharmony_ci matches[idx].init_data; 10528c2ecf20Sopenharmony_ci 10538c2ecf20Sopenharmony_ci ret = of_property_read_u32(matches[idx].of_node, 10548c2ecf20Sopenharmony_ci "ti,regulator-ext-sleep-control", &prop); 10558c2ecf20Sopenharmony_ci if (!ret) 10568c2ecf20Sopenharmony_ci pmic_plat_data->regulator_ext_sleep_control[idx] = prop; 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_ci } 10598c2ecf20Sopenharmony_ci 10608c2ecf20Sopenharmony_ci return pmic_plat_data; 10618c2ecf20Sopenharmony_ci} 10628c2ecf20Sopenharmony_ci#else 10638c2ecf20Sopenharmony_cistatic inline struct tps65910_board *tps65910_parse_dt_reg_data( 10648c2ecf20Sopenharmony_ci struct platform_device *pdev, 10658c2ecf20Sopenharmony_ci struct of_regulator_match **tps65910_reg_matches) 10668c2ecf20Sopenharmony_ci{ 10678c2ecf20Sopenharmony_ci *tps65910_reg_matches = NULL; 10688c2ecf20Sopenharmony_ci return NULL; 10698c2ecf20Sopenharmony_ci} 10708c2ecf20Sopenharmony_ci#endif 10718c2ecf20Sopenharmony_ci 10728c2ecf20Sopenharmony_cistatic int tps65910_probe(struct platform_device *pdev) 10738c2ecf20Sopenharmony_ci{ 10748c2ecf20Sopenharmony_ci struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent); 10758c2ecf20Sopenharmony_ci struct regulator_config config = { }; 10768c2ecf20Sopenharmony_ci struct tps_info *info; 10778c2ecf20Sopenharmony_ci struct regulator_dev *rdev; 10788c2ecf20Sopenharmony_ci struct tps65910_reg *pmic; 10798c2ecf20Sopenharmony_ci struct tps65910_board *pmic_plat_data; 10808c2ecf20Sopenharmony_ci struct of_regulator_match *tps65910_reg_matches = NULL; 10818c2ecf20Sopenharmony_ci int i, err; 10828c2ecf20Sopenharmony_ci 10838c2ecf20Sopenharmony_ci pmic_plat_data = dev_get_platdata(tps65910->dev); 10848c2ecf20Sopenharmony_ci if (!pmic_plat_data && tps65910->dev->of_node) 10858c2ecf20Sopenharmony_ci pmic_plat_data = tps65910_parse_dt_reg_data(pdev, 10868c2ecf20Sopenharmony_ci &tps65910_reg_matches); 10878c2ecf20Sopenharmony_ci 10888c2ecf20Sopenharmony_ci if (!pmic_plat_data) { 10898c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Platform data not found\n"); 10908c2ecf20Sopenharmony_ci return -EINVAL; 10918c2ecf20Sopenharmony_ci } 10928c2ecf20Sopenharmony_ci 10938c2ecf20Sopenharmony_ci pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL); 10948c2ecf20Sopenharmony_ci if (!pmic) 10958c2ecf20Sopenharmony_ci return -ENOMEM; 10968c2ecf20Sopenharmony_ci 10978c2ecf20Sopenharmony_ci pmic->mfd = tps65910; 10988c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, pmic); 10998c2ecf20Sopenharmony_ci 11008c2ecf20Sopenharmony_ci /* Give control of all register to control port */ 11018c2ecf20Sopenharmony_ci err = regmap_set_bits(pmic->mfd->regmap, TPS65910_DEVCTRL, 11028c2ecf20Sopenharmony_ci DEVCTRL_SR_CTL_I2C_SEL_MASK); 11038c2ecf20Sopenharmony_ci if (err < 0) 11048c2ecf20Sopenharmony_ci return err; 11058c2ecf20Sopenharmony_ci 11068c2ecf20Sopenharmony_ci switch (tps65910_chip_id(tps65910)) { 11078c2ecf20Sopenharmony_ci case TPS65910: 11088c2ecf20Sopenharmony_ci BUILD_BUG_ON(TPS65910_NUM_REGS < ARRAY_SIZE(tps65910_regs)); 11098c2ecf20Sopenharmony_ci pmic->get_ctrl_reg = &tps65910_get_ctrl_register; 11108c2ecf20Sopenharmony_ci pmic->num_regulators = ARRAY_SIZE(tps65910_regs); 11118c2ecf20Sopenharmony_ci pmic->ext_sleep_control = tps65910_ext_sleep_control; 11128c2ecf20Sopenharmony_ci info = tps65910_regs; 11138c2ecf20Sopenharmony_ci /* Work around silicon erratum SWCZ010: output programmed 11148c2ecf20Sopenharmony_ci * voltage level can go higher than expected or crash 11158c2ecf20Sopenharmony_ci * Workaround: use no synchronization of DCDC clocks 11168c2ecf20Sopenharmony_ci */ 11178c2ecf20Sopenharmony_ci regmap_clear_bits(pmic->mfd->regmap, TPS65910_DCDCCTRL, 11188c2ecf20Sopenharmony_ci DCDCCTRL_DCDCCKSYNC_MASK); 11198c2ecf20Sopenharmony_ci break; 11208c2ecf20Sopenharmony_ci case TPS65911: 11218c2ecf20Sopenharmony_ci BUILD_BUG_ON(TPS65910_NUM_REGS < ARRAY_SIZE(tps65911_regs)); 11228c2ecf20Sopenharmony_ci pmic->get_ctrl_reg = &tps65911_get_ctrl_register; 11238c2ecf20Sopenharmony_ci pmic->num_regulators = ARRAY_SIZE(tps65911_regs); 11248c2ecf20Sopenharmony_ci pmic->ext_sleep_control = tps65911_ext_sleep_control; 11258c2ecf20Sopenharmony_ci info = tps65911_regs; 11268c2ecf20Sopenharmony_ci break; 11278c2ecf20Sopenharmony_ci default: 11288c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Invalid tps chip version\n"); 11298c2ecf20Sopenharmony_ci return -ENODEV; 11308c2ecf20Sopenharmony_ci } 11318c2ecf20Sopenharmony_ci 11328c2ecf20Sopenharmony_ci pmic->desc = devm_kcalloc(&pdev->dev, 11338c2ecf20Sopenharmony_ci pmic->num_regulators, 11348c2ecf20Sopenharmony_ci sizeof(struct regulator_desc), 11358c2ecf20Sopenharmony_ci GFP_KERNEL); 11368c2ecf20Sopenharmony_ci if (!pmic->desc) 11378c2ecf20Sopenharmony_ci return -ENOMEM; 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_ci pmic->info = devm_kcalloc(&pdev->dev, 11408c2ecf20Sopenharmony_ci pmic->num_regulators, 11418c2ecf20Sopenharmony_ci sizeof(struct tps_info *), 11428c2ecf20Sopenharmony_ci GFP_KERNEL); 11438c2ecf20Sopenharmony_ci if (!pmic->info) 11448c2ecf20Sopenharmony_ci return -ENOMEM; 11458c2ecf20Sopenharmony_ci 11468c2ecf20Sopenharmony_ci pmic->rdev = devm_kcalloc(&pdev->dev, 11478c2ecf20Sopenharmony_ci pmic->num_regulators, 11488c2ecf20Sopenharmony_ci sizeof(struct regulator_dev *), 11498c2ecf20Sopenharmony_ci GFP_KERNEL); 11508c2ecf20Sopenharmony_ci if (!pmic->rdev) 11518c2ecf20Sopenharmony_ci return -ENOMEM; 11528c2ecf20Sopenharmony_ci 11538c2ecf20Sopenharmony_ci for (i = 0; i < pmic->num_regulators; i++, info++) { 11548c2ecf20Sopenharmony_ci /* Register the regulators */ 11558c2ecf20Sopenharmony_ci pmic->info[i] = info; 11568c2ecf20Sopenharmony_ci 11578c2ecf20Sopenharmony_ci pmic->desc[i].name = info->name; 11588c2ecf20Sopenharmony_ci pmic->desc[i].supply_name = info->vin_name; 11598c2ecf20Sopenharmony_ci pmic->desc[i].id = i; 11608c2ecf20Sopenharmony_ci pmic->desc[i].n_voltages = info->n_voltages; 11618c2ecf20Sopenharmony_ci pmic->desc[i].enable_time = info->enable_time_us; 11628c2ecf20Sopenharmony_ci 11638c2ecf20Sopenharmony_ci if (i == TPS65910_REG_VDD1 || i == TPS65910_REG_VDD2) { 11648c2ecf20Sopenharmony_ci pmic->desc[i].ops = &tps65910_ops_dcdc; 11658c2ecf20Sopenharmony_ci pmic->desc[i].n_voltages = VDD1_2_NUM_VOLT_FINE * 11668c2ecf20Sopenharmony_ci VDD1_2_NUM_VOLT_COARSE; 11678c2ecf20Sopenharmony_ci pmic->desc[i].ramp_delay = 12500; 11688c2ecf20Sopenharmony_ci } else if (i == TPS65910_REG_VDD3) { 11698c2ecf20Sopenharmony_ci if (tps65910_chip_id(tps65910) == TPS65910) { 11708c2ecf20Sopenharmony_ci pmic->desc[i].ops = &tps65910_ops_vdd3; 11718c2ecf20Sopenharmony_ci pmic->desc[i].volt_table = info->voltage_table; 11728c2ecf20Sopenharmony_ci } else { 11738c2ecf20Sopenharmony_ci pmic->desc[i].ops = &tps65910_ops_dcdc; 11748c2ecf20Sopenharmony_ci pmic->desc[i].ramp_delay = 5000; 11758c2ecf20Sopenharmony_ci } 11768c2ecf20Sopenharmony_ci } else if (i == TPS65910_REG_VBB && 11778c2ecf20Sopenharmony_ci tps65910_chip_id(tps65910) == TPS65910) { 11788c2ecf20Sopenharmony_ci pmic->desc[i].ops = &tps65910_ops_vbb; 11798c2ecf20Sopenharmony_ci pmic->desc[i].volt_table = info->voltage_table; 11808c2ecf20Sopenharmony_ci } else { 11818c2ecf20Sopenharmony_ci if (tps65910_chip_id(tps65910) == TPS65910) { 11828c2ecf20Sopenharmony_ci pmic->desc[i].ops = &tps65910_ops; 11838c2ecf20Sopenharmony_ci pmic->desc[i].volt_table = info->voltage_table; 11848c2ecf20Sopenharmony_ci } else { 11858c2ecf20Sopenharmony_ci pmic->desc[i].ops = &tps65911_ops; 11868c2ecf20Sopenharmony_ci } 11878c2ecf20Sopenharmony_ci } 11888c2ecf20Sopenharmony_ci 11898c2ecf20Sopenharmony_ci err = tps65910_set_ext_sleep_config(pmic, i, 11908c2ecf20Sopenharmony_ci pmic_plat_data->regulator_ext_sleep_control[i]); 11918c2ecf20Sopenharmony_ci /* 11928c2ecf20Sopenharmony_ci * Failing on regulator for configuring externally control 11938c2ecf20Sopenharmony_ci * is not a serious issue, just throw warning. 11948c2ecf20Sopenharmony_ci */ 11958c2ecf20Sopenharmony_ci if (err < 0) 11968c2ecf20Sopenharmony_ci dev_warn(tps65910->dev, 11978c2ecf20Sopenharmony_ci "Failed to initialise ext control config\n"); 11988c2ecf20Sopenharmony_ci 11998c2ecf20Sopenharmony_ci pmic->desc[i].type = REGULATOR_VOLTAGE; 12008c2ecf20Sopenharmony_ci pmic->desc[i].owner = THIS_MODULE; 12018c2ecf20Sopenharmony_ci pmic->desc[i].enable_reg = pmic->get_ctrl_reg(i); 12028c2ecf20Sopenharmony_ci pmic->desc[i].enable_mask = TPS65910_SUPPLY_STATE_ENABLED; 12038c2ecf20Sopenharmony_ci 12048c2ecf20Sopenharmony_ci config.dev = tps65910->dev; 12058c2ecf20Sopenharmony_ci config.init_data = pmic_plat_data->tps65910_pmic_init_data[i]; 12068c2ecf20Sopenharmony_ci config.driver_data = pmic; 12078c2ecf20Sopenharmony_ci config.regmap = tps65910->regmap; 12088c2ecf20Sopenharmony_ci 12098c2ecf20Sopenharmony_ci if (tps65910_reg_matches) 12108c2ecf20Sopenharmony_ci config.of_node = tps65910_reg_matches[i].of_node; 12118c2ecf20Sopenharmony_ci 12128c2ecf20Sopenharmony_ci rdev = devm_regulator_register(&pdev->dev, &pmic->desc[i], 12138c2ecf20Sopenharmony_ci &config); 12148c2ecf20Sopenharmony_ci if (IS_ERR(rdev)) 12158c2ecf20Sopenharmony_ci return dev_err_probe(tps65910->dev, PTR_ERR(rdev), 12168c2ecf20Sopenharmony_ci "failed to register %s regulator\n", 12178c2ecf20Sopenharmony_ci pdev->name); 12188c2ecf20Sopenharmony_ci 12198c2ecf20Sopenharmony_ci /* Save regulator for cleanup */ 12208c2ecf20Sopenharmony_ci pmic->rdev[i] = rdev; 12218c2ecf20Sopenharmony_ci } 12228c2ecf20Sopenharmony_ci return 0; 12238c2ecf20Sopenharmony_ci} 12248c2ecf20Sopenharmony_ci 12258c2ecf20Sopenharmony_cistatic void tps65910_shutdown(struct platform_device *pdev) 12268c2ecf20Sopenharmony_ci{ 12278c2ecf20Sopenharmony_ci struct tps65910_reg *pmic = platform_get_drvdata(pdev); 12288c2ecf20Sopenharmony_ci int i; 12298c2ecf20Sopenharmony_ci 12308c2ecf20Sopenharmony_ci /* 12318c2ecf20Sopenharmony_ci * Before bootloader jumps to kernel, it makes sure that required 12328c2ecf20Sopenharmony_ci * external control signals are in desired state so that given rails 12338c2ecf20Sopenharmony_ci * can be configure accordingly. 12348c2ecf20Sopenharmony_ci * If rails are configured to be controlled from external control 12358c2ecf20Sopenharmony_ci * then before shutting down/rebooting the system, the external 12368c2ecf20Sopenharmony_ci * control configuration need to be remove from the rails so that 12378c2ecf20Sopenharmony_ci * its output will be available as per register programming even 12388c2ecf20Sopenharmony_ci * if external controls are removed. This is require when the POR 12398c2ecf20Sopenharmony_ci * value of the control signals are not in active state and before 12408c2ecf20Sopenharmony_ci * bootloader initializes it, the system requires the rail output 12418c2ecf20Sopenharmony_ci * to be active for booting. 12428c2ecf20Sopenharmony_ci */ 12438c2ecf20Sopenharmony_ci for (i = 0; i < pmic->num_regulators; i++) { 12448c2ecf20Sopenharmony_ci int err; 12458c2ecf20Sopenharmony_ci if (!pmic->rdev[i]) 12468c2ecf20Sopenharmony_ci continue; 12478c2ecf20Sopenharmony_ci 12488c2ecf20Sopenharmony_ci err = tps65910_set_ext_sleep_config(pmic, i, 0); 12498c2ecf20Sopenharmony_ci if (err < 0) 12508c2ecf20Sopenharmony_ci dev_err(&pdev->dev, 12518c2ecf20Sopenharmony_ci "Error in clearing external control\n"); 12528c2ecf20Sopenharmony_ci } 12538c2ecf20Sopenharmony_ci} 12548c2ecf20Sopenharmony_ci 12558c2ecf20Sopenharmony_cistatic struct platform_driver tps65910_driver = { 12568c2ecf20Sopenharmony_ci .driver = { 12578c2ecf20Sopenharmony_ci .name = "tps65910-pmic", 12588c2ecf20Sopenharmony_ci }, 12598c2ecf20Sopenharmony_ci .probe = tps65910_probe, 12608c2ecf20Sopenharmony_ci .shutdown = tps65910_shutdown, 12618c2ecf20Sopenharmony_ci}; 12628c2ecf20Sopenharmony_ci 12638c2ecf20Sopenharmony_cistatic int __init tps65910_init(void) 12648c2ecf20Sopenharmony_ci{ 12658c2ecf20Sopenharmony_ci return platform_driver_register(&tps65910_driver); 12668c2ecf20Sopenharmony_ci} 12678c2ecf20Sopenharmony_cisubsys_initcall(tps65910_init); 12688c2ecf20Sopenharmony_ci 12698c2ecf20Sopenharmony_cistatic void __exit tps65910_cleanup(void) 12708c2ecf20Sopenharmony_ci{ 12718c2ecf20Sopenharmony_ci platform_driver_unregister(&tps65910_driver); 12728c2ecf20Sopenharmony_ci} 12738c2ecf20Sopenharmony_cimodule_exit(tps65910_cleanup); 12748c2ecf20Sopenharmony_ci 12758c2ecf20Sopenharmony_ciMODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>"); 12768c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("TPS65910/TPS65911 voltage regulator driver"); 12778c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 12788c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:tps65910-pmic"); 1279