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						&regulators[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