162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * max8973-regulator.c -- Maxim max8973A 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Regulator driver for MAXIM 8973A DC-DC step-down switching regulator. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright (c) 2012, NVIDIA Corporation. 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * Author: Laxman Dewangan <ldewangan@nvidia.com> 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <linux/kernel.h> 1362306a36Sopenharmony_ci#include <linux/module.h> 1462306a36Sopenharmony_ci#include <linux/init.h> 1562306a36Sopenharmony_ci#include <linux/err.h> 1662306a36Sopenharmony_ci#include <linux/of.h> 1762306a36Sopenharmony_ci#include <linux/of_device.h> 1862306a36Sopenharmony_ci#include <linux/platform_device.h> 1962306a36Sopenharmony_ci#include <linux/regulator/driver.h> 2062306a36Sopenharmony_ci#include <linux/regulator/machine.h> 2162306a36Sopenharmony_ci#include <linux/regulator/max8973-regulator.h> 2262306a36Sopenharmony_ci#include <linux/regulator/of_regulator.h> 2362306a36Sopenharmony_ci#include <linux/gpio.h> 2462306a36Sopenharmony_ci#include <linux/gpio/consumer.h> 2562306a36Sopenharmony_ci#include <linux/of_gpio.h> 2662306a36Sopenharmony_ci#include <linux/i2c.h> 2762306a36Sopenharmony_ci#include <linux/slab.h> 2862306a36Sopenharmony_ci#include <linux/regmap.h> 2962306a36Sopenharmony_ci#include <linux/thermal.h> 3062306a36Sopenharmony_ci#include <linux/irq.h> 3162306a36Sopenharmony_ci#include <linux/interrupt.h> 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci/* Register definitions */ 3462306a36Sopenharmony_ci#define MAX8973_VOUT 0x0 3562306a36Sopenharmony_ci#define MAX8973_VOUT_DVS 0x1 3662306a36Sopenharmony_ci#define MAX8973_CONTROL1 0x2 3762306a36Sopenharmony_ci#define MAX8973_CONTROL2 0x3 3862306a36Sopenharmony_ci#define MAX8973_CHIPID1 0x4 3962306a36Sopenharmony_ci#define MAX8973_CHIPID2 0x5 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci#define MAX8973_MAX_VOUT_REG 2 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci/* MAX8973_VOUT */ 4462306a36Sopenharmony_ci#define MAX8973_VOUT_ENABLE BIT(7) 4562306a36Sopenharmony_ci#define MAX8973_VOUT_MASK 0x7F 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci/* MAX8973_VOUT_DVS */ 4862306a36Sopenharmony_ci#define MAX8973_DVS_VOUT_MASK 0x7F 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci/* MAX8973_CONTROL1 */ 5162306a36Sopenharmony_ci#define MAX8973_SNS_ENABLE BIT(7) 5262306a36Sopenharmony_ci#define MAX8973_FPWM_EN_M BIT(6) 5362306a36Sopenharmony_ci#define MAX8973_NFSR_ENABLE BIT(5) 5462306a36Sopenharmony_ci#define MAX8973_AD_ENABLE BIT(4) 5562306a36Sopenharmony_ci#define MAX8973_BIAS_ENABLE BIT(3) 5662306a36Sopenharmony_ci#define MAX8973_FREQSHIFT_9PER BIT(2) 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci#define MAX8973_RAMP_12mV_PER_US 0x0 5962306a36Sopenharmony_ci#define MAX8973_RAMP_25mV_PER_US 0x1 6062306a36Sopenharmony_ci#define MAX8973_RAMP_50mV_PER_US 0x2 6162306a36Sopenharmony_ci#define MAX8973_RAMP_200mV_PER_US 0x3 6262306a36Sopenharmony_ci#define MAX8973_RAMP_MASK 0x3 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci/* MAX8973_CONTROL2 */ 6562306a36Sopenharmony_ci#define MAX8973_WDTMR_ENABLE BIT(6) 6662306a36Sopenharmony_ci#define MAX8973_DISCH_ENBABLE BIT(5) 6762306a36Sopenharmony_ci#define MAX8973_FT_ENABLE BIT(4) 6862306a36Sopenharmony_ci#define MAX77621_T_JUNCTION_120 BIT(7) 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci#define MAX8973_CKKADV_TRIP_MASK 0xC 7162306a36Sopenharmony_ci#define MAX8973_CKKADV_TRIP_DISABLE 0xC 7262306a36Sopenharmony_ci#define MAX8973_CKKADV_TRIP_75mV_PER_US 0x0 7362306a36Sopenharmony_ci#define MAX8973_CKKADV_TRIP_150mV_PER_US 0x4 7462306a36Sopenharmony_ci#define MAX8973_CKKADV_TRIP_75mV_PER_US_HIST_DIS 0x8 7562306a36Sopenharmony_ci#define MAX8973_CONTROL_CLKADV_TRIP_MASK 0x00030000 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci#define MAX8973_INDUCTOR_MIN_30_PER 0x0 7862306a36Sopenharmony_ci#define MAX8973_INDUCTOR_NOMINAL 0x1 7962306a36Sopenharmony_ci#define MAX8973_INDUCTOR_PLUS_30_PER 0x2 8062306a36Sopenharmony_ci#define MAX8973_INDUCTOR_PLUS_60_PER 0x3 8162306a36Sopenharmony_ci#define MAX8973_CONTROL_INDUCTOR_VALUE_MASK 0x00300000 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci#define MAX8973_MIN_VOLATGE 606250 8462306a36Sopenharmony_ci#define MAX8973_MAX_VOLATGE 1400000 8562306a36Sopenharmony_ci#define MAX8973_VOLATGE_STEP 6250 8662306a36Sopenharmony_ci#define MAX8973_BUCK_N_VOLTAGE 0x80 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci#define MAX77621_CHIPID_TJINT_S BIT(0) 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci#define MAX77621_NORMAL_OPERATING_TEMP 100000 9162306a36Sopenharmony_ci#define MAX77621_TJINT_WARNING_TEMP_120 120000 9262306a36Sopenharmony_ci#define MAX77621_TJINT_WARNING_TEMP_140 140000 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_cienum device_id { 9562306a36Sopenharmony_ci MAX8973, 9662306a36Sopenharmony_ci MAX77621 9762306a36Sopenharmony_ci}; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci/* Maxim 8973 chip information */ 10062306a36Sopenharmony_cistruct max8973_chip { 10162306a36Sopenharmony_ci struct device *dev; 10262306a36Sopenharmony_ci struct regulator_desc desc; 10362306a36Sopenharmony_ci struct regmap *regmap; 10462306a36Sopenharmony_ci bool enable_external_control; 10562306a36Sopenharmony_ci int dvs_gpio; 10662306a36Sopenharmony_ci int lru_index[MAX8973_MAX_VOUT_REG]; 10762306a36Sopenharmony_ci int curr_vout_val[MAX8973_MAX_VOUT_REG]; 10862306a36Sopenharmony_ci int curr_vout_reg; 10962306a36Sopenharmony_ci int curr_gpio_val; 11062306a36Sopenharmony_ci struct regulator_ops ops; 11162306a36Sopenharmony_ci enum device_id id; 11262306a36Sopenharmony_ci int junction_temp_warning; 11362306a36Sopenharmony_ci int irq; 11462306a36Sopenharmony_ci struct thermal_zone_device *tz_device; 11562306a36Sopenharmony_ci}; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci/* 11862306a36Sopenharmony_ci * find_voltage_set_register: Find new voltage configuration register (VOUT). 11962306a36Sopenharmony_ci * The finding of the new VOUT register will be based on the LRU mechanism. 12062306a36Sopenharmony_ci * Each VOUT register will have different voltage configured . This 12162306a36Sopenharmony_ci * Function will look if any of the VOUT register have requested voltage set 12262306a36Sopenharmony_ci * or not. 12362306a36Sopenharmony_ci * - If it is already there then it will make that register as most 12462306a36Sopenharmony_ci * recently used and return as found so that caller need not to set 12562306a36Sopenharmony_ci * the VOUT register but need to set the proper gpios to select this 12662306a36Sopenharmony_ci * VOUT register. 12762306a36Sopenharmony_ci * - If requested voltage is not found then it will use the least 12862306a36Sopenharmony_ci * recently mechanism to get new VOUT register for new configuration 12962306a36Sopenharmony_ci * and will return not_found so that caller need to set new VOUT 13062306a36Sopenharmony_ci * register and then gpios (both). 13162306a36Sopenharmony_ci */ 13262306a36Sopenharmony_cistatic bool find_voltage_set_register(struct max8973_chip *tps, 13362306a36Sopenharmony_ci int req_vsel, int *vout_reg, int *gpio_val) 13462306a36Sopenharmony_ci{ 13562306a36Sopenharmony_ci int i; 13662306a36Sopenharmony_ci bool found = false; 13762306a36Sopenharmony_ci int new_vout_reg = tps->lru_index[MAX8973_MAX_VOUT_REG - 1]; 13862306a36Sopenharmony_ci int found_index = MAX8973_MAX_VOUT_REG - 1; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci for (i = 0; i < MAX8973_MAX_VOUT_REG; ++i) { 14162306a36Sopenharmony_ci if (tps->curr_vout_val[tps->lru_index[i]] == req_vsel) { 14262306a36Sopenharmony_ci new_vout_reg = tps->lru_index[i]; 14362306a36Sopenharmony_ci found_index = i; 14462306a36Sopenharmony_ci found = true; 14562306a36Sopenharmony_ci goto update_lru_index; 14662306a36Sopenharmony_ci } 14762306a36Sopenharmony_ci } 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ciupdate_lru_index: 15062306a36Sopenharmony_ci for (i = found_index; i > 0; i--) 15162306a36Sopenharmony_ci tps->lru_index[i] = tps->lru_index[i - 1]; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci tps->lru_index[0] = new_vout_reg; 15462306a36Sopenharmony_ci *gpio_val = new_vout_reg; 15562306a36Sopenharmony_ci *vout_reg = MAX8973_VOUT + new_vout_reg; 15662306a36Sopenharmony_ci return found; 15762306a36Sopenharmony_ci} 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_cistatic int max8973_dcdc_get_voltage_sel(struct regulator_dev *rdev) 16062306a36Sopenharmony_ci{ 16162306a36Sopenharmony_ci struct max8973_chip *max = rdev_get_drvdata(rdev); 16262306a36Sopenharmony_ci unsigned int data; 16362306a36Sopenharmony_ci int ret; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci ret = regmap_read(max->regmap, max->curr_vout_reg, &data); 16662306a36Sopenharmony_ci if (ret < 0) { 16762306a36Sopenharmony_ci dev_err(max->dev, "register %d read failed, err = %d\n", 16862306a36Sopenharmony_ci max->curr_vout_reg, ret); 16962306a36Sopenharmony_ci return ret; 17062306a36Sopenharmony_ci } 17162306a36Sopenharmony_ci return data & MAX8973_VOUT_MASK; 17262306a36Sopenharmony_ci} 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_cistatic int max8973_dcdc_set_voltage_sel(struct regulator_dev *rdev, 17562306a36Sopenharmony_ci unsigned vsel) 17662306a36Sopenharmony_ci{ 17762306a36Sopenharmony_ci struct max8973_chip *max = rdev_get_drvdata(rdev); 17862306a36Sopenharmony_ci int ret; 17962306a36Sopenharmony_ci bool found = false; 18062306a36Sopenharmony_ci int vout_reg = max->curr_vout_reg; 18162306a36Sopenharmony_ci int gpio_val = max->curr_gpio_val; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci /* 18462306a36Sopenharmony_ci * If gpios are available to select the VOUT register then least 18562306a36Sopenharmony_ci * recently used register for new configuration. 18662306a36Sopenharmony_ci */ 18762306a36Sopenharmony_ci if (gpio_is_valid(max->dvs_gpio)) 18862306a36Sopenharmony_ci found = find_voltage_set_register(max, vsel, 18962306a36Sopenharmony_ci &vout_reg, &gpio_val); 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci if (!found) { 19262306a36Sopenharmony_ci ret = regmap_update_bits(max->regmap, vout_reg, 19362306a36Sopenharmony_ci MAX8973_VOUT_MASK, vsel); 19462306a36Sopenharmony_ci if (ret < 0) { 19562306a36Sopenharmony_ci dev_err(max->dev, "register %d update failed, err %d\n", 19662306a36Sopenharmony_ci vout_reg, ret); 19762306a36Sopenharmony_ci return ret; 19862306a36Sopenharmony_ci } 19962306a36Sopenharmony_ci max->curr_vout_reg = vout_reg; 20062306a36Sopenharmony_ci max->curr_vout_val[gpio_val] = vsel; 20162306a36Sopenharmony_ci } 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci /* Select proper VOUT register vio gpios */ 20462306a36Sopenharmony_ci if (gpio_is_valid(max->dvs_gpio)) { 20562306a36Sopenharmony_ci gpio_set_value_cansleep(max->dvs_gpio, gpio_val & 0x1); 20662306a36Sopenharmony_ci max->curr_gpio_val = gpio_val; 20762306a36Sopenharmony_ci } 20862306a36Sopenharmony_ci return 0; 20962306a36Sopenharmony_ci} 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_cistatic int max8973_dcdc_set_mode(struct regulator_dev *rdev, unsigned int mode) 21262306a36Sopenharmony_ci{ 21362306a36Sopenharmony_ci struct max8973_chip *max = rdev_get_drvdata(rdev); 21462306a36Sopenharmony_ci int ret; 21562306a36Sopenharmony_ci int pwm; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci /* Enable force PWM mode in FAST mode only. */ 21862306a36Sopenharmony_ci switch (mode) { 21962306a36Sopenharmony_ci case REGULATOR_MODE_FAST: 22062306a36Sopenharmony_ci pwm = MAX8973_FPWM_EN_M; 22162306a36Sopenharmony_ci break; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci case REGULATOR_MODE_NORMAL: 22462306a36Sopenharmony_ci pwm = 0; 22562306a36Sopenharmony_ci break; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci default: 22862306a36Sopenharmony_ci return -EINVAL; 22962306a36Sopenharmony_ci } 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci ret = regmap_update_bits(max->regmap, MAX8973_CONTROL1, 23262306a36Sopenharmony_ci MAX8973_FPWM_EN_M, pwm); 23362306a36Sopenharmony_ci if (ret < 0) 23462306a36Sopenharmony_ci dev_err(max->dev, "register %d update failed, err %d\n", 23562306a36Sopenharmony_ci MAX8973_CONTROL1, ret); 23662306a36Sopenharmony_ci return ret; 23762306a36Sopenharmony_ci} 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_cistatic unsigned int max8973_dcdc_get_mode(struct regulator_dev *rdev) 24062306a36Sopenharmony_ci{ 24162306a36Sopenharmony_ci struct max8973_chip *max = rdev_get_drvdata(rdev); 24262306a36Sopenharmony_ci unsigned int data; 24362306a36Sopenharmony_ci int ret; 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci ret = regmap_read(max->regmap, MAX8973_CONTROL1, &data); 24662306a36Sopenharmony_ci if (ret < 0) { 24762306a36Sopenharmony_ci dev_err(max->dev, "register %d read failed, err %d\n", 24862306a36Sopenharmony_ci MAX8973_CONTROL1, ret); 24962306a36Sopenharmony_ci return ret; 25062306a36Sopenharmony_ci } 25162306a36Sopenharmony_ci return (data & MAX8973_FPWM_EN_M) ? 25262306a36Sopenharmony_ci REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL; 25362306a36Sopenharmony_ci} 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_cistatic int max8973_set_current_limit(struct regulator_dev *rdev, 25662306a36Sopenharmony_ci int min_ua, int max_ua) 25762306a36Sopenharmony_ci{ 25862306a36Sopenharmony_ci struct max8973_chip *max = rdev_get_drvdata(rdev); 25962306a36Sopenharmony_ci unsigned int val; 26062306a36Sopenharmony_ci int ret; 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci if (max_ua <= 9000000) 26362306a36Sopenharmony_ci val = MAX8973_CKKADV_TRIP_75mV_PER_US; 26462306a36Sopenharmony_ci else if (max_ua <= 12000000) 26562306a36Sopenharmony_ci val = MAX8973_CKKADV_TRIP_150mV_PER_US; 26662306a36Sopenharmony_ci else 26762306a36Sopenharmony_ci val = MAX8973_CKKADV_TRIP_DISABLE; 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci ret = regmap_update_bits(max->regmap, MAX8973_CONTROL2, 27062306a36Sopenharmony_ci MAX8973_CKKADV_TRIP_MASK, val); 27162306a36Sopenharmony_ci if (ret < 0) { 27262306a36Sopenharmony_ci dev_err(max->dev, "register %d update failed: %d\n", 27362306a36Sopenharmony_ci MAX8973_CONTROL2, ret); 27462306a36Sopenharmony_ci return ret; 27562306a36Sopenharmony_ci } 27662306a36Sopenharmony_ci return 0; 27762306a36Sopenharmony_ci} 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_cistatic int max8973_get_current_limit(struct regulator_dev *rdev) 28062306a36Sopenharmony_ci{ 28162306a36Sopenharmony_ci struct max8973_chip *max = rdev_get_drvdata(rdev); 28262306a36Sopenharmony_ci unsigned int control2; 28362306a36Sopenharmony_ci int ret; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci ret = regmap_read(max->regmap, MAX8973_CONTROL2, &control2); 28662306a36Sopenharmony_ci if (ret < 0) { 28762306a36Sopenharmony_ci dev_err(max->dev, "register %d read failed: %d\n", 28862306a36Sopenharmony_ci MAX8973_CONTROL2, ret); 28962306a36Sopenharmony_ci return ret; 29062306a36Sopenharmony_ci } 29162306a36Sopenharmony_ci switch (control2 & MAX8973_CKKADV_TRIP_MASK) { 29262306a36Sopenharmony_ci case MAX8973_CKKADV_TRIP_DISABLE: 29362306a36Sopenharmony_ci return 15000000; 29462306a36Sopenharmony_ci case MAX8973_CKKADV_TRIP_150mV_PER_US: 29562306a36Sopenharmony_ci return 12000000; 29662306a36Sopenharmony_ci case MAX8973_CKKADV_TRIP_75mV_PER_US: 29762306a36Sopenharmony_ci return 9000000; 29862306a36Sopenharmony_ci default: 29962306a36Sopenharmony_ci break; 30062306a36Sopenharmony_ci } 30162306a36Sopenharmony_ci return 9000000; 30262306a36Sopenharmony_ci} 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_cistatic const unsigned int max8973_buck_ramp_table[] = { 30562306a36Sopenharmony_ci 12000, 25000, 50000, 200000 30662306a36Sopenharmony_ci}; 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_cistatic const struct regulator_ops max8973_dcdc_ops = { 30962306a36Sopenharmony_ci .get_voltage_sel = max8973_dcdc_get_voltage_sel, 31062306a36Sopenharmony_ci .set_voltage_sel = max8973_dcdc_set_voltage_sel, 31162306a36Sopenharmony_ci .list_voltage = regulator_list_voltage_linear, 31262306a36Sopenharmony_ci .set_mode = max8973_dcdc_set_mode, 31362306a36Sopenharmony_ci .get_mode = max8973_dcdc_get_mode, 31462306a36Sopenharmony_ci .set_voltage_time_sel = regulator_set_voltage_time_sel, 31562306a36Sopenharmony_ci .set_ramp_delay = regulator_set_ramp_delay_regmap, 31662306a36Sopenharmony_ci}; 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_cistatic int max8973_init_dcdc(struct max8973_chip *max, 31962306a36Sopenharmony_ci struct max8973_regulator_platform_data *pdata) 32062306a36Sopenharmony_ci{ 32162306a36Sopenharmony_ci int ret; 32262306a36Sopenharmony_ci uint8_t control1 = 0; 32362306a36Sopenharmony_ci uint8_t control2 = 0; 32462306a36Sopenharmony_ci unsigned int data; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci ret = regmap_read(max->regmap, MAX8973_CONTROL1, &data); 32762306a36Sopenharmony_ci if (ret < 0) { 32862306a36Sopenharmony_ci dev_err(max->dev, "register %d read failed, err = %d", 32962306a36Sopenharmony_ci MAX8973_CONTROL1, ret); 33062306a36Sopenharmony_ci return ret; 33162306a36Sopenharmony_ci } 33262306a36Sopenharmony_ci control1 = data & MAX8973_RAMP_MASK; 33362306a36Sopenharmony_ci switch (control1) { 33462306a36Sopenharmony_ci case MAX8973_RAMP_12mV_PER_US: 33562306a36Sopenharmony_ci max->desc.ramp_delay = 12000; 33662306a36Sopenharmony_ci break; 33762306a36Sopenharmony_ci case MAX8973_RAMP_25mV_PER_US: 33862306a36Sopenharmony_ci max->desc.ramp_delay = 25000; 33962306a36Sopenharmony_ci break; 34062306a36Sopenharmony_ci case MAX8973_RAMP_50mV_PER_US: 34162306a36Sopenharmony_ci max->desc.ramp_delay = 50000; 34262306a36Sopenharmony_ci break; 34362306a36Sopenharmony_ci case MAX8973_RAMP_200mV_PER_US: 34462306a36Sopenharmony_ci max->desc.ramp_delay = 200000; 34562306a36Sopenharmony_ci break; 34662306a36Sopenharmony_ci } 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci if (pdata->control_flags & MAX8973_CONTROL_REMOTE_SENSE_ENABLE) 34962306a36Sopenharmony_ci control1 |= MAX8973_SNS_ENABLE; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci if (!(pdata->control_flags & MAX8973_CONTROL_FALLING_SLEW_RATE_ENABLE)) 35262306a36Sopenharmony_ci control1 |= MAX8973_NFSR_ENABLE; 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci if (pdata->control_flags & MAX8973_CONTROL_OUTPUT_ACTIVE_DISCH_ENABLE) 35562306a36Sopenharmony_ci control1 |= MAX8973_AD_ENABLE; 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci if (pdata->control_flags & MAX8973_CONTROL_BIAS_ENABLE) { 35862306a36Sopenharmony_ci control1 |= MAX8973_BIAS_ENABLE; 35962306a36Sopenharmony_ci max->desc.enable_time = 20; 36062306a36Sopenharmony_ci } else { 36162306a36Sopenharmony_ci max->desc.enable_time = 240; 36262306a36Sopenharmony_ci } 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci if (pdata->control_flags & MAX8973_CONTROL_FREQ_SHIFT_9PER_ENABLE) 36562306a36Sopenharmony_ci control1 |= MAX8973_FREQSHIFT_9PER; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci if ((pdata->junction_temp_warning == MAX77621_TJINT_WARNING_TEMP_120) && 36862306a36Sopenharmony_ci (max->id == MAX77621)) 36962306a36Sopenharmony_ci control2 |= MAX77621_T_JUNCTION_120; 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci if (!(pdata->control_flags & MAX8973_CONTROL_PULL_DOWN_ENABLE)) 37262306a36Sopenharmony_ci control2 |= MAX8973_DISCH_ENBABLE; 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci /* Clock advance trip configuration */ 37562306a36Sopenharmony_ci switch (pdata->control_flags & MAX8973_CONTROL_CLKADV_TRIP_MASK) { 37662306a36Sopenharmony_ci case MAX8973_CONTROL_CLKADV_TRIP_DISABLED: 37762306a36Sopenharmony_ci control2 |= MAX8973_CKKADV_TRIP_DISABLE; 37862306a36Sopenharmony_ci break; 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci case MAX8973_CONTROL_CLKADV_TRIP_75mV_PER_US: 38162306a36Sopenharmony_ci control2 |= MAX8973_CKKADV_TRIP_75mV_PER_US; 38262306a36Sopenharmony_ci break; 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci case MAX8973_CONTROL_CLKADV_TRIP_150mV_PER_US: 38562306a36Sopenharmony_ci control2 |= MAX8973_CKKADV_TRIP_150mV_PER_US; 38662306a36Sopenharmony_ci break; 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci case MAX8973_CONTROL_CLKADV_TRIP_75mV_PER_US_HIST_DIS: 38962306a36Sopenharmony_ci control2 |= MAX8973_CKKADV_TRIP_75mV_PER_US_HIST_DIS; 39062306a36Sopenharmony_ci break; 39162306a36Sopenharmony_ci } 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci /* Configure inductor value */ 39462306a36Sopenharmony_ci switch (pdata->control_flags & MAX8973_CONTROL_INDUCTOR_VALUE_MASK) { 39562306a36Sopenharmony_ci case MAX8973_CONTROL_INDUCTOR_VALUE_NOMINAL: 39662306a36Sopenharmony_ci control2 |= MAX8973_INDUCTOR_NOMINAL; 39762306a36Sopenharmony_ci break; 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci case MAX8973_CONTROL_INDUCTOR_VALUE_MINUS_30_PER: 40062306a36Sopenharmony_ci control2 |= MAX8973_INDUCTOR_MIN_30_PER; 40162306a36Sopenharmony_ci break; 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci case MAX8973_CONTROL_INDUCTOR_VALUE_PLUS_30_PER: 40462306a36Sopenharmony_ci control2 |= MAX8973_INDUCTOR_PLUS_30_PER; 40562306a36Sopenharmony_ci break; 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci case MAX8973_CONTROL_INDUCTOR_VALUE_PLUS_60_PER: 40862306a36Sopenharmony_ci control2 |= MAX8973_INDUCTOR_PLUS_60_PER; 40962306a36Sopenharmony_ci break; 41062306a36Sopenharmony_ci } 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci ret = regmap_write(max->regmap, MAX8973_CONTROL1, control1); 41362306a36Sopenharmony_ci if (ret < 0) { 41462306a36Sopenharmony_ci dev_err(max->dev, "register %d write failed, err = %d", 41562306a36Sopenharmony_ci MAX8973_CONTROL1, ret); 41662306a36Sopenharmony_ci return ret; 41762306a36Sopenharmony_ci } 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci ret = regmap_write(max->regmap, MAX8973_CONTROL2, control2); 42062306a36Sopenharmony_ci if (ret < 0) { 42162306a36Sopenharmony_ci dev_err(max->dev, "register %d write failed, err = %d", 42262306a36Sopenharmony_ci MAX8973_CONTROL2, ret); 42362306a36Sopenharmony_ci return ret; 42462306a36Sopenharmony_ci } 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci /* If external control is enabled then disable EN bit */ 42762306a36Sopenharmony_ci if (max->enable_external_control && (max->id == MAX8973)) { 42862306a36Sopenharmony_ci ret = regmap_update_bits(max->regmap, MAX8973_VOUT, 42962306a36Sopenharmony_ci MAX8973_VOUT_ENABLE, 0); 43062306a36Sopenharmony_ci if (ret < 0) 43162306a36Sopenharmony_ci dev_err(max->dev, "register %d update failed, err = %d", 43262306a36Sopenharmony_ci MAX8973_VOUT, ret); 43362306a36Sopenharmony_ci } 43462306a36Sopenharmony_ci return ret; 43562306a36Sopenharmony_ci} 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_cistatic int max8973_thermal_read_temp(struct thermal_zone_device *tz, int *temp) 43862306a36Sopenharmony_ci{ 43962306a36Sopenharmony_ci struct max8973_chip *mchip = thermal_zone_device_priv(tz); 44062306a36Sopenharmony_ci unsigned int val; 44162306a36Sopenharmony_ci int ret; 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci ret = regmap_read(mchip->regmap, MAX8973_CHIPID1, &val); 44462306a36Sopenharmony_ci if (ret < 0) { 44562306a36Sopenharmony_ci dev_err(mchip->dev, "Failed to read register CHIPID1, %d", ret); 44662306a36Sopenharmony_ci return ret; 44762306a36Sopenharmony_ci } 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci /* +1 degC to trigger cool device */ 45062306a36Sopenharmony_ci if (val & MAX77621_CHIPID_TJINT_S) 45162306a36Sopenharmony_ci *temp = mchip->junction_temp_warning + 1000; 45262306a36Sopenharmony_ci else 45362306a36Sopenharmony_ci *temp = MAX77621_NORMAL_OPERATING_TEMP; 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci return 0; 45662306a36Sopenharmony_ci} 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_cistatic irqreturn_t max8973_thermal_irq(int irq, void *data) 45962306a36Sopenharmony_ci{ 46062306a36Sopenharmony_ci struct max8973_chip *mchip = data; 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci thermal_zone_device_update(mchip->tz_device, 46362306a36Sopenharmony_ci THERMAL_EVENT_UNSPECIFIED); 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci return IRQ_HANDLED; 46662306a36Sopenharmony_ci} 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_cistatic const struct thermal_zone_device_ops max77621_tz_ops = { 46962306a36Sopenharmony_ci .get_temp = max8973_thermal_read_temp, 47062306a36Sopenharmony_ci}; 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_cistatic int max8973_thermal_init(struct max8973_chip *mchip) 47362306a36Sopenharmony_ci{ 47462306a36Sopenharmony_ci struct thermal_zone_device *tzd; 47562306a36Sopenharmony_ci struct irq_data *irq_data; 47662306a36Sopenharmony_ci unsigned long irq_flags = 0; 47762306a36Sopenharmony_ci int ret; 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci if (mchip->id != MAX77621) 48062306a36Sopenharmony_ci return 0; 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci tzd = devm_thermal_of_zone_register(mchip->dev, 0, mchip, 48362306a36Sopenharmony_ci &max77621_tz_ops); 48462306a36Sopenharmony_ci if (IS_ERR(tzd)) { 48562306a36Sopenharmony_ci ret = PTR_ERR(tzd); 48662306a36Sopenharmony_ci dev_err(mchip->dev, "Failed to register thermal sensor: %d\n", 48762306a36Sopenharmony_ci ret); 48862306a36Sopenharmony_ci return ret; 48962306a36Sopenharmony_ci } 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci if (mchip->irq <= 0) 49262306a36Sopenharmony_ci return 0; 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci irq_data = irq_get_irq_data(mchip->irq); 49562306a36Sopenharmony_ci if (irq_data) 49662306a36Sopenharmony_ci irq_flags = irqd_get_trigger_type(irq_data); 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci ret = devm_request_threaded_irq(mchip->dev, mchip->irq, NULL, 49962306a36Sopenharmony_ci max8973_thermal_irq, 50062306a36Sopenharmony_ci IRQF_ONESHOT | IRQF_SHARED | irq_flags, 50162306a36Sopenharmony_ci dev_name(mchip->dev), mchip); 50262306a36Sopenharmony_ci if (ret < 0) { 50362306a36Sopenharmony_ci dev_err(mchip->dev, "Failed to request irq %d, %d\n", 50462306a36Sopenharmony_ci mchip->irq, ret); 50562306a36Sopenharmony_ci return ret; 50662306a36Sopenharmony_ci } 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci return 0; 50962306a36Sopenharmony_ci} 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_cistatic const struct regmap_config max8973_regmap_config = { 51262306a36Sopenharmony_ci .reg_bits = 8, 51362306a36Sopenharmony_ci .val_bits = 8, 51462306a36Sopenharmony_ci .max_register = MAX8973_CHIPID2, 51562306a36Sopenharmony_ci .cache_type = REGCACHE_RBTREE, 51662306a36Sopenharmony_ci}; 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_cistatic struct max8973_regulator_platform_data *max8973_parse_dt( 51962306a36Sopenharmony_ci struct device *dev) 52062306a36Sopenharmony_ci{ 52162306a36Sopenharmony_ci struct max8973_regulator_platform_data *pdata; 52262306a36Sopenharmony_ci struct device_node *np = dev->of_node; 52362306a36Sopenharmony_ci int ret; 52462306a36Sopenharmony_ci u32 pval; 52562306a36Sopenharmony_ci bool etr_enable; 52662306a36Sopenharmony_ci bool etr_sensitivity_high; 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); 52962306a36Sopenharmony_ci if (!pdata) 53062306a36Sopenharmony_ci return NULL; 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ci pdata->enable_ext_control = of_property_read_bool(np, 53362306a36Sopenharmony_ci "maxim,externally-enable"); 53462306a36Sopenharmony_ci pdata->dvs_gpio = of_get_named_gpio(np, "maxim,dvs-gpio", 0); 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci ret = of_property_read_u32(np, "maxim,dvs-default-state", &pval); 53762306a36Sopenharmony_ci if (!ret) 53862306a36Sopenharmony_ci pdata->dvs_def_state = pval; 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci if (of_property_read_bool(np, "maxim,enable-remote-sense")) 54162306a36Sopenharmony_ci pdata->control_flags |= MAX8973_CONTROL_REMOTE_SENSE_ENABLE; 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci if (of_property_read_bool(np, "maxim,enable-falling-slew-rate")) 54462306a36Sopenharmony_ci pdata->control_flags |= 54562306a36Sopenharmony_ci MAX8973_CONTROL_FALLING_SLEW_RATE_ENABLE; 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci if (of_property_read_bool(np, "maxim,enable-active-discharge")) 54862306a36Sopenharmony_ci pdata->control_flags |= 54962306a36Sopenharmony_ci MAX8973_CONTROL_OUTPUT_ACTIVE_DISCH_ENABLE; 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci if (of_property_read_bool(np, "maxim,enable-frequency-shift")) 55262306a36Sopenharmony_ci pdata->control_flags |= MAX8973_CONTROL_FREQ_SHIFT_9PER_ENABLE; 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci if (of_property_read_bool(np, "maxim,enable-bias-control")) 55562306a36Sopenharmony_ci pdata->control_flags |= MAX8973_CONTROL_BIAS_ENABLE; 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci etr_enable = of_property_read_bool(np, "maxim,enable-etr"); 55862306a36Sopenharmony_ci etr_sensitivity_high = of_property_read_bool(np, 55962306a36Sopenharmony_ci "maxim,enable-high-etr-sensitivity"); 56062306a36Sopenharmony_ci if (etr_sensitivity_high) 56162306a36Sopenharmony_ci etr_enable = true; 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci if (etr_enable) { 56462306a36Sopenharmony_ci if (etr_sensitivity_high) 56562306a36Sopenharmony_ci pdata->control_flags |= 56662306a36Sopenharmony_ci MAX8973_CONTROL_CLKADV_TRIP_75mV_PER_US; 56762306a36Sopenharmony_ci else 56862306a36Sopenharmony_ci pdata->control_flags |= 56962306a36Sopenharmony_ci MAX8973_CONTROL_CLKADV_TRIP_150mV_PER_US; 57062306a36Sopenharmony_ci } else { 57162306a36Sopenharmony_ci pdata->control_flags |= MAX8973_CONTROL_CLKADV_TRIP_DISABLED; 57262306a36Sopenharmony_ci } 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci pdata->junction_temp_warning = MAX77621_TJINT_WARNING_TEMP_140; 57562306a36Sopenharmony_ci ret = of_property_read_u32(np, "junction-warn-millicelsius", &pval); 57662306a36Sopenharmony_ci if (!ret && (pval <= MAX77621_TJINT_WARNING_TEMP_120)) 57762306a36Sopenharmony_ci pdata->junction_temp_warning = MAX77621_TJINT_WARNING_TEMP_120; 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci return pdata; 58062306a36Sopenharmony_ci} 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_cistatic const struct of_device_id of_max8973_match_tbl[] = { 58362306a36Sopenharmony_ci { .compatible = "maxim,max8973", .data = (void *)MAX8973, }, 58462306a36Sopenharmony_ci { .compatible = "maxim,max77621", .data = (void *)MAX77621, }, 58562306a36Sopenharmony_ci { }, 58662306a36Sopenharmony_ci}; 58762306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, of_max8973_match_tbl); 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_cistatic int max8973_probe(struct i2c_client *client) 59062306a36Sopenharmony_ci{ 59162306a36Sopenharmony_ci const struct i2c_device_id *id = i2c_client_get_device_id(client); 59262306a36Sopenharmony_ci struct max8973_regulator_platform_data *pdata; 59362306a36Sopenharmony_ci struct regulator_init_data *ridata; 59462306a36Sopenharmony_ci struct regulator_config config = { }; 59562306a36Sopenharmony_ci struct regulator_dev *rdev; 59662306a36Sopenharmony_ci struct max8973_chip *max; 59762306a36Sopenharmony_ci bool pdata_from_dt = false; 59862306a36Sopenharmony_ci unsigned int chip_id; 59962306a36Sopenharmony_ci struct gpio_desc *gpiod; 60062306a36Sopenharmony_ci enum gpiod_flags gflags; 60162306a36Sopenharmony_ci int ret; 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci pdata = dev_get_platdata(&client->dev); 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci if (!pdata && client->dev.of_node) { 60662306a36Sopenharmony_ci pdata = max8973_parse_dt(&client->dev); 60762306a36Sopenharmony_ci pdata_from_dt = true; 60862306a36Sopenharmony_ci } 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci if (!pdata) { 61162306a36Sopenharmony_ci dev_err(&client->dev, "No Platform data"); 61262306a36Sopenharmony_ci return -EIO; 61362306a36Sopenharmony_ci } 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_ci if (pdata->dvs_gpio == -EPROBE_DEFER) 61662306a36Sopenharmony_ci return -EPROBE_DEFER; 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci max = devm_kzalloc(&client->dev, sizeof(*max), GFP_KERNEL); 61962306a36Sopenharmony_ci if (!max) 62062306a36Sopenharmony_ci return -ENOMEM; 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci max->regmap = devm_regmap_init_i2c(client, &max8973_regmap_config); 62362306a36Sopenharmony_ci if (IS_ERR(max->regmap)) { 62462306a36Sopenharmony_ci ret = PTR_ERR(max->regmap); 62562306a36Sopenharmony_ci dev_err(&client->dev, "regmap init failed, err %d\n", ret); 62662306a36Sopenharmony_ci return ret; 62762306a36Sopenharmony_ci } 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci if (client->dev.of_node) { 63062306a36Sopenharmony_ci const struct of_device_id *match; 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci match = of_match_device(of_match_ptr(of_max8973_match_tbl), 63362306a36Sopenharmony_ci &client->dev); 63462306a36Sopenharmony_ci if (!match) 63562306a36Sopenharmony_ci return -ENODATA; 63662306a36Sopenharmony_ci max->id = (u32)((uintptr_t)match->data); 63762306a36Sopenharmony_ci } else { 63862306a36Sopenharmony_ci max->id = id->driver_data; 63962306a36Sopenharmony_ci } 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ci ret = regmap_read(max->regmap, MAX8973_CHIPID1, &chip_id); 64262306a36Sopenharmony_ci if (ret < 0) { 64362306a36Sopenharmony_ci dev_err(&client->dev, "register CHIPID1 read failed, %d", ret); 64462306a36Sopenharmony_ci return ret; 64562306a36Sopenharmony_ci } 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci dev_info(&client->dev, "CHIP-ID OTP: 0x%02x ID_M: 0x%02x\n", 64862306a36Sopenharmony_ci (chip_id >> 4) & 0xF, (chip_id >> 1) & 0x7); 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci i2c_set_clientdata(client, max); 65162306a36Sopenharmony_ci max->ops = max8973_dcdc_ops; 65262306a36Sopenharmony_ci max->dev = &client->dev; 65362306a36Sopenharmony_ci max->desc.name = id->name; 65462306a36Sopenharmony_ci max->desc.id = 0; 65562306a36Sopenharmony_ci max->desc.ops = &max->ops; 65662306a36Sopenharmony_ci max->desc.type = REGULATOR_VOLTAGE; 65762306a36Sopenharmony_ci max->desc.owner = THIS_MODULE; 65862306a36Sopenharmony_ci max->desc.min_uV = MAX8973_MIN_VOLATGE; 65962306a36Sopenharmony_ci max->desc.uV_step = MAX8973_VOLATGE_STEP; 66062306a36Sopenharmony_ci max->desc.n_voltages = MAX8973_BUCK_N_VOLTAGE; 66162306a36Sopenharmony_ci max->desc.ramp_reg = MAX8973_CONTROL1; 66262306a36Sopenharmony_ci max->desc.ramp_mask = MAX8973_RAMP_MASK; 66362306a36Sopenharmony_ci max->desc.ramp_delay_table = max8973_buck_ramp_table; 66462306a36Sopenharmony_ci max->desc.n_ramp_values = ARRAY_SIZE(max8973_buck_ramp_table); 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ci max->dvs_gpio = (pdata->dvs_gpio) ? pdata->dvs_gpio : -EINVAL; 66762306a36Sopenharmony_ci max->enable_external_control = pdata->enable_ext_control; 66862306a36Sopenharmony_ci max->curr_gpio_val = pdata->dvs_def_state; 66962306a36Sopenharmony_ci max->curr_vout_reg = MAX8973_VOUT + pdata->dvs_def_state; 67062306a36Sopenharmony_ci max->junction_temp_warning = pdata->junction_temp_warning; 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci max->lru_index[0] = max->curr_vout_reg; 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_ci if (gpio_is_valid(max->dvs_gpio)) { 67562306a36Sopenharmony_ci int gpio_flags; 67662306a36Sopenharmony_ci int i; 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_ci gpio_flags = (pdata->dvs_def_state) ? 67962306a36Sopenharmony_ci GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; 68062306a36Sopenharmony_ci ret = devm_gpio_request_one(&client->dev, max->dvs_gpio, 68162306a36Sopenharmony_ci gpio_flags, "max8973-dvs"); 68262306a36Sopenharmony_ci if (ret) { 68362306a36Sopenharmony_ci dev_err(&client->dev, 68462306a36Sopenharmony_ci "gpio_request for gpio %d failed, err = %d\n", 68562306a36Sopenharmony_ci max->dvs_gpio, ret); 68662306a36Sopenharmony_ci return ret; 68762306a36Sopenharmony_ci } 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_ci /* 69062306a36Sopenharmony_ci * Initialize the lru index with vout_reg id 69162306a36Sopenharmony_ci * The index 0 will be most recently used and 69262306a36Sopenharmony_ci * set with the max->curr_vout_reg */ 69362306a36Sopenharmony_ci for (i = 0; i < MAX8973_MAX_VOUT_REG; ++i) 69462306a36Sopenharmony_ci max->lru_index[i] = i; 69562306a36Sopenharmony_ci max->lru_index[0] = max->curr_vout_reg; 69662306a36Sopenharmony_ci max->lru_index[max->curr_vout_reg] = 0; 69762306a36Sopenharmony_ci } else { 69862306a36Sopenharmony_ci /* 69962306a36Sopenharmony_ci * If there is no DVS GPIO, the VOUT register 70062306a36Sopenharmony_ci * address is fixed. 70162306a36Sopenharmony_ci */ 70262306a36Sopenharmony_ci max->ops.set_voltage_sel = regulator_set_voltage_sel_regmap; 70362306a36Sopenharmony_ci max->ops.get_voltage_sel = regulator_get_voltage_sel_regmap; 70462306a36Sopenharmony_ci max->desc.vsel_reg = max->curr_vout_reg; 70562306a36Sopenharmony_ci max->desc.vsel_mask = MAX8973_VOUT_MASK; 70662306a36Sopenharmony_ci } 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ci if (pdata_from_dt) 70962306a36Sopenharmony_ci pdata->reg_init_data = of_get_regulator_init_data(&client->dev, 71062306a36Sopenharmony_ci client->dev.of_node, &max->desc); 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_ci ridata = pdata->reg_init_data; 71362306a36Sopenharmony_ci switch (max->id) { 71462306a36Sopenharmony_ci case MAX8973: 71562306a36Sopenharmony_ci if (!pdata->enable_ext_control) { 71662306a36Sopenharmony_ci max->desc.enable_reg = MAX8973_VOUT; 71762306a36Sopenharmony_ci max->desc.enable_mask = MAX8973_VOUT_ENABLE; 71862306a36Sopenharmony_ci max->ops.enable = regulator_enable_regmap; 71962306a36Sopenharmony_ci max->ops.disable = regulator_disable_regmap; 72062306a36Sopenharmony_ci max->ops.is_enabled = regulator_is_enabled_regmap; 72162306a36Sopenharmony_ci break; 72262306a36Sopenharmony_ci } 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci if (ridata && (ridata->constraints.always_on || 72562306a36Sopenharmony_ci ridata->constraints.boot_on)) 72662306a36Sopenharmony_ci gflags = GPIOD_OUT_HIGH; 72762306a36Sopenharmony_ci else 72862306a36Sopenharmony_ci gflags = GPIOD_OUT_LOW; 72962306a36Sopenharmony_ci gflags |= GPIOD_FLAGS_BIT_NONEXCLUSIVE; 73062306a36Sopenharmony_ci gpiod = devm_gpiod_get_optional(&client->dev, 73162306a36Sopenharmony_ci "maxim,enable", 73262306a36Sopenharmony_ci gflags); 73362306a36Sopenharmony_ci if (IS_ERR(gpiod)) 73462306a36Sopenharmony_ci return PTR_ERR(gpiod); 73562306a36Sopenharmony_ci if (gpiod) { 73662306a36Sopenharmony_ci config.ena_gpiod = gpiod; 73762306a36Sopenharmony_ci max->enable_external_control = true; 73862306a36Sopenharmony_ci } 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci break; 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci case MAX77621: 74362306a36Sopenharmony_ci /* 74462306a36Sopenharmony_ci * We do not let the core switch this regulator on/off, 74562306a36Sopenharmony_ci * we just leave it on. 74662306a36Sopenharmony_ci */ 74762306a36Sopenharmony_ci gpiod = devm_gpiod_get_optional(&client->dev, 74862306a36Sopenharmony_ci "maxim,enable", 74962306a36Sopenharmony_ci GPIOD_OUT_HIGH); 75062306a36Sopenharmony_ci if (IS_ERR(gpiod)) 75162306a36Sopenharmony_ci return PTR_ERR(gpiod); 75262306a36Sopenharmony_ci if (gpiod) 75362306a36Sopenharmony_ci max->enable_external_control = true; 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci max->desc.enable_reg = MAX8973_VOUT; 75662306a36Sopenharmony_ci max->desc.enable_mask = MAX8973_VOUT_ENABLE; 75762306a36Sopenharmony_ci max->ops.enable = regulator_enable_regmap; 75862306a36Sopenharmony_ci max->ops.disable = regulator_disable_regmap; 75962306a36Sopenharmony_ci max->ops.is_enabled = regulator_is_enabled_regmap; 76062306a36Sopenharmony_ci max->ops.set_current_limit = max8973_set_current_limit; 76162306a36Sopenharmony_ci max->ops.get_current_limit = max8973_get_current_limit; 76262306a36Sopenharmony_ci break; 76362306a36Sopenharmony_ci default: 76462306a36Sopenharmony_ci break; 76562306a36Sopenharmony_ci } 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_ci ret = max8973_init_dcdc(max, pdata); 76862306a36Sopenharmony_ci if (ret < 0) { 76962306a36Sopenharmony_ci dev_err(max->dev, "Max8973 Init failed, err = %d\n", ret); 77062306a36Sopenharmony_ci return ret; 77162306a36Sopenharmony_ci } 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_ci config.dev = &client->dev; 77462306a36Sopenharmony_ci config.init_data = pdata->reg_init_data; 77562306a36Sopenharmony_ci config.driver_data = max; 77662306a36Sopenharmony_ci config.of_node = client->dev.of_node; 77762306a36Sopenharmony_ci config.regmap = max->regmap; 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_ci /* 78062306a36Sopenharmony_ci * Register the regulators 78162306a36Sopenharmony_ci * Turn the GPIO descriptor over to the regulator core for 78262306a36Sopenharmony_ci * lifecycle management if we pass an ena_gpiod. 78362306a36Sopenharmony_ci */ 78462306a36Sopenharmony_ci if (config.ena_gpiod) 78562306a36Sopenharmony_ci devm_gpiod_unhinge(&client->dev, config.ena_gpiod); 78662306a36Sopenharmony_ci rdev = devm_regulator_register(&client->dev, &max->desc, &config); 78762306a36Sopenharmony_ci if (IS_ERR(rdev)) { 78862306a36Sopenharmony_ci ret = PTR_ERR(rdev); 78962306a36Sopenharmony_ci dev_err(max->dev, "regulator register failed, err %d\n", ret); 79062306a36Sopenharmony_ci return ret; 79162306a36Sopenharmony_ci } 79262306a36Sopenharmony_ci 79362306a36Sopenharmony_ci max8973_thermal_init(max); 79462306a36Sopenharmony_ci return 0; 79562306a36Sopenharmony_ci} 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_cistatic const struct i2c_device_id max8973_id[] = { 79862306a36Sopenharmony_ci {.name = "max8973", .driver_data = MAX8973}, 79962306a36Sopenharmony_ci {.name = "max77621", .driver_data = MAX77621}, 80062306a36Sopenharmony_ci {}, 80162306a36Sopenharmony_ci}; 80262306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, max8973_id); 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_cistatic struct i2c_driver max8973_i2c_driver = { 80562306a36Sopenharmony_ci .driver = { 80662306a36Sopenharmony_ci .name = "max8973", 80762306a36Sopenharmony_ci .probe_type = PROBE_PREFER_ASYNCHRONOUS, 80862306a36Sopenharmony_ci .of_match_table = of_max8973_match_tbl, 80962306a36Sopenharmony_ci }, 81062306a36Sopenharmony_ci .probe = max8973_probe, 81162306a36Sopenharmony_ci .id_table = max8973_id, 81262306a36Sopenharmony_ci}; 81362306a36Sopenharmony_ci 81462306a36Sopenharmony_cistatic int __init max8973_init(void) 81562306a36Sopenharmony_ci{ 81662306a36Sopenharmony_ci return i2c_add_driver(&max8973_i2c_driver); 81762306a36Sopenharmony_ci} 81862306a36Sopenharmony_cisubsys_initcall(max8973_init); 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_cistatic void __exit max8973_cleanup(void) 82162306a36Sopenharmony_ci{ 82262306a36Sopenharmony_ci i2c_del_driver(&max8973_i2c_driver); 82362306a36Sopenharmony_ci} 82462306a36Sopenharmony_cimodule_exit(max8973_cleanup); 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_ciMODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>"); 82762306a36Sopenharmony_ciMODULE_DESCRIPTION("MAX8973 voltage regulator driver"); 82862306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 829