15b1c2028SLaxman Dewangan /*
25b1c2028SLaxman Dewangan  * Maxim MAX77620 Regulator driver
35b1c2028SLaxman Dewangan  *
45b1c2028SLaxman Dewangan  * Copyright (c) 2016, NVIDIA CORPORATION.  All rights reserved.
55b1c2028SLaxman Dewangan  *
65b1c2028SLaxman Dewangan  * Author: Mallikarjun Kasoju <mkasoju@nvidia.com>
75b1c2028SLaxman Dewangan  *	Laxman Dewangan <ldewangan@nvidia.com>
85b1c2028SLaxman Dewangan  *
95b1c2028SLaxman Dewangan  * This program is free software; you can redistribute it and/or modify it
105b1c2028SLaxman Dewangan  * under the terms and conditions of the GNU General Public License,
115b1c2028SLaxman Dewangan  * version 2, as published by the Free Software Foundation.
125b1c2028SLaxman Dewangan  */
135b1c2028SLaxman Dewangan 
145b1c2028SLaxman Dewangan #include <linux/init.h>
155b1c2028SLaxman Dewangan #include <linux/mfd/max77620.h>
165b1c2028SLaxman Dewangan #include <linux/module.h>
175b1c2028SLaxman Dewangan #include <linux/of.h>
185b1c2028SLaxman Dewangan #include <linux/platform_device.h>
195b1c2028SLaxman Dewangan #include <linux/regmap.h>
205b1c2028SLaxman Dewangan #include <linux/regulator/driver.h>
215b1c2028SLaxman Dewangan #include <linux/regulator/machine.h>
225b1c2028SLaxman Dewangan #include <linux/regulator/of_regulator.h>
235b1c2028SLaxman Dewangan 
245b1c2028SLaxman Dewangan #define max77620_rails(_name)	"max77620-"#_name
255b1c2028SLaxman Dewangan 
265b1c2028SLaxman Dewangan /* Power Mode */
275b1c2028SLaxman Dewangan #define MAX77620_POWER_MODE_NORMAL		3
285b1c2028SLaxman Dewangan #define MAX77620_POWER_MODE_LPM			2
295b1c2028SLaxman Dewangan #define MAX77620_POWER_MODE_GLPM		1
305b1c2028SLaxman Dewangan #define MAX77620_POWER_MODE_DISABLE		0
315b1c2028SLaxman Dewangan 
325b1c2028SLaxman Dewangan /* SD Slew Rate */
335b1c2028SLaxman Dewangan #define MAX77620_SD_SR_13_75			0
345b1c2028SLaxman Dewangan #define MAX77620_SD_SR_27_5			1
355b1c2028SLaxman Dewangan #define MAX77620_SD_SR_55			2
365b1c2028SLaxman Dewangan #define MAX77620_SD_SR_100			3
375b1c2028SLaxman Dewangan 
385b1c2028SLaxman Dewangan enum max77620_regulators {
395b1c2028SLaxman Dewangan 	MAX77620_REGULATOR_ID_SD0,
405b1c2028SLaxman Dewangan 	MAX77620_REGULATOR_ID_SD1,
415b1c2028SLaxman Dewangan 	MAX77620_REGULATOR_ID_SD2,
425b1c2028SLaxman Dewangan 	MAX77620_REGULATOR_ID_SD3,
435b1c2028SLaxman Dewangan 	MAX77620_REGULATOR_ID_SD4,
445b1c2028SLaxman Dewangan 	MAX77620_REGULATOR_ID_LDO0,
455b1c2028SLaxman Dewangan 	MAX77620_REGULATOR_ID_LDO1,
465b1c2028SLaxman Dewangan 	MAX77620_REGULATOR_ID_LDO2,
475b1c2028SLaxman Dewangan 	MAX77620_REGULATOR_ID_LDO3,
485b1c2028SLaxman Dewangan 	MAX77620_REGULATOR_ID_LDO4,
495b1c2028SLaxman Dewangan 	MAX77620_REGULATOR_ID_LDO5,
505b1c2028SLaxman Dewangan 	MAX77620_REGULATOR_ID_LDO6,
515b1c2028SLaxman Dewangan 	MAX77620_REGULATOR_ID_LDO7,
525b1c2028SLaxman Dewangan 	MAX77620_REGULATOR_ID_LDO8,
535b1c2028SLaxman Dewangan 	MAX77620_NUM_REGS,
545b1c2028SLaxman Dewangan };
555b1c2028SLaxman Dewangan 
565b1c2028SLaxman Dewangan /* Regulator types */
575b1c2028SLaxman Dewangan enum max77620_regulator_type {
585b1c2028SLaxman Dewangan 	MAX77620_REGULATOR_TYPE_SD,
595b1c2028SLaxman Dewangan 	MAX77620_REGULATOR_TYPE_LDO_N,
605b1c2028SLaxman Dewangan 	MAX77620_REGULATOR_TYPE_LDO_P,
615b1c2028SLaxman Dewangan };
625b1c2028SLaxman Dewangan 
635b1c2028SLaxman Dewangan struct max77620_regulator_info {
645b1c2028SLaxman Dewangan 	u8 type;
655b1c2028SLaxman Dewangan 	u8 fps_addr;
665b1c2028SLaxman Dewangan 	u8 volt_addr;
675b1c2028SLaxman Dewangan 	u8 cfg_addr;
685b1c2028SLaxman Dewangan 	u8 power_mode_mask;
695b1c2028SLaxman Dewangan 	u8 power_mode_shift;
705b1c2028SLaxman Dewangan 	u8 remote_sense_addr;
715b1c2028SLaxman Dewangan 	u8 remote_sense_mask;
725b1c2028SLaxman Dewangan 	struct regulator_desc desc;
735b1c2028SLaxman Dewangan };
745b1c2028SLaxman Dewangan 
755b1c2028SLaxman Dewangan struct max77620_regulator_pdata {
765b1c2028SLaxman Dewangan 	struct regulator_init_data *reg_idata;
775b1c2028SLaxman Dewangan 	int active_fps_src;
785b1c2028SLaxman Dewangan 	int active_fps_pd_slot;
795b1c2028SLaxman Dewangan 	int active_fps_pu_slot;
805b1c2028SLaxman Dewangan 	int suspend_fps_src;
815b1c2028SLaxman Dewangan 	int suspend_fps_pd_slot;
825b1c2028SLaxman Dewangan 	int suspend_fps_pu_slot;
835b1c2028SLaxman Dewangan 	int current_mode;
845aa43599SLaxman Dewangan 	int ramp_rate_setting;
855b1c2028SLaxman Dewangan };
865b1c2028SLaxman Dewangan 
875b1c2028SLaxman Dewangan struct max77620_regulator {
885b1c2028SLaxman Dewangan 	struct device *dev;
895b1c2028SLaxman Dewangan 	struct regmap *rmap;
905b1c2028SLaxman Dewangan 	struct max77620_regulator_info *rinfo[MAX77620_NUM_REGS];
915b1c2028SLaxman Dewangan 	struct max77620_regulator_pdata reg_pdata[MAX77620_NUM_REGS];
925b1c2028SLaxman Dewangan 	int enable_power_mode[MAX77620_NUM_REGS];
935b1c2028SLaxman Dewangan 	int current_power_mode[MAX77620_NUM_REGS];
945b1c2028SLaxman Dewangan 	int active_fps_src[MAX77620_NUM_REGS];
955b1c2028SLaxman Dewangan };
965b1c2028SLaxman Dewangan 
975b1c2028SLaxman Dewangan #define fps_src_name(fps_src)	\
985b1c2028SLaxman Dewangan 	(fps_src == MAX77620_FPS_SRC_0 ? "FPS_SRC_0" :	\
995b1c2028SLaxman Dewangan 	fps_src == MAX77620_FPS_SRC_1 ? "FPS_SRC_1" :	\
1005b1c2028SLaxman Dewangan 	fps_src == MAX77620_FPS_SRC_2 ? "FPS_SRC_2" : "FPS_SRC_NONE")
1015b1c2028SLaxman Dewangan 
1025b1c2028SLaxman Dewangan static int max77620_regulator_get_fps_src(struct max77620_regulator *pmic,
1035b1c2028SLaxman Dewangan 					  int id)
1045b1c2028SLaxman Dewangan {
1055b1c2028SLaxman Dewangan 	struct max77620_regulator_info *rinfo = pmic->rinfo[id];
1065b1c2028SLaxman Dewangan 	unsigned int val;
1075b1c2028SLaxman Dewangan 	int ret;
1085b1c2028SLaxman Dewangan 
1095b1c2028SLaxman Dewangan 	ret = regmap_read(pmic->rmap, rinfo->fps_addr, &val);
1105b1c2028SLaxman Dewangan 	if (ret < 0) {
1115b1c2028SLaxman Dewangan 		dev_err(pmic->dev, "Reg 0x%02x read failed %d\n",
1125b1c2028SLaxman Dewangan 			rinfo->fps_addr, ret);
1135b1c2028SLaxman Dewangan 		return ret;
1145b1c2028SLaxman Dewangan 	}
1155b1c2028SLaxman Dewangan 
1165b1c2028SLaxman Dewangan 	return (val & MAX77620_FPS_SRC_MASK) >> MAX77620_FPS_SRC_SHIFT;
1175b1c2028SLaxman Dewangan }
1185b1c2028SLaxman Dewangan 
1195b1c2028SLaxman Dewangan static int max77620_regulator_set_fps_src(struct max77620_regulator *pmic,
1205b1c2028SLaxman Dewangan 					  int fps_src, int id)
1215b1c2028SLaxman Dewangan {
1225b1c2028SLaxman Dewangan 	struct max77620_regulator_info *rinfo = pmic->rinfo[id];
1235b1c2028SLaxman Dewangan 	unsigned int val;
1245b1c2028SLaxman Dewangan 	int ret;
1255b1c2028SLaxman Dewangan 
12691ff811fSVenkat Reddy Talla 	if (!rinfo)
12791ff811fSVenkat Reddy Talla 		return 0;
12891ff811fSVenkat Reddy Talla 
1295b1c2028SLaxman Dewangan 	switch (fps_src) {
1305b1c2028SLaxman Dewangan 	case MAX77620_FPS_SRC_0:
1315b1c2028SLaxman Dewangan 	case MAX77620_FPS_SRC_1:
1325b1c2028SLaxman Dewangan 	case MAX77620_FPS_SRC_2:
1335b1c2028SLaxman Dewangan 	case MAX77620_FPS_SRC_NONE:
1345b1c2028SLaxman Dewangan 		break;
1355b1c2028SLaxman Dewangan 
1365b1c2028SLaxman Dewangan 	case MAX77620_FPS_SRC_DEF:
1375b1c2028SLaxman Dewangan 		ret = regmap_read(pmic->rmap, rinfo->fps_addr, &val);
1385b1c2028SLaxman Dewangan 		if (ret < 0) {
1395b1c2028SLaxman Dewangan 			dev_err(pmic->dev, "Reg 0x%02x read failed %d\n",
1405b1c2028SLaxman Dewangan 				rinfo->fps_addr, ret);
1415b1c2028SLaxman Dewangan 			return ret;
1425b1c2028SLaxman Dewangan 		}
1435b1c2028SLaxman Dewangan 		ret = (val & MAX77620_FPS_SRC_MASK) >> MAX77620_FPS_SRC_SHIFT;
1445b1c2028SLaxman Dewangan 		pmic->active_fps_src[id] = ret;
1455b1c2028SLaxman Dewangan 		return 0;
1465b1c2028SLaxman Dewangan 
1475b1c2028SLaxman Dewangan 	default:
1485b1c2028SLaxman Dewangan 		dev_err(pmic->dev, "Invalid FPS %d for regulator %d\n",
1495b1c2028SLaxman Dewangan 			fps_src, id);
1505b1c2028SLaxman Dewangan 		return -EINVAL;
1515b1c2028SLaxman Dewangan 	}
1525b1c2028SLaxman Dewangan 
1535b1c2028SLaxman Dewangan 	ret = regmap_update_bits(pmic->rmap, rinfo->fps_addr,
1545b1c2028SLaxman Dewangan 				 MAX77620_FPS_SRC_MASK,
1555b1c2028SLaxman Dewangan 				 fps_src << MAX77620_FPS_SRC_SHIFT);
1565b1c2028SLaxman Dewangan 	if (ret < 0) {
1575b1c2028SLaxman Dewangan 		dev_err(pmic->dev, "Reg 0x%02x update failed %d\n",
1585b1c2028SLaxman Dewangan 			rinfo->fps_addr, ret);
1595b1c2028SLaxman Dewangan 		return ret;
1605b1c2028SLaxman Dewangan 	}
1615b1c2028SLaxman Dewangan 	pmic->active_fps_src[id] = fps_src;
1625b1c2028SLaxman Dewangan 
1635b1c2028SLaxman Dewangan 	return 0;
1645b1c2028SLaxman Dewangan }
1655b1c2028SLaxman Dewangan 
1665b1c2028SLaxman Dewangan static int max77620_regulator_set_fps_slots(struct max77620_regulator *pmic,
1675b1c2028SLaxman Dewangan 					    int id, bool is_suspend)
1685b1c2028SLaxman Dewangan {
1695b1c2028SLaxman Dewangan 	struct max77620_regulator_pdata *rpdata = &pmic->reg_pdata[id];
1705b1c2028SLaxman Dewangan 	struct max77620_regulator_info *rinfo = pmic->rinfo[id];
1715b1c2028SLaxman Dewangan 	unsigned int val = 0;
1725b1c2028SLaxman Dewangan 	unsigned int mask = 0;
1735b1c2028SLaxman Dewangan 	int pu = rpdata->active_fps_pu_slot;
1745b1c2028SLaxman Dewangan 	int pd = rpdata->active_fps_pd_slot;
1755b1c2028SLaxman Dewangan 	int ret = 0;
1765b1c2028SLaxman Dewangan 
17791ff811fSVenkat Reddy Talla 	if (!rinfo)
17891ff811fSVenkat Reddy Talla 		return 0;
17991ff811fSVenkat Reddy Talla 
1805b1c2028SLaxman Dewangan 	if (is_suspend) {
1815b1c2028SLaxman Dewangan 		pu = rpdata->suspend_fps_pu_slot;
1825b1c2028SLaxman Dewangan 		pd = rpdata->suspend_fps_pd_slot;
1835b1c2028SLaxman Dewangan 	}
1845b1c2028SLaxman Dewangan 
1855b1c2028SLaxman Dewangan 	/* FPS power up period setting */
1865b1c2028SLaxman Dewangan 	if (pu >= 0) {
1875b1c2028SLaxman Dewangan 		val |= (pu << MAX77620_FPS_PU_PERIOD_SHIFT);
1885b1c2028SLaxman Dewangan 		mask |= MAX77620_FPS_PU_PERIOD_MASK;
1895b1c2028SLaxman Dewangan 	}
1905b1c2028SLaxman Dewangan 
1915b1c2028SLaxman Dewangan 	/* FPS power down period setting */
1925b1c2028SLaxman Dewangan 	if (pd >= 0) {
1935b1c2028SLaxman Dewangan 		val |= (pd << MAX77620_FPS_PD_PERIOD_SHIFT);
1945b1c2028SLaxman Dewangan 		mask |= MAX77620_FPS_PD_PERIOD_MASK;
1955b1c2028SLaxman Dewangan 	}
1965b1c2028SLaxman Dewangan 
1975b1c2028SLaxman Dewangan 	if (mask) {
1985b1c2028SLaxman Dewangan 		ret = regmap_update_bits(pmic->rmap, rinfo->fps_addr,
1995b1c2028SLaxman Dewangan 					 mask, val);
2005b1c2028SLaxman Dewangan 		if (ret < 0) {
2015b1c2028SLaxman Dewangan 			dev_err(pmic->dev, "Reg 0x%02x update failed: %d\n",
2025b1c2028SLaxman Dewangan 				rinfo->fps_addr, ret);
2035b1c2028SLaxman Dewangan 			return ret;
2045b1c2028SLaxman Dewangan 		}
2055b1c2028SLaxman Dewangan 	}
2065b1c2028SLaxman Dewangan 
2075b1c2028SLaxman Dewangan 	return ret;
2085b1c2028SLaxman Dewangan }
2095b1c2028SLaxman Dewangan 
2105b1c2028SLaxman Dewangan static int max77620_regulator_set_power_mode(struct max77620_regulator *pmic,
2115b1c2028SLaxman Dewangan 					     int power_mode, int id)
2125b1c2028SLaxman Dewangan {
2135b1c2028SLaxman Dewangan 	struct max77620_regulator_info *rinfo = pmic->rinfo[id];
2145b1c2028SLaxman Dewangan 	u8 mask = rinfo->power_mode_mask;
2155b1c2028SLaxman Dewangan 	u8 shift = rinfo->power_mode_shift;
2165b1c2028SLaxman Dewangan 	u8 addr;
2175b1c2028SLaxman Dewangan 	int ret;
2185b1c2028SLaxman Dewangan 
2195b1c2028SLaxman Dewangan 	switch (rinfo->type) {
2205b1c2028SLaxman Dewangan 	case MAX77620_REGULATOR_TYPE_SD:
2215b1c2028SLaxman Dewangan 		addr = rinfo->cfg_addr;
2225b1c2028SLaxman Dewangan 		break;
2235b1c2028SLaxman Dewangan 	default:
2245b1c2028SLaxman Dewangan 		addr = rinfo->volt_addr;
2255b1c2028SLaxman Dewangan 		break;
2265b1c2028SLaxman Dewangan 	}
2275b1c2028SLaxman Dewangan 
2285b1c2028SLaxman Dewangan 	ret = regmap_update_bits(pmic->rmap, addr, mask, power_mode << shift);
2295b1c2028SLaxman Dewangan 	if (ret < 0) {
2305b1c2028SLaxman Dewangan 		dev_err(pmic->dev, "Regulator %d mode set failed: %d\n",
2315b1c2028SLaxman Dewangan 			id, ret);
2325b1c2028SLaxman Dewangan 		return ret;
2335b1c2028SLaxman Dewangan 	}
2345b1c2028SLaxman Dewangan 	pmic->current_power_mode[id] = power_mode;
2355b1c2028SLaxman Dewangan 
2365b1c2028SLaxman Dewangan 	return ret;
2375b1c2028SLaxman Dewangan }
2385b1c2028SLaxman Dewangan 
2395b1c2028SLaxman Dewangan static int max77620_regulator_get_power_mode(struct max77620_regulator *pmic,
2405b1c2028SLaxman Dewangan 					     int id)
2415b1c2028SLaxman Dewangan {
2425b1c2028SLaxman Dewangan 	struct max77620_regulator_info *rinfo = pmic->rinfo[id];
2435b1c2028SLaxman Dewangan 	unsigned int val, addr;
2445b1c2028SLaxman Dewangan 	u8 mask = rinfo->power_mode_mask;
2455b1c2028SLaxman Dewangan 	u8 shift = rinfo->power_mode_shift;
2465b1c2028SLaxman Dewangan 	int ret;
2475b1c2028SLaxman Dewangan 
2485b1c2028SLaxman Dewangan 	switch (rinfo->type) {
2495b1c2028SLaxman Dewangan 	case MAX77620_REGULATOR_TYPE_SD:
2505b1c2028SLaxman Dewangan 		addr = rinfo->cfg_addr;
2515b1c2028SLaxman Dewangan 		break;
2525b1c2028SLaxman Dewangan 	default:
2535b1c2028SLaxman Dewangan 		addr = rinfo->volt_addr;
2545b1c2028SLaxman Dewangan 		break;
2555b1c2028SLaxman Dewangan 	}
2565b1c2028SLaxman Dewangan 
2575b1c2028SLaxman Dewangan 	ret = regmap_read(pmic->rmap, addr, &val);
2585b1c2028SLaxman Dewangan 	if (ret < 0) {
2595b1c2028SLaxman Dewangan 		dev_err(pmic->dev, "Regulator %d: Reg 0x%02x read failed: %d\n",
2605b1c2028SLaxman Dewangan 			id, addr, ret);
2615b1c2028SLaxman Dewangan 		return ret;
2625b1c2028SLaxman Dewangan 	}
2635b1c2028SLaxman Dewangan 
2645b1c2028SLaxman Dewangan 	return (val & mask) >> shift;
2655b1c2028SLaxman Dewangan }
2665b1c2028SLaxman Dewangan 
2675b1c2028SLaxman Dewangan static int max77620_read_slew_rate(struct max77620_regulator *pmic, int id)
2685b1c2028SLaxman Dewangan {
2695b1c2028SLaxman Dewangan 	struct max77620_regulator_info *rinfo = pmic->rinfo[id];
2705b1c2028SLaxman Dewangan 	unsigned int rval;
2715b1c2028SLaxman Dewangan 	int slew_rate;
2725b1c2028SLaxman Dewangan 	int ret;
2735b1c2028SLaxman Dewangan 
2745b1c2028SLaxman Dewangan 	ret = regmap_read(pmic->rmap, rinfo->cfg_addr, &rval);
2755b1c2028SLaxman Dewangan 	if (ret < 0) {
2765b1c2028SLaxman Dewangan 		dev_err(pmic->dev, "Register 0x%02x read failed: %d\n",
2775b1c2028SLaxman Dewangan 			rinfo->cfg_addr, ret);
2785b1c2028SLaxman Dewangan 		return ret;
2795b1c2028SLaxman Dewangan 	}
2805b1c2028SLaxman Dewangan 
281aad76f74SAxel Lin 	switch (rinfo->type) {
282aad76f74SAxel Lin 	case MAX77620_REGULATOR_TYPE_SD:
2835b1c2028SLaxman Dewangan 		slew_rate = (rval >> MAX77620_SD_SR_SHIFT) & 0x3;
2845b1c2028SLaxman Dewangan 		switch (slew_rate) {
2855b1c2028SLaxman Dewangan 		case 0:
2865b1c2028SLaxman Dewangan 			slew_rate = 13750;
2875b1c2028SLaxman Dewangan 			break;
2885b1c2028SLaxman Dewangan 		case 1:
2895b1c2028SLaxman Dewangan 			slew_rate = 27500;
2905b1c2028SLaxman Dewangan 			break;
2915b1c2028SLaxman Dewangan 		case 2:
2925b1c2028SLaxman Dewangan 			slew_rate = 55000;
2935b1c2028SLaxman Dewangan 			break;
2945b1c2028SLaxman Dewangan 		case 3:
2955b1c2028SLaxman Dewangan 			slew_rate = 100000;
2965b1c2028SLaxman Dewangan 			break;
2975b1c2028SLaxman Dewangan 		}
2985b1c2028SLaxman Dewangan 		rinfo->desc.ramp_delay = slew_rate;
2995b1c2028SLaxman Dewangan 		break;
3005b1c2028SLaxman Dewangan 	default:
3015b1c2028SLaxman Dewangan 		slew_rate = rval & 0x1;
3025b1c2028SLaxman Dewangan 		switch (slew_rate) {
3035b1c2028SLaxman Dewangan 		case 0:
3045b1c2028SLaxman Dewangan 			slew_rate = 100000;
3055b1c2028SLaxman Dewangan 			break;
3065b1c2028SLaxman Dewangan 		case 1:
3075b1c2028SLaxman Dewangan 			slew_rate = 5000;
3085b1c2028SLaxman Dewangan 			break;
3095b1c2028SLaxman Dewangan 		}
3105b1c2028SLaxman Dewangan 		rinfo->desc.ramp_delay = slew_rate;
3115b1c2028SLaxman Dewangan 		break;
3125b1c2028SLaxman Dewangan 	}
3135b1c2028SLaxman Dewangan 
3145b1c2028SLaxman Dewangan 	return 0;
3155b1c2028SLaxman Dewangan }
3165b1c2028SLaxman Dewangan 
3175aa43599SLaxman Dewangan static int max77620_set_slew_rate(struct max77620_regulator *pmic, int id,
3185aa43599SLaxman Dewangan 				  int slew_rate)
3195aa43599SLaxman Dewangan {
3205aa43599SLaxman Dewangan 	struct max77620_regulator_info *rinfo = pmic->rinfo[id];
3215aa43599SLaxman Dewangan 	unsigned int val;
3225aa43599SLaxman Dewangan 	int ret;
3235aa43599SLaxman Dewangan 	u8 mask;
3245aa43599SLaxman Dewangan 
3255aa43599SLaxman Dewangan 	if (rinfo->type == MAX77620_REGULATOR_TYPE_SD) {
3265aa43599SLaxman Dewangan 		if (slew_rate <= 13750)
3275aa43599SLaxman Dewangan 			val = 0;
3285aa43599SLaxman Dewangan 		else if (slew_rate <= 27500)
3295aa43599SLaxman Dewangan 			val = 1;
3305aa43599SLaxman Dewangan 		else if (slew_rate <= 55000)
3315aa43599SLaxman Dewangan 			val = 2;
3325aa43599SLaxman Dewangan 		else
3335aa43599SLaxman Dewangan 			val = 3;
3345aa43599SLaxman Dewangan 		val <<= MAX77620_SD_SR_SHIFT;
3355aa43599SLaxman Dewangan 		mask = MAX77620_SD_SR_MASK;
3365aa43599SLaxman Dewangan 	} else {
3375aa43599SLaxman Dewangan 		if (slew_rate <= 5000)
3385aa43599SLaxman Dewangan 			val = 1;
3395aa43599SLaxman Dewangan 		else
3405aa43599SLaxman Dewangan 			val = 0;
3415aa43599SLaxman Dewangan 		mask = MAX77620_LDO_SLEW_RATE_MASK;
3425aa43599SLaxman Dewangan 	}
3435aa43599SLaxman Dewangan 
3445aa43599SLaxman Dewangan 	ret = regmap_update_bits(pmic->rmap, rinfo->cfg_addr, mask, val);
3455aa43599SLaxman Dewangan 	if (ret < 0) {
3465aa43599SLaxman Dewangan 		dev_err(pmic->dev, "Regulator %d slew rate set failed: %d\n",
3475aa43599SLaxman Dewangan 			id, ret);
3485aa43599SLaxman Dewangan 		return ret;
3495aa43599SLaxman Dewangan 	}
3505aa43599SLaxman Dewangan 
3515aa43599SLaxman Dewangan 	return 0;
3525aa43599SLaxman Dewangan }
3535aa43599SLaxman Dewangan 
3545b1c2028SLaxman Dewangan static int max77620_init_pmic(struct max77620_regulator *pmic, int id)
3555b1c2028SLaxman Dewangan {
3565b1c2028SLaxman Dewangan 	struct max77620_regulator_pdata *rpdata = &pmic->reg_pdata[id];
3575b1c2028SLaxman Dewangan 	int ret;
3585b1c2028SLaxman Dewangan 
3595b1c2028SLaxman Dewangan 	/* Update power mode */
3605b1c2028SLaxman Dewangan 	ret = max77620_regulator_get_power_mode(pmic, id);
3615b1c2028SLaxman Dewangan 	if (ret < 0)
3625b1c2028SLaxman Dewangan 		return ret;
3635b1c2028SLaxman Dewangan 
3645b1c2028SLaxman Dewangan 	pmic->current_power_mode[id] = ret;
3655b1c2028SLaxman Dewangan 	pmic->enable_power_mode[id] = MAX77620_POWER_MODE_NORMAL;
3665b1c2028SLaxman Dewangan 
3675b1c2028SLaxman Dewangan 	if (rpdata->active_fps_src == MAX77620_FPS_SRC_DEF) {
3685b1c2028SLaxman Dewangan 		ret = max77620_regulator_get_fps_src(pmic, id);
3695b1c2028SLaxman Dewangan 		if (ret < 0)
3705b1c2028SLaxman Dewangan 			return ret;
3715b1c2028SLaxman Dewangan 		rpdata->active_fps_src = ret;
3725b1c2028SLaxman Dewangan 	}
3735b1c2028SLaxman Dewangan 
3745b1c2028SLaxman Dewangan 	 /* If rails are externally control of FPS then enable it always. */
3755b1c2028SLaxman Dewangan 	if (rpdata->active_fps_src == MAX77620_FPS_SRC_NONE) {
3765b1c2028SLaxman Dewangan 		ret = max77620_regulator_set_power_mode(pmic,
3775b1c2028SLaxman Dewangan 					pmic->enable_power_mode[id], id);
3785b1c2028SLaxman Dewangan 		if (ret < 0)
3795b1c2028SLaxman Dewangan 			return ret;
3805b1c2028SLaxman Dewangan 	} else {
3815b1c2028SLaxman Dewangan 		if (pmic->current_power_mode[id] !=
3825b1c2028SLaxman Dewangan 		     pmic->enable_power_mode[id]) {
3835b1c2028SLaxman Dewangan 			ret = max77620_regulator_set_power_mode(pmic,
3845b1c2028SLaxman Dewangan 					pmic->enable_power_mode[id], id);
3855b1c2028SLaxman Dewangan 			if (ret < 0)
3865b1c2028SLaxman Dewangan 				return ret;
3875b1c2028SLaxman Dewangan 		}
3885b1c2028SLaxman Dewangan 	}
3895b1c2028SLaxman Dewangan 
3905b1c2028SLaxman Dewangan 	ret = max77620_regulator_set_fps_src(pmic, rpdata->active_fps_src, id);
3915b1c2028SLaxman Dewangan 	if (ret < 0)
3925b1c2028SLaxman Dewangan 		return ret;
3935b1c2028SLaxman Dewangan 
3945b1c2028SLaxman Dewangan 	ret = max77620_regulator_set_fps_slots(pmic, id, false);
3955b1c2028SLaxman Dewangan 	if (ret < 0)
3965b1c2028SLaxman Dewangan 		return ret;
3975b1c2028SLaxman Dewangan 
3985aa43599SLaxman Dewangan 	if (rpdata->ramp_rate_setting) {
3995aa43599SLaxman Dewangan 		ret = max77620_set_slew_rate(pmic, id,
4005aa43599SLaxman Dewangan 					     rpdata->ramp_rate_setting);
4015aa43599SLaxman Dewangan 		if (ret < 0)
4025aa43599SLaxman Dewangan 			return ret;
4035aa43599SLaxman Dewangan 	}
4045aa43599SLaxman Dewangan 
4055b1c2028SLaxman Dewangan 	return 0;
4065b1c2028SLaxman Dewangan }
4075b1c2028SLaxman Dewangan 
4085b1c2028SLaxman Dewangan static int max77620_regulator_enable(struct regulator_dev *rdev)
4095b1c2028SLaxman Dewangan {
4105b1c2028SLaxman Dewangan 	struct max77620_regulator *pmic = rdev_get_drvdata(rdev);
4115b1c2028SLaxman Dewangan 	int id = rdev_get_id(rdev);
4125b1c2028SLaxman Dewangan 
4135b1c2028SLaxman Dewangan 	if (pmic->active_fps_src[id] != MAX77620_FPS_SRC_NONE)
4145b1c2028SLaxman Dewangan 		return 0;
4155b1c2028SLaxman Dewangan 
4165b1c2028SLaxman Dewangan 	return max77620_regulator_set_power_mode(pmic,
4175b1c2028SLaxman Dewangan 			pmic->enable_power_mode[id], id);
4185b1c2028SLaxman Dewangan }
4195b1c2028SLaxman Dewangan 
4205b1c2028SLaxman Dewangan static int max77620_regulator_disable(struct regulator_dev *rdev)
4215b1c2028SLaxman Dewangan {
4225b1c2028SLaxman Dewangan 	struct max77620_regulator *pmic = rdev_get_drvdata(rdev);
4235b1c2028SLaxman Dewangan 	int id = rdev_get_id(rdev);
4245b1c2028SLaxman Dewangan 
4255b1c2028SLaxman Dewangan 	if (pmic->active_fps_src[id] != MAX77620_FPS_SRC_NONE)
4265b1c2028SLaxman Dewangan 		return 0;
4275b1c2028SLaxman Dewangan 
4285b1c2028SLaxman Dewangan 	return max77620_regulator_set_power_mode(pmic,
4295b1c2028SLaxman Dewangan 			MAX77620_POWER_MODE_DISABLE, id);
4305b1c2028SLaxman Dewangan }
4315b1c2028SLaxman Dewangan 
4325b1c2028SLaxman Dewangan static int max77620_regulator_is_enabled(struct regulator_dev *rdev)
4335b1c2028SLaxman Dewangan {
4345b1c2028SLaxman Dewangan 	struct max77620_regulator *pmic = rdev_get_drvdata(rdev);
4355b1c2028SLaxman Dewangan 	int id = rdev_get_id(rdev);
4365b1c2028SLaxman Dewangan 	int ret = 1;
4375b1c2028SLaxman Dewangan 
4385b1c2028SLaxman Dewangan 	if (pmic->active_fps_src[id] != MAX77620_FPS_SRC_NONE)
4395b1c2028SLaxman Dewangan 		return 1;
4405b1c2028SLaxman Dewangan 
4415b1c2028SLaxman Dewangan 	ret = max77620_regulator_get_power_mode(pmic, id);
4425b1c2028SLaxman Dewangan 	if (ret < 0)
4435b1c2028SLaxman Dewangan 		return ret;
4445b1c2028SLaxman Dewangan 
4455b1c2028SLaxman Dewangan 	if (ret != MAX77620_POWER_MODE_DISABLE)
4465b1c2028SLaxman Dewangan 		return 1;
4475b1c2028SLaxman Dewangan 
4485b1c2028SLaxman Dewangan 	return 0;
4495b1c2028SLaxman Dewangan }
4505b1c2028SLaxman Dewangan 
4515b1c2028SLaxman Dewangan static int max77620_regulator_set_mode(struct regulator_dev *rdev,
4525b1c2028SLaxman Dewangan 				       unsigned int mode)
4535b1c2028SLaxman Dewangan {
4545b1c2028SLaxman Dewangan 	struct max77620_regulator *pmic = rdev_get_drvdata(rdev);
4555b1c2028SLaxman Dewangan 	int id = rdev_get_id(rdev);
4565b1c2028SLaxman Dewangan 	struct max77620_regulator_info *rinfo = pmic->rinfo[id];
4575b1c2028SLaxman Dewangan 	struct max77620_regulator_pdata *rpdata = &pmic->reg_pdata[id];
4585b1c2028SLaxman Dewangan 	bool fpwm = false;
4595b1c2028SLaxman Dewangan 	int power_mode;
4605b1c2028SLaxman Dewangan 	int ret;
4615b1c2028SLaxman Dewangan 	u8 val;
4625b1c2028SLaxman Dewangan 
4635b1c2028SLaxman Dewangan 	switch (mode) {
4645b1c2028SLaxman Dewangan 	case REGULATOR_MODE_FAST:
4655b1c2028SLaxman Dewangan 		fpwm = true;
4665b1c2028SLaxman Dewangan 		power_mode = MAX77620_POWER_MODE_NORMAL;
4675b1c2028SLaxman Dewangan 		break;
4685b1c2028SLaxman Dewangan 
4695b1c2028SLaxman Dewangan 	case REGULATOR_MODE_NORMAL:
4705b1c2028SLaxman Dewangan 		power_mode = MAX77620_POWER_MODE_NORMAL;
4715b1c2028SLaxman Dewangan 		break;
4725b1c2028SLaxman Dewangan 
4735b1c2028SLaxman Dewangan 	case REGULATOR_MODE_IDLE:
4745b1c2028SLaxman Dewangan 		power_mode = MAX77620_POWER_MODE_LPM;
4755b1c2028SLaxman Dewangan 		break;
4765b1c2028SLaxman Dewangan 
4775b1c2028SLaxman Dewangan 	default:
4785b1c2028SLaxman Dewangan 		dev_err(pmic->dev, "Regulator %d mode %d is invalid\n",
4795b1c2028SLaxman Dewangan 			id, mode);
4805b1c2028SLaxman Dewangan 		return -EINVAL;
4815b1c2028SLaxman Dewangan 	}
4825b1c2028SLaxman Dewangan 
4835b1c2028SLaxman Dewangan 	if (rinfo->type != MAX77620_REGULATOR_TYPE_SD)
4845b1c2028SLaxman Dewangan 		goto skip_fpwm;
4855b1c2028SLaxman Dewangan 
4865b1c2028SLaxman Dewangan 	val = (fpwm) ? MAX77620_SD_FPWM_MASK : 0;
4875b1c2028SLaxman Dewangan 	ret = regmap_update_bits(pmic->rmap, rinfo->cfg_addr,
4885b1c2028SLaxman Dewangan 				 MAX77620_SD_FPWM_MASK, val);
4895b1c2028SLaxman Dewangan 	if (ret < 0) {
4905b1c2028SLaxman Dewangan 		dev_err(pmic->dev, "Reg 0x%02x update failed: %d\n",
4915b1c2028SLaxman Dewangan 			rinfo->cfg_addr, ret);
4925b1c2028SLaxman Dewangan 		return ret;
4935b1c2028SLaxman Dewangan 	}
4945b1c2028SLaxman Dewangan 	rpdata->current_mode = mode;
4955b1c2028SLaxman Dewangan 
4965b1c2028SLaxman Dewangan skip_fpwm:
4975b1c2028SLaxman Dewangan 	ret = max77620_regulator_set_power_mode(pmic, power_mode, id);
4985b1c2028SLaxman Dewangan 	if (ret < 0)
4995b1c2028SLaxman Dewangan 		return ret;
5005b1c2028SLaxman Dewangan 
5015b1c2028SLaxman Dewangan 	pmic->enable_power_mode[id] = power_mode;
5025b1c2028SLaxman Dewangan 
5035b1c2028SLaxman Dewangan 	return 0;
5045b1c2028SLaxman Dewangan }
5055b1c2028SLaxman Dewangan 
5065b1c2028SLaxman Dewangan static unsigned int max77620_regulator_get_mode(struct regulator_dev *rdev)
5075b1c2028SLaxman Dewangan {
5085b1c2028SLaxman Dewangan 	struct max77620_regulator *pmic = rdev_get_drvdata(rdev);
5095b1c2028SLaxman Dewangan 	int id = rdev_get_id(rdev);
5105b1c2028SLaxman Dewangan 	struct max77620_regulator_info *rinfo = pmic->rinfo[id];
5115b1c2028SLaxman Dewangan 	int fpwm = 0;
5125b1c2028SLaxman Dewangan 	int ret;
5135b1c2028SLaxman Dewangan 	int pm_mode, reg_mode;
5145b1c2028SLaxman Dewangan 	unsigned int val;
5155b1c2028SLaxman Dewangan 
5165b1c2028SLaxman Dewangan 	ret = max77620_regulator_get_power_mode(pmic, id);
5175b1c2028SLaxman Dewangan 	if (ret < 0)
5185b1c2028SLaxman Dewangan 		return 0;
5195b1c2028SLaxman Dewangan 
5205b1c2028SLaxman Dewangan 	pm_mode = ret;
5215b1c2028SLaxman Dewangan 
5225b1c2028SLaxman Dewangan 	if (rinfo->type == MAX77620_REGULATOR_TYPE_SD) {
5235b1c2028SLaxman Dewangan 		ret = regmap_read(pmic->rmap, rinfo->cfg_addr, &val);
5245b1c2028SLaxman Dewangan 		if (ret < 0) {
5255b1c2028SLaxman Dewangan 			dev_err(pmic->dev, "Reg 0x%02x read failed: %d\n",
5265b1c2028SLaxman Dewangan 				rinfo->cfg_addr, ret);
5275b1c2028SLaxman Dewangan 			return ret;
5285b1c2028SLaxman Dewangan 		}
5295b1c2028SLaxman Dewangan 		fpwm = !!(val & MAX77620_SD_FPWM_MASK);
5305b1c2028SLaxman Dewangan 	}
5315b1c2028SLaxman Dewangan 
5325b1c2028SLaxman Dewangan 	switch (pm_mode) {
5335b1c2028SLaxman Dewangan 	case MAX77620_POWER_MODE_NORMAL:
5345b1c2028SLaxman Dewangan 	case MAX77620_POWER_MODE_DISABLE:
5355b1c2028SLaxman Dewangan 		if (fpwm)
5365b1c2028SLaxman Dewangan 			reg_mode = REGULATOR_MODE_FAST;
5375b1c2028SLaxman Dewangan 		else
5385b1c2028SLaxman Dewangan 			reg_mode = REGULATOR_MODE_NORMAL;
5395b1c2028SLaxman Dewangan 		break;
5405b1c2028SLaxman Dewangan 	case MAX77620_POWER_MODE_LPM:
5415b1c2028SLaxman Dewangan 	case MAX77620_POWER_MODE_GLPM:
5425b1c2028SLaxman Dewangan 		reg_mode = REGULATOR_MODE_IDLE;
5435b1c2028SLaxman Dewangan 		break;
5445b1c2028SLaxman Dewangan 	default:
5455b1c2028SLaxman Dewangan 		return 0;
5465b1c2028SLaxman Dewangan 	}
5475b1c2028SLaxman Dewangan 
5485b1c2028SLaxman Dewangan 	return reg_mode;
5495b1c2028SLaxman Dewangan }
5505b1c2028SLaxman Dewangan 
5515b1c2028SLaxman Dewangan static int max77620_regulator_set_ramp_delay(struct regulator_dev *rdev,
5525b1c2028SLaxman Dewangan 					     int ramp_delay)
5535b1c2028SLaxman Dewangan {
5545b1c2028SLaxman Dewangan 	struct max77620_regulator *pmic = rdev_get_drvdata(rdev);
5555b1c2028SLaxman Dewangan 	int id = rdev_get_id(rdev);
5565aa43599SLaxman Dewangan 	struct max77620_regulator_pdata *rpdata = &pmic->reg_pdata[id];
5575b1c2028SLaxman Dewangan 
5585aa43599SLaxman Dewangan 	/* Device specific ramp rate setting tells that platform has
5595aa43599SLaxman Dewangan 	 * different ramp rate from advertised value. In this case,
5605aa43599SLaxman Dewangan 	 * do not configure anything and just return success.
5615aa43599SLaxman Dewangan 	 */
5625aa43599SLaxman Dewangan 	if (rpdata->ramp_rate_setting)
5635aa43599SLaxman Dewangan 		return 0;
5645b1c2028SLaxman Dewangan 
5655aa43599SLaxman Dewangan 	return max77620_set_slew_rate(pmic, id, ramp_delay);
5665b1c2028SLaxman Dewangan }
5675b1c2028SLaxman Dewangan 
5685b1c2028SLaxman Dewangan static int max77620_of_parse_cb(struct device_node *np,
5695b1c2028SLaxman Dewangan 				const struct regulator_desc *desc,
5705b1c2028SLaxman Dewangan 				struct regulator_config *config)
5715b1c2028SLaxman Dewangan {
5725b1c2028SLaxman Dewangan 	struct max77620_regulator *pmic = config->driver_data;
5735b1c2028SLaxman Dewangan 	struct max77620_regulator_pdata *rpdata = &pmic->reg_pdata[desc->id];
5745b1c2028SLaxman Dewangan 	u32 pval;
5755b1c2028SLaxman Dewangan 	int ret;
5765b1c2028SLaxman Dewangan 
5775b1c2028SLaxman Dewangan 	ret = of_property_read_u32(np, "maxim,active-fps-source", &pval);
5785b1c2028SLaxman Dewangan 	rpdata->active_fps_src = (!ret) ? pval : MAX77620_FPS_SRC_DEF;
5795b1c2028SLaxman Dewangan 
5805b1c2028SLaxman Dewangan 	ret = of_property_read_u32(np, "maxim,active-fps-power-up-slot", &pval);
5815b1c2028SLaxman Dewangan 	rpdata->active_fps_pu_slot = (!ret) ? pval : -1;
5825b1c2028SLaxman Dewangan 
5835b1c2028SLaxman Dewangan 	ret = of_property_read_u32(
5845b1c2028SLaxman Dewangan 			np, "maxim,active-fps-power-down-slot", &pval);
5855b1c2028SLaxman Dewangan 	rpdata->active_fps_pd_slot = (!ret) ? pval : -1;
5865b1c2028SLaxman Dewangan 
5875b1c2028SLaxman Dewangan 	ret = of_property_read_u32(np, "maxim,suspend-fps-source", &pval);
5885b1c2028SLaxman Dewangan 	rpdata->suspend_fps_src = (!ret) ? pval : -1;
5895b1c2028SLaxman Dewangan 
5905b1c2028SLaxman Dewangan 	ret = of_property_read_u32(
5915b1c2028SLaxman Dewangan 			np, "maxim,suspend-fps-power-up-slot", &pval);
5925b1c2028SLaxman Dewangan 	rpdata->suspend_fps_pu_slot = (!ret) ? pval : -1;
5935b1c2028SLaxman Dewangan 
5945b1c2028SLaxman Dewangan 	ret = of_property_read_u32(
5955b1c2028SLaxman Dewangan 			np, "maxim,suspend-fps-power-down-slot", &pval);
5965b1c2028SLaxman Dewangan 	rpdata->suspend_fps_pd_slot = (!ret) ? pval : -1;
5975b1c2028SLaxman Dewangan 
5985aa43599SLaxman Dewangan 	ret = of_property_read_u32(np, "maxim,ramp-rate-setting", &pval);
5995aa43599SLaxman Dewangan 	rpdata->ramp_rate_setting = (!ret) ? pval : 0;
6005aa43599SLaxman Dewangan 
6015b1c2028SLaxman Dewangan 	return max77620_init_pmic(pmic, desc->id);
6025b1c2028SLaxman Dewangan }
6035b1c2028SLaxman Dewangan 
6045b1c2028SLaxman Dewangan static struct regulator_ops max77620_regulator_ops = {
6055b1c2028SLaxman Dewangan 	.is_enabled = max77620_regulator_is_enabled,
6065b1c2028SLaxman Dewangan 	.enable = max77620_regulator_enable,
6075b1c2028SLaxman Dewangan 	.disable = max77620_regulator_disable,
6085b1c2028SLaxman Dewangan 	.list_voltage = regulator_list_voltage_linear,
6095b1c2028SLaxman Dewangan 	.map_voltage = regulator_map_voltage_linear,
6105b1c2028SLaxman Dewangan 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
6115b1c2028SLaxman Dewangan 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
6125b1c2028SLaxman Dewangan 	.set_mode = max77620_regulator_set_mode,
6135b1c2028SLaxman Dewangan 	.get_mode = max77620_regulator_get_mode,
6145b1c2028SLaxman Dewangan 	.set_ramp_delay = max77620_regulator_set_ramp_delay,
6155b1c2028SLaxman Dewangan 	.set_voltage_time_sel = regulator_set_voltage_time_sel,
61651817f46SLaxman Dewangan 	.set_active_discharge = regulator_set_active_discharge_regmap,
6175b1c2028SLaxman Dewangan };
6185b1c2028SLaxman Dewangan 
6195b1c2028SLaxman Dewangan #define MAX77620_SD_CNF2_ROVS_EN_NONE	0
6205b1c2028SLaxman Dewangan #define RAIL_SD(_id, _name, _sname, _volt_mask, _min_uV, _max_uV,	\
6215b1c2028SLaxman Dewangan 		_step_uV, _rs_add, _rs_mask)				\
6225b1c2028SLaxman Dewangan 	[MAX77620_REGULATOR_ID_##_id] = {				\
6235b1c2028SLaxman Dewangan 		.type = MAX77620_REGULATOR_TYPE_SD,			\
6245b1c2028SLaxman Dewangan 		.volt_addr = MAX77620_REG_##_id,			\
6255b1c2028SLaxman Dewangan 		.cfg_addr = MAX77620_REG_##_id##_CFG,			\
6265b1c2028SLaxman Dewangan 		.fps_addr = MAX77620_REG_FPS_##_id,			\
6275b1c2028SLaxman Dewangan 		.remote_sense_addr = _rs_add,				\
6285b1c2028SLaxman Dewangan 		.remote_sense_mask = MAX77620_SD_CNF2_ROVS_EN_##_rs_mask, \
6295b1c2028SLaxman Dewangan 		.power_mode_mask = MAX77620_SD_POWER_MODE_MASK,		\
6305b1c2028SLaxman Dewangan 		.power_mode_shift = MAX77620_SD_POWER_MODE_SHIFT,	\
6315b1c2028SLaxman Dewangan 		.desc = {						\
6325b1c2028SLaxman Dewangan 			.name = max77620_rails(_name),			\
6335b1c2028SLaxman Dewangan 			.of_match = of_match_ptr(#_name),		\
6345b1c2028SLaxman Dewangan 			.regulators_node = of_match_ptr("regulators"),	\
6355b1c2028SLaxman Dewangan 			.of_parse_cb = max77620_of_parse_cb,		\
6365b1c2028SLaxman Dewangan 			.supply_name = _sname,				\
6375b1c2028SLaxman Dewangan 			.id = MAX77620_REGULATOR_ID_##_id,		\
6385b1c2028SLaxman Dewangan 			.ops = &max77620_regulator_ops,			\
6395b1c2028SLaxman Dewangan 			.n_voltages = ((_max_uV - _min_uV) / _step_uV) + 1, \
6405b1c2028SLaxman Dewangan 			.min_uV = _min_uV,				\
6415b1c2028SLaxman Dewangan 			.uV_step = _step_uV,				\
6425b1c2028SLaxman Dewangan 			.enable_time = 500,				\
6435b1c2028SLaxman Dewangan 			.vsel_mask = MAX77620_##_volt_mask##_VOLT_MASK,	\
6445b1c2028SLaxman Dewangan 			.vsel_reg = MAX77620_REG_##_id,			\
64551817f46SLaxman Dewangan 			.active_discharge_off = 0,			\
64651817f46SLaxman Dewangan 			.active_discharge_on = MAX77620_SD_CFG1_ADE_ENABLE, \
64751817f46SLaxman Dewangan 			.active_discharge_mask = MAX77620_SD_CFG1_ADE_MASK, \
64851817f46SLaxman Dewangan 			.active_discharge_reg = MAX77620_REG_##_id##_CFG, \
6495b1c2028SLaxman Dewangan 			.type = REGULATOR_VOLTAGE,			\
6505b1c2028SLaxman Dewangan 		},							\
6515b1c2028SLaxman Dewangan 	}
6525b1c2028SLaxman Dewangan 
6535b1c2028SLaxman Dewangan #define RAIL_LDO(_id, _name, _sname, _type, _min_uV, _max_uV, _step_uV) \
6545b1c2028SLaxman Dewangan 	[MAX77620_REGULATOR_ID_##_id] = {				\
6555b1c2028SLaxman Dewangan 		.type = MAX77620_REGULATOR_TYPE_LDO_##_type,		\
6565b1c2028SLaxman Dewangan 		.volt_addr = MAX77620_REG_##_id##_CFG,			\
6575b1c2028SLaxman Dewangan 		.cfg_addr = MAX77620_REG_##_id##_CFG2,			\
6585b1c2028SLaxman Dewangan 		.fps_addr = MAX77620_REG_FPS_##_id,			\
6595b1c2028SLaxman Dewangan 		.remote_sense_addr = 0xFF,				\
6605b1c2028SLaxman Dewangan 		.power_mode_mask = MAX77620_LDO_POWER_MODE_MASK,	\
6615b1c2028SLaxman Dewangan 		.power_mode_shift = MAX77620_LDO_POWER_MODE_SHIFT,	\
6625b1c2028SLaxman Dewangan 		.desc = {						\
6635b1c2028SLaxman Dewangan 			.name = max77620_rails(_name),			\
6645b1c2028SLaxman Dewangan 			.of_match = of_match_ptr(#_name),		\
6655b1c2028SLaxman Dewangan 			.regulators_node = of_match_ptr("regulators"),	\
6665b1c2028SLaxman Dewangan 			.of_parse_cb = max77620_of_parse_cb,		\
6675b1c2028SLaxman Dewangan 			.supply_name = _sname,				\
6685b1c2028SLaxman Dewangan 			.id = MAX77620_REGULATOR_ID_##_id,		\
6695b1c2028SLaxman Dewangan 			.ops = &max77620_regulator_ops,			\
6705b1c2028SLaxman Dewangan 			.n_voltages = ((_max_uV - _min_uV) / _step_uV) + 1, \
6715b1c2028SLaxman Dewangan 			.min_uV = _min_uV,				\
6725b1c2028SLaxman Dewangan 			.uV_step = _step_uV,				\
6735b1c2028SLaxman Dewangan 			.enable_time = 500,				\
6745b1c2028SLaxman Dewangan 			.vsel_mask = MAX77620_LDO_VOLT_MASK,		\
6755b1c2028SLaxman Dewangan 			.vsel_reg = MAX77620_REG_##_id##_CFG,		\
67651817f46SLaxman Dewangan 			.active_discharge_off = 0,			\
67751817f46SLaxman Dewangan 			.active_discharge_on = MAX77620_LDO_CFG2_ADE_ENABLE, \
67851817f46SLaxman Dewangan 			.active_discharge_mask = MAX77620_LDO_CFG2_ADE_MASK, \
67951817f46SLaxman Dewangan 			.active_discharge_reg = MAX77620_REG_##_id##_CFG2, \
6805b1c2028SLaxman Dewangan 			.type = REGULATOR_VOLTAGE,			\
6815b1c2028SLaxman Dewangan 		},							\
6825b1c2028SLaxman Dewangan 	}
6835b1c2028SLaxman Dewangan 
6845b1c2028SLaxman Dewangan static struct max77620_regulator_info max77620_regs_info[MAX77620_NUM_REGS] = {
6855b1c2028SLaxman Dewangan 	RAIL_SD(SD0, sd0, "in-sd0", SD0, 600000, 1400000, 12500, 0x22, SD0),
6865b1c2028SLaxman Dewangan 	RAIL_SD(SD1, sd1, "in-sd1", SD1, 600000, 1550000, 12500, 0x22, SD1),
6875b1c2028SLaxman Dewangan 	RAIL_SD(SD2, sd2, "in-sd2", SDX, 600000, 3787500, 12500, 0xFF, NONE),
6885b1c2028SLaxman Dewangan 	RAIL_SD(SD3, sd3, "in-sd3", SDX, 600000, 3787500, 12500, 0xFF, NONE),
6895b1c2028SLaxman Dewangan 
6905b1c2028SLaxman Dewangan 	RAIL_LDO(LDO0, ldo0, "in-ldo0-1", N, 800000, 2375000, 25000),
6915b1c2028SLaxman Dewangan 	RAIL_LDO(LDO1, ldo1, "in-ldo0-1", N, 800000, 2375000, 25000),
6925b1c2028SLaxman Dewangan 	RAIL_LDO(LDO2, ldo2, "in-ldo2",   P, 800000, 3950000, 50000),
6935b1c2028SLaxman Dewangan 	RAIL_LDO(LDO3, ldo3, "in-ldo3-5", P, 800000, 3950000, 50000),
6945b1c2028SLaxman Dewangan 	RAIL_LDO(LDO4, ldo4, "in-ldo4-6", P, 800000, 1587500, 12500),
6955b1c2028SLaxman Dewangan 	RAIL_LDO(LDO5, ldo5, "in-ldo3-5", P, 800000, 3950000, 50000),
6965b1c2028SLaxman Dewangan 	RAIL_LDO(LDO6, ldo6, "in-ldo4-6", P, 800000, 3950000, 50000),
6975b1c2028SLaxman Dewangan 	RAIL_LDO(LDO7, ldo7, "in-ldo7-8", N, 800000, 3950000, 50000),
6985b1c2028SLaxman Dewangan 	RAIL_LDO(LDO8, ldo8, "in-ldo7-8", N, 800000, 3950000, 50000),
6995b1c2028SLaxman Dewangan };
7005b1c2028SLaxman Dewangan 
7015b1c2028SLaxman Dewangan static struct max77620_regulator_info max20024_regs_info[MAX77620_NUM_REGS] = {
7025b1c2028SLaxman Dewangan 	RAIL_SD(SD0, sd0, "in-sd0", SD0, 800000, 1587500, 12500, 0x22, SD0),
7035b1c2028SLaxman Dewangan 	RAIL_SD(SD1, sd1, "in-sd1", SD1, 600000, 3387500, 12500, 0x22, SD1),
7045b1c2028SLaxman Dewangan 	RAIL_SD(SD2, sd2, "in-sd2", SDX, 600000, 3787500, 12500, 0xFF, NONE),
7055b1c2028SLaxman Dewangan 	RAIL_SD(SD3, sd3, "in-sd3", SDX, 600000, 3787500, 12500, 0xFF, NONE),
7065b1c2028SLaxman Dewangan 	RAIL_SD(SD4, sd4, "in-sd4", SDX, 600000, 3787500, 12500, 0xFF, NONE),
7075b1c2028SLaxman Dewangan 
7085b1c2028SLaxman Dewangan 	RAIL_LDO(LDO0, ldo0, "in-ldo0-1", N, 800000, 2375000, 25000),
7095b1c2028SLaxman Dewangan 	RAIL_LDO(LDO1, ldo1, "in-ldo0-1", N, 800000, 2375000, 25000),
7105b1c2028SLaxman Dewangan 	RAIL_LDO(LDO2, ldo2, "in-ldo2",   P, 800000, 3950000, 50000),
7115b1c2028SLaxman Dewangan 	RAIL_LDO(LDO3, ldo3, "in-ldo3-5", P, 800000, 3950000, 50000),
7125b1c2028SLaxman Dewangan 	RAIL_LDO(LDO4, ldo4, "in-ldo4-6", P, 800000, 1587500, 12500),
7135b1c2028SLaxman Dewangan 	RAIL_LDO(LDO5, ldo5, "in-ldo3-5", P, 800000, 3950000, 50000),
7145b1c2028SLaxman Dewangan 	RAIL_LDO(LDO6, ldo6, "in-ldo4-6", P, 800000, 3950000, 50000),
7155b1c2028SLaxman Dewangan 	RAIL_LDO(LDO7, ldo7, "in-ldo7-8", N, 800000, 3950000, 50000),
7165b1c2028SLaxman Dewangan 	RAIL_LDO(LDO8, ldo8, "in-ldo7-8", N, 800000, 3950000, 50000),
7175b1c2028SLaxman Dewangan };
7185b1c2028SLaxman Dewangan 
7195b1c2028SLaxman Dewangan static int max77620_regulator_probe(struct platform_device *pdev)
7205b1c2028SLaxman Dewangan {
7215b1c2028SLaxman Dewangan 	struct max77620_chip *max77620_chip = dev_get_drvdata(pdev->dev.parent);
7225b1c2028SLaxman Dewangan 	struct max77620_regulator_info *rinfo;
7235b1c2028SLaxman Dewangan 	struct device *dev = &pdev->dev;
7245b1c2028SLaxman Dewangan 	struct regulator_config config = { };
7255b1c2028SLaxman Dewangan 	struct max77620_regulator *pmic;
7265b1c2028SLaxman Dewangan 	int ret = 0;
7275b1c2028SLaxman Dewangan 	int id;
7285b1c2028SLaxman Dewangan 
7295b1c2028SLaxman Dewangan 	pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL);
7305b1c2028SLaxman Dewangan 	if (!pmic)
7315b1c2028SLaxman Dewangan 		return -ENOMEM;
7325b1c2028SLaxman Dewangan 
7335b1c2028SLaxman Dewangan 	platform_set_drvdata(pdev, pmic);
7345b1c2028SLaxman Dewangan 	pmic->dev = dev;
7355b1c2028SLaxman Dewangan 	pmic->rmap = max77620_chip->rmap;
7365b1c2028SLaxman Dewangan 	if (!dev->of_node)
7375b1c2028SLaxman Dewangan 		dev->of_node = pdev->dev.parent->of_node;
7385b1c2028SLaxman Dewangan 
7395b1c2028SLaxman Dewangan 	switch (max77620_chip->chip_id) {
7405b1c2028SLaxman Dewangan 	case MAX77620:
7415b1c2028SLaxman Dewangan 		rinfo = max77620_regs_info;
7425b1c2028SLaxman Dewangan 		break;
7435b1c2028SLaxman Dewangan 	default:
7445b1c2028SLaxman Dewangan 		rinfo = max20024_regs_info;
7455b1c2028SLaxman Dewangan 		break;
7465b1c2028SLaxman Dewangan 	}
7475b1c2028SLaxman Dewangan 
7485b1c2028SLaxman Dewangan 	config.regmap = pmic->rmap;
7495b1c2028SLaxman Dewangan 	config.dev = dev;
7505b1c2028SLaxman Dewangan 	config.driver_data = pmic;
7515b1c2028SLaxman Dewangan 
7525b1c2028SLaxman Dewangan 	for (id = 0; id < MAX77620_NUM_REGS; id++) {
7535b1c2028SLaxman Dewangan 		struct regulator_dev *rdev;
7545b1c2028SLaxman Dewangan 		struct regulator_desc *rdesc;
7555b1c2028SLaxman Dewangan 
7565b1c2028SLaxman Dewangan 		if ((max77620_chip->chip_id == MAX77620) &&
7575b1c2028SLaxman Dewangan 		    (id == MAX77620_REGULATOR_ID_SD4))
7585b1c2028SLaxman Dewangan 			continue;
7595b1c2028SLaxman Dewangan 
7605b1c2028SLaxman Dewangan 		rdesc = &rinfo[id].desc;
7615b1c2028SLaxman Dewangan 		pmic->rinfo[id] = &max77620_regs_info[id];
7625b1c2028SLaxman Dewangan 		pmic->enable_power_mode[id] = MAX77620_POWER_MODE_NORMAL;
7635b1c2028SLaxman Dewangan 
7645b1c2028SLaxman Dewangan 		ret = max77620_read_slew_rate(pmic, id);
7655b1c2028SLaxman Dewangan 		if (ret < 0)
7665b1c2028SLaxman Dewangan 			return ret;
7675b1c2028SLaxman Dewangan 
7685b1c2028SLaxman Dewangan 		rdev = devm_regulator_register(dev, rdesc, &config);
7695b1c2028SLaxman Dewangan 		if (IS_ERR(rdev)) {
7705b1c2028SLaxman Dewangan 			ret = PTR_ERR(rdev);
7715b1c2028SLaxman Dewangan 			dev_err(dev, "Regulator registration %s failed: %d\n",
7725b1c2028SLaxman Dewangan 				rdesc->name, ret);
7735b1c2028SLaxman Dewangan 			return ret;
7745b1c2028SLaxman Dewangan 		}
7755b1c2028SLaxman Dewangan 	}
7765b1c2028SLaxman Dewangan 
7775b1c2028SLaxman Dewangan 	return 0;
7785b1c2028SLaxman Dewangan }
7795b1c2028SLaxman Dewangan 
7805b1c2028SLaxman Dewangan #ifdef CONFIG_PM_SLEEP
7815b1c2028SLaxman Dewangan static int max77620_regulator_suspend(struct device *dev)
7825b1c2028SLaxman Dewangan {
7835b1c2028SLaxman Dewangan 	struct max77620_regulator *pmic = dev_get_drvdata(dev);
7845b1c2028SLaxman Dewangan 	struct max77620_regulator_pdata *reg_pdata;
7855b1c2028SLaxman Dewangan 	int id;
7865b1c2028SLaxman Dewangan 
7875b1c2028SLaxman Dewangan 	for (id = 0; id < MAX77620_NUM_REGS; id++) {
7885b1c2028SLaxman Dewangan 		reg_pdata = &pmic->reg_pdata[id];
7895b1c2028SLaxman Dewangan 
7905b1c2028SLaxman Dewangan 		max77620_regulator_set_fps_slots(pmic, id, true);
7915b1c2028SLaxman Dewangan 		if (reg_pdata->suspend_fps_src < 0)
7925b1c2028SLaxman Dewangan 			continue;
7935b1c2028SLaxman Dewangan 
7945b1c2028SLaxman Dewangan 		max77620_regulator_set_fps_src(pmic, reg_pdata->suspend_fps_src,
7955b1c2028SLaxman Dewangan 					       id);
7965b1c2028SLaxman Dewangan 	}
7975b1c2028SLaxman Dewangan 
7985b1c2028SLaxman Dewangan 	return 0;
7995b1c2028SLaxman Dewangan }
8005b1c2028SLaxman Dewangan 
8015b1c2028SLaxman Dewangan static int max77620_regulator_resume(struct device *dev)
8025b1c2028SLaxman Dewangan {
8035b1c2028SLaxman Dewangan 	struct max77620_regulator *pmic = dev_get_drvdata(dev);
8045b1c2028SLaxman Dewangan 	struct max77620_regulator_pdata *reg_pdata;
8055b1c2028SLaxman Dewangan 	int id;
8065b1c2028SLaxman Dewangan 
8075b1c2028SLaxman Dewangan 	for (id = 0; id < MAX77620_NUM_REGS; id++) {
8085b1c2028SLaxman Dewangan 		reg_pdata = &pmic->reg_pdata[id];
8095b1c2028SLaxman Dewangan 
8105b1c2028SLaxman Dewangan 		max77620_regulator_set_fps_slots(pmic, id, false);
8115b1c2028SLaxman Dewangan 		if (reg_pdata->active_fps_src < 0)
8125b1c2028SLaxman Dewangan 			continue;
8135b1c2028SLaxman Dewangan 		max77620_regulator_set_fps_src(pmic, reg_pdata->active_fps_src,
8145b1c2028SLaxman Dewangan 					       id);
8155b1c2028SLaxman Dewangan 	}
8165b1c2028SLaxman Dewangan 
8175b1c2028SLaxman Dewangan 	return 0;
8185b1c2028SLaxman Dewangan }
8195b1c2028SLaxman Dewangan #endif
8205b1c2028SLaxman Dewangan 
8215b1c2028SLaxman Dewangan static const struct dev_pm_ops max77620_regulator_pm_ops = {
8225b1c2028SLaxman Dewangan 	SET_SYSTEM_SLEEP_PM_OPS(max77620_regulator_suspend,
8235b1c2028SLaxman Dewangan 				max77620_regulator_resume)
8245b1c2028SLaxman Dewangan };
8255b1c2028SLaxman Dewangan 
8265b1c2028SLaxman Dewangan static const struct platform_device_id max77620_regulator_devtype[] = {
8275b1c2028SLaxman Dewangan 	{ .name = "max77620-pmic", },
8285b1c2028SLaxman Dewangan 	{ .name = "max20024-pmic", },
8295b1c2028SLaxman Dewangan 	{},
8305b1c2028SLaxman Dewangan };
8315b1c2028SLaxman Dewangan MODULE_DEVICE_TABLE(platform, max77620_regulator_devtype);
8325b1c2028SLaxman Dewangan 
8335b1c2028SLaxman Dewangan static struct platform_driver max77620_regulator_driver = {
8345b1c2028SLaxman Dewangan 	.probe = max77620_regulator_probe,
8355b1c2028SLaxman Dewangan 	.id_table = max77620_regulator_devtype,
8365b1c2028SLaxman Dewangan 	.driver = {
8375b1c2028SLaxman Dewangan 		.name = "max77620-pmic",
8385b1c2028SLaxman Dewangan 		.pm = &max77620_regulator_pm_ops,
8395b1c2028SLaxman Dewangan 	},
8405b1c2028SLaxman Dewangan };
8415b1c2028SLaxman Dewangan 
8425b1c2028SLaxman Dewangan module_platform_driver(max77620_regulator_driver);
8435b1c2028SLaxman Dewangan 
8445b1c2028SLaxman Dewangan MODULE_DESCRIPTION("MAX77620/MAX20024 regulator driver");
8455b1c2028SLaxman Dewangan MODULE_AUTHOR("Mallikarjun Kasoju <mkasoju@nvidia.com>");
8465b1c2028SLaxman Dewangan MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
8475b1c2028SLaxman Dewangan MODULE_LICENSE("GPL v2");
848