18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci// 38c2ecf20Sopenharmony_ci// Copyright (C) 2018 BayLibre SAS 48c2ecf20Sopenharmony_ci// Author: Bartosz Golaszewski <bgolaszewski@baylibre.com> 58c2ecf20Sopenharmony_ci// 68c2ecf20Sopenharmony_ci// Regulator driver for MAXIM 77650/77651 charger/power-supply. 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/of.h> 98c2ecf20Sopenharmony_ci#include <linux/mfd/max77650.h> 108c2ecf20Sopenharmony_ci#include <linux/module.h> 118c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 128c2ecf20Sopenharmony_ci#include <linux/regmap.h> 138c2ecf20Sopenharmony_ci#include <linux/regulator/driver.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#define MAX77650_REGULATOR_EN_CTRL_MASK GENMASK(3, 0) 168c2ecf20Sopenharmony_ci#define MAX77650_REGULATOR_EN_CTRL_BITS(_reg) \ 178c2ecf20Sopenharmony_ci ((_reg) & MAX77650_REGULATOR_EN_CTRL_MASK) 188c2ecf20Sopenharmony_ci#define MAX77650_REGULATOR_ENABLED GENMASK(2, 1) 198c2ecf20Sopenharmony_ci#define MAX77650_REGULATOR_DISABLED BIT(2) 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#define MAX77650_REGULATOR_V_LDO_MASK GENMASK(6, 0) 228c2ecf20Sopenharmony_ci#define MAX77650_REGULATOR_V_SBB_MASK GENMASK(5, 0) 238c2ecf20Sopenharmony_ci#define MAX77651_REGULATOR_V_SBB1_MASK GENMASK(5, 2) 248c2ecf20Sopenharmony_ci#define MAX77651_REGULATOR_V_SBB1_RANGE_MASK GENMASK(1, 0) 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#define MAX77650_REGULATOR_AD_MASK BIT(3) 278c2ecf20Sopenharmony_ci#define MAX77650_REGULATOR_AD_DISABLED 0x00 288c2ecf20Sopenharmony_ci#define MAX77650_REGULATOR_AD_ENABLED BIT(3) 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#define MAX77650_REGULATOR_CURR_LIM_MASK GENMASK(7, 6) 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_cienum { 338c2ecf20Sopenharmony_ci MAX77650_REGULATOR_ID_LDO = 0, 348c2ecf20Sopenharmony_ci MAX77650_REGULATOR_ID_SBB0, 358c2ecf20Sopenharmony_ci MAX77650_REGULATOR_ID_SBB1, 368c2ecf20Sopenharmony_ci MAX77650_REGULATOR_ID_SBB2, 378c2ecf20Sopenharmony_ci MAX77650_REGULATOR_NUM_REGULATORS, 388c2ecf20Sopenharmony_ci}; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_cistruct max77650_regulator_desc { 418c2ecf20Sopenharmony_ci struct regulator_desc desc; 428c2ecf20Sopenharmony_ci unsigned int regA; 438c2ecf20Sopenharmony_ci unsigned int regB; 448c2ecf20Sopenharmony_ci}; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_cistatic struct max77650_regulator_desc max77651_SBB1_desc; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_cistatic const unsigned int max77651_sbb1_volt_range_sel[] = { 498c2ecf20Sopenharmony_ci 0x0, 0x1, 0x2, 0x3 508c2ecf20Sopenharmony_ci}; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_cistatic const struct linear_range max77651_sbb1_volt_ranges[] = { 538c2ecf20Sopenharmony_ci /* range index 0 */ 548c2ecf20Sopenharmony_ci REGULATOR_LINEAR_RANGE(2400000, 0x00, 0x0f, 50000), 558c2ecf20Sopenharmony_ci /* range index 1 */ 568c2ecf20Sopenharmony_ci REGULATOR_LINEAR_RANGE(3200000, 0x00, 0x0f, 50000), 578c2ecf20Sopenharmony_ci /* range index 2 */ 588c2ecf20Sopenharmony_ci REGULATOR_LINEAR_RANGE(4000000, 0x00, 0x0f, 50000), 598c2ecf20Sopenharmony_ci /* range index 3 */ 608c2ecf20Sopenharmony_ci REGULATOR_LINEAR_RANGE(4800000, 0x00, 0x09, 50000), 618c2ecf20Sopenharmony_ci}; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_cistatic const unsigned int max77650_current_limit_table[] = { 648c2ecf20Sopenharmony_ci 1000000, 866000, 707000, 500000, 658c2ecf20Sopenharmony_ci}; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_cistatic int max77650_regulator_is_enabled(struct regulator_dev *rdev) 688c2ecf20Sopenharmony_ci{ 698c2ecf20Sopenharmony_ci struct max77650_regulator_desc *rdesc; 708c2ecf20Sopenharmony_ci struct regmap *map; 718c2ecf20Sopenharmony_ci int val, rv, en; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci rdesc = rdev_get_drvdata(rdev); 748c2ecf20Sopenharmony_ci map = rdev_get_regmap(rdev); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci rv = regmap_read(map, rdesc->regB, &val); 778c2ecf20Sopenharmony_ci if (rv) 788c2ecf20Sopenharmony_ci return rv; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci en = MAX77650_REGULATOR_EN_CTRL_BITS(val); 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci return en != MAX77650_REGULATOR_DISABLED; 838c2ecf20Sopenharmony_ci} 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_cistatic int max77650_regulator_enable(struct regulator_dev *rdev) 868c2ecf20Sopenharmony_ci{ 878c2ecf20Sopenharmony_ci struct max77650_regulator_desc *rdesc; 888c2ecf20Sopenharmony_ci struct regmap *map; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci rdesc = rdev_get_drvdata(rdev); 918c2ecf20Sopenharmony_ci map = rdev_get_regmap(rdev); 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci return regmap_update_bits(map, rdesc->regB, 948c2ecf20Sopenharmony_ci MAX77650_REGULATOR_EN_CTRL_MASK, 958c2ecf20Sopenharmony_ci MAX77650_REGULATOR_ENABLED); 968c2ecf20Sopenharmony_ci} 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_cistatic int max77650_regulator_disable(struct regulator_dev *rdev) 998c2ecf20Sopenharmony_ci{ 1008c2ecf20Sopenharmony_ci struct max77650_regulator_desc *rdesc; 1018c2ecf20Sopenharmony_ci struct regmap *map; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci rdesc = rdev_get_drvdata(rdev); 1048c2ecf20Sopenharmony_ci map = rdev_get_regmap(rdev); 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci return regmap_update_bits(map, rdesc->regB, 1078c2ecf20Sopenharmony_ci MAX77650_REGULATOR_EN_CTRL_MASK, 1088c2ecf20Sopenharmony_ci MAX77650_REGULATOR_DISABLED); 1098c2ecf20Sopenharmony_ci} 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_cistatic const struct regulator_ops max77650_regulator_LDO_ops = { 1128c2ecf20Sopenharmony_ci .is_enabled = max77650_regulator_is_enabled, 1138c2ecf20Sopenharmony_ci .enable = max77650_regulator_enable, 1148c2ecf20Sopenharmony_ci .disable = max77650_regulator_disable, 1158c2ecf20Sopenharmony_ci .list_voltage = regulator_list_voltage_linear, 1168c2ecf20Sopenharmony_ci .map_voltage = regulator_map_voltage_linear, 1178c2ecf20Sopenharmony_ci .get_voltage_sel = regulator_get_voltage_sel_regmap, 1188c2ecf20Sopenharmony_ci .set_voltage_sel = regulator_set_voltage_sel_regmap, 1198c2ecf20Sopenharmony_ci .set_active_discharge = regulator_set_active_discharge_regmap, 1208c2ecf20Sopenharmony_ci}; 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_cistatic const struct regulator_ops max77650_regulator_SBB_ops = { 1238c2ecf20Sopenharmony_ci .is_enabled = max77650_regulator_is_enabled, 1248c2ecf20Sopenharmony_ci .enable = max77650_regulator_enable, 1258c2ecf20Sopenharmony_ci .disable = max77650_regulator_disable, 1268c2ecf20Sopenharmony_ci .list_voltage = regulator_list_voltage_linear, 1278c2ecf20Sopenharmony_ci .map_voltage = regulator_map_voltage_linear, 1288c2ecf20Sopenharmony_ci .get_voltage_sel = regulator_get_voltage_sel_regmap, 1298c2ecf20Sopenharmony_ci .set_voltage_sel = regulator_set_voltage_sel_regmap, 1308c2ecf20Sopenharmony_ci .get_current_limit = regulator_get_current_limit_regmap, 1318c2ecf20Sopenharmony_ci .set_current_limit = regulator_set_current_limit_regmap, 1328c2ecf20Sopenharmony_ci .set_active_discharge = regulator_set_active_discharge_regmap, 1338c2ecf20Sopenharmony_ci}; 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci/* Special case for max77651 SBB1 - pickable linear-range voltage mapping. */ 1368c2ecf20Sopenharmony_cistatic const struct regulator_ops max77651_SBB1_regulator_ops = { 1378c2ecf20Sopenharmony_ci .is_enabled = max77650_regulator_is_enabled, 1388c2ecf20Sopenharmony_ci .enable = max77650_regulator_enable, 1398c2ecf20Sopenharmony_ci .disable = max77650_regulator_disable, 1408c2ecf20Sopenharmony_ci .list_voltage = regulator_list_voltage_pickable_linear_range, 1418c2ecf20Sopenharmony_ci .get_voltage_sel = regulator_get_voltage_sel_pickable_regmap, 1428c2ecf20Sopenharmony_ci .set_voltage_sel = regulator_set_voltage_sel_pickable_regmap, 1438c2ecf20Sopenharmony_ci .get_current_limit = regulator_get_current_limit_regmap, 1448c2ecf20Sopenharmony_ci .set_current_limit = regulator_set_current_limit_regmap, 1458c2ecf20Sopenharmony_ci .set_active_discharge = regulator_set_active_discharge_regmap, 1468c2ecf20Sopenharmony_ci}; 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_cistatic struct max77650_regulator_desc max77650_LDO_desc = { 1498c2ecf20Sopenharmony_ci .desc = { 1508c2ecf20Sopenharmony_ci .name = "ldo", 1518c2ecf20Sopenharmony_ci .of_match = of_match_ptr("ldo"), 1528c2ecf20Sopenharmony_ci .regulators_node = of_match_ptr("regulators"), 1538c2ecf20Sopenharmony_ci .supply_name = "in-ldo", 1548c2ecf20Sopenharmony_ci .id = MAX77650_REGULATOR_ID_LDO, 1558c2ecf20Sopenharmony_ci .ops = &max77650_regulator_LDO_ops, 1568c2ecf20Sopenharmony_ci .min_uV = 1350000, 1578c2ecf20Sopenharmony_ci .uV_step = 12500, 1588c2ecf20Sopenharmony_ci .n_voltages = 128, 1598c2ecf20Sopenharmony_ci .vsel_step = 1, 1608c2ecf20Sopenharmony_ci .vsel_mask = MAX77650_REGULATOR_V_LDO_MASK, 1618c2ecf20Sopenharmony_ci .vsel_reg = MAX77650_REG_CNFG_LDO_A, 1628c2ecf20Sopenharmony_ci .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED, 1638c2ecf20Sopenharmony_ci .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED, 1648c2ecf20Sopenharmony_ci .active_discharge_mask = MAX77650_REGULATOR_AD_MASK, 1658c2ecf20Sopenharmony_ci .active_discharge_reg = MAX77650_REG_CNFG_LDO_B, 1668c2ecf20Sopenharmony_ci .enable_time = 100, 1678c2ecf20Sopenharmony_ci .type = REGULATOR_VOLTAGE, 1688c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 1698c2ecf20Sopenharmony_ci }, 1708c2ecf20Sopenharmony_ci .regA = MAX77650_REG_CNFG_LDO_A, 1718c2ecf20Sopenharmony_ci .regB = MAX77650_REG_CNFG_LDO_B, 1728c2ecf20Sopenharmony_ci}; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_cistatic struct max77650_regulator_desc max77650_SBB0_desc = { 1758c2ecf20Sopenharmony_ci .desc = { 1768c2ecf20Sopenharmony_ci .name = "sbb0", 1778c2ecf20Sopenharmony_ci .of_match = of_match_ptr("sbb0"), 1788c2ecf20Sopenharmony_ci .regulators_node = of_match_ptr("regulators"), 1798c2ecf20Sopenharmony_ci .supply_name = "in-sbb0", 1808c2ecf20Sopenharmony_ci .id = MAX77650_REGULATOR_ID_SBB0, 1818c2ecf20Sopenharmony_ci .ops = &max77650_regulator_SBB_ops, 1828c2ecf20Sopenharmony_ci .min_uV = 800000, 1838c2ecf20Sopenharmony_ci .uV_step = 25000, 1848c2ecf20Sopenharmony_ci .n_voltages = 64, 1858c2ecf20Sopenharmony_ci .vsel_step = 1, 1868c2ecf20Sopenharmony_ci .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK, 1878c2ecf20Sopenharmony_ci .vsel_reg = MAX77650_REG_CNFG_SBB0_A, 1888c2ecf20Sopenharmony_ci .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED, 1898c2ecf20Sopenharmony_ci .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED, 1908c2ecf20Sopenharmony_ci .active_discharge_mask = MAX77650_REGULATOR_AD_MASK, 1918c2ecf20Sopenharmony_ci .active_discharge_reg = MAX77650_REG_CNFG_SBB0_B, 1928c2ecf20Sopenharmony_ci .enable_time = 100, 1938c2ecf20Sopenharmony_ci .type = REGULATOR_VOLTAGE, 1948c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 1958c2ecf20Sopenharmony_ci .csel_reg = MAX77650_REG_CNFG_SBB0_A, 1968c2ecf20Sopenharmony_ci .csel_mask = MAX77650_REGULATOR_CURR_LIM_MASK, 1978c2ecf20Sopenharmony_ci .curr_table = max77650_current_limit_table, 1988c2ecf20Sopenharmony_ci .n_current_limits = ARRAY_SIZE(max77650_current_limit_table), 1998c2ecf20Sopenharmony_ci }, 2008c2ecf20Sopenharmony_ci .regA = MAX77650_REG_CNFG_SBB0_A, 2018c2ecf20Sopenharmony_ci .regB = MAX77650_REG_CNFG_SBB0_B, 2028c2ecf20Sopenharmony_ci}; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_cistatic struct max77650_regulator_desc max77650_SBB1_desc = { 2058c2ecf20Sopenharmony_ci .desc = { 2068c2ecf20Sopenharmony_ci .name = "sbb1", 2078c2ecf20Sopenharmony_ci .of_match = of_match_ptr("sbb1"), 2088c2ecf20Sopenharmony_ci .regulators_node = of_match_ptr("regulators"), 2098c2ecf20Sopenharmony_ci .supply_name = "in-sbb1", 2108c2ecf20Sopenharmony_ci .id = MAX77650_REGULATOR_ID_SBB1, 2118c2ecf20Sopenharmony_ci .ops = &max77650_regulator_SBB_ops, 2128c2ecf20Sopenharmony_ci .min_uV = 800000, 2138c2ecf20Sopenharmony_ci .uV_step = 12500, 2148c2ecf20Sopenharmony_ci .n_voltages = 64, 2158c2ecf20Sopenharmony_ci .vsel_step = 1, 2168c2ecf20Sopenharmony_ci .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK, 2178c2ecf20Sopenharmony_ci .vsel_reg = MAX77650_REG_CNFG_SBB1_A, 2188c2ecf20Sopenharmony_ci .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED, 2198c2ecf20Sopenharmony_ci .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED, 2208c2ecf20Sopenharmony_ci .active_discharge_mask = MAX77650_REGULATOR_AD_MASK, 2218c2ecf20Sopenharmony_ci .active_discharge_reg = MAX77650_REG_CNFG_SBB1_B, 2228c2ecf20Sopenharmony_ci .enable_time = 100, 2238c2ecf20Sopenharmony_ci .type = REGULATOR_VOLTAGE, 2248c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 2258c2ecf20Sopenharmony_ci .csel_reg = MAX77650_REG_CNFG_SBB1_A, 2268c2ecf20Sopenharmony_ci .csel_mask = MAX77650_REGULATOR_CURR_LIM_MASK, 2278c2ecf20Sopenharmony_ci .curr_table = max77650_current_limit_table, 2288c2ecf20Sopenharmony_ci .n_current_limits = ARRAY_SIZE(max77650_current_limit_table), 2298c2ecf20Sopenharmony_ci }, 2308c2ecf20Sopenharmony_ci .regA = MAX77650_REG_CNFG_SBB1_A, 2318c2ecf20Sopenharmony_ci .regB = MAX77650_REG_CNFG_SBB1_B, 2328c2ecf20Sopenharmony_ci}; 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_cistatic struct max77650_regulator_desc max77651_SBB1_desc = { 2358c2ecf20Sopenharmony_ci .desc = { 2368c2ecf20Sopenharmony_ci .name = "sbb1", 2378c2ecf20Sopenharmony_ci .of_match = of_match_ptr("sbb1"), 2388c2ecf20Sopenharmony_ci .regulators_node = of_match_ptr("regulators"), 2398c2ecf20Sopenharmony_ci .supply_name = "in-sbb1", 2408c2ecf20Sopenharmony_ci .id = MAX77650_REGULATOR_ID_SBB1, 2418c2ecf20Sopenharmony_ci .ops = &max77651_SBB1_regulator_ops, 2428c2ecf20Sopenharmony_ci .linear_range_selectors = max77651_sbb1_volt_range_sel, 2438c2ecf20Sopenharmony_ci .linear_ranges = max77651_sbb1_volt_ranges, 2448c2ecf20Sopenharmony_ci .n_linear_ranges = ARRAY_SIZE(max77651_sbb1_volt_ranges), 2458c2ecf20Sopenharmony_ci .n_voltages = 58, 2468c2ecf20Sopenharmony_ci .vsel_step = 1, 2478c2ecf20Sopenharmony_ci .vsel_range_mask = MAX77651_REGULATOR_V_SBB1_RANGE_MASK, 2488c2ecf20Sopenharmony_ci .vsel_range_reg = MAX77650_REG_CNFG_SBB1_A, 2498c2ecf20Sopenharmony_ci .vsel_mask = MAX77651_REGULATOR_V_SBB1_MASK, 2508c2ecf20Sopenharmony_ci .vsel_reg = MAX77650_REG_CNFG_SBB1_A, 2518c2ecf20Sopenharmony_ci .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED, 2528c2ecf20Sopenharmony_ci .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED, 2538c2ecf20Sopenharmony_ci .active_discharge_mask = MAX77650_REGULATOR_AD_MASK, 2548c2ecf20Sopenharmony_ci .active_discharge_reg = MAX77650_REG_CNFG_SBB1_B, 2558c2ecf20Sopenharmony_ci .enable_time = 100, 2568c2ecf20Sopenharmony_ci .type = REGULATOR_VOLTAGE, 2578c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 2588c2ecf20Sopenharmony_ci .csel_reg = MAX77650_REG_CNFG_SBB1_A, 2598c2ecf20Sopenharmony_ci .csel_mask = MAX77650_REGULATOR_CURR_LIM_MASK, 2608c2ecf20Sopenharmony_ci .curr_table = max77650_current_limit_table, 2618c2ecf20Sopenharmony_ci .n_current_limits = ARRAY_SIZE(max77650_current_limit_table), 2628c2ecf20Sopenharmony_ci }, 2638c2ecf20Sopenharmony_ci .regA = MAX77650_REG_CNFG_SBB1_A, 2648c2ecf20Sopenharmony_ci .regB = MAX77650_REG_CNFG_SBB1_B, 2658c2ecf20Sopenharmony_ci}; 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_cistatic struct max77650_regulator_desc max77650_SBB2_desc = { 2688c2ecf20Sopenharmony_ci .desc = { 2698c2ecf20Sopenharmony_ci .name = "sbb2", 2708c2ecf20Sopenharmony_ci .of_match = of_match_ptr("sbb2"), 2718c2ecf20Sopenharmony_ci .regulators_node = of_match_ptr("regulators"), 2728c2ecf20Sopenharmony_ci .supply_name = "in-sbb0", 2738c2ecf20Sopenharmony_ci .id = MAX77650_REGULATOR_ID_SBB2, 2748c2ecf20Sopenharmony_ci .ops = &max77650_regulator_SBB_ops, 2758c2ecf20Sopenharmony_ci .min_uV = 800000, 2768c2ecf20Sopenharmony_ci .uV_step = 50000, 2778c2ecf20Sopenharmony_ci .n_voltages = 64, 2788c2ecf20Sopenharmony_ci .vsel_step = 1, 2798c2ecf20Sopenharmony_ci .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK, 2808c2ecf20Sopenharmony_ci .vsel_reg = MAX77650_REG_CNFG_SBB2_A, 2818c2ecf20Sopenharmony_ci .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED, 2828c2ecf20Sopenharmony_ci .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED, 2838c2ecf20Sopenharmony_ci .active_discharge_mask = MAX77650_REGULATOR_AD_MASK, 2848c2ecf20Sopenharmony_ci .active_discharge_reg = MAX77650_REG_CNFG_SBB2_B, 2858c2ecf20Sopenharmony_ci .enable_time = 100, 2868c2ecf20Sopenharmony_ci .type = REGULATOR_VOLTAGE, 2878c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 2888c2ecf20Sopenharmony_ci .csel_reg = MAX77650_REG_CNFG_SBB2_A, 2898c2ecf20Sopenharmony_ci .csel_mask = MAX77650_REGULATOR_CURR_LIM_MASK, 2908c2ecf20Sopenharmony_ci .curr_table = max77650_current_limit_table, 2918c2ecf20Sopenharmony_ci .n_current_limits = ARRAY_SIZE(max77650_current_limit_table), 2928c2ecf20Sopenharmony_ci }, 2938c2ecf20Sopenharmony_ci .regA = MAX77650_REG_CNFG_SBB2_A, 2948c2ecf20Sopenharmony_ci .regB = MAX77650_REG_CNFG_SBB2_B, 2958c2ecf20Sopenharmony_ci}; 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_cistatic struct max77650_regulator_desc max77651_SBB2_desc = { 2988c2ecf20Sopenharmony_ci .desc = { 2998c2ecf20Sopenharmony_ci .name = "sbb2", 3008c2ecf20Sopenharmony_ci .of_match = of_match_ptr("sbb2"), 3018c2ecf20Sopenharmony_ci .regulators_node = of_match_ptr("regulators"), 3028c2ecf20Sopenharmony_ci .supply_name = "in-sbb0", 3038c2ecf20Sopenharmony_ci .id = MAX77650_REGULATOR_ID_SBB2, 3048c2ecf20Sopenharmony_ci .ops = &max77650_regulator_SBB_ops, 3058c2ecf20Sopenharmony_ci .min_uV = 2400000, 3068c2ecf20Sopenharmony_ci .uV_step = 50000, 3078c2ecf20Sopenharmony_ci .n_voltages = 64, 3088c2ecf20Sopenharmony_ci .vsel_step = 1, 3098c2ecf20Sopenharmony_ci .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK, 3108c2ecf20Sopenharmony_ci .vsel_reg = MAX77650_REG_CNFG_SBB2_A, 3118c2ecf20Sopenharmony_ci .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED, 3128c2ecf20Sopenharmony_ci .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED, 3138c2ecf20Sopenharmony_ci .active_discharge_mask = MAX77650_REGULATOR_AD_MASK, 3148c2ecf20Sopenharmony_ci .active_discharge_reg = MAX77650_REG_CNFG_SBB2_B, 3158c2ecf20Sopenharmony_ci .enable_time = 100, 3168c2ecf20Sopenharmony_ci .type = REGULATOR_VOLTAGE, 3178c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 3188c2ecf20Sopenharmony_ci .csel_reg = MAX77650_REG_CNFG_SBB2_A, 3198c2ecf20Sopenharmony_ci .csel_mask = MAX77650_REGULATOR_CURR_LIM_MASK, 3208c2ecf20Sopenharmony_ci .curr_table = max77650_current_limit_table, 3218c2ecf20Sopenharmony_ci .n_current_limits = ARRAY_SIZE(max77650_current_limit_table), 3228c2ecf20Sopenharmony_ci }, 3238c2ecf20Sopenharmony_ci .regA = MAX77650_REG_CNFG_SBB2_A, 3248c2ecf20Sopenharmony_ci .regB = MAX77650_REG_CNFG_SBB2_B, 3258c2ecf20Sopenharmony_ci}; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_cistatic int max77650_regulator_probe(struct platform_device *pdev) 3288c2ecf20Sopenharmony_ci{ 3298c2ecf20Sopenharmony_ci struct max77650_regulator_desc **rdescs; 3308c2ecf20Sopenharmony_ci struct max77650_regulator_desc *rdesc; 3318c2ecf20Sopenharmony_ci struct regulator_config config = { }; 3328c2ecf20Sopenharmony_ci struct device *dev, *parent; 3338c2ecf20Sopenharmony_ci struct regulator_dev *rdev; 3348c2ecf20Sopenharmony_ci struct regmap *map; 3358c2ecf20Sopenharmony_ci unsigned int val; 3368c2ecf20Sopenharmony_ci int i, rv; 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci dev = &pdev->dev; 3398c2ecf20Sopenharmony_ci parent = dev->parent; 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci if (!dev->of_node) 3428c2ecf20Sopenharmony_ci dev->of_node = parent->of_node; 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci rdescs = devm_kcalloc(dev, MAX77650_REGULATOR_NUM_REGULATORS, 3458c2ecf20Sopenharmony_ci sizeof(*rdescs), GFP_KERNEL); 3468c2ecf20Sopenharmony_ci if (!rdescs) 3478c2ecf20Sopenharmony_ci return -ENOMEM; 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci map = dev_get_regmap(parent, NULL); 3508c2ecf20Sopenharmony_ci if (!map) 3518c2ecf20Sopenharmony_ci return -ENODEV; 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci rv = regmap_read(map, MAX77650_REG_CID, &val); 3548c2ecf20Sopenharmony_ci if (rv) 3558c2ecf20Sopenharmony_ci return rv; 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci rdescs[MAX77650_REGULATOR_ID_LDO] = &max77650_LDO_desc; 3588c2ecf20Sopenharmony_ci rdescs[MAX77650_REGULATOR_ID_SBB0] = &max77650_SBB0_desc; 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci switch (MAX77650_CID_BITS(val)) { 3618c2ecf20Sopenharmony_ci case MAX77650_CID_77650A: 3628c2ecf20Sopenharmony_ci case MAX77650_CID_77650C: 3638c2ecf20Sopenharmony_ci rdescs[MAX77650_REGULATOR_ID_SBB1] = &max77650_SBB1_desc; 3648c2ecf20Sopenharmony_ci rdescs[MAX77650_REGULATOR_ID_SBB2] = &max77650_SBB2_desc; 3658c2ecf20Sopenharmony_ci break; 3668c2ecf20Sopenharmony_ci case MAX77650_CID_77651A: 3678c2ecf20Sopenharmony_ci case MAX77650_CID_77651B: 3688c2ecf20Sopenharmony_ci rdescs[MAX77650_REGULATOR_ID_SBB1] = &max77651_SBB1_desc; 3698c2ecf20Sopenharmony_ci rdescs[MAX77650_REGULATOR_ID_SBB2] = &max77651_SBB2_desc; 3708c2ecf20Sopenharmony_ci break; 3718c2ecf20Sopenharmony_ci default: 3728c2ecf20Sopenharmony_ci return -ENODEV; 3738c2ecf20Sopenharmony_ci } 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci config.dev = parent; 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci for (i = 0; i < MAX77650_REGULATOR_NUM_REGULATORS; i++) { 3788c2ecf20Sopenharmony_ci rdesc = rdescs[i]; 3798c2ecf20Sopenharmony_ci config.driver_data = rdesc; 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci rdev = devm_regulator_register(dev, &rdesc->desc, &config); 3828c2ecf20Sopenharmony_ci if (IS_ERR(rdev)) 3838c2ecf20Sopenharmony_ci return PTR_ERR(rdev); 3848c2ecf20Sopenharmony_ci } 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci return 0; 3878c2ecf20Sopenharmony_ci} 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_cistatic const struct of_device_id max77650_regulator_of_match[] = { 3908c2ecf20Sopenharmony_ci { .compatible = "maxim,max77650-regulator" }, 3918c2ecf20Sopenharmony_ci { } 3928c2ecf20Sopenharmony_ci}; 3938c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, max77650_regulator_of_match); 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_cistatic struct platform_driver max77650_regulator_driver = { 3968c2ecf20Sopenharmony_ci .driver = { 3978c2ecf20Sopenharmony_ci .name = "max77650-regulator", 3988c2ecf20Sopenharmony_ci .of_match_table = max77650_regulator_of_match, 3998c2ecf20Sopenharmony_ci }, 4008c2ecf20Sopenharmony_ci .probe = max77650_regulator_probe, 4018c2ecf20Sopenharmony_ci}; 4028c2ecf20Sopenharmony_cimodule_platform_driver(max77650_regulator_driver); 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("MAXIM 77650/77651 regulator driver"); 4058c2ecf20Sopenharmony_ciMODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>"); 4068c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 4078c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:max77650-regulator"); 408