18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 28c2ecf20Sopenharmony_ci// 38c2ecf20Sopenharmony_ci// Copyright (c) 2013 Samsung Electronics Co., Ltd 48c2ecf20Sopenharmony_ci// http://www.samsung.com 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <linux/bug.h> 78c2ecf20Sopenharmony_ci#include <linux/err.h> 88c2ecf20Sopenharmony_ci#include <linux/gpio.h> 98c2ecf20Sopenharmony_ci#include <linux/slab.h> 108c2ecf20Sopenharmony_ci#include <linux/module.h> 118c2ecf20Sopenharmony_ci#include <linux/of.h> 128c2ecf20Sopenharmony_ci#include <linux/regmap.h> 138c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 148c2ecf20Sopenharmony_ci#include <linux/regulator/driver.h> 158c2ecf20Sopenharmony_ci#include <linux/regulator/machine.h> 168c2ecf20Sopenharmony_ci#include <linux/regulator/of_regulator.h> 178c2ecf20Sopenharmony_ci#include <linux/mfd/samsung/core.h> 188c2ecf20Sopenharmony_ci#include <linux/mfd/samsung/s2mpa01.h> 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cistruct s2mpa01_info { 218c2ecf20Sopenharmony_ci int ramp_delay24; 228c2ecf20Sopenharmony_ci int ramp_delay3; 238c2ecf20Sopenharmony_ci int ramp_delay5; 248c2ecf20Sopenharmony_ci int ramp_delay16; 258c2ecf20Sopenharmony_ci int ramp_delay7; 268c2ecf20Sopenharmony_ci int ramp_delay8910; 278c2ecf20Sopenharmony_ci}; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_cistatic int get_ramp_delay(int ramp_delay) 308c2ecf20Sopenharmony_ci{ 318c2ecf20Sopenharmony_ci unsigned char cnt = 0; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci ramp_delay /= 6250; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci while (true) { 368c2ecf20Sopenharmony_ci ramp_delay = ramp_delay >> 1; 378c2ecf20Sopenharmony_ci if (ramp_delay == 0) 388c2ecf20Sopenharmony_ci break; 398c2ecf20Sopenharmony_ci cnt++; 408c2ecf20Sopenharmony_ci } 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci if (cnt > 3) 438c2ecf20Sopenharmony_ci cnt = 3; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci return cnt; 468c2ecf20Sopenharmony_ci} 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_cistatic int s2mpa01_regulator_set_voltage_time_sel(struct regulator_dev *rdev, 498c2ecf20Sopenharmony_ci unsigned int old_selector, 508c2ecf20Sopenharmony_ci unsigned int new_selector) 518c2ecf20Sopenharmony_ci{ 528c2ecf20Sopenharmony_ci struct s2mpa01_info *s2mpa01 = rdev_get_drvdata(rdev); 538c2ecf20Sopenharmony_ci unsigned int ramp_delay = 0; 548c2ecf20Sopenharmony_ci int old_volt, new_volt; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci switch (rdev_get_id(rdev)) { 578c2ecf20Sopenharmony_ci case S2MPA01_BUCK2: 588c2ecf20Sopenharmony_ci case S2MPA01_BUCK4: 598c2ecf20Sopenharmony_ci ramp_delay = s2mpa01->ramp_delay24; 608c2ecf20Sopenharmony_ci break; 618c2ecf20Sopenharmony_ci case S2MPA01_BUCK3: 628c2ecf20Sopenharmony_ci ramp_delay = s2mpa01->ramp_delay3; 638c2ecf20Sopenharmony_ci break; 648c2ecf20Sopenharmony_ci case S2MPA01_BUCK5: 658c2ecf20Sopenharmony_ci ramp_delay = s2mpa01->ramp_delay5; 668c2ecf20Sopenharmony_ci break; 678c2ecf20Sopenharmony_ci case S2MPA01_BUCK1: 688c2ecf20Sopenharmony_ci case S2MPA01_BUCK6: 698c2ecf20Sopenharmony_ci ramp_delay = s2mpa01->ramp_delay16; 708c2ecf20Sopenharmony_ci break; 718c2ecf20Sopenharmony_ci case S2MPA01_BUCK7: 728c2ecf20Sopenharmony_ci ramp_delay = s2mpa01->ramp_delay7; 738c2ecf20Sopenharmony_ci break; 748c2ecf20Sopenharmony_ci case S2MPA01_BUCK8: 758c2ecf20Sopenharmony_ci case S2MPA01_BUCK9: 768c2ecf20Sopenharmony_ci case S2MPA01_BUCK10: 778c2ecf20Sopenharmony_ci ramp_delay = s2mpa01->ramp_delay8910; 788c2ecf20Sopenharmony_ci break; 798c2ecf20Sopenharmony_ci } 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci if (ramp_delay == 0) 828c2ecf20Sopenharmony_ci ramp_delay = rdev->desc->ramp_delay; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci old_volt = rdev->desc->min_uV + (rdev->desc->uV_step * old_selector); 858c2ecf20Sopenharmony_ci new_volt = rdev->desc->min_uV + (rdev->desc->uV_step * new_selector); 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci return DIV_ROUND_UP(abs(new_volt - old_volt), ramp_delay); 888c2ecf20Sopenharmony_ci} 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_cistatic int s2mpa01_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) 918c2ecf20Sopenharmony_ci{ 928c2ecf20Sopenharmony_ci struct s2mpa01_info *s2mpa01 = rdev_get_drvdata(rdev); 938c2ecf20Sopenharmony_ci unsigned int ramp_val, ramp_shift, ramp_reg = S2MPA01_REG_RAMP2; 948c2ecf20Sopenharmony_ci unsigned int ramp_enable = 1, enable_shift = 0; 958c2ecf20Sopenharmony_ci int ret; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci switch (rdev_get_id(rdev)) { 988c2ecf20Sopenharmony_ci case S2MPA01_BUCK1: 998c2ecf20Sopenharmony_ci enable_shift = S2MPA01_BUCK1_RAMP_EN_SHIFT; 1008c2ecf20Sopenharmony_ci if (!ramp_delay) { 1018c2ecf20Sopenharmony_ci ramp_enable = 0; 1028c2ecf20Sopenharmony_ci break; 1038c2ecf20Sopenharmony_ci } 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci if (ramp_delay > s2mpa01->ramp_delay16) 1068c2ecf20Sopenharmony_ci s2mpa01->ramp_delay16 = ramp_delay; 1078c2ecf20Sopenharmony_ci else 1088c2ecf20Sopenharmony_ci ramp_delay = s2mpa01->ramp_delay16; 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci ramp_shift = S2MPA01_BUCK16_RAMP_SHIFT; 1118c2ecf20Sopenharmony_ci break; 1128c2ecf20Sopenharmony_ci case S2MPA01_BUCK2: 1138c2ecf20Sopenharmony_ci enable_shift = S2MPA01_BUCK2_RAMP_EN_SHIFT; 1148c2ecf20Sopenharmony_ci if (!ramp_delay) { 1158c2ecf20Sopenharmony_ci ramp_enable = 0; 1168c2ecf20Sopenharmony_ci break; 1178c2ecf20Sopenharmony_ci } 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci if (ramp_delay > s2mpa01->ramp_delay24) 1208c2ecf20Sopenharmony_ci s2mpa01->ramp_delay24 = ramp_delay; 1218c2ecf20Sopenharmony_ci else 1228c2ecf20Sopenharmony_ci ramp_delay = s2mpa01->ramp_delay24; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci ramp_shift = S2MPA01_BUCK24_RAMP_SHIFT; 1258c2ecf20Sopenharmony_ci ramp_reg = S2MPA01_REG_RAMP1; 1268c2ecf20Sopenharmony_ci break; 1278c2ecf20Sopenharmony_ci case S2MPA01_BUCK3: 1288c2ecf20Sopenharmony_ci enable_shift = S2MPA01_BUCK3_RAMP_EN_SHIFT; 1298c2ecf20Sopenharmony_ci if (!ramp_delay) { 1308c2ecf20Sopenharmony_ci ramp_enable = 0; 1318c2ecf20Sopenharmony_ci break; 1328c2ecf20Sopenharmony_ci } 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci s2mpa01->ramp_delay3 = ramp_delay; 1358c2ecf20Sopenharmony_ci ramp_shift = S2MPA01_BUCK3_RAMP_SHIFT; 1368c2ecf20Sopenharmony_ci ramp_reg = S2MPA01_REG_RAMP1; 1378c2ecf20Sopenharmony_ci break; 1388c2ecf20Sopenharmony_ci case S2MPA01_BUCK4: 1398c2ecf20Sopenharmony_ci enable_shift = S2MPA01_BUCK4_RAMP_EN_SHIFT; 1408c2ecf20Sopenharmony_ci if (!ramp_delay) { 1418c2ecf20Sopenharmony_ci ramp_enable = 0; 1428c2ecf20Sopenharmony_ci break; 1438c2ecf20Sopenharmony_ci } 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci if (ramp_delay > s2mpa01->ramp_delay24) 1468c2ecf20Sopenharmony_ci s2mpa01->ramp_delay24 = ramp_delay; 1478c2ecf20Sopenharmony_ci else 1488c2ecf20Sopenharmony_ci ramp_delay = s2mpa01->ramp_delay24; 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci ramp_shift = S2MPA01_BUCK24_RAMP_SHIFT; 1518c2ecf20Sopenharmony_ci ramp_reg = S2MPA01_REG_RAMP1; 1528c2ecf20Sopenharmony_ci break; 1538c2ecf20Sopenharmony_ci case S2MPA01_BUCK5: 1548c2ecf20Sopenharmony_ci s2mpa01->ramp_delay5 = ramp_delay; 1558c2ecf20Sopenharmony_ci ramp_shift = S2MPA01_BUCK5_RAMP_SHIFT; 1568c2ecf20Sopenharmony_ci break; 1578c2ecf20Sopenharmony_ci case S2MPA01_BUCK6: 1588c2ecf20Sopenharmony_ci if (ramp_delay > s2mpa01->ramp_delay16) 1598c2ecf20Sopenharmony_ci s2mpa01->ramp_delay16 = ramp_delay; 1608c2ecf20Sopenharmony_ci else 1618c2ecf20Sopenharmony_ci ramp_delay = s2mpa01->ramp_delay16; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci ramp_shift = S2MPA01_BUCK16_RAMP_SHIFT; 1648c2ecf20Sopenharmony_ci break; 1658c2ecf20Sopenharmony_ci case S2MPA01_BUCK7: 1668c2ecf20Sopenharmony_ci s2mpa01->ramp_delay7 = ramp_delay; 1678c2ecf20Sopenharmony_ci ramp_shift = S2MPA01_BUCK7_RAMP_SHIFT; 1688c2ecf20Sopenharmony_ci break; 1698c2ecf20Sopenharmony_ci case S2MPA01_BUCK8: 1708c2ecf20Sopenharmony_ci case S2MPA01_BUCK9: 1718c2ecf20Sopenharmony_ci case S2MPA01_BUCK10: 1728c2ecf20Sopenharmony_ci if (ramp_delay > s2mpa01->ramp_delay8910) 1738c2ecf20Sopenharmony_ci s2mpa01->ramp_delay8910 = ramp_delay; 1748c2ecf20Sopenharmony_ci else 1758c2ecf20Sopenharmony_ci ramp_delay = s2mpa01->ramp_delay8910; 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci ramp_shift = S2MPA01_BUCK8910_RAMP_SHIFT; 1788c2ecf20Sopenharmony_ci break; 1798c2ecf20Sopenharmony_ci default: 1808c2ecf20Sopenharmony_ci return 0; 1818c2ecf20Sopenharmony_ci } 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci if (!ramp_enable) 1848c2ecf20Sopenharmony_ci goto ramp_disable; 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci /* Ramp delay can be enabled/disabled only for buck[1234] */ 1878c2ecf20Sopenharmony_ci if (rdev_get_id(rdev) >= S2MPA01_BUCK1 && 1888c2ecf20Sopenharmony_ci rdev_get_id(rdev) <= S2MPA01_BUCK4) { 1898c2ecf20Sopenharmony_ci ret = regmap_update_bits(rdev->regmap, S2MPA01_REG_RAMP1, 1908c2ecf20Sopenharmony_ci 1 << enable_shift, 1 << enable_shift); 1918c2ecf20Sopenharmony_ci if (ret) { 1928c2ecf20Sopenharmony_ci dev_err(&rdev->dev, "failed to enable ramp rate\n"); 1938c2ecf20Sopenharmony_ci return ret; 1948c2ecf20Sopenharmony_ci } 1958c2ecf20Sopenharmony_ci } 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci ramp_val = get_ramp_delay(ramp_delay); 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci return regmap_update_bits(rdev->regmap, ramp_reg, 0x3 << ramp_shift, 2008c2ecf20Sopenharmony_ci ramp_val << ramp_shift); 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ciramp_disable: 2038c2ecf20Sopenharmony_ci return regmap_update_bits(rdev->regmap, S2MPA01_REG_RAMP1, 2048c2ecf20Sopenharmony_ci 1 << enable_shift, 0); 2058c2ecf20Sopenharmony_ci} 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_cistatic const struct regulator_ops s2mpa01_ldo_ops = { 2088c2ecf20Sopenharmony_ci .list_voltage = regulator_list_voltage_linear, 2098c2ecf20Sopenharmony_ci .map_voltage = regulator_map_voltage_linear, 2108c2ecf20Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 2118c2ecf20Sopenharmony_ci .enable = regulator_enable_regmap, 2128c2ecf20Sopenharmony_ci .disable = regulator_disable_regmap, 2138c2ecf20Sopenharmony_ci .get_voltage_sel = regulator_get_voltage_sel_regmap, 2148c2ecf20Sopenharmony_ci .set_voltage_sel = regulator_set_voltage_sel_regmap, 2158c2ecf20Sopenharmony_ci .set_voltage_time_sel = regulator_set_voltage_time_sel, 2168c2ecf20Sopenharmony_ci}; 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_cistatic const struct regulator_ops s2mpa01_buck_ops = { 2198c2ecf20Sopenharmony_ci .list_voltage = regulator_list_voltage_linear, 2208c2ecf20Sopenharmony_ci .map_voltage = regulator_map_voltage_linear, 2218c2ecf20Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 2228c2ecf20Sopenharmony_ci .enable = regulator_enable_regmap, 2238c2ecf20Sopenharmony_ci .disable = regulator_disable_regmap, 2248c2ecf20Sopenharmony_ci .get_voltage_sel = regulator_get_voltage_sel_regmap, 2258c2ecf20Sopenharmony_ci .set_voltage_sel = regulator_set_voltage_sel_regmap, 2268c2ecf20Sopenharmony_ci .set_voltage_time_sel = s2mpa01_regulator_set_voltage_time_sel, 2278c2ecf20Sopenharmony_ci .set_ramp_delay = s2mpa01_set_ramp_delay, 2288c2ecf20Sopenharmony_ci}; 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci#define regulator_desc_ldo(num, step) { \ 2318c2ecf20Sopenharmony_ci .name = "LDO"#num, \ 2328c2ecf20Sopenharmony_ci .of_match = of_match_ptr("LDO"#num), \ 2338c2ecf20Sopenharmony_ci .regulators_node = of_match_ptr("regulators"), \ 2348c2ecf20Sopenharmony_ci .id = S2MPA01_LDO##num, \ 2358c2ecf20Sopenharmony_ci .ops = &s2mpa01_ldo_ops, \ 2368c2ecf20Sopenharmony_ci .type = REGULATOR_VOLTAGE, \ 2378c2ecf20Sopenharmony_ci .owner = THIS_MODULE, \ 2388c2ecf20Sopenharmony_ci .min_uV = MIN_800_MV, \ 2398c2ecf20Sopenharmony_ci .uV_step = step, \ 2408c2ecf20Sopenharmony_ci .n_voltages = S2MPA01_LDO_N_VOLTAGES, \ 2418c2ecf20Sopenharmony_ci .vsel_reg = S2MPA01_REG_L1CTRL + num - 1, \ 2428c2ecf20Sopenharmony_ci .vsel_mask = S2MPA01_LDO_VSEL_MASK, \ 2438c2ecf20Sopenharmony_ci .enable_reg = S2MPA01_REG_L1CTRL + num - 1, \ 2448c2ecf20Sopenharmony_ci .enable_mask = S2MPA01_ENABLE_MASK \ 2458c2ecf20Sopenharmony_ci} 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci#define regulator_desc_buck1_4(num) { \ 2488c2ecf20Sopenharmony_ci .name = "BUCK"#num, \ 2498c2ecf20Sopenharmony_ci .of_match = of_match_ptr("BUCK"#num), \ 2508c2ecf20Sopenharmony_ci .regulators_node = of_match_ptr("regulators"), \ 2518c2ecf20Sopenharmony_ci .id = S2MPA01_BUCK##num, \ 2528c2ecf20Sopenharmony_ci .ops = &s2mpa01_buck_ops, \ 2538c2ecf20Sopenharmony_ci .type = REGULATOR_VOLTAGE, \ 2548c2ecf20Sopenharmony_ci .owner = THIS_MODULE, \ 2558c2ecf20Sopenharmony_ci .min_uV = MIN_600_MV, \ 2568c2ecf20Sopenharmony_ci .uV_step = STEP_6_25_MV, \ 2578c2ecf20Sopenharmony_ci .n_voltages = S2MPA01_BUCK_N_VOLTAGES, \ 2588c2ecf20Sopenharmony_ci .ramp_delay = S2MPA01_RAMP_DELAY, \ 2598c2ecf20Sopenharmony_ci .vsel_reg = S2MPA01_REG_B1CTRL2 + (num - 1) * 2, \ 2608c2ecf20Sopenharmony_ci .vsel_mask = S2MPA01_BUCK_VSEL_MASK, \ 2618c2ecf20Sopenharmony_ci .enable_reg = S2MPA01_REG_B1CTRL1 + (num - 1) * 2, \ 2628c2ecf20Sopenharmony_ci .enable_mask = S2MPA01_ENABLE_MASK \ 2638c2ecf20Sopenharmony_ci} 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci#define regulator_desc_buck5 { \ 2668c2ecf20Sopenharmony_ci .name = "BUCK5", \ 2678c2ecf20Sopenharmony_ci .of_match = of_match_ptr("BUCK5"), \ 2688c2ecf20Sopenharmony_ci .regulators_node = of_match_ptr("regulators"), \ 2698c2ecf20Sopenharmony_ci .id = S2MPA01_BUCK5, \ 2708c2ecf20Sopenharmony_ci .ops = &s2mpa01_buck_ops, \ 2718c2ecf20Sopenharmony_ci .type = REGULATOR_VOLTAGE, \ 2728c2ecf20Sopenharmony_ci .owner = THIS_MODULE, \ 2738c2ecf20Sopenharmony_ci .min_uV = MIN_800_MV, \ 2748c2ecf20Sopenharmony_ci .uV_step = STEP_6_25_MV, \ 2758c2ecf20Sopenharmony_ci .n_voltages = S2MPA01_BUCK_N_VOLTAGES, \ 2768c2ecf20Sopenharmony_ci .ramp_delay = S2MPA01_RAMP_DELAY, \ 2778c2ecf20Sopenharmony_ci .vsel_reg = S2MPA01_REG_B5CTRL2, \ 2788c2ecf20Sopenharmony_ci .vsel_mask = S2MPA01_BUCK_VSEL_MASK, \ 2798c2ecf20Sopenharmony_ci .enable_reg = S2MPA01_REG_B5CTRL1, \ 2808c2ecf20Sopenharmony_ci .enable_mask = S2MPA01_ENABLE_MASK \ 2818c2ecf20Sopenharmony_ci} 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci#define regulator_desc_buck6_10(num, min, step) { \ 2848c2ecf20Sopenharmony_ci .name = "BUCK"#num, \ 2858c2ecf20Sopenharmony_ci .of_match = of_match_ptr("BUCK"#num), \ 2868c2ecf20Sopenharmony_ci .regulators_node = of_match_ptr("regulators"), \ 2878c2ecf20Sopenharmony_ci .id = S2MPA01_BUCK##num, \ 2888c2ecf20Sopenharmony_ci .ops = &s2mpa01_buck_ops, \ 2898c2ecf20Sopenharmony_ci .type = REGULATOR_VOLTAGE, \ 2908c2ecf20Sopenharmony_ci .owner = THIS_MODULE, \ 2918c2ecf20Sopenharmony_ci .min_uV = min, \ 2928c2ecf20Sopenharmony_ci .uV_step = step, \ 2938c2ecf20Sopenharmony_ci .n_voltages = S2MPA01_BUCK_N_VOLTAGES, \ 2948c2ecf20Sopenharmony_ci .ramp_delay = S2MPA01_RAMP_DELAY, \ 2958c2ecf20Sopenharmony_ci .vsel_reg = S2MPA01_REG_B6CTRL2 + (num - 6) * 2, \ 2968c2ecf20Sopenharmony_ci .vsel_mask = S2MPA01_BUCK_VSEL_MASK, \ 2978c2ecf20Sopenharmony_ci .enable_reg = S2MPA01_REG_B6CTRL1 + (num - 6) * 2, \ 2988c2ecf20Sopenharmony_ci .enable_mask = S2MPA01_ENABLE_MASK \ 2998c2ecf20Sopenharmony_ci} 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_cistatic const struct regulator_desc regulators[] = { 3028c2ecf20Sopenharmony_ci regulator_desc_ldo(1, STEP_25_MV), 3038c2ecf20Sopenharmony_ci regulator_desc_ldo(2, STEP_50_MV), 3048c2ecf20Sopenharmony_ci regulator_desc_ldo(3, STEP_50_MV), 3058c2ecf20Sopenharmony_ci regulator_desc_ldo(4, STEP_50_MV), 3068c2ecf20Sopenharmony_ci regulator_desc_ldo(5, STEP_25_MV), 3078c2ecf20Sopenharmony_ci regulator_desc_ldo(6, STEP_25_MV), 3088c2ecf20Sopenharmony_ci regulator_desc_ldo(7, STEP_50_MV), 3098c2ecf20Sopenharmony_ci regulator_desc_ldo(8, STEP_50_MV), 3108c2ecf20Sopenharmony_ci regulator_desc_ldo(9, STEP_50_MV), 3118c2ecf20Sopenharmony_ci regulator_desc_ldo(10, STEP_50_MV), 3128c2ecf20Sopenharmony_ci regulator_desc_ldo(11, STEP_50_MV), 3138c2ecf20Sopenharmony_ci regulator_desc_ldo(12, STEP_50_MV), 3148c2ecf20Sopenharmony_ci regulator_desc_ldo(13, STEP_50_MV), 3158c2ecf20Sopenharmony_ci regulator_desc_ldo(14, STEP_50_MV), 3168c2ecf20Sopenharmony_ci regulator_desc_ldo(15, STEP_50_MV), 3178c2ecf20Sopenharmony_ci regulator_desc_ldo(16, STEP_50_MV), 3188c2ecf20Sopenharmony_ci regulator_desc_ldo(17, STEP_50_MV), 3198c2ecf20Sopenharmony_ci regulator_desc_ldo(18, STEP_50_MV), 3208c2ecf20Sopenharmony_ci regulator_desc_ldo(19, STEP_50_MV), 3218c2ecf20Sopenharmony_ci regulator_desc_ldo(20, STEP_50_MV), 3228c2ecf20Sopenharmony_ci regulator_desc_ldo(21, STEP_50_MV), 3238c2ecf20Sopenharmony_ci regulator_desc_ldo(22, STEP_50_MV), 3248c2ecf20Sopenharmony_ci regulator_desc_ldo(23, STEP_50_MV), 3258c2ecf20Sopenharmony_ci regulator_desc_ldo(24, STEP_50_MV), 3268c2ecf20Sopenharmony_ci regulator_desc_ldo(25, STEP_50_MV), 3278c2ecf20Sopenharmony_ci regulator_desc_ldo(26, STEP_25_MV), 3288c2ecf20Sopenharmony_ci regulator_desc_buck1_4(1), 3298c2ecf20Sopenharmony_ci regulator_desc_buck1_4(2), 3308c2ecf20Sopenharmony_ci regulator_desc_buck1_4(3), 3318c2ecf20Sopenharmony_ci regulator_desc_buck1_4(4), 3328c2ecf20Sopenharmony_ci regulator_desc_buck5, 3338c2ecf20Sopenharmony_ci regulator_desc_buck6_10(6, MIN_600_MV, STEP_6_25_MV), 3348c2ecf20Sopenharmony_ci regulator_desc_buck6_10(7, MIN_600_MV, STEP_6_25_MV), 3358c2ecf20Sopenharmony_ci regulator_desc_buck6_10(8, MIN_800_MV, STEP_12_5_MV), 3368c2ecf20Sopenharmony_ci regulator_desc_buck6_10(9, MIN_1500_MV, STEP_12_5_MV), 3378c2ecf20Sopenharmony_ci regulator_desc_buck6_10(10, MIN_1000_MV, STEP_12_5_MV), 3388c2ecf20Sopenharmony_ci}; 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_cistatic int s2mpa01_pmic_probe(struct platform_device *pdev) 3418c2ecf20Sopenharmony_ci{ 3428c2ecf20Sopenharmony_ci struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); 3438c2ecf20Sopenharmony_ci struct sec_platform_data *pdata = dev_get_platdata(iodev->dev); 3448c2ecf20Sopenharmony_ci struct regulator_config config = { }; 3458c2ecf20Sopenharmony_ci struct s2mpa01_info *s2mpa01; 3468c2ecf20Sopenharmony_ci int i; 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci s2mpa01 = devm_kzalloc(&pdev->dev, sizeof(*s2mpa01), GFP_KERNEL); 3498c2ecf20Sopenharmony_ci if (!s2mpa01) 3508c2ecf20Sopenharmony_ci return -ENOMEM; 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci config.dev = iodev->dev; 3538c2ecf20Sopenharmony_ci config.regmap = iodev->regmap_pmic; 3548c2ecf20Sopenharmony_ci config.driver_data = s2mpa01; 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci for (i = 0; i < S2MPA01_REGULATOR_MAX; i++) { 3578c2ecf20Sopenharmony_ci struct regulator_dev *rdev; 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci if (pdata) 3608c2ecf20Sopenharmony_ci config.init_data = pdata->regulators[i].initdata; 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci rdev = devm_regulator_register(&pdev->dev, 3638c2ecf20Sopenharmony_ci ®ulators[i], &config); 3648c2ecf20Sopenharmony_ci if (IS_ERR(rdev)) { 3658c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "regulator init failed for %d\n", 3668c2ecf20Sopenharmony_ci i); 3678c2ecf20Sopenharmony_ci return PTR_ERR(rdev); 3688c2ecf20Sopenharmony_ci } 3698c2ecf20Sopenharmony_ci } 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci return 0; 3728c2ecf20Sopenharmony_ci} 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_cistatic const struct platform_device_id s2mpa01_pmic_id[] = { 3758c2ecf20Sopenharmony_ci { "s2mpa01-pmic", 0}, 3768c2ecf20Sopenharmony_ci { }, 3778c2ecf20Sopenharmony_ci}; 3788c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(platform, s2mpa01_pmic_id); 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_cistatic struct platform_driver s2mpa01_pmic_driver = { 3818c2ecf20Sopenharmony_ci .driver = { 3828c2ecf20Sopenharmony_ci .name = "s2mpa01-pmic", 3838c2ecf20Sopenharmony_ci }, 3848c2ecf20Sopenharmony_ci .probe = s2mpa01_pmic_probe, 3858c2ecf20Sopenharmony_ci .id_table = s2mpa01_pmic_id, 3868c2ecf20Sopenharmony_ci}; 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_cimodule_platform_driver(s2mpa01_pmic_driver); 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci/* Module information */ 3918c2ecf20Sopenharmony_ciMODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>"); 3928c2ecf20Sopenharmony_ciMODULE_AUTHOR("Sachin Kamat <sachin.kamat@samsung.com>"); 3938c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Samsung S2MPA01 Regulator Driver"); 3948c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 395