175a6faf6SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
25b1c2028SLaxman Dewangan /*
35b1c2028SLaxman Dewangan * Maxim MAX77620 Regulator driver
45b1c2028SLaxman Dewangan *
50ab66b3cSMark Zhang * Copyright (c) 2016-2018, NVIDIA CORPORATION. All rights reserved.
65b1c2028SLaxman Dewangan *
75b1c2028SLaxman Dewangan * Author: Mallikarjun Kasoju <mkasoju@nvidia.com>
85b1c2028SLaxman Dewangan * Laxman Dewangan <ldewangan@nvidia.com>
95b1c2028SLaxman Dewangan */
105b1c2028SLaxman Dewangan
115b1c2028SLaxman Dewangan #include <linux/init.h>
125b1c2028SLaxman Dewangan #include <linux/mfd/max77620.h>
135b1c2028SLaxman Dewangan #include <linux/module.h>
145b1c2028SLaxman Dewangan #include <linux/of.h>
155b1c2028SLaxman Dewangan #include <linux/platform_device.h>
165b1c2028SLaxman Dewangan #include <linux/regmap.h>
175b1c2028SLaxman Dewangan #include <linux/regulator/driver.h>
185b1c2028SLaxman Dewangan #include <linux/regulator/machine.h>
195b1c2028SLaxman Dewangan #include <linux/regulator/of_regulator.h>
205b1c2028SLaxman Dewangan
215b1c2028SLaxman Dewangan #define max77620_rails(_name) "max77620-"#_name
225b1c2028SLaxman Dewangan
235b1c2028SLaxman Dewangan /* Power Mode */
245b1c2028SLaxman Dewangan #define MAX77620_POWER_MODE_NORMAL 3
255b1c2028SLaxman Dewangan #define MAX77620_POWER_MODE_LPM 2
265b1c2028SLaxman Dewangan #define MAX77620_POWER_MODE_GLPM 1
275b1c2028SLaxman Dewangan #define MAX77620_POWER_MODE_DISABLE 0
285b1c2028SLaxman Dewangan
295b1c2028SLaxman Dewangan /* SD Slew Rate */
305b1c2028SLaxman Dewangan #define MAX77620_SD_SR_13_75 0
315b1c2028SLaxman Dewangan #define MAX77620_SD_SR_27_5 1
325b1c2028SLaxman Dewangan #define MAX77620_SD_SR_55 2
335b1c2028SLaxman Dewangan #define MAX77620_SD_SR_100 3
345b1c2028SLaxman Dewangan
355b1c2028SLaxman Dewangan enum max77620_regulators {
365b1c2028SLaxman Dewangan MAX77620_REGULATOR_ID_SD0,
375b1c2028SLaxman Dewangan MAX77620_REGULATOR_ID_SD1,
385b1c2028SLaxman Dewangan MAX77620_REGULATOR_ID_SD2,
395b1c2028SLaxman Dewangan MAX77620_REGULATOR_ID_SD3,
405b1c2028SLaxman Dewangan MAX77620_REGULATOR_ID_SD4,
415b1c2028SLaxman Dewangan MAX77620_REGULATOR_ID_LDO0,
425b1c2028SLaxman Dewangan MAX77620_REGULATOR_ID_LDO1,
435b1c2028SLaxman Dewangan MAX77620_REGULATOR_ID_LDO2,
445b1c2028SLaxman Dewangan MAX77620_REGULATOR_ID_LDO3,
455b1c2028SLaxman Dewangan MAX77620_REGULATOR_ID_LDO4,
465b1c2028SLaxman Dewangan MAX77620_REGULATOR_ID_LDO5,
475b1c2028SLaxman Dewangan MAX77620_REGULATOR_ID_LDO6,
485b1c2028SLaxman Dewangan MAX77620_REGULATOR_ID_LDO7,
495b1c2028SLaxman Dewangan MAX77620_REGULATOR_ID_LDO8,
505b1c2028SLaxman Dewangan MAX77620_NUM_REGS,
515b1c2028SLaxman Dewangan };
525b1c2028SLaxman Dewangan
535b1c2028SLaxman Dewangan /* Regulator types */
545b1c2028SLaxman Dewangan enum max77620_regulator_type {
555b1c2028SLaxman Dewangan MAX77620_REGULATOR_TYPE_SD,
565b1c2028SLaxman Dewangan MAX77620_REGULATOR_TYPE_LDO_N,
575b1c2028SLaxman Dewangan MAX77620_REGULATOR_TYPE_LDO_P,
585b1c2028SLaxman Dewangan };
595b1c2028SLaxman Dewangan
605b1c2028SLaxman Dewangan struct max77620_regulator_info {
615b1c2028SLaxman Dewangan u8 type;
625b1c2028SLaxman Dewangan u8 fps_addr;
635b1c2028SLaxman Dewangan u8 volt_addr;
645b1c2028SLaxman Dewangan u8 cfg_addr;
655b1c2028SLaxman Dewangan u8 power_mode_mask;
665b1c2028SLaxman Dewangan u8 power_mode_shift;
675b1c2028SLaxman Dewangan u8 remote_sense_addr;
685b1c2028SLaxman Dewangan u8 remote_sense_mask;
695b1c2028SLaxman Dewangan struct regulator_desc desc;
705b1c2028SLaxman Dewangan };
715b1c2028SLaxman Dewangan
725b1c2028SLaxman Dewangan struct max77620_regulator_pdata {
735b1c2028SLaxman Dewangan int active_fps_src;
745b1c2028SLaxman Dewangan int active_fps_pd_slot;
755b1c2028SLaxman Dewangan int active_fps_pu_slot;
765b1c2028SLaxman Dewangan int suspend_fps_src;
775b1c2028SLaxman Dewangan int suspend_fps_pd_slot;
785b1c2028SLaxman Dewangan int suspend_fps_pu_slot;
795b1c2028SLaxman Dewangan int current_mode;
80383d0fcaSVenkat Reddy Talla int power_ok;
815aa43599SLaxman Dewangan int ramp_rate_setting;
825b1c2028SLaxman Dewangan };
835b1c2028SLaxman Dewangan
845b1c2028SLaxman Dewangan struct max77620_regulator {
855b1c2028SLaxman Dewangan struct device *dev;
865b1c2028SLaxman Dewangan struct regmap *rmap;
875b1c2028SLaxman Dewangan struct max77620_regulator_info *rinfo[MAX77620_NUM_REGS];
885b1c2028SLaxman Dewangan struct max77620_regulator_pdata reg_pdata[MAX77620_NUM_REGS];
895b1c2028SLaxman Dewangan int enable_power_mode[MAX77620_NUM_REGS];
905b1c2028SLaxman Dewangan int current_power_mode[MAX77620_NUM_REGS];
915b1c2028SLaxman Dewangan int active_fps_src[MAX77620_NUM_REGS];
925b1c2028SLaxman Dewangan };
935b1c2028SLaxman Dewangan
945b1c2028SLaxman Dewangan #define fps_src_name(fps_src) \
955b1c2028SLaxman Dewangan (fps_src == MAX77620_FPS_SRC_0 ? "FPS_SRC_0" : \
965b1c2028SLaxman Dewangan fps_src == MAX77620_FPS_SRC_1 ? "FPS_SRC_1" : \
975b1c2028SLaxman Dewangan fps_src == MAX77620_FPS_SRC_2 ? "FPS_SRC_2" : "FPS_SRC_NONE")
985b1c2028SLaxman Dewangan
max77620_regulator_get_fps_src(struct max77620_regulator * pmic,int id)995b1c2028SLaxman Dewangan static int max77620_regulator_get_fps_src(struct max77620_regulator *pmic,
1005b1c2028SLaxman Dewangan int id)
1015b1c2028SLaxman Dewangan {
1025b1c2028SLaxman Dewangan struct max77620_regulator_info *rinfo = pmic->rinfo[id];
1035b1c2028SLaxman Dewangan unsigned int val;
1045b1c2028SLaxman Dewangan int ret;
1055b1c2028SLaxman Dewangan
1065b1c2028SLaxman Dewangan ret = regmap_read(pmic->rmap, rinfo->fps_addr, &val);
1075b1c2028SLaxman Dewangan if (ret < 0) {
1085b1c2028SLaxman Dewangan dev_err(pmic->dev, "Reg 0x%02x read failed %d\n",
1095b1c2028SLaxman Dewangan rinfo->fps_addr, ret);
1105b1c2028SLaxman Dewangan return ret;
1115b1c2028SLaxman Dewangan }
1125b1c2028SLaxman Dewangan
1135b1c2028SLaxman Dewangan return (val & MAX77620_FPS_SRC_MASK) >> MAX77620_FPS_SRC_SHIFT;
1145b1c2028SLaxman Dewangan }
1155b1c2028SLaxman Dewangan
max77620_regulator_set_fps_src(struct max77620_regulator * pmic,int fps_src,int id)1165b1c2028SLaxman Dewangan static int max77620_regulator_set_fps_src(struct max77620_regulator *pmic,
1175b1c2028SLaxman Dewangan int fps_src, int id)
1185b1c2028SLaxman Dewangan {
1195b1c2028SLaxman Dewangan struct max77620_regulator_info *rinfo = pmic->rinfo[id];
1205b1c2028SLaxman Dewangan unsigned int val;
1215b1c2028SLaxman Dewangan int ret;
1225b1c2028SLaxman Dewangan
12391ff811fSVenkat Reddy Talla if (!rinfo)
12491ff811fSVenkat Reddy Talla return 0;
12591ff811fSVenkat Reddy Talla
1265b1c2028SLaxman Dewangan switch (fps_src) {
1275b1c2028SLaxman Dewangan case MAX77620_FPS_SRC_0:
1285b1c2028SLaxman Dewangan case MAX77620_FPS_SRC_1:
1295b1c2028SLaxman Dewangan case MAX77620_FPS_SRC_2:
1305b1c2028SLaxman Dewangan case MAX77620_FPS_SRC_NONE:
1315b1c2028SLaxman Dewangan break;
1325b1c2028SLaxman Dewangan
1335b1c2028SLaxman Dewangan case MAX77620_FPS_SRC_DEF:
1345b1c2028SLaxman Dewangan ret = regmap_read(pmic->rmap, rinfo->fps_addr, &val);
1355b1c2028SLaxman Dewangan if (ret < 0) {
1365b1c2028SLaxman Dewangan dev_err(pmic->dev, "Reg 0x%02x read failed %d\n",
1375b1c2028SLaxman Dewangan rinfo->fps_addr, ret);
1385b1c2028SLaxman Dewangan return ret;
1395b1c2028SLaxman Dewangan }
1405b1c2028SLaxman Dewangan ret = (val & MAX77620_FPS_SRC_MASK) >> MAX77620_FPS_SRC_SHIFT;
1415b1c2028SLaxman Dewangan pmic->active_fps_src[id] = ret;
1425b1c2028SLaxman Dewangan return 0;
1435b1c2028SLaxman Dewangan
1445b1c2028SLaxman Dewangan default:
1455b1c2028SLaxman Dewangan dev_err(pmic->dev, "Invalid FPS %d for regulator %d\n",
1465b1c2028SLaxman Dewangan fps_src, id);
1475b1c2028SLaxman Dewangan return -EINVAL;
1485b1c2028SLaxman Dewangan }
1495b1c2028SLaxman Dewangan
1505b1c2028SLaxman Dewangan ret = regmap_update_bits(pmic->rmap, rinfo->fps_addr,
1515b1c2028SLaxman Dewangan MAX77620_FPS_SRC_MASK,
1525b1c2028SLaxman Dewangan fps_src << MAX77620_FPS_SRC_SHIFT);
1535b1c2028SLaxman Dewangan if (ret < 0) {
1545b1c2028SLaxman Dewangan dev_err(pmic->dev, "Reg 0x%02x update failed %d\n",
1555b1c2028SLaxman Dewangan rinfo->fps_addr, ret);
1565b1c2028SLaxman Dewangan return ret;
1575b1c2028SLaxman Dewangan }
1585b1c2028SLaxman Dewangan pmic->active_fps_src[id] = fps_src;
1595b1c2028SLaxman Dewangan
1605b1c2028SLaxman Dewangan return 0;
1615b1c2028SLaxman Dewangan }
1625b1c2028SLaxman Dewangan
max77620_regulator_set_fps_slots(struct max77620_regulator * pmic,int id,bool is_suspend)1635b1c2028SLaxman Dewangan static int max77620_regulator_set_fps_slots(struct max77620_regulator *pmic,
1645b1c2028SLaxman Dewangan int id, bool is_suspend)
1655b1c2028SLaxman Dewangan {
1665b1c2028SLaxman Dewangan struct max77620_regulator_pdata *rpdata = &pmic->reg_pdata[id];
1675b1c2028SLaxman Dewangan struct max77620_regulator_info *rinfo = pmic->rinfo[id];
1685b1c2028SLaxman Dewangan unsigned int val = 0;
1695b1c2028SLaxman Dewangan unsigned int mask = 0;
1705b1c2028SLaxman Dewangan int pu = rpdata->active_fps_pu_slot;
1715b1c2028SLaxman Dewangan int pd = rpdata->active_fps_pd_slot;
1725b1c2028SLaxman Dewangan int ret = 0;
1735b1c2028SLaxman Dewangan
17491ff811fSVenkat Reddy Talla if (!rinfo)
17591ff811fSVenkat Reddy Talla return 0;
17691ff811fSVenkat Reddy Talla
1775b1c2028SLaxman Dewangan if (is_suspend) {
1785b1c2028SLaxman Dewangan pu = rpdata->suspend_fps_pu_slot;
1795b1c2028SLaxman Dewangan pd = rpdata->suspend_fps_pd_slot;
1805b1c2028SLaxman Dewangan }
1815b1c2028SLaxman Dewangan
1825b1c2028SLaxman Dewangan /* FPS power up period setting */
1835b1c2028SLaxman Dewangan if (pu >= 0) {
1845b1c2028SLaxman Dewangan val |= (pu << MAX77620_FPS_PU_PERIOD_SHIFT);
1855b1c2028SLaxman Dewangan mask |= MAX77620_FPS_PU_PERIOD_MASK;
1865b1c2028SLaxman Dewangan }
1875b1c2028SLaxman Dewangan
1885b1c2028SLaxman Dewangan /* FPS power down period setting */
1895b1c2028SLaxman Dewangan if (pd >= 0) {
1905b1c2028SLaxman Dewangan val |= (pd << MAX77620_FPS_PD_PERIOD_SHIFT);
1915b1c2028SLaxman Dewangan mask |= MAX77620_FPS_PD_PERIOD_MASK;
1925b1c2028SLaxman Dewangan }
1935b1c2028SLaxman Dewangan
1945b1c2028SLaxman Dewangan if (mask) {
1955b1c2028SLaxman Dewangan ret = regmap_update_bits(pmic->rmap, rinfo->fps_addr,
1965b1c2028SLaxman Dewangan mask, val);
1975b1c2028SLaxman Dewangan if (ret < 0) {
1985b1c2028SLaxman Dewangan dev_err(pmic->dev, "Reg 0x%02x update failed: %d\n",
1995b1c2028SLaxman Dewangan rinfo->fps_addr, ret);
2005b1c2028SLaxman Dewangan return ret;
2015b1c2028SLaxman Dewangan }
2025b1c2028SLaxman Dewangan }
2035b1c2028SLaxman Dewangan
2045b1c2028SLaxman Dewangan return ret;
2055b1c2028SLaxman Dewangan }
2065b1c2028SLaxman Dewangan
max77620_regulator_set_power_mode(struct max77620_regulator * pmic,int power_mode,int id)2075b1c2028SLaxman Dewangan static int max77620_regulator_set_power_mode(struct max77620_regulator *pmic,
2085b1c2028SLaxman Dewangan int power_mode, int id)
2095b1c2028SLaxman Dewangan {
2105b1c2028SLaxman Dewangan struct max77620_regulator_info *rinfo = pmic->rinfo[id];
2115b1c2028SLaxman Dewangan u8 mask = rinfo->power_mode_mask;
2125b1c2028SLaxman Dewangan u8 shift = rinfo->power_mode_shift;
2135b1c2028SLaxman Dewangan u8 addr;
2145b1c2028SLaxman Dewangan int ret;
2155b1c2028SLaxman Dewangan
2165b1c2028SLaxman Dewangan switch (rinfo->type) {
2175b1c2028SLaxman Dewangan case MAX77620_REGULATOR_TYPE_SD:
2185b1c2028SLaxman Dewangan addr = rinfo->cfg_addr;
2195b1c2028SLaxman Dewangan break;
2205b1c2028SLaxman Dewangan default:
2215b1c2028SLaxman Dewangan addr = rinfo->volt_addr;
2225b1c2028SLaxman Dewangan break;
2235b1c2028SLaxman Dewangan }
2245b1c2028SLaxman Dewangan
2255b1c2028SLaxman Dewangan ret = regmap_update_bits(pmic->rmap, addr, mask, power_mode << shift);
2265b1c2028SLaxman Dewangan if (ret < 0) {
2275b1c2028SLaxman Dewangan dev_err(pmic->dev, "Regulator %d mode set failed: %d\n",
2285b1c2028SLaxman Dewangan id, ret);
2295b1c2028SLaxman Dewangan return ret;
2305b1c2028SLaxman Dewangan }
2315b1c2028SLaxman Dewangan pmic->current_power_mode[id] = power_mode;
2325b1c2028SLaxman Dewangan
2335b1c2028SLaxman Dewangan return ret;
2345b1c2028SLaxman Dewangan }
2355b1c2028SLaxman Dewangan
max77620_regulator_get_power_mode(struct max77620_regulator * pmic,int id)2365b1c2028SLaxman Dewangan static int max77620_regulator_get_power_mode(struct max77620_regulator *pmic,
2375b1c2028SLaxman Dewangan int id)
2385b1c2028SLaxman Dewangan {
2395b1c2028SLaxman Dewangan struct max77620_regulator_info *rinfo = pmic->rinfo[id];
2405b1c2028SLaxman Dewangan unsigned int val, addr;
2415b1c2028SLaxman Dewangan u8 mask = rinfo->power_mode_mask;
2425b1c2028SLaxman Dewangan u8 shift = rinfo->power_mode_shift;
2435b1c2028SLaxman Dewangan int ret;
2445b1c2028SLaxman Dewangan
2455b1c2028SLaxman Dewangan switch (rinfo->type) {
2465b1c2028SLaxman Dewangan case MAX77620_REGULATOR_TYPE_SD:
2475b1c2028SLaxman Dewangan addr = rinfo->cfg_addr;
2485b1c2028SLaxman Dewangan break;
2495b1c2028SLaxman Dewangan default:
2505b1c2028SLaxman Dewangan addr = rinfo->volt_addr;
2515b1c2028SLaxman Dewangan break;
2525b1c2028SLaxman Dewangan }
2535b1c2028SLaxman Dewangan
2545b1c2028SLaxman Dewangan ret = regmap_read(pmic->rmap, addr, &val);
2555b1c2028SLaxman Dewangan if (ret < 0) {
2565b1c2028SLaxman Dewangan dev_err(pmic->dev, "Regulator %d: Reg 0x%02x read failed: %d\n",
2575b1c2028SLaxman Dewangan id, addr, ret);
2585b1c2028SLaxman Dewangan return ret;
2595b1c2028SLaxman Dewangan }
2605b1c2028SLaxman Dewangan
2615b1c2028SLaxman Dewangan return (val & mask) >> shift;
2625b1c2028SLaxman Dewangan }
2635b1c2028SLaxman Dewangan
max77620_read_slew_rate(struct max77620_regulator * pmic,int id)2645b1c2028SLaxman Dewangan static int max77620_read_slew_rate(struct max77620_regulator *pmic, int id)
2655b1c2028SLaxman Dewangan {
2665b1c2028SLaxman Dewangan struct max77620_regulator_info *rinfo = pmic->rinfo[id];
2675b1c2028SLaxman Dewangan unsigned int rval;
2685b1c2028SLaxman Dewangan int slew_rate;
2695b1c2028SLaxman Dewangan int ret;
2705b1c2028SLaxman Dewangan
2715b1c2028SLaxman Dewangan ret = regmap_read(pmic->rmap, rinfo->cfg_addr, &rval);
2725b1c2028SLaxman Dewangan if (ret < 0) {
2735b1c2028SLaxman Dewangan dev_err(pmic->dev, "Register 0x%02x read failed: %d\n",
2745b1c2028SLaxman Dewangan rinfo->cfg_addr, ret);
2755b1c2028SLaxman Dewangan return ret;
2765b1c2028SLaxman Dewangan }
2775b1c2028SLaxman Dewangan
278aad76f74SAxel Lin switch (rinfo->type) {
279aad76f74SAxel Lin case MAX77620_REGULATOR_TYPE_SD:
2805b1c2028SLaxman Dewangan slew_rate = (rval >> MAX77620_SD_SR_SHIFT) & 0x3;
2815b1c2028SLaxman Dewangan switch (slew_rate) {
2825b1c2028SLaxman Dewangan case 0:
2835b1c2028SLaxman Dewangan slew_rate = 13750;
2845b1c2028SLaxman Dewangan break;
2855b1c2028SLaxman Dewangan case 1:
2865b1c2028SLaxman Dewangan slew_rate = 27500;
2875b1c2028SLaxman Dewangan break;
2885b1c2028SLaxman Dewangan case 2:
2895b1c2028SLaxman Dewangan slew_rate = 55000;
2905b1c2028SLaxman Dewangan break;
2915b1c2028SLaxman Dewangan case 3:
2925b1c2028SLaxman Dewangan slew_rate = 100000;
2935b1c2028SLaxman Dewangan break;
2945b1c2028SLaxman Dewangan }
2955b1c2028SLaxman Dewangan rinfo->desc.ramp_delay = slew_rate;
2965b1c2028SLaxman Dewangan break;
2975b1c2028SLaxman Dewangan default:
2985b1c2028SLaxman Dewangan slew_rate = rval & 0x1;
2995b1c2028SLaxman Dewangan switch (slew_rate) {
3005b1c2028SLaxman Dewangan case 0:
3015b1c2028SLaxman Dewangan slew_rate = 100000;
3025b1c2028SLaxman Dewangan break;
3035b1c2028SLaxman Dewangan case 1:
3045b1c2028SLaxman Dewangan slew_rate = 5000;
3055b1c2028SLaxman Dewangan break;
3065b1c2028SLaxman Dewangan }
3075b1c2028SLaxman Dewangan rinfo->desc.ramp_delay = slew_rate;
3085b1c2028SLaxman Dewangan break;
3095b1c2028SLaxman Dewangan }
3105b1c2028SLaxman Dewangan
3115b1c2028SLaxman Dewangan return 0;
3125b1c2028SLaxman Dewangan }
3135b1c2028SLaxman Dewangan
max77620_set_slew_rate(struct max77620_regulator * pmic,int id,int slew_rate)3145aa43599SLaxman Dewangan static int max77620_set_slew_rate(struct max77620_regulator *pmic, int id,
3155aa43599SLaxman Dewangan int slew_rate)
3165aa43599SLaxman Dewangan {
3175aa43599SLaxman Dewangan struct max77620_regulator_info *rinfo = pmic->rinfo[id];
3185aa43599SLaxman Dewangan unsigned int val;
3195aa43599SLaxman Dewangan int ret;
3205aa43599SLaxman Dewangan u8 mask;
3215aa43599SLaxman Dewangan
3225aa43599SLaxman Dewangan if (rinfo->type == MAX77620_REGULATOR_TYPE_SD) {
3235aa43599SLaxman Dewangan if (slew_rate <= 13750)
3245aa43599SLaxman Dewangan val = 0;
3255aa43599SLaxman Dewangan else if (slew_rate <= 27500)
3265aa43599SLaxman Dewangan val = 1;
3275aa43599SLaxman Dewangan else if (slew_rate <= 55000)
3285aa43599SLaxman Dewangan val = 2;
3295aa43599SLaxman Dewangan else
3305aa43599SLaxman Dewangan val = 3;
3315aa43599SLaxman Dewangan val <<= MAX77620_SD_SR_SHIFT;
3325aa43599SLaxman Dewangan mask = MAX77620_SD_SR_MASK;
3335aa43599SLaxman Dewangan } else {
3345aa43599SLaxman Dewangan if (slew_rate <= 5000)
3355aa43599SLaxman Dewangan val = 1;
3365aa43599SLaxman Dewangan else
3375aa43599SLaxman Dewangan val = 0;
3385aa43599SLaxman Dewangan mask = MAX77620_LDO_SLEW_RATE_MASK;
3395aa43599SLaxman Dewangan }
3405aa43599SLaxman Dewangan
3415aa43599SLaxman Dewangan ret = regmap_update_bits(pmic->rmap, rinfo->cfg_addr, mask, val);
3425aa43599SLaxman Dewangan if (ret < 0) {
3435aa43599SLaxman Dewangan dev_err(pmic->dev, "Regulator %d slew rate set failed: %d\n",
3445aa43599SLaxman Dewangan id, ret);
3455aa43599SLaxman Dewangan return ret;
3465aa43599SLaxman Dewangan }
3475aa43599SLaxman Dewangan
3485aa43599SLaxman Dewangan return 0;
3495aa43599SLaxman Dewangan }
3505aa43599SLaxman Dewangan
max77620_config_power_ok(struct max77620_regulator * pmic,int id)351383d0fcaSVenkat Reddy Talla static int max77620_config_power_ok(struct max77620_regulator *pmic, int id)
352383d0fcaSVenkat Reddy Talla {
353383d0fcaSVenkat Reddy Talla struct max77620_regulator_pdata *rpdata = &pmic->reg_pdata[id];
354383d0fcaSVenkat Reddy Talla struct max77620_regulator_info *rinfo = pmic->rinfo[id];
355383d0fcaSVenkat Reddy Talla struct max77620_chip *chip = dev_get_drvdata(pmic->dev->parent);
356383d0fcaSVenkat Reddy Talla u8 val, mask;
357383d0fcaSVenkat Reddy Talla int ret;
358383d0fcaSVenkat Reddy Talla
359383d0fcaSVenkat Reddy Talla switch (chip->chip_id) {
360383d0fcaSVenkat Reddy Talla case MAX20024:
361383d0fcaSVenkat Reddy Talla if (rpdata->power_ok >= 0) {
362383d0fcaSVenkat Reddy Talla if (rinfo->type == MAX77620_REGULATOR_TYPE_SD)
363383d0fcaSVenkat Reddy Talla mask = MAX20024_SD_CFG1_MPOK_MASK;
364383d0fcaSVenkat Reddy Talla else
365383d0fcaSVenkat Reddy Talla mask = MAX20024_LDO_CFG2_MPOK_MASK;
366383d0fcaSVenkat Reddy Talla
367383d0fcaSVenkat Reddy Talla val = rpdata->power_ok ? mask : 0;
368383d0fcaSVenkat Reddy Talla
369383d0fcaSVenkat Reddy Talla ret = regmap_update_bits(pmic->rmap, rinfo->cfg_addr,
370383d0fcaSVenkat Reddy Talla mask, val);
371383d0fcaSVenkat Reddy Talla if (ret < 0) {
372383d0fcaSVenkat Reddy Talla dev_err(pmic->dev, "Reg 0x%02x update failed %d\n",
373383d0fcaSVenkat Reddy Talla rinfo->cfg_addr, ret);
374383d0fcaSVenkat Reddy Talla return ret;
375383d0fcaSVenkat Reddy Talla }
376383d0fcaSVenkat Reddy Talla }
377383d0fcaSVenkat Reddy Talla break;
378383d0fcaSVenkat Reddy Talla
379383d0fcaSVenkat Reddy Talla default:
380383d0fcaSVenkat Reddy Talla break;
381383d0fcaSVenkat Reddy Talla }
382383d0fcaSVenkat Reddy Talla
383383d0fcaSVenkat Reddy Talla return 0;
384383d0fcaSVenkat Reddy Talla }
385383d0fcaSVenkat Reddy Talla
max77620_init_pmic(struct max77620_regulator * pmic,int id)3865b1c2028SLaxman Dewangan static int max77620_init_pmic(struct max77620_regulator *pmic, int id)
3875b1c2028SLaxman Dewangan {
3885b1c2028SLaxman Dewangan struct max77620_regulator_pdata *rpdata = &pmic->reg_pdata[id];
3895b1c2028SLaxman Dewangan int ret;
3905b1c2028SLaxman Dewangan
391383d0fcaSVenkat Reddy Talla max77620_config_power_ok(pmic, id);
392383d0fcaSVenkat Reddy Talla
3935b1c2028SLaxman Dewangan /* Update power mode */
3945b1c2028SLaxman Dewangan ret = max77620_regulator_get_power_mode(pmic, id);
3955b1c2028SLaxman Dewangan if (ret < 0)
3965b1c2028SLaxman Dewangan return ret;
3975b1c2028SLaxman Dewangan
3985b1c2028SLaxman Dewangan pmic->current_power_mode[id] = ret;
3995b1c2028SLaxman Dewangan pmic->enable_power_mode[id] = MAX77620_POWER_MODE_NORMAL;
4005b1c2028SLaxman Dewangan
4015b1c2028SLaxman Dewangan if (rpdata->active_fps_src == MAX77620_FPS_SRC_DEF) {
4025b1c2028SLaxman Dewangan ret = max77620_regulator_get_fps_src(pmic, id);
4035b1c2028SLaxman Dewangan if (ret < 0)
4045b1c2028SLaxman Dewangan return ret;
4055b1c2028SLaxman Dewangan rpdata->active_fps_src = ret;
4065b1c2028SLaxman Dewangan }
4075b1c2028SLaxman Dewangan
4085b1c2028SLaxman Dewangan /* If rails are externally control of FPS then enable it always. */
4095b1c2028SLaxman Dewangan if (rpdata->active_fps_src == MAX77620_FPS_SRC_NONE) {
4105b1c2028SLaxman Dewangan ret = max77620_regulator_set_power_mode(pmic,
4115b1c2028SLaxman Dewangan pmic->enable_power_mode[id], id);
4125b1c2028SLaxman Dewangan if (ret < 0)
4135b1c2028SLaxman Dewangan return ret;
4145b1c2028SLaxman Dewangan } else {
4155b1c2028SLaxman Dewangan if (pmic->current_power_mode[id] !=
4165b1c2028SLaxman Dewangan pmic->enable_power_mode[id]) {
4175b1c2028SLaxman Dewangan ret = max77620_regulator_set_power_mode(pmic,
4185b1c2028SLaxman Dewangan pmic->enable_power_mode[id], id);
4195b1c2028SLaxman Dewangan if (ret < 0)
4205b1c2028SLaxman Dewangan return ret;
4215b1c2028SLaxman Dewangan }
4225b1c2028SLaxman Dewangan }
4235b1c2028SLaxman Dewangan
4245b1c2028SLaxman Dewangan ret = max77620_regulator_set_fps_src(pmic, rpdata->active_fps_src, id);
4255b1c2028SLaxman Dewangan if (ret < 0)
4265b1c2028SLaxman Dewangan return ret;
4275b1c2028SLaxman Dewangan
4285b1c2028SLaxman Dewangan ret = max77620_regulator_set_fps_slots(pmic, id, false);
4295b1c2028SLaxman Dewangan if (ret < 0)
4305b1c2028SLaxman Dewangan return ret;
4315b1c2028SLaxman Dewangan
4325aa43599SLaxman Dewangan if (rpdata->ramp_rate_setting) {
4335aa43599SLaxman Dewangan ret = max77620_set_slew_rate(pmic, id,
4345aa43599SLaxman Dewangan rpdata->ramp_rate_setting);
4355aa43599SLaxman Dewangan if (ret < 0)
4365aa43599SLaxman Dewangan return ret;
4375aa43599SLaxman Dewangan }
4385aa43599SLaxman Dewangan
4395b1c2028SLaxman Dewangan return 0;
4405b1c2028SLaxman Dewangan }
4415b1c2028SLaxman Dewangan
max77620_regulator_enable(struct regulator_dev * rdev)4425b1c2028SLaxman Dewangan static int max77620_regulator_enable(struct regulator_dev *rdev)
4435b1c2028SLaxman Dewangan {
4445b1c2028SLaxman Dewangan struct max77620_regulator *pmic = rdev_get_drvdata(rdev);
4455b1c2028SLaxman Dewangan int id = rdev_get_id(rdev);
4465b1c2028SLaxman Dewangan
4475b1c2028SLaxman Dewangan if (pmic->active_fps_src[id] != MAX77620_FPS_SRC_NONE)
4485b1c2028SLaxman Dewangan return 0;
4495b1c2028SLaxman Dewangan
4505b1c2028SLaxman Dewangan return max77620_regulator_set_power_mode(pmic,
4515b1c2028SLaxman Dewangan pmic->enable_power_mode[id], id);
4525b1c2028SLaxman Dewangan }
4535b1c2028SLaxman Dewangan
max77620_regulator_disable(struct regulator_dev * rdev)4545b1c2028SLaxman Dewangan static int max77620_regulator_disable(struct regulator_dev *rdev)
4555b1c2028SLaxman Dewangan {
4565b1c2028SLaxman Dewangan struct max77620_regulator *pmic = rdev_get_drvdata(rdev);
4575b1c2028SLaxman Dewangan int id = rdev_get_id(rdev);
4585b1c2028SLaxman Dewangan
4595b1c2028SLaxman Dewangan if (pmic->active_fps_src[id] != MAX77620_FPS_SRC_NONE)
4605b1c2028SLaxman Dewangan return 0;
4615b1c2028SLaxman Dewangan
4625b1c2028SLaxman Dewangan return max77620_regulator_set_power_mode(pmic,
4635b1c2028SLaxman Dewangan MAX77620_POWER_MODE_DISABLE, id);
4645b1c2028SLaxman Dewangan }
4655b1c2028SLaxman Dewangan
max77620_regulator_is_enabled(struct regulator_dev * rdev)4665b1c2028SLaxman Dewangan static int max77620_regulator_is_enabled(struct regulator_dev *rdev)
4675b1c2028SLaxman Dewangan {
4685b1c2028SLaxman Dewangan struct max77620_regulator *pmic = rdev_get_drvdata(rdev);
4695b1c2028SLaxman Dewangan int id = rdev_get_id(rdev);
470a3c7c029SColin Ian King int ret;
4715b1c2028SLaxman Dewangan
4725b1c2028SLaxman Dewangan if (pmic->active_fps_src[id] != MAX77620_FPS_SRC_NONE)
4735b1c2028SLaxman Dewangan return 1;
4745b1c2028SLaxman Dewangan
4755b1c2028SLaxman Dewangan ret = max77620_regulator_get_power_mode(pmic, id);
4765b1c2028SLaxman Dewangan if (ret < 0)
4775b1c2028SLaxman Dewangan return ret;
4785b1c2028SLaxman Dewangan
4795b1c2028SLaxman Dewangan if (ret != MAX77620_POWER_MODE_DISABLE)
4805b1c2028SLaxman Dewangan return 1;
4815b1c2028SLaxman Dewangan
4825b1c2028SLaxman Dewangan return 0;
4835b1c2028SLaxman Dewangan }
4845b1c2028SLaxman Dewangan
max77620_regulator_set_mode(struct regulator_dev * rdev,unsigned int mode)4855b1c2028SLaxman Dewangan static int max77620_regulator_set_mode(struct regulator_dev *rdev,
4865b1c2028SLaxman Dewangan unsigned int mode)
4875b1c2028SLaxman Dewangan {
4885b1c2028SLaxman Dewangan struct max77620_regulator *pmic = rdev_get_drvdata(rdev);
4895b1c2028SLaxman Dewangan int id = rdev_get_id(rdev);
4905b1c2028SLaxman Dewangan struct max77620_regulator_info *rinfo = pmic->rinfo[id];
4915b1c2028SLaxman Dewangan struct max77620_regulator_pdata *rpdata = &pmic->reg_pdata[id];
4925b1c2028SLaxman Dewangan bool fpwm = false;
4935b1c2028SLaxman Dewangan int power_mode;
4945b1c2028SLaxman Dewangan int ret;
4955b1c2028SLaxman Dewangan u8 val;
4965b1c2028SLaxman Dewangan
4975b1c2028SLaxman Dewangan switch (mode) {
4985b1c2028SLaxman Dewangan case REGULATOR_MODE_FAST:
4995b1c2028SLaxman Dewangan fpwm = true;
5005b1c2028SLaxman Dewangan power_mode = MAX77620_POWER_MODE_NORMAL;
5015b1c2028SLaxman Dewangan break;
5025b1c2028SLaxman Dewangan
5035b1c2028SLaxman Dewangan case REGULATOR_MODE_NORMAL:
5045b1c2028SLaxman Dewangan power_mode = MAX77620_POWER_MODE_NORMAL;
5055b1c2028SLaxman Dewangan break;
5065b1c2028SLaxman Dewangan
5075b1c2028SLaxman Dewangan case REGULATOR_MODE_IDLE:
5085b1c2028SLaxman Dewangan power_mode = MAX77620_POWER_MODE_LPM;
5095b1c2028SLaxman Dewangan break;
5105b1c2028SLaxman Dewangan
5115b1c2028SLaxman Dewangan default:
5125b1c2028SLaxman Dewangan dev_err(pmic->dev, "Regulator %d mode %d is invalid\n",
5135b1c2028SLaxman Dewangan id, mode);
5145b1c2028SLaxman Dewangan return -EINVAL;
5155b1c2028SLaxman Dewangan }
5165b1c2028SLaxman Dewangan
5175b1c2028SLaxman Dewangan if (rinfo->type != MAX77620_REGULATOR_TYPE_SD)
5185b1c2028SLaxman Dewangan goto skip_fpwm;
5195b1c2028SLaxman Dewangan
5205b1c2028SLaxman Dewangan val = (fpwm) ? MAX77620_SD_FPWM_MASK : 0;
5215b1c2028SLaxman Dewangan ret = regmap_update_bits(pmic->rmap, rinfo->cfg_addr,
5225b1c2028SLaxman Dewangan MAX77620_SD_FPWM_MASK, val);
5235b1c2028SLaxman Dewangan if (ret < 0) {
5245b1c2028SLaxman Dewangan dev_err(pmic->dev, "Reg 0x%02x update failed: %d\n",
5255b1c2028SLaxman Dewangan rinfo->cfg_addr, ret);
5265b1c2028SLaxman Dewangan return ret;
5275b1c2028SLaxman Dewangan }
5285b1c2028SLaxman Dewangan rpdata->current_mode = mode;
5295b1c2028SLaxman Dewangan
5305b1c2028SLaxman Dewangan skip_fpwm:
5315b1c2028SLaxman Dewangan ret = max77620_regulator_set_power_mode(pmic, power_mode, id);
5325b1c2028SLaxman Dewangan if (ret < 0)
5335b1c2028SLaxman Dewangan return ret;
5345b1c2028SLaxman Dewangan
5355b1c2028SLaxman Dewangan pmic->enable_power_mode[id] = power_mode;
5365b1c2028SLaxman Dewangan
5375b1c2028SLaxman Dewangan return 0;
5385b1c2028SLaxman Dewangan }
5395b1c2028SLaxman Dewangan
max77620_regulator_get_mode(struct regulator_dev * rdev)5405b1c2028SLaxman Dewangan static unsigned int max77620_regulator_get_mode(struct regulator_dev *rdev)
5415b1c2028SLaxman Dewangan {
5425b1c2028SLaxman Dewangan struct max77620_regulator *pmic = rdev_get_drvdata(rdev);
5435b1c2028SLaxman Dewangan int id = rdev_get_id(rdev);
5445b1c2028SLaxman Dewangan struct max77620_regulator_info *rinfo = pmic->rinfo[id];
5455b1c2028SLaxman Dewangan int fpwm = 0;
5465b1c2028SLaxman Dewangan int ret;
5475b1c2028SLaxman Dewangan int pm_mode, reg_mode;
5485b1c2028SLaxman Dewangan unsigned int val;
5495b1c2028SLaxman Dewangan
5505b1c2028SLaxman Dewangan ret = max77620_regulator_get_power_mode(pmic, id);
5515b1c2028SLaxman Dewangan if (ret < 0)
5525b1c2028SLaxman Dewangan return 0;
5535b1c2028SLaxman Dewangan
5545b1c2028SLaxman Dewangan pm_mode = ret;
5555b1c2028SLaxman Dewangan
5565b1c2028SLaxman Dewangan if (rinfo->type == MAX77620_REGULATOR_TYPE_SD) {
5575b1c2028SLaxman Dewangan ret = regmap_read(pmic->rmap, rinfo->cfg_addr, &val);
5585b1c2028SLaxman Dewangan if (ret < 0) {
5595b1c2028SLaxman Dewangan dev_err(pmic->dev, "Reg 0x%02x read failed: %d\n",
5605b1c2028SLaxman Dewangan rinfo->cfg_addr, ret);
5615b1c2028SLaxman Dewangan return ret;
5625b1c2028SLaxman Dewangan }
5635b1c2028SLaxman Dewangan fpwm = !!(val & MAX77620_SD_FPWM_MASK);
5645b1c2028SLaxman Dewangan }
5655b1c2028SLaxman Dewangan
5665b1c2028SLaxman Dewangan switch (pm_mode) {
5675b1c2028SLaxman Dewangan case MAX77620_POWER_MODE_NORMAL:
5685b1c2028SLaxman Dewangan case MAX77620_POWER_MODE_DISABLE:
5695b1c2028SLaxman Dewangan if (fpwm)
5705b1c2028SLaxman Dewangan reg_mode = REGULATOR_MODE_FAST;
5715b1c2028SLaxman Dewangan else
5725b1c2028SLaxman Dewangan reg_mode = REGULATOR_MODE_NORMAL;
5735b1c2028SLaxman Dewangan break;
5745b1c2028SLaxman Dewangan case MAX77620_POWER_MODE_LPM:
5755b1c2028SLaxman Dewangan case MAX77620_POWER_MODE_GLPM:
5765b1c2028SLaxman Dewangan reg_mode = REGULATOR_MODE_IDLE;
5775b1c2028SLaxman Dewangan break;
5785b1c2028SLaxman Dewangan default:
5795b1c2028SLaxman Dewangan return 0;
5805b1c2028SLaxman Dewangan }
5815b1c2028SLaxman Dewangan
5825b1c2028SLaxman Dewangan return reg_mode;
5835b1c2028SLaxman Dewangan }
5845b1c2028SLaxman Dewangan
max77620_regulator_set_ramp_delay(struct regulator_dev * rdev,int ramp_delay)5855b1c2028SLaxman Dewangan static int max77620_regulator_set_ramp_delay(struct regulator_dev *rdev,
5865b1c2028SLaxman Dewangan int ramp_delay)
5875b1c2028SLaxman Dewangan {
5885b1c2028SLaxman Dewangan struct max77620_regulator *pmic = rdev_get_drvdata(rdev);
5895b1c2028SLaxman Dewangan int id = rdev_get_id(rdev);
5905aa43599SLaxman Dewangan struct max77620_regulator_pdata *rpdata = &pmic->reg_pdata[id];
5915b1c2028SLaxman Dewangan
5925aa43599SLaxman Dewangan /* Device specific ramp rate setting tells that platform has
5935aa43599SLaxman Dewangan * different ramp rate from advertised value. In this case,
5945aa43599SLaxman Dewangan * do not configure anything and just return success.
5955aa43599SLaxman Dewangan */
5965aa43599SLaxman Dewangan if (rpdata->ramp_rate_setting)
5975aa43599SLaxman Dewangan return 0;
5985b1c2028SLaxman Dewangan
5995aa43599SLaxman Dewangan return max77620_set_slew_rate(pmic, id, ramp_delay);
6005b1c2028SLaxman Dewangan }
6015b1c2028SLaxman Dewangan
max77620_of_parse_cb(struct device_node * np,const struct regulator_desc * desc,struct regulator_config * config)6025b1c2028SLaxman Dewangan static int max77620_of_parse_cb(struct device_node *np,
6035b1c2028SLaxman Dewangan const struct regulator_desc *desc,
6045b1c2028SLaxman Dewangan struct regulator_config *config)
6055b1c2028SLaxman Dewangan {
6065b1c2028SLaxman Dewangan struct max77620_regulator *pmic = config->driver_data;
6075b1c2028SLaxman Dewangan struct max77620_regulator_pdata *rpdata = &pmic->reg_pdata[desc->id];
6085b1c2028SLaxman Dewangan u32 pval;
6095b1c2028SLaxman Dewangan int ret;
6105b1c2028SLaxman Dewangan
6115b1c2028SLaxman Dewangan ret = of_property_read_u32(np, "maxim,active-fps-source", &pval);
6125b1c2028SLaxman Dewangan rpdata->active_fps_src = (!ret) ? pval : MAX77620_FPS_SRC_DEF;
6135b1c2028SLaxman Dewangan
6145b1c2028SLaxman Dewangan ret = of_property_read_u32(np, "maxim,active-fps-power-up-slot", &pval);
6155b1c2028SLaxman Dewangan rpdata->active_fps_pu_slot = (!ret) ? pval : -1;
6165b1c2028SLaxman Dewangan
6175b1c2028SLaxman Dewangan ret = of_property_read_u32(
6185b1c2028SLaxman Dewangan np, "maxim,active-fps-power-down-slot", &pval);
6195b1c2028SLaxman Dewangan rpdata->active_fps_pd_slot = (!ret) ? pval : -1;
6205b1c2028SLaxman Dewangan
6215b1c2028SLaxman Dewangan ret = of_property_read_u32(np, "maxim,suspend-fps-source", &pval);
6225b1c2028SLaxman Dewangan rpdata->suspend_fps_src = (!ret) ? pval : -1;
6235b1c2028SLaxman Dewangan
6245b1c2028SLaxman Dewangan ret = of_property_read_u32(
6255b1c2028SLaxman Dewangan np, "maxim,suspend-fps-power-up-slot", &pval);
6265b1c2028SLaxman Dewangan rpdata->suspend_fps_pu_slot = (!ret) ? pval : -1;
6275b1c2028SLaxman Dewangan
6285b1c2028SLaxman Dewangan ret = of_property_read_u32(
6295b1c2028SLaxman Dewangan np, "maxim,suspend-fps-power-down-slot", &pval);
6305b1c2028SLaxman Dewangan rpdata->suspend_fps_pd_slot = (!ret) ? pval : -1;
6315b1c2028SLaxman Dewangan
632383d0fcaSVenkat Reddy Talla ret = of_property_read_u32(np, "maxim,power-ok-control", &pval);
633383d0fcaSVenkat Reddy Talla if (!ret)
634383d0fcaSVenkat Reddy Talla rpdata->power_ok = pval;
635383d0fcaSVenkat Reddy Talla else
636383d0fcaSVenkat Reddy Talla rpdata->power_ok = -1;
637383d0fcaSVenkat Reddy Talla
6385aa43599SLaxman Dewangan ret = of_property_read_u32(np, "maxim,ramp-rate-setting", &pval);
6395aa43599SLaxman Dewangan rpdata->ramp_rate_setting = (!ret) ? pval : 0;
6405aa43599SLaxman Dewangan
6415b1c2028SLaxman Dewangan return max77620_init_pmic(pmic, desc->id);
6425b1c2028SLaxman Dewangan }
6435b1c2028SLaxman Dewangan
644634dc7abSBhumika Goyal static const struct regulator_ops max77620_regulator_ops = {
6455b1c2028SLaxman Dewangan .is_enabled = max77620_regulator_is_enabled,
6465b1c2028SLaxman Dewangan .enable = max77620_regulator_enable,
6475b1c2028SLaxman Dewangan .disable = max77620_regulator_disable,
6485b1c2028SLaxman Dewangan .list_voltage = regulator_list_voltage_linear,
6495b1c2028SLaxman Dewangan .map_voltage = regulator_map_voltage_linear,
6505b1c2028SLaxman Dewangan .get_voltage_sel = regulator_get_voltage_sel_regmap,
6515b1c2028SLaxman Dewangan .set_voltage_sel = regulator_set_voltage_sel_regmap,
6525b1c2028SLaxman Dewangan .set_mode = max77620_regulator_set_mode,
6535b1c2028SLaxman Dewangan .get_mode = max77620_regulator_get_mode,
6545b1c2028SLaxman Dewangan .set_ramp_delay = max77620_regulator_set_ramp_delay,
6555b1c2028SLaxman Dewangan .set_voltage_time_sel = regulator_set_voltage_time_sel,
65651817f46SLaxman Dewangan .set_active_discharge = regulator_set_active_discharge_regmap,
6575b1c2028SLaxman Dewangan };
6585b1c2028SLaxman Dewangan
6595b1c2028SLaxman Dewangan #define MAX77620_SD_CNF2_ROVS_EN_NONE 0
6605b1c2028SLaxman Dewangan #define RAIL_SD(_id, _name, _sname, _volt_mask, _min_uV, _max_uV, \
6615b1c2028SLaxman Dewangan _step_uV, _rs_add, _rs_mask) \
6625b1c2028SLaxman Dewangan [MAX77620_REGULATOR_ID_##_id] = { \
6635b1c2028SLaxman Dewangan .type = MAX77620_REGULATOR_TYPE_SD, \
6645b1c2028SLaxman Dewangan .volt_addr = MAX77620_REG_##_id, \
6655b1c2028SLaxman Dewangan .cfg_addr = MAX77620_REG_##_id##_CFG, \
6665b1c2028SLaxman Dewangan .fps_addr = MAX77620_REG_FPS_##_id, \
6675b1c2028SLaxman Dewangan .remote_sense_addr = _rs_add, \
6685b1c2028SLaxman Dewangan .remote_sense_mask = MAX77620_SD_CNF2_ROVS_EN_##_rs_mask, \
6695b1c2028SLaxman Dewangan .power_mode_mask = MAX77620_SD_POWER_MODE_MASK, \
6705b1c2028SLaxman Dewangan .power_mode_shift = MAX77620_SD_POWER_MODE_SHIFT, \
6715b1c2028SLaxman Dewangan .desc = { \
6725b1c2028SLaxman Dewangan .name = max77620_rails(_name), \
6735b1c2028SLaxman Dewangan .of_match = of_match_ptr(#_name), \
6745b1c2028SLaxman Dewangan .regulators_node = of_match_ptr("regulators"), \
6755b1c2028SLaxman Dewangan .of_parse_cb = max77620_of_parse_cb, \
6765b1c2028SLaxman Dewangan .supply_name = _sname, \
6775b1c2028SLaxman Dewangan .id = MAX77620_REGULATOR_ID_##_id, \
6785b1c2028SLaxman Dewangan .ops = &max77620_regulator_ops, \
6795b1c2028SLaxman Dewangan .n_voltages = ((_max_uV - _min_uV) / _step_uV) + 1, \
6805b1c2028SLaxman Dewangan .min_uV = _min_uV, \
6815b1c2028SLaxman Dewangan .uV_step = _step_uV, \
6825b1c2028SLaxman Dewangan .enable_time = 500, \
6835b1c2028SLaxman Dewangan .vsel_mask = MAX77620_##_volt_mask##_VOLT_MASK, \
6845b1c2028SLaxman Dewangan .vsel_reg = MAX77620_REG_##_id, \
68551817f46SLaxman Dewangan .active_discharge_off = 0, \
68651817f46SLaxman Dewangan .active_discharge_on = MAX77620_SD_CFG1_ADE_ENABLE, \
68751817f46SLaxman Dewangan .active_discharge_mask = MAX77620_SD_CFG1_ADE_MASK, \
68851817f46SLaxman Dewangan .active_discharge_reg = MAX77620_REG_##_id##_CFG, \
6895b1c2028SLaxman Dewangan .type = REGULATOR_VOLTAGE, \
69096173b8cSAxel Lin .owner = THIS_MODULE, \
6915b1c2028SLaxman Dewangan }, \
6925b1c2028SLaxman Dewangan }
6935b1c2028SLaxman Dewangan
6945b1c2028SLaxman Dewangan #define RAIL_LDO(_id, _name, _sname, _type, _min_uV, _max_uV, _step_uV) \
6955b1c2028SLaxman Dewangan [MAX77620_REGULATOR_ID_##_id] = { \
6965b1c2028SLaxman Dewangan .type = MAX77620_REGULATOR_TYPE_LDO_##_type, \
6975b1c2028SLaxman Dewangan .volt_addr = MAX77620_REG_##_id##_CFG, \
6985b1c2028SLaxman Dewangan .cfg_addr = MAX77620_REG_##_id##_CFG2, \
6995b1c2028SLaxman Dewangan .fps_addr = MAX77620_REG_FPS_##_id, \
7005b1c2028SLaxman Dewangan .remote_sense_addr = 0xFF, \
7015b1c2028SLaxman Dewangan .power_mode_mask = MAX77620_LDO_POWER_MODE_MASK, \
7025b1c2028SLaxman Dewangan .power_mode_shift = MAX77620_LDO_POWER_MODE_SHIFT, \
7035b1c2028SLaxman Dewangan .desc = { \
7045b1c2028SLaxman Dewangan .name = max77620_rails(_name), \
7055b1c2028SLaxman Dewangan .of_match = of_match_ptr(#_name), \
7065b1c2028SLaxman Dewangan .regulators_node = of_match_ptr("regulators"), \
7075b1c2028SLaxman Dewangan .of_parse_cb = max77620_of_parse_cb, \
7085b1c2028SLaxman Dewangan .supply_name = _sname, \
7095b1c2028SLaxman Dewangan .id = MAX77620_REGULATOR_ID_##_id, \
7105b1c2028SLaxman Dewangan .ops = &max77620_regulator_ops, \
7115b1c2028SLaxman Dewangan .n_voltages = ((_max_uV - _min_uV) / _step_uV) + 1, \
7125b1c2028SLaxman Dewangan .min_uV = _min_uV, \
7135b1c2028SLaxman Dewangan .uV_step = _step_uV, \
7145b1c2028SLaxman Dewangan .enable_time = 500, \
7155b1c2028SLaxman Dewangan .vsel_mask = MAX77620_LDO_VOLT_MASK, \
7165b1c2028SLaxman Dewangan .vsel_reg = MAX77620_REG_##_id##_CFG, \
71751817f46SLaxman Dewangan .active_discharge_off = 0, \
71851817f46SLaxman Dewangan .active_discharge_on = MAX77620_LDO_CFG2_ADE_ENABLE, \
71951817f46SLaxman Dewangan .active_discharge_mask = MAX77620_LDO_CFG2_ADE_MASK, \
72051817f46SLaxman Dewangan .active_discharge_reg = MAX77620_REG_##_id##_CFG2, \
7215b1c2028SLaxman Dewangan .type = REGULATOR_VOLTAGE, \
72296173b8cSAxel Lin .owner = THIS_MODULE, \
7235b1c2028SLaxman Dewangan }, \
7245b1c2028SLaxman Dewangan }
7255b1c2028SLaxman Dewangan
7265b1c2028SLaxman Dewangan static struct max77620_regulator_info max77620_regs_info[MAX77620_NUM_REGS] = {
7275b1c2028SLaxman Dewangan RAIL_SD(SD0, sd0, "in-sd0", SD0, 600000, 1400000, 12500, 0x22, SD0),
7285b1c2028SLaxman Dewangan RAIL_SD(SD1, sd1, "in-sd1", SD1, 600000, 1550000, 12500, 0x22, SD1),
7295b1c2028SLaxman Dewangan RAIL_SD(SD2, sd2, "in-sd2", SDX, 600000, 3787500, 12500, 0xFF, NONE),
7305b1c2028SLaxman Dewangan RAIL_SD(SD3, sd3, "in-sd3", SDX, 600000, 3787500, 12500, 0xFF, NONE),
7315b1c2028SLaxman Dewangan
7325b1c2028SLaxman Dewangan RAIL_LDO(LDO0, ldo0, "in-ldo0-1", N, 800000, 2375000, 25000),
7335b1c2028SLaxman Dewangan RAIL_LDO(LDO1, ldo1, "in-ldo0-1", N, 800000, 2375000, 25000),
7345b1c2028SLaxman Dewangan RAIL_LDO(LDO2, ldo2, "in-ldo2", P, 800000, 3950000, 50000),
7355b1c2028SLaxman Dewangan RAIL_LDO(LDO3, ldo3, "in-ldo3-5", P, 800000, 3950000, 50000),
7365b1c2028SLaxman Dewangan RAIL_LDO(LDO4, ldo4, "in-ldo4-6", P, 800000, 1587500, 12500),
7375b1c2028SLaxman Dewangan RAIL_LDO(LDO5, ldo5, "in-ldo3-5", P, 800000, 3950000, 50000),
7385b1c2028SLaxman Dewangan RAIL_LDO(LDO6, ldo6, "in-ldo4-6", P, 800000, 3950000, 50000),
7395b1c2028SLaxman Dewangan RAIL_LDO(LDO7, ldo7, "in-ldo7-8", N, 800000, 3950000, 50000),
7405b1c2028SLaxman Dewangan RAIL_LDO(LDO8, ldo8, "in-ldo7-8", N, 800000, 3950000, 50000),
7415b1c2028SLaxman Dewangan };
7425b1c2028SLaxman Dewangan
7435b1c2028SLaxman Dewangan static struct max77620_regulator_info max20024_regs_info[MAX77620_NUM_REGS] = {
7445b1c2028SLaxman Dewangan RAIL_SD(SD0, sd0, "in-sd0", SD0, 800000, 1587500, 12500, 0x22, SD0),
7455b1c2028SLaxman Dewangan RAIL_SD(SD1, sd1, "in-sd1", SD1, 600000, 3387500, 12500, 0x22, SD1),
7465b1c2028SLaxman Dewangan RAIL_SD(SD2, sd2, "in-sd2", SDX, 600000, 3787500, 12500, 0xFF, NONE),
7475b1c2028SLaxman Dewangan RAIL_SD(SD3, sd3, "in-sd3", SDX, 600000, 3787500, 12500, 0xFF, NONE),
7485b1c2028SLaxman Dewangan RAIL_SD(SD4, sd4, "in-sd4", SDX, 600000, 3787500, 12500, 0xFF, NONE),
7495b1c2028SLaxman Dewangan
7505b1c2028SLaxman Dewangan RAIL_LDO(LDO0, ldo0, "in-ldo0-1", N, 800000, 2375000, 25000),
7515b1c2028SLaxman Dewangan RAIL_LDO(LDO1, ldo1, "in-ldo0-1", N, 800000, 2375000, 25000),
7525b1c2028SLaxman Dewangan RAIL_LDO(LDO2, ldo2, "in-ldo2", P, 800000, 3950000, 50000),
7535b1c2028SLaxman Dewangan RAIL_LDO(LDO3, ldo3, "in-ldo3-5", P, 800000, 3950000, 50000),
7545b1c2028SLaxman Dewangan RAIL_LDO(LDO4, ldo4, "in-ldo4-6", P, 800000, 1587500, 12500),
7555b1c2028SLaxman Dewangan RAIL_LDO(LDO5, ldo5, "in-ldo3-5", P, 800000, 3950000, 50000),
7565b1c2028SLaxman Dewangan RAIL_LDO(LDO6, ldo6, "in-ldo4-6", P, 800000, 3950000, 50000),
7575b1c2028SLaxman Dewangan RAIL_LDO(LDO7, ldo7, "in-ldo7-8", N, 800000, 3950000, 50000),
7585b1c2028SLaxman Dewangan RAIL_LDO(LDO8, ldo8, "in-ldo7-8", N, 800000, 3950000, 50000),
7595b1c2028SLaxman Dewangan };
7605b1c2028SLaxman Dewangan
761cbafbd1dSDmitry Osipenko static struct max77620_regulator_info max77663_regs_info[MAX77620_NUM_REGS] = {
762cbafbd1dSDmitry Osipenko RAIL_SD(SD0, sd0, "in-sd0", SD0, 600000, 3387500, 12500, 0xFF, NONE),
763cbafbd1dSDmitry Osipenko RAIL_SD(SD1, sd1, "in-sd1", SD1, 800000, 1587500, 12500, 0xFF, NONE),
764cbafbd1dSDmitry Osipenko RAIL_SD(SD2, sd2, "in-sd2", SDX, 600000, 3787500, 12500, 0xFF, NONE),
765cbafbd1dSDmitry Osipenko RAIL_SD(SD3, sd3, "in-sd3", SDX, 600000, 3787500, 12500, 0xFF, NONE),
766cbafbd1dSDmitry Osipenko RAIL_SD(SD4, sd4, "in-sd4", SDX, 600000, 3787500, 12500, 0xFF, NONE),
767cbafbd1dSDmitry Osipenko
768cbafbd1dSDmitry Osipenko RAIL_LDO(LDO0, ldo0, "in-ldo0-1", N, 800000, 2375000, 25000),
769cbafbd1dSDmitry Osipenko RAIL_LDO(LDO1, ldo1, "in-ldo0-1", N, 800000, 2375000, 25000),
770cbafbd1dSDmitry Osipenko RAIL_LDO(LDO2, ldo2, "in-ldo2", P, 800000, 3950000, 50000),
771cbafbd1dSDmitry Osipenko RAIL_LDO(LDO3, ldo3, "in-ldo3-5", P, 800000, 3950000, 50000),
772cbafbd1dSDmitry Osipenko RAIL_LDO(LDO4, ldo4, "in-ldo4-6", P, 800000, 1587500, 12500),
773cbafbd1dSDmitry Osipenko RAIL_LDO(LDO5, ldo5, "in-ldo3-5", P, 800000, 3950000, 50000),
774cbafbd1dSDmitry Osipenko RAIL_LDO(LDO6, ldo6, "in-ldo4-6", P, 800000, 3950000, 50000),
775cbafbd1dSDmitry Osipenko RAIL_LDO(LDO7, ldo7, "in-ldo7-8", N, 800000, 3950000, 50000),
776cbafbd1dSDmitry Osipenko RAIL_LDO(LDO8, ldo8, "in-ldo7-8", N, 800000, 3950000, 50000),
777cbafbd1dSDmitry Osipenko };
778cbafbd1dSDmitry Osipenko
max77620_regulator_probe(struct platform_device * pdev)7795b1c2028SLaxman Dewangan static int max77620_regulator_probe(struct platform_device *pdev)
7805b1c2028SLaxman Dewangan {
7815b1c2028SLaxman Dewangan struct max77620_chip *max77620_chip = dev_get_drvdata(pdev->dev.parent);
7825b1c2028SLaxman Dewangan struct max77620_regulator_info *rinfo;
7835b1c2028SLaxman Dewangan struct device *dev = &pdev->dev;
7845b1c2028SLaxman Dewangan struct regulator_config config = { };
7855b1c2028SLaxman Dewangan struct max77620_regulator *pmic;
7865b1c2028SLaxman Dewangan int ret = 0;
7875b1c2028SLaxman Dewangan int id;
7885b1c2028SLaxman Dewangan
7895b1c2028SLaxman Dewangan pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL);
7905b1c2028SLaxman Dewangan if (!pmic)
7915b1c2028SLaxman Dewangan return -ENOMEM;
7925b1c2028SLaxman Dewangan
7935b1c2028SLaxman Dewangan platform_set_drvdata(pdev, pmic);
7945b1c2028SLaxman Dewangan pmic->dev = dev;
7955b1c2028SLaxman Dewangan pmic->rmap = max77620_chip->rmap;
7965b1c2028SLaxman Dewangan if (!dev->of_node)
7975b1c2028SLaxman Dewangan dev->of_node = pdev->dev.parent->of_node;
7985b1c2028SLaxman Dewangan
7995b1c2028SLaxman Dewangan switch (max77620_chip->chip_id) {
8005b1c2028SLaxman Dewangan case MAX77620:
8015b1c2028SLaxman Dewangan rinfo = max77620_regs_info;
8025b1c2028SLaxman Dewangan break;
803cbafbd1dSDmitry Osipenko case MAX20024:
8045b1c2028SLaxman Dewangan rinfo = max20024_regs_info;
8055b1c2028SLaxman Dewangan break;
806cbafbd1dSDmitry Osipenko case MAX77663:
807cbafbd1dSDmitry Osipenko rinfo = max77663_regs_info;
808cbafbd1dSDmitry Osipenko break;
809cbafbd1dSDmitry Osipenko default:
810cbafbd1dSDmitry Osipenko return -EINVAL;
8115b1c2028SLaxman Dewangan }
8125b1c2028SLaxman Dewangan
8135b1c2028SLaxman Dewangan config.regmap = pmic->rmap;
8145b1c2028SLaxman Dewangan config.dev = dev;
8155b1c2028SLaxman Dewangan config.driver_data = pmic;
8165b1c2028SLaxman Dewangan
8176f55c5ddSDmitry Osipenko /*
8186f55c5ddSDmitry Osipenko * Set of_node_reuse flag to prevent driver core from attempting to
8196f55c5ddSDmitry Osipenko * claim any pinmux resources already claimed by the parent device.
8206f55c5ddSDmitry Osipenko * Otherwise PMIC driver will fail to re-probe.
8216f55c5ddSDmitry Osipenko */
8226f55c5ddSDmitry Osipenko device_set_of_node_from_dev(&pdev->dev, pdev->dev.parent);
8236f55c5ddSDmitry Osipenko
8245b1c2028SLaxman Dewangan for (id = 0; id < MAX77620_NUM_REGS; id++) {
8255b1c2028SLaxman Dewangan struct regulator_dev *rdev;
8265b1c2028SLaxman Dewangan struct regulator_desc *rdesc;
8275b1c2028SLaxman Dewangan
8285b1c2028SLaxman Dewangan if ((max77620_chip->chip_id == MAX77620) &&
8295b1c2028SLaxman Dewangan (id == MAX77620_REGULATOR_ID_SD4))
8305b1c2028SLaxman Dewangan continue;
8315b1c2028SLaxman Dewangan
8325b1c2028SLaxman Dewangan rdesc = &rinfo[id].desc;
833734008e7SAxel Lin pmic->rinfo[id] = &rinfo[id];
8345b1c2028SLaxman Dewangan pmic->enable_power_mode[id] = MAX77620_POWER_MODE_NORMAL;
8350ab66b3cSMark Zhang pmic->reg_pdata[id].active_fps_src = -1;
8360ab66b3cSMark Zhang pmic->reg_pdata[id].active_fps_pd_slot = -1;
8370ab66b3cSMark Zhang pmic->reg_pdata[id].active_fps_pu_slot = -1;
8380ab66b3cSMark Zhang pmic->reg_pdata[id].suspend_fps_src = -1;
8390ab66b3cSMark Zhang pmic->reg_pdata[id].suspend_fps_pd_slot = -1;
8400ab66b3cSMark Zhang pmic->reg_pdata[id].suspend_fps_pu_slot = -1;
8410ab66b3cSMark Zhang pmic->reg_pdata[id].power_ok = -1;
8420ab66b3cSMark Zhang pmic->reg_pdata[id].ramp_rate_setting = -1;
8435b1c2028SLaxman Dewangan
8445b1c2028SLaxman Dewangan ret = max77620_read_slew_rate(pmic, id);
8455b1c2028SLaxman Dewangan if (ret < 0)
8465b1c2028SLaxman Dewangan return ret;
8475b1c2028SLaxman Dewangan
8485b1c2028SLaxman Dewangan rdev = devm_regulator_register(dev, rdesc, &config);
84962499a94SDmitry Osipenko if (IS_ERR(rdev))
85062499a94SDmitry Osipenko return dev_err_probe(dev, PTR_ERR(rdev),
85162499a94SDmitry Osipenko "Regulator registration %s failed\n",
85262499a94SDmitry Osipenko rdesc->name);
8535b1c2028SLaxman Dewangan }
8545b1c2028SLaxman Dewangan
8555b1c2028SLaxman Dewangan return 0;
8565b1c2028SLaxman Dewangan }
8575b1c2028SLaxman Dewangan
8585b1c2028SLaxman Dewangan #ifdef CONFIG_PM_SLEEP
max77620_regulator_suspend(struct device * dev)8595b1c2028SLaxman Dewangan static int max77620_regulator_suspend(struct device *dev)
8605b1c2028SLaxman Dewangan {
8615b1c2028SLaxman Dewangan struct max77620_regulator *pmic = dev_get_drvdata(dev);
8625b1c2028SLaxman Dewangan struct max77620_regulator_pdata *reg_pdata;
8635b1c2028SLaxman Dewangan int id;
8645b1c2028SLaxman Dewangan
8655b1c2028SLaxman Dewangan for (id = 0; id < MAX77620_NUM_REGS; id++) {
8665b1c2028SLaxman Dewangan reg_pdata = &pmic->reg_pdata[id];
8675b1c2028SLaxman Dewangan
8685b1c2028SLaxman Dewangan max77620_regulator_set_fps_slots(pmic, id, true);
8695b1c2028SLaxman Dewangan if (reg_pdata->suspend_fps_src < 0)
8705b1c2028SLaxman Dewangan continue;
8715b1c2028SLaxman Dewangan
8725b1c2028SLaxman Dewangan max77620_regulator_set_fps_src(pmic, reg_pdata->suspend_fps_src,
8735b1c2028SLaxman Dewangan id);
8745b1c2028SLaxman Dewangan }
8755b1c2028SLaxman Dewangan
8765b1c2028SLaxman Dewangan return 0;
8775b1c2028SLaxman Dewangan }
8785b1c2028SLaxman Dewangan
max77620_regulator_resume(struct device * dev)8795b1c2028SLaxman Dewangan static int max77620_regulator_resume(struct device *dev)
8805b1c2028SLaxman Dewangan {
8815b1c2028SLaxman Dewangan struct max77620_regulator *pmic = dev_get_drvdata(dev);
8825b1c2028SLaxman Dewangan struct max77620_regulator_pdata *reg_pdata;
8835b1c2028SLaxman Dewangan int id;
8845b1c2028SLaxman Dewangan
8855b1c2028SLaxman Dewangan for (id = 0; id < MAX77620_NUM_REGS; id++) {
8865b1c2028SLaxman Dewangan reg_pdata = &pmic->reg_pdata[id];
8875b1c2028SLaxman Dewangan
888383d0fcaSVenkat Reddy Talla max77620_config_power_ok(pmic, id);
889383d0fcaSVenkat Reddy Talla
8905b1c2028SLaxman Dewangan max77620_regulator_set_fps_slots(pmic, id, false);
8915b1c2028SLaxman Dewangan if (reg_pdata->active_fps_src < 0)
8925b1c2028SLaxman Dewangan continue;
8935b1c2028SLaxman Dewangan max77620_regulator_set_fps_src(pmic, reg_pdata->active_fps_src,
8945b1c2028SLaxman Dewangan id);
8955b1c2028SLaxman Dewangan }
8965b1c2028SLaxman Dewangan
8975b1c2028SLaxman Dewangan return 0;
8985b1c2028SLaxman Dewangan }
8995b1c2028SLaxman Dewangan #endif
9005b1c2028SLaxman Dewangan
9015b1c2028SLaxman Dewangan static const struct dev_pm_ops max77620_regulator_pm_ops = {
9025b1c2028SLaxman Dewangan SET_SYSTEM_SLEEP_PM_OPS(max77620_regulator_suspend,
9035b1c2028SLaxman Dewangan max77620_regulator_resume)
9045b1c2028SLaxman Dewangan };
9055b1c2028SLaxman Dewangan
9065b1c2028SLaxman Dewangan static const struct platform_device_id max77620_regulator_devtype[] = {
9075b1c2028SLaxman Dewangan { .name = "max77620-pmic", },
9085b1c2028SLaxman Dewangan { .name = "max20024-pmic", },
909cbafbd1dSDmitry Osipenko { .name = "max77663-pmic", },
9105b1c2028SLaxman Dewangan {},
9115b1c2028SLaxman Dewangan };
9125b1c2028SLaxman Dewangan MODULE_DEVICE_TABLE(platform, max77620_regulator_devtype);
9135b1c2028SLaxman Dewangan
9145b1c2028SLaxman Dewangan static struct platform_driver max77620_regulator_driver = {
9155b1c2028SLaxman Dewangan .probe = max77620_regulator_probe,
9165b1c2028SLaxman Dewangan .id_table = max77620_regulator_devtype,
9175b1c2028SLaxman Dewangan .driver = {
9185b1c2028SLaxman Dewangan .name = "max77620-pmic",
919*259b93b2SDouglas Anderson .probe_type = PROBE_PREFER_ASYNCHRONOUS,
9205b1c2028SLaxman Dewangan .pm = &max77620_regulator_pm_ops,
9215b1c2028SLaxman Dewangan },
9225b1c2028SLaxman Dewangan };
9235b1c2028SLaxman Dewangan
9245b1c2028SLaxman Dewangan module_platform_driver(max77620_regulator_driver);
9255b1c2028SLaxman Dewangan
9265b1c2028SLaxman Dewangan MODULE_DESCRIPTION("MAX77620/MAX20024 regulator driver");
9275b1c2028SLaxman Dewangan MODULE_AUTHOR("Mallikarjun Kasoju <mkasoju@nvidia.com>");
9285b1c2028SLaxman Dewangan MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
9295b1c2028SLaxman Dewangan MODULE_LICENSE("GPL v2");
930