16219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan/* 26219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * tps62360.c -- TI tps62360 36219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * 4d1cf4f65e1eb17bc8768d822755780588e42cf37Axel Lin * Driver for processor core supply tps62360, tps62361B, tps62362 and tps62363. 56219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * 66219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * Copyright (c) 2012, NVIDIA Corporation. 76219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * 86219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * Author: Laxman Dewangan <ldewangan@nvidia.com> 96219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * 106219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * This program is free software; you can redistribute it and/or 116219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * modify it under the terms of the GNU General Public License as 126219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * published by the Free Software Foundation version 2. 136219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * 146219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind, 156219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * whether express or implied; without even the implied warranty of 166219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 176219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * General Public License for more details. 186219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * 196219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * You should have received a copy of the GNU General Public License 206219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * along with this program; if not, write to the Free Software 216219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 226219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * 02111-1307, USA 236219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan */ 246219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 256219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan#include <linux/kernel.h> 266219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan#include <linux/module.h> 276219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan#include <linux/init.h> 286219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan#include <linux/err.h> 29684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan#include <linux/of.h> 30684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan#include <linux/of_device.h> 31684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan#include <linux/of_gpio.h> 32684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan#include <linux/regulator/of_regulator.h> 336219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan#include <linux/platform_device.h> 346219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan#include <linux/regulator/driver.h> 356219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan#include <linux/regulator/machine.h> 366219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan#include <linux/regulator/tps62360.h> 376219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan#include <linux/gpio.h> 386219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan#include <linux/i2c.h> 396219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan#include <linux/slab.h> 406219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan#include <linux/regmap.h> 416219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 426219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan/* Register definitions */ 436219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan#define REG_VSET0 0 446219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan#define REG_VSET1 1 456219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan#define REG_VSET2 2 466219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan#define REG_VSET3 3 476219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan#define REG_CONTROL 4 486219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan#define REG_TEMP 5 496219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan#define REG_RAMPCTRL 6 506219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan#define REG_CHIPID 8 516219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 529a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan#define FORCE_PWM_ENABLE BIT(7) 539a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan 54d1cf4f65e1eb17bc8768d822755780588e42cf37Axel Linenum chips {TPS62360, TPS62361, TPS62362, TPS62363}; 556219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 562935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan#define TPS62360_BASE_VOLTAGE 770000 576219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan#define TPS62360_N_VOLTAGES 64 586219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 592935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan#define TPS62361_BASE_VOLTAGE 500000 606219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan#define TPS62361_N_VOLTAGES 128 616219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 626219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan/* tps 62360 chip information */ 636219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewanganstruct tps62360_chip { 646219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan struct device *dev; 656219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan struct regulator_desc desc; 666219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan struct regulator_dev *rdev; 676219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan struct regmap *regmap; 686219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan int vsel0_gpio; 696219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan int vsel1_gpio; 706219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan u8 voltage_reg_mask; 716219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan bool en_internal_pulldn; 726219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan bool en_discharge; 736219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan bool valid_gpios; 746219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan int lru_index[4]; 756219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan int curr_vset_vsel[4]; 766219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan int curr_vset_id; 776219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan}; 786219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 796219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan/* 806219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * find_voltage_set_register: Find new voltage configuration register 816219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * (VSET) id. 826219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * The finding of the new VSET register will be based on the LRU mechanism. 836219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * Each VSET register will have different voltage configured . This 846219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * Function will look if any of the VSET register have requested voltage set 856219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * or not. 866219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * - If it is already there then it will make that register as most 876219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * recently used and return as found so that caller need not to set 886219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * the VSET register but need to set the proper gpios to select this 896219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * VSET register. 906219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * - If requested voltage is not found then it will use the least 916219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * recently mechanism to get new VSET register for new configuration 926219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * and will return not_found so that caller need to set new VSET 936219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * register and then gpios (both). 946219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan */ 956219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewanganstatic bool find_voltage_set_register(struct tps62360_chip *tps, 966219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan int req_vsel, int *vset_reg_id) 976219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan{ 986219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan int i; 996219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan bool found = false; 1006219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan int new_vset_reg = tps->lru_index[3]; 1016219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan int found_index = 3; 1022935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan 1036219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan for (i = 0; i < 4; ++i) { 1046219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan if (tps->curr_vset_vsel[tps->lru_index[i]] == req_vsel) { 1056219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan new_vset_reg = tps->lru_index[i]; 1066219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan found_index = i; 1076219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan found = true; 1086219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan goto update_lru_index; 1096219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan } 1106219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan } 1116219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 1126219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewanganupdate_lru_index: 1136219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan for (i = found_index; i > 0; i--) 1146219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan tps->lru_index[i] = tps->lru_index[i - 1]; 1156219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 1166219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan tps->lru_index[0] = new_vset_reg; 1176219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan *vset_reg_id = new_vset_reg; 1186219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan return found; 1196219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan} 1206219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 121a60cfce051dd5e22329df1018d278bf3e52d82bcLaxman Dewanganstatic int tps62360_dcdc_get_voltage_sel(struct regulator_dev *dev) 1226219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan{ 1236219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan struct tps62360_chip *tps = rdev_get_drvdata(dev); 1246219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan int vsel; 1256219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan unsigned int data; 1266219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan int ret; 1276219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 1286219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan ret = regmap_read(tps->regmap, REG_VSET0 + tps->curr_vset_id, &data); 1296219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan if (ret < 0) { 1302935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan dev_err(tps->dev, "%s(): register %d read failed with err %d\n", 1312935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan __func__, REG_VSET0 + tps->curr_vset_id, ret); 1326219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan return ret; 1336219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan } 1346219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan vsel = (int)data & tps->voltage_reg_mask; 135a60cfce051dd5e22329df1018d278bf3e52d82bcLaxman Dewangan return vsel; 1366219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan} 1376219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 13841097afd64108348a935c658c78662bce1ea6355Axel Linstatic int tps62360_dcdc_set_voltage_sel(struct regulator_dev *dev, 13941097afd64108348a935c658c78662bce1ea6355Axel Lin unsigned selector) 1406219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan{ 1416219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan struct tps62360_chip *tps = rdev_get_drvdata(dev); 1426219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan int ret; 1436219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan bool found = false; 1446219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan int new_vset_id = tps->curr_vset_id; 1456219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 1466219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan /* 1476219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * If gpios are available to select the VSET register then least 1486219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * recently used register for new configuration. 1496219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan */ 1506219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan if (tps->valid_gpios) 15141097afd64108348a935c658c78662bce1ea6355Axel Lin found = find_voltage_set_register(tps, selector, &new_vset_id); 1526219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 1536219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan if (!found) { 1546219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan ret = regmap_update_bits(tps->regmap, REG_VSET0 + new_vset_id, 15541097afd64108348a935c658c78662bce1ea6355Axel Lin tps->voltage_reg_mask, selector); 1566219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan if (ret < 0) { 1572935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan dev_err(tps->dev, 1582935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan "%s(): register %d update failed with err %d\n", 1592935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan __func__, REG_VSET0 + new_vset_id, ret); 1606219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan return ret; 1616219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan } 1626219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan tps->curr_vset_id = new_vset_id; 16341097afd64108348a935c658c78662bce1ea6355Axel Lin tps->curr_vset_vsel[new_vset_id] = selector; 1646219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan } 1656219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 1666219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan /* Select proper VSET register vio gpios */ 1676219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan if (tps->valid_gpios) { 1682935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan gpio_set_value_cansleep(tps->vsel0_gpio, new_vset_id & 0x1); 1696219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan gpio_set_value_cansleep(tps->vsel1_gpio, 1706219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan (new_vset_id >> 1) & 0x1); 1716219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan } 1726219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan return 0; 1736219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan} 1746219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 1759a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewanganstatic int tps62360_set_mode(struct regulator_dev *rdev, unsigned int mode) 1769a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan{ 1779a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan struct tps62360_chip *tps = rdev_get_drvdata(rdev); 1789a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan int i; 1799a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan int val; 1809a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan int ret; 1819a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan 1829a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan /* Enable force PWM mode in FAST mode only. */ 1839a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan switch (mode) { 1849a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan case REGULATOR_MODE_FAST: 1859a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan val = FORCE_PWM_ENABLE; 1869a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan break; 1879a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan 1889a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan case REGULATOR_MODE_NORMAL: 1899a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan val = 0; 1909a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan break; 1919a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan 1929a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan default: 1939a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan return -EINVAL; 1949a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan } 1959a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan 1969a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan if (!tps->valid_gpios) { 1979a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan ret = regmap_update_bits(tps->regmap, 1989a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan REG_VSET0 + tps->curr_vset_id, FORCE_PWM_ENABLE, val); 1999a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan if (ret < 0) 2009a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan dev_err(tps->dev, 2019a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan "%s(): register %d update failed with err %d\n", 2029a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan __func__, REG_VSET0 + tps->curr_vset_id, ret); 2039a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan return ret; 2049a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan } 2059a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan 2069a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan /* If gpios are valid then all register set need to be control */ 2079a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan for (i = 0; i < 4; ++i) { 2089a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan ret = regmap_update_bits(tps->regmap, 2099a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan REG_VSET0 + i, FORCE_PWM_ENABLE, val); 2109a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan if (ret < 0) { 2119a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan dev_err(tps->dev, 2129a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan "%s(): register %d update failed with err %d\n", 2139a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan __func__, REG_VSET0 + i, ret); 2149a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan return ret; 2159a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan } 2169a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan } 2179a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan return ret; 2189a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan} 2199a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan 2209a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewanganstatic unsigned int tps62360_get_mode(struct regulator_dev *rdev) 2219a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan{ 2229a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan struct tps62360_chip *tps = rdev_get_drvdata(rdev); 2239a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan unsigned int data; 2249a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan int ret; 2259a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan 2269a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan ret = regmap_read(tps->regmap, REG_VSET0 + tps->curr_vset_id, &data); 2279a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan if (ret < 0) { 2289a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan dev_err(tps->dev, "%s(): register %d read failed with err %d\n", 2299a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan __func__, REG_VSET0 + tps->curr_vset_id, ret); 2309a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan return ret; 2319a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan } 2329a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan return (data & FORCE_PWM_ENABLE) ? 2339a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL; 2349a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan} 2359a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan 2366219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewanganstatic struct regulator_ops tps62360_dcdc_ops = { 237a60cfce051dd5e22329df1018d278bf3e52d82bcLaxman Dewangan .get_voltage_sel = tps62360_dcdc_get_voltage_sel, 23841097afd64108348a935c658c78662bce1ea6355Axel Lin .set_voltage_sel = tps62360_dcdc_set_voltage_sel, 2397f225ba5850886b9834f3473c6e584a94c5fc53bAxel Lin .list_voltage = regulator_list_voltage_linear, 24041097afd64108348a935c658c78662bce1ea6355Axel Lin .map_voltage = regulator_map_voltage_linear, 2410072f0a82ce78ceb634f00a57d80c9b421b061d4Axel Lin .set_voltage_time_sel = regulator_set_voltage_time_sel, 2429a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan .set_mode = tps62360_set_mode, 2439a00630c3db8ca064a8904dbcd9632fb81244bc0Laxman Dewangan .get_mode = tps62360_get_mode, 2446219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan}; 2456219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 246a5023574d120ca3b9337cedd4e27de90cae9aff7Bill Pembertonstatic int tps62360_init_dcdc(struct tps62360_chip *tps, 2476219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan struct tps62360_regulator_platform_data *pdata) 2486219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan{ 2496219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan int ret; 250a60cfce051dd5e22329df1018d278bf3e52d82bcLaxman Dewangan unsigned int ramp_ctrl; 2516219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 2522935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan /* Initialize internal pull up/down control */ 2536219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan if (tps->en_internal_pulldn) 2546219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan ret = regmap_write(tps->regmap, REG_CONTROL, 0xE0); 2556219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan else 2566219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan ret = regmap_write(tps->regmap, REG_CONTROL, 0x0); 2576219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan if (ret < 0) { 2582935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan dev_err(tps->dev, 2592935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan "%s(): register %d write failed with err %d\n", 2602935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan __func__, REG_CONTROL, ret); 2616219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan return ret; 2626219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan } 2636219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 2646219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan /* Reset output discharge path to reduce power consumption */ 2656219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan ret = regmap_update_bits(tps->regmap, REG_RAMPCTRL, BIT(2), 0); 266a60cfce051dd5e22329df1018d278bf3e52d82bcLaxman Dewangan if (ret < 0) { 2672935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan dev_err(tps->dev, 2682935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan "%s(): register %d update failed with err %d\n", 2692935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan __func__, REG_RAMPCTRL, ret); 270a60cfce051dd5e22329df1018d278bf3e52d82bcLaxman Dewangan return ret; 271a60cfce051dd5e22329df1018d278bf3e52d82bcLaxman Dewangan } 272a60cfce051dd5e22329df1018d278bf3e52d82bcLaxman Dewangan 273a60cfce051dd5e22329df1018d278bf3e52d82bcLaxman Dewangan /* Get ramp value from ramp control register */ 274a60cfce051dd5e22329df1018d278bf3e52d82bcLaxman Dewangan ret = regmap_read(tps->regmap, REG_RAMPCTRL, &ramp_ctrl); 275a60cfce051dd5e22329df1018d278bf3e52d82bcLaxman Dewangan if (ret < 0) { 2762935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan dev_err(tps->dev, 2772935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan "%s(): register %d read failed with err %d\n", 2782935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan __func__, REG_RAMPCTRL, ret); 279a60cfce051dd5e22329df1018d278bf3e52d82bcLaxman Dewangan return ret; 280a60cfce051dd5e22329df1018d278bf3e52d82bcLaxman Dewangan } 2811864b670902260d1c239f37e984f26de8fbad319Axel Lin ramp_ctrl = (ramp_ctrl >> 5) & 0x7; 282a60cfce051dd5e22329df1018d278bf3e52d82bcLaxman Dewangan 283a60cfce051dd5e22329df1018d278bf3e52d82bcLaxman Dewangan /* ramp mV/us = 32/(2^ramp_ctrl) */ 2840072f0a82ce78ceb634f00a57d80c9b421b061d4Axel Lin tps->desc.ramp_delay = DIV_ROUND_UP(32000, BIT(ramp_ctrl)); 2856219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan return ret; 2866219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan} 2876219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 2886219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewanganstatic const struct regmap_config tps62360_regmap_config = { 28916ea003bd1c95ea55a0b88187ce7cbeaca760fcfLaxman Dewangan .reg_bits = 8, 29016ea003bd1c95ea55a0b88187ce7cbeaca760fcfLaxman Dewangan .val_bits = 8, 29116ea003bd1c95ea55a0b88187ce7cbeaca760fcfLaxman Dewangan .max_register = REG_CHIPID, 29216ea003bd1c95ea55a0b88187ce7cbeaca760fcfLaxman Dewangan .cache_type = REGCACHE_RBTREE, 2936219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan}; 2946219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 295684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewanganstatic struct tps62360_regulator_platform_data * 296684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan of_get_tps62360_platform_data(struct device *dev) 297684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan{ 298684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan struct tps62360_regulator_platform_data *pdata; 299684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan struct device_node *np = dev->of_node; 300684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan 301684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); 30233e63ba6c698740bebc49dc9a7e652526ca005ccSachin Kamat if (!pdata) 303684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan return NULL; 304684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan 305684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan pdata->reg_init_data = of_get_regulator_init_data(dev, dev->of_node); 306684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan if (!pdata->reg_init_data) { 307684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan dev_err(dev, "Not able to get OF regulator init data\n"); 308684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan return NULL; 309684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan } 310684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan 311684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan pdata->vsel0_gpio = of_get_named_gpio(np, "vsel0-gpio", 0); 312684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan pdata->vsel1_gpio = of_get_named_gpio(np, "vsel1-gpio", 0); 313684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan 314684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan if (of_find_property(np, "ti,vsel0-state-high", NULL)) 315684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan pdata->vsel0_def_state = 1; 316684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan 317684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan if (of_find_property(np, "ti,vsel1-state-high", NULL)) 318684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan pdata->vsel1_def_state = 1; 319684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan 320684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan if (of_find_property(np, "ti,enable-pull-down", NULL)) 321684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan pdata->en_internal_pulldn = true; 322684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan 323684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan if (of_find_property(np, "ti,enable-vout-discharge", NULL)) 324684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan pdata->en_discharge = true; 325684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan 326684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan return pdata; 327684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan} 328684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan 329684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan#if defined(CONFIG_OF) 330684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewanganstatic const struct of_device_id tps62360_of_match[] = { 331684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan { .compatible = "ti,tps62360", .data = (void *)TPS62360}, 332684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan { .compatible = "ti,tps62361", .data = (void *)TPS62361}, 333684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan { .compatible = "ti,tps62362", .data = (void *)TPS62362}, 334684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan { .compatible = "ti,tps62363", .data = (void *)TPS62363}, 335684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan {}, 336be15411d97b6b9b2883b7f1ec52ef03bc770a6d4Axel Lin}; 337684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman DewanganMODULE_DEVICE_TABLE(of, tps62360_of_match); 338684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan#endif 339684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan 340a5023574d120ca3b9337cedd4e27de90cae9aff7Bill Pembertonstatic int tps62360_probe(struct i2c_client *client, 3416219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan const struct i2c_device_id *id) 3426219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan{ 343c172708d38a401b2f3f841dfcd862b469fa0b670Mark Brown struct regulator_config config = { }; 3446219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan struct tps62360_regulator_platform_data *pdata; 3456219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan struct regulator_dev *rdev; 3466219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan struct tps62360_chip *tps; 3476219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan int ret; 3486219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan int i; 349684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan int chip_id; 3506219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 351dff91d0b721bf8f036c1071a8f16a7effaa87514Jingoo Han pdata = dev_get_platdata(&client->dev); 352684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan 353684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan if (client->dev.of_node) { 354684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan const struct of_device_id *match; 355684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan match = of_match_device(of_match_ptr(tps62360_of_match), 356684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan &client->dev); 357684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan if (!match) { 358684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan dev_err(&client->dev, "Error: No device match found\n"); 359684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan return -ENODEV; 360684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan } 361541f597f1080ee615534cb6ccb2253891a29535cDavid Howells chip_id = (int)(long)match->data; 362684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan if (!pdata) 363684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan pdata = of_get_tps62360_platform_data(&client->dev); 3640a62d03b4844988c5477f13bd17c3553f816ce87Tuomas Tynkkynen } else if (id) { 3650a62d03b4844988c5477f13bd17c3553f816ce87Tuomas Tynkkynen chip_id = id->driver_data; 3660a62d03b4844988c5477f13bd17c3553f816ce87Tuomas Tynkkynen } else { 3670a62d03b4844988c5477f13bd17c3553f816ce87Tuomas Tynkkynen dev_err(&client->dev, "No device tree match or id table match found\n"); 3680a62d03b4844988c5477f13bd17c3553f816ce87Tuomas Tynkkynen return -ENODEV; 369684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan } 370684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan 3716219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan if (!pdata) { 3722935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan dev_err(&client->dev, "%s(): Platform data not found\n", 3736219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan __func__); 3746219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan return -EIO; 3756219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan } 3766219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 3776219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL); 37833e63ba6c698740bebc49dc9a7e652526ca005ccSachin Kamat if (!tps) 3796219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan return -ENOMEM; 3806219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 3816219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan tps->en_discharge = pdata->en_discharge; 3826219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan tps->en_internal_pulldn = pdata->en_internal_pulldn; 3836219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan tps->vsel0_gpio = pdata->vsel0_gpio; 3846219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan tps->vsel1_gpio = pdata->vsel1_gpio; 3856219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan tps->dev = &client->dev; 386d1cf4f65e1eb17bc8768d822755780588e42cf37Axel Lin 387684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan switch (chip_id) { 388d1cf4f65e1eb17bc8768d822755780588e42cf37Axel Lin case TPS62360: 389d1cf4f65e1eb17bc8768d822755780588e42cf37Axel Lin case TPS62362: 390b5152415225ba0d489939778f3b85217b25036dbAxel Lin tps->desc.min_uV = TPS62360_BASE_VOLTAGE; 391d1cf4f65e1eb17bc8768d822755780588e42cf37Axel Lin tps->voltage_reg_mask = 0x3F; 392d1cf4f65e1eb17bc8768d822755780588e42cf37Axel Lin tps->desc.n_voltages = TPS62360_N_VOLTAGES; 393d1cf4f65e1eb17bc8768d822755780588e42cf37Axel Lin break; 394d1cf4f65e1eb17bc8768d822755780588e42cf37Axel Lin case TPS62361: 395d1cf4f65e1eb17bc8768d822755780588e42cf37Axel Lin case TPS62363: 396b5152415225ba0d489939778f3b85217b25036dbAxel Lin tps->desc.min_uV = TPS62361_BASE_VOLTAGE; 397d1cf4f65e1eb17bc8768d822755780588e42cf37Axel Lin tps->voltage_reg_mask = 0x7F; 398d1cf4f65e1eb17bc8768d822755780588e42cf37Axel Lin tps->desc.n_voltages = TPS62361_N_VOLTAGES; 399d1cf4f65e1eb17bc8768d822755780588e42cf37Axel Lin break; 400d1cf4f65e1eb17bc8768d822755780588e42cf37Axel Lin default: 401d1cf4f65e1eb17bc8768d822755780588e42cf37Axel Lin return -ENODEV; 402d1cf4f65e1eb17bc8768d822755780588e42cf37Axel Lin } 4036219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 4040a62d03b4844988c5477f13bd17c3553f816ce87Tuomas Tynkkynen tps->desc.name = client->name; 4056219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan tps->desc.id = 0; 4066219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan tps->desc.ops = &tps62360_dcdc_ops; 4076219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan tps->desc.type = REGULATOR_VOLTAGE; 4086219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan tps->desc.owner = THIS_MODULE; 4097f225ba5850886b9834f3473c6e584a94c5fc53bAxel Lin tps->desc.uV_step = 10000; 4107f225ba5850886b9834f3473c6e584a94c5fc53bAxel Lin 4119a4bdd87a29bf297d9046410b011d726d51c3999Axel Lin tps->regmap = devm_regmap_init_i2c(client, &tps62360_regmap_config); 4126219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan if (IS_ERR(tps->regmap)) { 4136219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan ret = PTR_ERR(tps->regmap); 4142935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan dev_err(&client->dev, 4152935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan "%s(): regmap allocation failed with err %d\n", 4162935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan __func__, ret); 4176219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan return ret; 4186219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan } 4196219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan i2c_set_clientdata(client, tps); 4206219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 4216219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan tps->curr_vset_id = (pdata->vsel1_def_state & 1) * 2 + 4226219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan (pdata->vsel0_def_state & 1); 4236219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan tps->lru_index[0] = tps->curr_vset_id; 4246219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan tps->valid_gpios = false; 4256219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 4266219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan if (gpio_is_valid(tps->vsel0_gpio) && gpio_is_valid(tps->vsel1_gpio)) { 4272935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan int gpio_flags; 4282935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan gpio_flags = (pdata->vsel0_def_state) ? 4292935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; 4308a8e3d5915b3b40a64a5e7dc5aeb208594917a15Laxman Dewangan ret = devm_gpio_request_one(&client->dev, tps->vsel0_gpio, 4312935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan gpio_flags, "tps62360-vsel0"); 4326219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan if (ret) { 4336219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan dev_err(&client->dev, 4342935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan "%s(): Could not obtain vsel0 GPIO %d: %d\n", 4352935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan __func__, tps->vsel0_gpio, ret); 4368a8e3d5915b3b40a64a5e7dc5aeb208594917a15Laxman Dewangan return ret; 4376219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan } 4386219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 4392935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan gpio_flags = (pdata->vsel1_def_state) ? 4402935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; 4418a8e3d5915b3b40a64a5e7dc5aeb208594917a15Laxman Dewangan ret = devm_gpio_request_one(&client->dev, tps->vsel1_gpio, 4422935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan gpio_flags, "tps62360-vsel1"); 4436219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan if (ret) { 4446219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan dev_err(&client->dev, 4452935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan "%s(): Could not obtain vsel1 GPIO %d: %d\n", 4462935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan __func__, tps->vsel1_gpio, ret); 4478a8e3d5915b3b40a64a5e7dc5aeb208594917a15Laxman Dewangan return ret; 4486219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan } 4496219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan tps->valid_gpios = true; 4506219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 4516219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan /* 4526219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * Initialize the lru index with vset_reg id 4536219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * The index 0 will be most recently used and 4546219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan * set with the tps->curr_vset_id */ 4556219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan for (i = 0; i < 4; ++i) 4566219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan tps->lru_index[i] = i; 4576219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan tps->lru_index[0] = tps->curr_vset_id; 4586219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan tps->lru_index[tps->curr_vset_id] = 0; 4596219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan } 4606219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 4616219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan ret = tps62360_init_dcdc(tps, pdata); 4626219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan if (ret < 0) { 4632935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan dev_err(tps->dev, "%s(): Init failed with err = %d\n", 4646219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan __func__, ret); 4658a8e3d5915b3b40a64a5e7dc5aeb208594917a15Laxman Dewangan return ret; 4666219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan } 4676219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 468c172708d38a401b2f3f841dfcd862b469fa0b670Mark Brown config.dev = &client->dev; 4698bdca009e66bb18a990a4be1830c73acacfce331Laxman Dewangan config.init_data = pdata->reg_init_data; 470c172708d38a401b2f3f841dfcd862b469fa0b670Mark Brown config.driver_data = tps; 4719fc3815e26efd044c1a1d0770b4335cd00c833c0Laxman Dewangan config.of_node = client->dev.of_node; 472c172708d38a401b2f3f841dfcd862b469fa0b670Mark Brown 4736219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan /* Register the regulators */ 47458c6e938c00de744d52f739aa426a4b1b13ef22bSachin Kamat rdev = devm_regulator_register(&client->dev, &tps->desc, &config); 4756219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan if (IS_ERR(rdev)) { 4762935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan dev_err(tps->dev, 4772935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan "%s(): regulator register failed with err %s\n", 4782935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan __func__, id->name); 4798a8e3d5915b3b40a64a5e7dc5aeb208594917a15Laxman Dewangan return PTR_ERR(rdev); 4806219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan } 4816219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 4826219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan tps->rdev = rdev; 4836219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan return 0; 4846219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan} 4856219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 4866219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewanganstatic void tps62360_shutdown(struct i2c_client *client) 4876219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan{ 4886219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan struct tps62360_chip *tps = i2c_get_clientdata(client); 4896219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan int st; 4906219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 4916219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan if (!tps->en_discharge) 4926219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan return; 4936219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 4946219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan /* Configure the output discharge path */ 4956219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan st = regmap_update_bits(tps->regmap, REG_RAMPCTRL, BIT(2), BIT(2)); 4966219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan if (st < 0) 4972935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan dev_err(tps->dev, 4982935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan "%s(): register %d update failed with err %d\n", 4992935fb18aa1e75e6afaab3303cdd1a4ac62be63eLaxman Dewangan __func__, REG_RAMPCTRL, st); 5006219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan} 5016219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 5026219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewanganstatic const struct i2c_device_id tps62360_id[] = { 5036219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan {.name = "tps62360", .driver_data = TPS62360}, 5046219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan {.name = "tps62361", .driver_data = TPS62361}, 505d1cf4f65e1eb17bc8768d822755780588e42cf37Axel Lin {.name = "tps62362", .driver_data = TPS62362}, 506d1cf4f65e1eb17bc8768d822755780588e42cf37Axel Lin {.name = "tps62363", .driver_data = TPS62363}, 5076219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan {}, 5086219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan}; 5096219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 5106219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman DewanganMODULE_DEVICE_TABLE(i2c, tps62360_id); 5116219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 5126219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewanganstatic struct i2c_driver tps62360_i2c_driver = { 5136219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan .driver = { 5146219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan .name = "tps62360", 5156219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan .owner = THIS_MODULE, 516684ae39b91ee7fd2855c35be7f3bf226d42516a5Laxman Dewangan .of_match_table = of_match_ptr(tps62360_of_match), 5176219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan }, 5186219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan .probe = tps62360_probe, 5196219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan .shutdown = tps62360_shutdown, 5206219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan .id_table = tps62360_id, 5216219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan}; 5226219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 5236219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewanganstatic int __init tps62360_init(void) 5246219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan{ 5256219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan return i2c_add_driver(&tps62360_i2c_driver); 5266219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan} 5276219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangansubsys_initcall(tps62360_init); 5286219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 5296219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewanganstatic void __exit tps62360_cleanup(void) 5306219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan{ 5316219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan i2c_del_driver(&tps62360_i2c_driver); 5326219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan} 5336219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewanganmodule_exit(tps62360_cleanup); 5346219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman Dewangan 5356219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman DewanganMODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>"); 536d1cf4f65e1eb17bc8768d822755780588e42cf37Axel LinMODULE_DESCRIPTION("TPS6236x voltage regulator driver"); 5376219929f5f82708309b3054ec7db6cb6e3ee47d5Laxman DewanganMODULE_LICENSE("GPL v2"); 538