brintos

brintos / linux-shallow public Read only

0
0
Text · 42.7 KiB · c839293 Raw
1643 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Summit Microelectronics SMB347 Battery Charger Driver4 *5 * Copyright (C) 2011, Intel Corporation6 *7 * Authors: Bruce E. Robertson <bruce.e.robertson@intel.com>8 *          Mika Westerberg <mika.westerberg@linux.intel.com>9 */10 11#include <linux/delay.h>12#include <linux/err.h>13#include <linux/kernel.h>14#include <linux/module.h>15#include <linux/init.h>16#include <linux/interrupt.h>17#include <linux/i2c.h>18#include <linux/power_supply.h>19#include <linux/property.h>20#include <linux/regmap.h>21#include <linux/regulator/driver.h>22 23#include <dt-bindings/power/summit,smb347-charger.h>24 25/* Use the default compensation method */26#define SMB3XX_SOFT_TEMP_COMPENSATE_DEFAULT -127 28/* Use default factory programmed value for hard/soft temperature limit */29#define SMB3XX_TEMP_USE_DEFAULT		-27330 31/*32 * Configuration registers. These are mirrored to volatile RAM and can be33 * written once %CMD_A_ALLOW_WRITE is set in %CMD_A register. They will be34 * reloaded from non-volatile registers after POR.35 */36#define CFG_CHARGE_CURRENT			0x0037#define CFG_CHARGE_CURRENT_FCC_MASK		0xe038#define CFG_CHARGE_CURRENT_FCC_SHIFT		539#define CFG_CHARGE_CURRENT_PCC_MASK		0x1840#define CFG_CHARGE_CURRENT_PCC_SHIFT		341#define CFG_CHARGE_CURRENT_TC_MASK		0x0742#define CFG_CURRENT_LIMIT			0x0143#define CFG_CURRENT_LIMIT_DC_MASK		0xf044#define CFG_CURRENT_LIMIT_DC_SHIFT		445#define CFG_CURRENT_LIMIT_USB_MASK		0x0f46#define CFG_FLOAT_VOLTAGE			0x0347#define CFG_FLOAT_VOLTAGE_FLOAT_MASK		0x3f48#define CFG_FLOAT_VOLTAGE_THRESHOLD_MASK	0xc049#define CFG_FLOAT_VOLTAGE_THRESHOLD_SHIFT	650#define CFG_STAT				0x0551#define CFG_STAT_DISABLED			BIT(5)52#define CFG_STAT_ACTIVE_HIGH			BIT(7)53#define CFG_PIN					0x0654#define CFG_PIN_EN_CTRL_MASK			0x6055#define CFG_PIN_EN_CTRL_ACTIVE_HIGH		0x4056#define CFG_PIN_EN_CTRL_ACTIVE_LOW		0x6057#define CFG_PIN_EN_APSD_IRQ			BIT(1)58#define CFG_PIN_EN_CHARGER_ERROR		BIT(2)59#define CFG_PIN_EN_CTRL				BIT(4)60#define CFG_THERM				0x0761#define CFG_THERM_SOFT_HOT_COMPENSATION_MASK	0x0362#define CFG_THERM_SOFT_HOT_COMPENSATION_SHIFT	063#define CFG_THERM_SOFT_COLD_COMPENSATION_MASK	0x0c64#define CFG_THERM_SOFT_COLD_COMPENSATION_SHIFT	265#define CFG_THERM_MONITOR_DISABLED		BIT(4)66#define CFG_SYSOK				0x0867#define CFG_SYSOK_INOK_ACTIVE_HIGH		BIT(0)68#define CFG_SYSOK_SUSPEND_HARD_LIMIT_DISABLED	BIT(2)69#define CFG_OTHER				0x0970#define CFG_OTHER_RID_MASK			0xc071#define CFG_OTHER_RID_ENABLED_AUTO_OTG		0xc072#define CFG_OTG					0x0a73#define CFG_OTG_TEMP_THRESHOLD_MASK		0x3074#define CFG_OTG_CURRENT_LIMIT_250mA		BIT(2)75#define CFG_OTG_CURRENT_LIMIT_750mA		BIT(3)76#define CFG_OTG_TEMP_THRESHOLD_SHIFT		477#define CFG_OTG_CC_COMPENSATION_MASK		0xc078#define CFG_OTG_CC_COMPENSATION_SHIFT		679#define CFG_TEMP_LIMIT				0x0b80#define CFG_TEMP_LIMIT_SOFT_HOT_MASK		0x0381#define CFG_TEMP_LIMIT_SOFT_HOT_SHIFT		082#define CFG_TEMP_LIMIT_SOFT_COLD_MASK		0x0c83#define CFG_TEMP_LIMIT_SOFT_COLD_SHIFT		284#define CFG_TEMP_LIMIT_HARD_HOT_MASK		0x3085#define CFG_TEMP_LIMIT_HARD_HOT_SHIFT		486#define CFG_TEMP_LIMIT_HARD_COLD_MASK		0xc087#define CFG_TEMP_LIMIT_HARD_COLD_SHIFT		688#define CFG_FAULT_IRQ				0x0c89#define CFG_FAULT_IRQ_DCIN_UV			BIT(2)90#define CFG_STATUS_IRQ				0x0d91#define CFG_STATUS_IRQ_TERMINATION_OR_TAPER	BIT(4)92#define CFG_STATUS_IRQ_CHARGE_TIMEOUT		BIT(7)93#define CFG_ADDRESS				0x0e94 95/* Command registers */96#define CMD_A					0x3097#define CMD_A_CHG_ENABLED			BIT(1)98#define CMD_A_SUSPEND_ENABLED			BIT(2)99#define CMD_A_OTG_ENABLED			BIT(4)100#define CMD_A_ALLOW_WRITE			BIT(7)101#define CMD_B					0x31102#define CMD_C					0x33103 104/* Interrupt Status registers */105#define IRQSTAT_A				0x35106#define IRQSTAT_C				0x37107#define IRQSTAT_C_TERMINATION_STAT		BIT(0)108#define IRQSTAT_C_TERMINATION_IRQ		BIT(1)109#define IRQSTAT_C_TAPER_IRQ			BIT(3)110#define IRQSTAT_D				0x38111#define IRQSTAT_D_CHARGE_TIMEOUT_STAT		BIT(2)112#define IRQSTAT_D_CHARGE_TIMEOUT_IRQ		BIT(3)113#define IRQSTAT_E				0x39114#define IRQSTAT_E_USBIN_UV_STAT			BIT(0)115#define IRQSTAT_E_USBIN_UV_IRQ			BIT(1)116#define IRQSTAT_E_DCIN_UV_STAT			BIT(4)117#define IRQSTAT_E_DCIN_UV_IRQ			BIT(5)118#define IRQSTAT_F				0x3a119 120/* Status registers */121#define STAT_A					0x3b122#define STAT_A_FLOAT_VOLTAGE_MASK		0x3f123#define STAT_B					0x3c124#define STAT_C					0x3d125#define STAT_C_CHG_ENABLED			BIT(0)126#define STAT_C_HOLDOFF_STAT			BIT(3)127#define STAT_C_CHG_MASK				0x06128#define STAT_C_CHG_SHIFT			1129#define STAT_C_CHG_TERM				BIT(5)130#define STAT_C_CHARGER_ERROR			BIT(6)131#define STAT_E					0x3f132 133#define SMB347_MAX_REGISTER			0x3f134 135/**136 * struct smb347_charger - smb347 charger instance137 * @dev: pointer to device138 * @regmap: pointer to driver regmap139 * @mains: power_supply instance for AC/DC power140 * @usb: power_supply instance for USB power141 * @usb_rdev: USB VBUS regulator device142 * @id: SMB charger ID143 * @mains_online: is AC/DC input connected144 * @usb_online: is USB input connected145 * @irq_unsupported: is interrupt unsupported by SMB hardware146 * @usb_vbus_enabled: is USB VBUS powered by SMB charger147 * @max_charge_current: maximum current (in uA) the battery can be charged148 * @max_charge_voltage: maximum voltage (in uV) the battery can be charged149 * @pre_charge_current: current (in uA) to use in pre-charging phase150 * @termination_current: current (in uA) used to determine when the151 *			 charging cycle terminates152 * @pre_to_fast_voltage: voltage (in uV) treshold used for transitioning to153 *			 pre-charge to fast charge mode154 * @mains_current_limit: maximum input current drawn from AC/DC input (in uA)155 * @usb_hc_current_limit: maximum input high current (in uA) drawn from USB156 *			  input157 * @chip_temp_threshold: die temperature where device starts limiting charge158 *			 current [%100 - %130] (in degree C)159 * @soft_cold_temp_limit: soft cold temperature limit [%0 - %15] (in degree C),160 *			  granularity is 5 deg C.161 * @soft_hot_temp_limit: soft hot temperature limit [%40 - %55] (in degree  C),162 *			 granularity is 5 deg C.163 * @hard_cold_temp_limit: hard cold temperature limit [%-5 - %10] (in degree C),164 *			  granularity is 5 deg C.165 * @hard_hot_temp_limit: hard hot temperature limit [%50 - %65] (in degree C),166 *			 granularity is 5 deg C.167 * @suspend_on_hard_temp_limit: suspend charging when hard limit is hit168 * @soft_temp_limit_compensation: compensation method when soft temperature169 *				  limit is hit170 * @charge_current_compensation: current (in uA) for charging compensation171 *				 current when temperature hits soft limits172 * @use_mains: AC/DC input can be used173 * @use_usb: USB input can be used174 * @use_usb_otg: USB OTG output can be used (not implemented yet)175 * @enable_control: how charging enable/disable is controlled176 *		    (driver/pin controls)177 * @inok_polarity: polarity of INOK signal which denotes presence of external178 *		   power supply179 *180 * @use_main, @use_usb, and @use_usb_otg are means to enable/disable181 * hardware support for these. This is useful when we want to have for182 * example OTG charging controlled via OTG transceiver driver and not by183 * the SMB347 hardware.184 *185 * Hard and soft temperature limit values are given as described in the186 * device data sheet and assuming NTC beta value is %3750. Even if this is187 * not the case, these values should be used. They can be mapped to the188 * corresponding NTC beta values with the help of table %2 in the data189 * sheet. So for example if NTC beta is %3375 and we want to program hard190 * hot limit to be %53 deg C, @hard_hot_temp_limit should be set to %50.191 *192 * If zero value is given in any of the current and voltage values, the193 * factory programmed default will be used. For soft/hard temperature194 * values, pass in %SMB3XX_TEMP_USE_DEFAULT instead.195 */196struct smb347_charger {197	struct device		*dev;198	struct regmap		*regmap;199	struct power_supply	*mains;200	struct power_supply	*usb;201	struct regulator_dev	*usb_rdev;202	unsigned int		id;203	bool			mains_online;204	bool			usb_online;205	bool			irq_unsupported;206	bool			usb_vbus_enabled;207 208	unsigned int		max_charge_current;209	unsigned int		max_charge_voltage;210	unsigned int		pre_charge_current;211	unsigned int		termination_current;212	unsigned int		pre_to_fast_voltage;213	unsigned int		mains_current_limit;214	unsigned int		usb_hc_current_limit;215	unsigned int		chip_temp_threshold;216	int			soft_cold_temp_limit;217	int			soft_hot_temp_limit;218	int			hard_cold_temp_limit;219	int			hard_hot_temp_limit;220	bool			suspend_on_hard_temp_limit;221	unsigned int		soft_temp_limit_compensation;222	unsigned int		charge_current_compensation;223	bool			use_mains;224	bool			use_usb;225	bool			use_usb_otg;226	unsigned int		enable_control;227	unsigned int		inok_polarity;228};229 230enum smb_charger_chipid {231	SMB345,232	SMB347,233	SMB358,234	NUM_CHIP_TYPES,235};236 237/* Fast charge current in uA */238static const unsigned int fcc_tbl[NUM_CHIP_TYPES][8] = {239	[SMB345] = {  200000,  450000,  600000,  900000,240		     1300000, 1500000, 1800000, 2000000 },241	[SMB347] = {  700000,  900000, 1200000, 1500000,242		     1800000, 2000000, 2200000, 2500000 },243	[SMB358] = {  200000,  450000,  600000,  900000,244		     1300000, 1500000, 1800000, 2000000 },245};246/* Pre-charge current in uA */247static const unsigned int pcc_tbl[NUM_CHIP_TYPES][4] = {248	[SMB345] = { 150000, 250000, 350000, 450000 },249	[SMB347] = { 100000, 150000, 200000, 250000 },250	[SMB358] = { 150000, 250000, 350000, 450000 },251};252 253/* Termination current in uA */254static const unsigned int tc_tbl[NUM_CHIP_TYPES][8] = {255	[SMB345] = {  30000,  40000,  60000,  80000,256		     100000, 125000, 150000, 200000 },257	[SMB347] = {  37500,  50000, 100000, 150000,258		     200000, 250000, 500000, 600000 },259	[SMB358] = {  30000,  40000,  60000,  80000,260		     100000, 125000, 150000, 200000 },261};262 263/* Input current limit in uA */264static const unsigned int icl_tbl[NUM_CHIP_TYPES][10] = {265	[SMB345] = {  300000,  500000,  700000, 1000000, 1500000,266		     1800000, 2000000, 2000000, 2000000, 2000000 },267	[SMB347] = {  300000,  500000,  700000,  900000, 1200000,268		     1500000, 1800000, 2000000, 2200000, 2500000 },269	[SMB358] = {  300000,  500000,  700000, 1000000, 1500000,270		     1800000, 2000000, 2000000, 2000000, 2000000 },271};272 273/* Charge current compensation in uA */274static const unsigned int ccc_tbl[NUM_CHIP_TYPES][4] = {275	[SMB345] = {  200000,  450000,  600000,  900000 },276	[SMB347] = {  250000,  700000,  900000, 1200000 },277	[SMB358] = {  200000,  450000,  600000,  900000 },278};279 280/* Convert register value to current using lookup table */281static int hw_to_current(const unsigned int *tbl, size_t size, unsigned int val)282{283	if (val >= size)284		return -EINVAL;285	return tbl[val];286}287 288/* Convert current to register value using lookup table */289static int current_to_hw(const unsigned int *tbl, size_t size, unsigned int val)290{291	size_t i;292 293	for (i = 0; i < size; i++)294		if (val < tbl[i])295			break;296	return i > 0 ? i - 1 : -EINVAL;297}298 299/**300 * smb347_update_ps_status - refreshes the power source status301 * @smb: pointer to smb347 charger instance302 *303 * Function checks whether any power source is connected to the charger and304 * updates internal state accordingly. If there is a change to previous state305 * function returns %1, otherwise %0 and negative errno in case of errror.306 */307static int smb347_update_ps_status(struct smb347_charger *smb)308{309	bool usb = false;310	bool dc = false;311	unsigned int val;312	int ret;313 314	ret = regmap_read(smb->regmap, IRQSTAT_E, &val);315	if (ret < 0)316		return ret;317 318	/*319	 * Dc and usb are set depending on whether they are enabled in320	 * platform data _and_ whether corresponding undervoltage is set.321	 */322	if (smb->use_mains)323		dc = !(val & IRQSTAT_E_DCIN_UV_STAT);324	if (smb->use_usb)325		usb = !(val & IRQSTAT_E_USBIN_UV_STAT);326 327	ret = smb->mains_online != dc || smb->usb_online != usb;328	smb->mains_online = dc;329	smb->usb_online = usb;330 331	return ret;332}333 334/*335 * smb347_is_ps_online - returns whether input power source is connected336 * @smb: pointer to smb347 charger instance337 *338 * Returns %true if input power source is connected. Note that this is339 * dependent on what platform has configured for usable power sources. For340 * example if USB is disabled, this will return %false even if the USB cable341 * is connected.342 */343static bool smb347_is_ps_online(struct smb347_charger *smb)344{345	return smb->usb_online || smb->mains_online;346}347 348/**349 * smb347_charging_status - returns status of charging350 * @smb: pointer to smb347 charger instance351 *352 * Function returns charging status. %0 means no charging is in progress,353 * %1 means pre-charging, %2 fast-charging and %3 taper-charging.354 */355static int smb347_charging_status(struct smb347_charger *smb)356{357	unsigned int val;358	int ret;359 360	if (!smb347_is_ps_online(smb))361		return 0;362 363	ret = regmap_read(smb->regmap, STAT_C, &val);364	if (ret < 0)365		return 0;366 367	return (val & STAT_C_CHG_MASK) >> STAT_C_CHG_SHIFT;368}369 370static int smb347_charging_set(struct smb347_charger *smb, bool enable)371{372	if (smb->enable_control != SMB3XX_CHG_ENABLE_SW) {373		dev_dbg(smb->dev, "charging enable/disable in SW disabled\n");374		return 0;375	}376 377	if (enable && smb->usb_vbus_enabled) {378		dev_dbg(smb->dev, "charging not enabled because USB is in host mode\n");379		return 0;380	}381 382	return regmap_update_bits(smb->regmap, CMD_A, CMD_A_CHG_ENABLED,383				  enable ? CMD_A_CHG_ENABLED : 0);384}385 386static inline int smb347_charging_enable(struct smb347_charger *smb)387{388	return smb347_charging_set(smb, true);389}390 391static inline int smb347_charging_disable(struct smb347_charger *smb)392{393	return smb347_charging_set(smb, false);394}395 396static int smb347_start_stop_charging(struct smb347_charger *smb)397{398	int ret;399 400	/*401	 * Depending on whether valid power source is connected or not, we402	 * disable or enable the charging. We do it manually because it403	 * depends on how the platform has configured the valid inputs.404	 */405	if (smb347_is_ps_online(smb)) {406		ret = smb347_charging_enable(smb);407		if (ret < 0)408			dev_err(smb->dev, "failed to enable charging\n");409	} else {410		ret = smb347_charging_disable(smb);411		if (ret < 0)412			dev_err(smb->dev, "failed to disable charging\n");413	}414 415	return ret;416}417 418static int smb347_set_charge_current(struct smb347_charger *smb)419{420	unsigned int id = smb->id;421	int ret;422 423	if (smb->max_charge_current) {424		ret = current_to_hw(fcc_tbl[id], ARRAY_SIZE(fcc_tbl[id]),425				    smb->max_charge_current);426		if (ret < 0)427			return ret;428 429		ret = regmap_update_bits(smb->regmap, CFG_CHARGE_CURRENT,430					 CFG_CHARGE_CURRENT_FCC_MASK,431					 ret << CFG_CHARGE_CURRENT_FCC_SHIFT);432		if (ret < 0)433			return ret;434	}435 436	if (smb->pre_charge_current) {437		ret = current_to_hw(pcc_tbl[id], ARRAY_SIZE(pcc_tbl[id]),438				    smb->pre_charge_current);439		if (ret < 0)440			return ret;441 442		ret = regmap_update_bits(smb->regmap, CFG_CHARGE_CURRENT,443					 CFG_CHARGE_CURRENT_PCC_MASK,444					 ret << CFG_CHARGE_CURRENT_PCC_SHIFT);445		if (ret < 0)446			return ret;447	}448 449	if (smb->termination_current) {450		ret = current_to_hw(tc_tbl[id], ARRAY_SIZE(tc_tbl[id]),451				    smb->termination_current);452		if (ret < 0)453			return ret;454 455		ret = regmap_update_bits(smb->regmap, CFG_CHARGE_CURRENT,456					 CFG_CHARGE_CURRENT_TC_MASK, ret);457		if (ret < 0)458			return ret;459	}460 461	return 0;462}463 464static int smb347_set_current_limits(struct smb347_charger *smb)465{466	unsigned int id = smb->id;467	int ret;468 469	if (smb->mains_current_limit) {470		ret = current_to_hw(icl_tbl[id], ARRAY_SIZE(icl_tbl[id]),471				    smb->mains_current_limit);472		if (ret < 0)473			return ret;474 475		ret = regmap_update_bits(smb->regmap, CFG_CURRENT_LIMIT,476					 CFG_CURRENT_LIMIT_DC_MASK,477					 ret << CFG_CURRENT_LIMIT_DC_SHIFT);478		if (ret < 0)479			return ret;480	}481 482	if (smb->usb_hc_current_limit) {483		ret = current_to_hw(icl_tbl[id], ARRAY_SIZE(icl_tbl[id]),484				    smb->usb_hc_current_limit);485		if (ret < 0)486			return ret;487 488		ret = regmap_update_bits(smb->regmap, CFG_CURRENT_LIMIT,489					 CFG_CURRENT_LIMIT_USB_MASK, ret);490		if (ret < 0)491			return ret;492	}493 494	return 0;495}496 497static int smb347_set_voltage_limits(struct smb347_charger *smb)498{499	int ret;500 501	if (smb->pre_to_fast_voltage) {502		ret = smb->pre_to_fast_voltage;503 504		/* uV */505		ret = clamp_val(ret, 2400000, 3000000) - 2400000;506		ret /= 200000;507 508		ret = regmap_update_bits(smb->regmap, CFG_FLOAT_VOLTAGE,509				CFG_FLOAT_VOLTAGE_THRESHOLD_MASK,510				ret << CFG_FLOAT_VOLTAGE_THRESHOLD_SHIFT);511		if (ret < 0)512			return ret;513	}514 515	if (smb->max_charge_voltage) {516		ret = smb->max_charge_voltage;517 518		/* uV */519		ret = clamp_val(ret, 3500000, 4500000) - 3500000;520		ret /= 20000;521 522		ret = regmap_update_bits(smb->regmap, CFG_FLOAT_VOLTAGE,523					 CFG_FLOAT_VOLTAGE_FLOAT_MASK, ret);524		if (ret < 0)525			return ret;526	}527 528	return 0;529}530 531static int smb347_set_temp_limits(struct smb347_charger *smb)532{533	unsigned int id = smb->id;534	bool enable_therm_monitor = false;535	int ret = 0;536	int val;537 538	if (smb->chip_temp_threshold) {539		val = smb->chip_temp_threshold;540 541		/* degree C */542		val = clamp_val(val, 100, 130) - 100;543		val /= 10;544 545		ret = regmap_update_bits(smb->regmap, CFG_OTG,546					 CFG_OTG_TEMP_THRESHOLD_MASK,547					 val << CFG_OTG_TEMP_THRESHOLD_SHIFT);548		if (ret < 0)549			return ret;550	}551 552	if (smb->soft_cold_temp_limit != SMB3XX_TEMP_USE_DEFAULT) {553		val = smb->soft_cold_temp_limit;554 555		val = clamp_val(val, 0, 15);556		val /= 5;557		/* this goes from higher to lower so invert the value */558		val = ~val & 0x3;559 560		ret = regmap_update_bits(smb->regmap, CFG_TEMP_LIMIT,561					 CFG_TEMP_LIMIT_SOFT_COLD_MASK,562					 val << CFG_TEMP_LIMIT_SOFT_COLD_SHIFT);563		if (ret < 0)564			return ret;565 566		enable_therm_monitor = true;567	}568 569	if (smb->soft_hot_temp_limit != SMB3XX_TEMP_USE_DEFAULT) {570		val = smb->soft_hot_temp_limit;571 572		val = clamp_val(val, 40, 55) - 40;573		val /= 5;574 575		ret = regmap_update_bits(smb->regmap, CFG_TEMP_LIMIT,576					 CFG_TEMP_LIMIT_SOFT_HOT_MASK,577					 val << CFG_TEMP_LIMIT_SOFT_HOT_SHIFT);578		if (ret < 0)579			return ret;580 581		enable_therm_monitor = true;582	}583 584	if (smb->hard_cold_temp_limit != SMB3XX_TEMP_USE_DEFAULT) {585		val = smb->hard_cold_temp_limit;586 587		val = clamp_val(val, -5, 10) + 5;588		val /= 5;589		/* this goes from higher to lower so invert the value */590		val = ~val & 0x3;591 592		ret = regmap_update_bits(smb->regmap, CFG_TEMP_LIMIT,593					 CFG_TEMP_LIMIT_HARD_COLD_MASK,594					 val << CFG_TEMP_LIMIT_HARD_COLD_SHIFT);595		if (ret < 0)596			return ret;597 598		enable_therm_monitor = true;599	}600 601	if (smb->hard_hot_temp_limit != SMB3XX_TEMP_USE_DEFAULT) {602		val = smb->hard_hot_temp_limit;603 604		val = clamp_val(val, 50, 65) - 50;605		val /= 5;606 607		ret = regmap_update_bits(smb->regmap, CFG_TEMP_LIMIT,608					 CFG_TEMP_LIMIT_HARD_HOT_MASK,609					 val << CFG_TEMP_LIMIT_HARD_HOT_SHIFT);610		if (ret < 0)611			return ret;612 613		enable_therm_monitor = true;614	}615 616	/*617	 * If any of the temperature limits are set, we also enable the618	 * thermistor monitoring.619	 *620	 * When soft limits are hit, the device will start to compensate621	 * current and/or voltage depending on the configuration.622	 *623	 * When hard limit is hit, the device will suspend charging624	 * depending on the configuration.625	 */626	if (enable_therm_monitor) {627		ret = regmap_update_bits(smb->regmap, CFG_THERM,628					 CFG_THERM_MONITOR_DISABLED, 0);629		if (ret < 0)630			return ret;631	}632 633	if (smb->suspend_on_hard_temp_limit) {634		ret = regmap_update_bits(smb->regmap, CFG_SYSOK,635				 CFG_SYSOK_SUSPEND_HARD_LIMIT_DISABLED, 0);636		if (ret < 0)637			return ret;638	}639 640	if (smb->soft_temp_limit_compensation !=641	    SMB3XX_SOFT_TEMP_COMPENSATE_DEFAULT) {642		val = smb->soft_temp_limit_compensation & 0x3;643 644		ret = regmap_update_bits(smb->regmap, CFG_THERM,645				 CFG_THERM_SOFT_HOT_COMPENSATION_MASK,646				 val << CFG_THERM_SOFT_HOT_COMPENSATION_SHIFT);647		if (ret < 0)648			return ret;649 650		ret = regmap_update_bits(smb->regmap, CFG_THERM,651				 CFG_THERM_SOFT_COLD_COMPENSATION_MASK,652				 val << CFG_THERM_SOFT_COLD_COMPENSATION_SHIFT);653		if (ret < 0)654			return ret;655	}656 657	if (smb->charge_current_compensation) {658		val = current_to_hw(ccc_tbl[id], ARRAY_SIZE(ccc_tbl[id]),659				    smb->charge_current_compensation);660		if (val < 0)661			return val;662 663		ret = regmap_update_bits(smb->regmap, CFG_OTG,664				CFG_OTG_CC_COMPENSATION_MASK,665				(val & 0x3) << CFG_OTG_CC_COMPENSATION_SHIFT);666		if (ret < 0)667			return ret;668	}669 670	return ret;671}672 673/*674 * smb347_set_writable - enables/disables writing to non-volatile registers675 * @smb: pointer to smb347 charger instance676 *677 * You can enable/disable writing to the non-volatile configuration678 * registers by calling this function.679 *680 * Returns %0 on success and negative errno in case of failure.681 */682static int smb347_set_writable(struct smb347_charger *smb, bool writable,683			       bool irq_toggle)684{685	struct i2c_client *client = to_i2c_client(smb->dev);686	int ret;687 688	if (writable && irq_toggle && !smb->irq_unsupported)689		disable_irq(client->irq);690 691	ret = regmap_update_bits(smb->regmap, CMD_A, CMD_A_ALLOW_WRITE,692				 writable ? CMD_A_ALLOW_WRITE : 0);693 694	if ((!writable || ret) && irq_toggle && !smb->irq_unsupported)695		enable_irq(client->irq);696 697	return ret;698}699 700static int smb347_hw_init(struct smb347_charger *smb)701{702	unsigned int val;703	int ret;704 705	ret = smb347_set_writable(smb, true, false);706	if (ret < 0)707		return ret;708 709	/*710	 * Program the platform specific configuration values to the device711	 * first.712	 */713	ret = smb347_set_charge_current(smb);714	if (ret < 0)715		goto fail;716 717	ret = smb347_set_current_limits(smb);718	if (ret < 0)719		goto fail;720 721	ret = smb347_set_voltage_limits(smb);722	if (ret < 0)723		goto fail;724 725	ret = smb347_set_temp_limits(smb);726	if (ret < 0)727		goto fail;728 729	/* If USB charging is disabled we put the USB in suspend mode */730	if (!smb->use_usb) {731		ret = regmap_update_bits(smb->regmap, CMD_A,732					 CMD_A_SUSPEND_ENABLED,733					 CMD_A_SUSPEND_ENABLED);734		if (ret < 0)735			goto fail;736	}737 738	/*739	 * If configured by platform data, we enable hardware Auto-OTG740	 * support for driving VBUS. Otherwise we disable it.741	 */742	ret = regmap_update_bits(smb->regmap, CFG_OTHER, CFG_OTHER_RID_MASK,743		smb->use_usb_otg ? CFG_OTHER_RID_ENABLED_AUTO_OTG : 0);744	if (ret < 0)745		goto fail;746 747	/* Activate pin control, making it writable. */748	switch (smb->enable_control) {749	case SMB3XX_CHG_ENABLE_PIN_ACTIVE_LOW:750	case SMB3XX_CHG_ENABLE_PIN_ACTIVE_HIGH:751		ret = regmap_set_bits(smb->regmap, CFG_PIN, CFG_PIN_EN_CTRL);752		if (ret < 0)753			goto fail;754	}755 756	/*757	 * Make the charging functionality controllable by a write to the758	 * command register unless pin control is specified in the platform759	 * data.760	 */761	switch (smb->enable_control) {762	case SMB3XX_CHG_ENABLE_PIN_ACTIVE_LOW:763		val = CFG_PIN_EN_CTRL_ACTIVE_LOW;764		break;765	case SMB3XX_CHG_ENABLE_PIN_ACTIVE_HIGH:766		val = CFG_PIN_EN_CTRL_ACTIVE_HIGH;767		break;768	default:769		val = 0;770		break;771	}772 773	ret = regmap_update_bits(smb->regmap, CFG_PIN, CFG_PIN_EN_CTRL_MASK,774				 val);775	if (ret < 0)776		goto fail;777 778	/* Disable Automatic Power Source Detection (APSD) interrupt. */779	ret = regmap_update_bits(smb->regmap, CFG_PIN, CFG_PIN_EN_APSD_IRQ, 0);780	if (ret < 0)781		goto fail;782 783	ret = smb347_update_ps_status(smb);784	if (ret < 0)785		goto fail;786 787	ret = smb347_start_stop_charging(smb);788 789fail:790	smb347_set_writable(smb, false, false);791	return ret;792}793 794static irqreturn_t smb347_interrupt(int irq, void *data)795{796	struct smb347_charger *smb = data;797	unsigned int stat_c, irqstat_c, irqstat_d, irqstat_e;798	bool handled = false;799	int ret;800 801	/* SMB347 it needs at least 20ms for setting IRQSTAT_E_*IN_UV_IRQ */802	usleep_range(25000, 35000);803 804	ret = regmap_read(smb->regmap, STAT_C, &stat_c);805	if (ret < 0) {806		dev_warn(smb->dev, "reading STAT_C failed\n");807		return IRQ_NONE;808	}809 810	ret = regmap_read(smb->regmap, IRQSTAT_C, &irqstat_c);811	if (ret < 0) {812		dev_warn(smb->dev, "reading IRQSTAT_C failed\n");813		return IRQ_NONE;814	}815 816	ret = regmap_read(smb->regmap, IRQSTAT_D, &irqstat_d);817	if (ret < 0) {818		dev_warn(smb->dev, "reading IRQSTAT_D failed\n");819		return IRQ_NONE;820	}821 822	ret = regmap_read(smb->regmap, IRQSTAT_E, &irqstat_e);823	if (ret < 0) {824		dev_warn(smb->dev, "reading IRQSTAT_E failed\n");825		return IRQ_NONE;826	}827 828	/*829	 * If we get charger error we report the error back to user.830	 * If the error is recovered charging will resume again.831	 */832	if (stat_c & STAT_C_CHARGER_ERROR) {833		dev_err(smb->dev, "charging stopped due to charger error\n");834		if (smb->use_mains)835			power_supply_changed(smb->mains);836		if (smb->use_usb)837			power_supply_changed(smb->usb);838		handled = true;839	}840 841	/*842	 * If we reached the termination current the battery is charged and843	 * we can update the status now. Charging is automatically844	 * disabled by the hardware.845	 */846	if (irqstat_c & (IRQSTAT_C_TERMINATION_IRQ | IRQSTAT_C_TAPER_IRQ)) {847		if (irqstat_c & IRQSTAT_C_TERMINATION_STAT) {848			if (smb->use_mains)849				power_supply_changed(smb->mains);850			if (smb->use_usb)851				power_supply_changed(smb->usb);852		}853		dev_dbg(smb->dev, "going to HW maintenance mode\n");854		handled = true;855	}856 857	/*858	 * If we got a charger timeout INT that means the charge859	 * full is not detected with in charge timeout value.860	 */861	if (irqstat_d & IRQSTAT_D_CHARGE_TIMEOUT_IRQ) {862		dev_dbg(smb->dev, "total Charge Timeout INT received\n");863 864		if (irqstat_d & IRQSTAT_D_CHARGE_TIMEOUT_STAT)865			dev_warn(smb->dev, "charging stopped due to timeout\n");866		if (smb->use_mains)867			power_supply_changed(smb->mains);868		if (smb->use_usb)869			power_supply_changed(smb->usb);870		handled = true;871	}872 873	/*874	 * If we got an under voltage interrupt it means that AC/USB input875	 * was connected or disconnected.876	 */877	if (irqstat_e & (IRQSTAT_E_USBIN_UV_IRQ | IRQSTAT_E_DCIN_UV_IRQ)) {878		if (smb347_update_ps_status(smb) > 0) {879			smb347_start_stop_charging(smb);880			if (smb->use_mains)881				power_supply_changed(smb->mains);882			if (smb->use_usb)883				power_supply_changed(smb->usb);884		}885		handled = true;886	}887 888	return handled ? IRQ_HANDLED : IRQ_NONE;889}890 891static int smb347_irq_set(struct smb347_charger *smb, bool enable)892{893	int ret;894 895	if (smb->irq_unsupported)896		return 0;897 898	ret = smb347_set_writable(smb, true, true);899	if (ret < 0)900		return ret;901 902	/*903	 * Enable/disable interrupts for:904	 *	- under voltage905	 *	- termination current reached906	 *	- charger timeout907	 *	- charger error908	 */909	ret = regmap_update_bits(smb->regmap, CFG_FAULT_IRQ, 0xff,910				 enable ? CFG_FAULT_IRQ_DCIN_UV : 0);911	if (ret < 0)912		goto fail;913 914	ret = regmap_update_bits(smb->regmap, CFG_STATUS_IRQ, 0xff,915			enable ? (CFG_STATUS_IRQ_TERMINATION_OR_TAPER |916					CFG_STATUS_IRQ_CHARGE_TIMEOUT) : 0);917	if (ret < 0)918		goto fail;919 920	ret = regmap_update_bits(smb->regmap, CFG_PIN, CFG_PIN_EN_CHARGER_ERROR,921				 enable ? CFG_PIN_EN_CHARGER_ERROR : 0);922fail:923	smb347_set_writable(smb, false, true);924	return ret;925}926 927static inline int smb347_irq_enable(struct smb347_charger *smb)928{929	return smb347_irq_set(smb, true);930}931 932static inline int smb347_irq_disable(struct smb347_charger *smb)933{934	return smb347_irq_set(smb, false);935}936 937static int smb347_irq_init(struct smb347_charger *smb,938			   struct i2c_client *client)939{940	int ret;941 942	smb->irq_unsupported = true;943 944	/*945	 * Interrupt pin is optional. If it is connected, we setup the946	 * interrupt support here.947	 */948	if (!client->irq)949		return 0;950 951	ret = smb347_set_writable(smb, true, false);952	if (ret < 0)953		return ret;954 955	/*956	 * Configure the STAT output to be suitable for interrupts: disable957	 * all other output (except interrupts) and make it active low.958	 */959	ret = regmap_update_bits(smb->regmap, CFG_STAT,960				 CFG_STAT_ACTIVE_HIGH | CFG_STAT_DISABLED,961				 CFG_STAT_DISABLED);962 963	smb347_set_writable(smb, false, false);964 965	if (ret < 0) {966		dev_warn(smb->dev, "failed to initialize IRQ: %d\n", ret);967		dev_warn(smb->dev, "disabling IRQ support\n");968		return 0;969	}970 971	ret = devm_request_threaded_irq(smb->dev, client->irq, NULL,972					smb347_interrupt, IRQF_ONESHOT,973					client->name, smb);974	if (ret)975		return ret;976 977	smb->irq_unsupported = false;978 979	ret = smb347_irq_enable(smb);980	if (ret < 0)981		return ret;982 983	return 0;984}985 986/*987 * Returns the constant charge current programmed988 * into the charger in uA.989 */990static int get_const_charge_current(struct smb347_charger *smb)991{992	unsigned int id = smb->id;993	int ret, intval;994	unsigned int v;995 996	if (!smb347_is_ps_online(smb))997		return -ENODATA;998 999	ret = regmap_read(smb->regmap, STAT_B, &v);1000	if (ret < 0)1001		return ret;1002 1003	/*1004	 * The current value is composition of FCC and PCC values1005	 * and we can detect which table to use from bit 5.1006	 */1007	if (v & 0x20) {1008		intval = hw_to_current(fcc_tbl[id],1009				       ARRAY_SIZE(fcc_tbl[id]), v & 7);1010	} else {1011		v >>= 3;1012		intval = hw_to_current(pcc_tbl[id],1013				       ARRAY_SIZE(pcc_tbl[id]), v & 7);1014	}1015 1016	return intval;1017}1018 1019/*1020 * Returns the constant charge voltage programmed1021 * into the charger in uV.1022 */1023static int get_const_charge_voltage(struct smb347_charger *smb)1024{1025	int ret, intval;1026	unsigned int v;1027 1028	if (!smb347_is_ps_online(smb))1029		return -ENODATA;1030 1031	ret = regmap_read(smb->regmap, STAT_A, &v);1032	if (ret < 0)1033		return ret;1034 1035	v &= STAT_A_FLOAT_VOLTAGE_MASK;1036	if (v > 0x3d)1037		v = 0x3d;1038 1039	intval = 3500000 + v * 20000;1040 1041	return intval;1042}1043 1044static int smb347_get_charging_status(struct smb347_charger *smb,1045				      struct power_supply *psy)1046{1047	int ret, status;1048	unsigned int val;1049 1050	if (psy->desc->type == POWER_SUPPLY_TYPE_USB) {1051		if (!smb->usb_online)1052			return POWER_SUPPLY_STATUS_DISCHARGING;1053	} else {1054		if (!smb->mains_online)1055			return POWER_SUPPLY_STATUS_DISCHARGING;1056	}1057 1058	ret = regmap_read(smb->regmap, STAT_C, &val);1059	if (ret < 0)1060		return ret;1061 1062	if ((val & STAT_C_CHARGER_ERROR) ||1063			(val & STAT_C_HOLDOFF_STAT)) {1064		/*1065		 * set to NOT CHARGING upon charger error1066		 * or charging has stopped.1067		 */1068		status = POWER_SUPPLY_STATUS_NOT_CHARGING;1069	} else {1070		if ((val & STAT_C_CHG_MASK) >> STAT_C_CHG_SHIFT) {1071			/*1072			 * set to charging if battery is in pre-charge,1073			 * fast charge or taper charging mode.1074			 */1075			status = POWER_SUPPLY_STATUS_CHARGING;1076		} else if (val & STAT_C_CHG_TERM) {1077			/*1078			 * set the status to FULL if battery is not in pre1079			 * charge, fast charge or taper charging mode AND1080			 * charging is terminated at least once.1081			 */1082			status = POWER_SUPPLY_STATUS_FULL;1083		} else {1084			/*1085			 * in this case no charger error or termination1086			 * occured but charging is not in progress!!!1087			 */1088			status = POWER_SUPPLY_STATUS_NOT_CHARGING;1089		}1090	}1091 1092	return status;1093}1094 1095static int smb347_get_property_locked(struct power_supply *psy,1096				      enum power_supply_property prop,1097				      union power_supply_propval *val)1098{1099	struct smb347_charger *smb = power_supply_get_drvdata(psy);1100	int ret;1101 1102	switch (prop) {1103	case POWER_SUPPLY_PROP_STATUS:1104		ret = smb347_get_charging_status(smb, psy);1105		if (ret < 0)1106			return ret;1107		val->intval = ret;1108		break;1109 1110	case POWER_SUPPLY_PROP_CHARGE_TYPE:1111		if (psy->desc->type == POWER_SUPPLY_TYPE_USB) {1112			if (!smb->usb_online)1113				return -ENODATA;1114		} else {1115			if (!smb->mains_online)1116				return -ENODATA;1117		}1118 1119		/*1120		 * We handle trickle and pre-charging the same, and taper1121		 * and none the same.1122		 */1123		switch (smb347_charging_status(smb)) {1124		case 1:1125			val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;1126			break;1127		case 2:1128			val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST;1129			break;1130		default:1131			val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;1132			break;1133		}1134		break;1135 1136	case POWER_SUPPLY_PROP_ONLINE:1137		if (psy->desc->type == POWER_SUPPLY_TYPE_USB)1138			val->intval = smb->usb_online;1139		else1140			val->intval = smb->mains_online;1141		break;1142 1143	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:1144		ret = get_const_charge_voltage(smb);1145		if (ret < 0)1146			return ret;1147		val->intval = ret;1148		break;1149 1150	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:1151		ret = get_const_charge_current(smb);1152		if (ret < 0)1153			return ret;1154		val->intval = ret;1155		break;1156 1157	default:1158		return -EINVAL;1159	}1160 1161	return 0;1162}1163 1164static int smb347_get_property(struct power_supply *psy,1165			       enum power_supply_property prop,1166			       union power_supply_propval *val)1167{1168	struct smb347_charger *smb = power_supply_get_drvdata(psy);1169	struct i2c_client *client = to_i2c_client(smb->dev);1170	int ret;1171 1172	if (!smb->irq_unsupported)1173		disable_irq(client->irq);1174 1175	ret = smb347_get_property_locked(psy, prop, val);1176 1177	if (!smb->irq_unsupported)1178		enable_irq(client->irq);1179 1180	return ret;1181}1182 1183static enum power_supply_property smb347_properties[] = {1184	POWER_SUPPLY_PROP_STATUS,1185	POWER_SUPPLY_PROP_CHARGE_TYPE,1186	POWER_SUPPLY_PROP_ONLINE,1187	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,1188	POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,1189};1190 1191static bool smb347_volatile_reg(struct device *dev, unsigned int reg)1192{1193	switch (reg) {1194	case IRQSTAT_A:1195	case IRQSTAT_C:1196	case IRQSTAT_D:1197	case IRQSTAT_E:1198	case IRQSTAT_F:1199	case STAT_A:1200	case STAT_B:1201	case STAT_C:1202	case STAT_E:1203		return true;1204	}1205 1206	return false;1207}1208 1209static bool smb347_readable_reg(struct device *dev, unsigned int reg)1210{1211	switch (reg) {1212	case CFG_CHARGE_CURRENT:1213	case CFG_CURRENT_LIMIT:1214	case CFG_FLOAT_VOLTAGE:1215	case CFG_STAT:1216	case CFG_PIN:1217	case CFG_THERM:1218	case CFG_SYSOK:1219	case CFG_OTHER:1220	case CFG_OTG:1221	case CFG_TEMP_LIMIT:1222	case CFG_FAULT_IRQ:1223	case CFG_STATUS_IRQ:1224	case CFG_ADDRESS:1225	case CMD_A:1226	case CMD_B:1227	case CMD_C:1228		return true;1229	}1230 1231	return smb347_volatile_reg(dev, reg);1232}1233 1234static void smb347_dt_parse_dev_info(struct smb347_charger *smb)1235{1236	struct device *dev = smb->dev;1237 1238	smb->soft_temp_limit_compensation =1239					SMB3XX_SOFT_TEMP_COMPENSATE_DEFAULT;1240	/*1241	 * These properties come from the battery info, still we need to1242	 * pre-initialize the values. See smb347_get_battery_info() below.1243	 */1244	smb->soft_cold_temp_limit = SMB3XX_TEMP_USE_DEFAULT;1245	smb->hard_cold_temp_limit = SMB3XX_TEMP_USE_DEFAULT;1246	smb->soft_hot_temp_limit  = SMB3XX_TEMP_USE_DEFAULT;1247	smb->hard_hot_temp_limit  = SMB3XX_TEMP_USE_DEFAULT;1248 1249	/* Charging constraints */1250	device_property_read_u32(dev, "summit,fast-voltage-threshold-microvolt",1251				 &smb->pre_to_fast_voltage);1252	device_property_read_u32(dev, "summit,mains-current-limit-microamp",1253				 &smb->mains_current_limit);1254	device_property_read_u32(dev, "summit,usb-current-limit-microamp",1255				 &smb->usb_hc_current_limit);1256 1257	/* For thermometer monitoring */1258	device_property_read_u32(dev, "summit,chip-temperature-threshold-celsius",1259				 &smb->chip_temp_threshold);1260	device_property_read_u32(dev, "summit,soft-compensation-method",1261				 &smb->soft_temp_limit_compensation);1262	device_property_read_u32(dev, "summit,charge-current-compensation-microamp",1263				 &smb->charge_current_compensation);1264 1265	/* Supported charging mode */1266	smb->use_mains = device_property_read_bool(dev, "summit,enable-mains-charging");1267	smb->use_usb = device_property_read_bool(dev, "summit,enable-usb-charging");1268	smb->use_usb_otg = device_property_read_bool(dev, "summit,enable-otg-charging");1269 1270	/* Select charging control */1271	device_property_read_u32(dev, "summit,enable-charge-control",1272				 &smb->enable_control);1273 1274	/*1275	 * Polarity of INOK signal indicating presence of external power1276	 * supply connected to the charger.1277	 */1278	device_property_read_u32(dev, "summit,inok-polarity",1279				 &smb->inok_polarity);1280}1281 1282static int smb347_get_battery_info(struct smb347_charger *smb)1283{1284	struct power_supply_battery_info *info;1285	struct power_supply *supply;1286	int err;1287 1288	if (smb->mains)1289		supply = smb->mains;1290	else1291		supply = smb->usb;1292 1293	err = power_supply_get_battery_info(supply, &info);1294	if (err == -ENXIO || err == -ENODEV)1295		return 0;1296	if (err)1297		return err;1298 1299	if (info->constant_charge_current_max_ua != -EINVAL)1300		smb->max_charge_current = info->constant_charge_current_max_ua;1301 1302	if (info->constant_charge_voltage_max_uv != -EINVAL)1303		smb->max_charge_voltage = info->constant_charge_voltage_max_uv;1304 1305	if (info->precharge_current_ua != -EINVAL)1306		smb->pre_charge_current = info->precharge_current_ua;1307 1308	if (info->charge_term_current_ua != -EINVAL)1309		smb->termination_current = info->charge_term_current_ua;1310 1311	if (info->temp_alert_min != INT_MIN)1312		smb->soft_cold_temp_limit = info->temp_alert_min;1313 1314	if (info->temp_alert_max != INT_MAX)1315		smb->soft_hot_temp_limit = info->temp_alert_max;1316 1317	if (info->temp_min != INT_MIN)1318		smb->hard_cold_temp_limit = info->temp_min;1319 1320	if (info->temp_max != INT_MAX)1321		smb->hard_hot_temp_limit = info->temp_max;1322 1323	/* Suspend when battery temperature is outside hard limits */1324	if (smb->hard_cold_temp_limit != SMB3XX_TEMP_USE_DEFAULT ||1325	    smb->hard_hot_temp_limit != SMB3XX_TEMP_USE_DEFAULT)1326		smb->suspend_on_hard_temp_limit = true;1327 1328	return 0;1329}1330 1331static int smb347_usb_vbus_get_current_limit(struct regulator_dev *rdev)1332{1333	struct smb347_charger *smb = rdev_get_drvdata(rdev);1334	unsigned int val;1335	int ret;1336 1337	ret = regmap_read(smb->regmap, CFG_OTG, &val);1338	if (ret < 0)1339		return ret;1340 1341	/*1342	 * It's unknown what happens if this bit is unset due to lack of1343	 * access to the datasheet, assume it's limit-enable.1344	 */1345	if (!(val & CFG_OTG_CURRENT_LIMIT_250mA))1346		return 0;1347 1348	return val & CFG_OTG_CURRENT_LIMIT_750mA ? 750000 : 250000;1349}1350 1351static int smb347_usb_vbus_set_new_current_limit(struct smb347_charger *smb,1352						 int max_uA)1353{1354	const unsigned int mask = CFG_OTG_CURRENT_LIMIT_750mA |1355				  CFG_OTG_CURRENT_LIMIT_250mA;1356	unsigned int val = CFG_OTG_CURRENT_LIMIT_250mA;1357	int ret;1358 1359	if (max_uA >= 750000)1360		val |= CFG_OTG_CURRENT_LIMIT_750mA;1361 1362	ret = regmap_update_bits(smb->regmap, CFG_OTG, mask, val);1363	if (ret < 0)1364		dev_err(smb->dev, "failed to change USB current limit\n");1365 1366	return ret;1367}1368 1369static int smb347_usb_vbus_set_current_limit(struct regulator_dev *rdev,1370					     int min_uA, int max_uA)1371{1372	struct smb347_charger *smb = rdev_get_drvdata(rdev);1373	int ret;1374 1375	ret = smb347_set_writable(smb, true, true);1376	if (ret < 0)1377		return ret;1378 1379	ret = smb347_usb_vbus_set_new_current_limit(smb, max_uA);1380	smb347_set_writable(smb, false, true);1381 1382	return ret;1383}1384 1385static int smb347_usb_vbus_regulator_enable(struct regulator_dev *rdev)1386{1387	struct smb347_charger *smb = rdev_get_drvdata(rdev);1388	int ret, max_uA;1389 1390	ret = smb347_set_writable(smb, true, true);1391	if (ret < 0)1392		return ret;1393 1394	smb347_charging_disable(smb);1395 1396	if (device_property_read_bool(&rdev->dev, "summit,needs-inok-toggle")) {1397		unsigned int sysok = 0;1398 1399		if (smb->inok_polarity == SMB3XX_SYSOK_INOK_ACTIVE_LOW)1400			sysok = CFG_SYSOK_INOK_ACTIVE_HIGH;1401 1402		/*1403		 * VBUS won't be powered if INOK is active, so we need to1404		 * manually disable INOK on some platforms.1405		 */1406		ret = regmap_update_bits(smb->regmap, CFG_SYSOK,1407					 CFG_SYSOK_INOK_ACTIVE_HIGH, sysok);1408		if (ret < 0) {1409			dev_err(smb->dev, "failed to disable INOK\n");1410			goto done;1411		}1412	}1413 1414	ret = smb347_usb_vbus_get_current_limit(rdev);1415	if (ret < 0) {1416		dev_err(smb->dev, "failed to get USB VBUS current limit\n");1417		goto done;1418	}1419 1420	max_uA = ret;1421 1422	ret = smb347_usb_vbus_set_new_current_limit(smb, 250000);1423	if (ret < 0) {1424		dev_err(smb->dev, "failed to preset USB VBUS current limit\n");1425		goto done;1426	}1427 1428	ret = regmap_set_bits(smb->regmap, CMD_A, CMD_A_OTG_ENABLED);1429	if (ret < 0) {1430		dev_err(smb->dev, "failed to enable USB VBUS\n");1431		goto done;1432	}1433 1434	smb->usb_vbus_enabled = true;1435 1436	ret = smb347_usb_vbus_set_new_current_limit(smb, max_uA);1437	if (ret < 0) {1438		dev_err(smb->dev, "failed to restore USB VBUS current limit\n");1439		goto done;1440	}1441done:1442	smb347_set_writable(smb, false, true);1443 1444	return ret;1445}1446 1447static int smb347_usb_vbus_regulator_disable(struct regulator_dev *rdev)1448{1449	struct smb347_charger *smb = rdev_get_drvdata(rdev);1450	int ret;1451 1452	ret = smb347_set_writable(smb, true, true);1453	if (ret < 0)1454		return ret;1455 1456	ret = regmap_clear_bits(smb->regmap, CMD_A, CMD_A_OTG_ENABLED);1457	if (ret < 0) {1458		dev_err(smb->dev, "failed to disable USB VBUS\n");1459		goto done;1460	}1461 1462	smb->usb_vbus_enabled = false;1463 1464	if (device_property_read_bool(&rdev->dev, "summit,needs-inok-toggle")) {1465		unsigned int sysok = 0;1466 1467		if (smb->inok_polarity == SMB3XX_SYSOK_INOK_ACTIVE_HIGH)1468			sysok = CFG_SYSOK_INOK_ACTIVE_HIGH;1469 1470		ret = regmap_update_bits(smb->regmap, CFG_SYSOK,1471					 CFG_SYSOK_INOK_ACTIVE_HIGH, sysok);1472		if (ret < 0) {1473			dev_err(smb->dev, "failed to enable INOK\n");1474			goto done;1475		}1476	}1477 1478	smb347_start_stop_charging(smb);1479done:1480	smb347_set_writable(smb, false, true);1481 1482	return ret;1483}1484 1485static const struct regmap_config smb347_regmap = {1486	.reg_bits	= 8,1487	.val_bits	= 8,1488	.max_register	= SMB347_MAX_REGISTER,1489	.volatile_reg	= smb347_volatile_reg,1490	.readable_reg	= smb347_readable_reg,1491	.cache_type	= REGCACHE_RBTREE,1492};1493 1494static const struct regulator_ops smb347_usb_vbus_regulator_ops = {1495	.is_enabled	= regulator_is_enabled_regmap,1496	.enable		= smb347_usb_vbus_regulator_enable,1497	.disable	= smb347_usb_vbus_regulator_disable,1498	.get_current_limit = smb347_usb_vbus_get_current_limit,1499	.set_current_limit = smb347_usb_vbus_set_current_limit,1500};1501 1502static const struct power_supply_desc smb347_mains_desc = {1503	.name		= "smb347-mains",1504	.type		= POWER_SUPPLY_TYPE_MAINS,1505	.get_property	= smb347_get_property,1506	.properties	= smb347_properties,1507	.num_properties	= ARRAY_SIZE(smb347_properties),1508};1509 1510static const struct power_supply_desc smb347_usb_desc = {1511	.name		= "smb347-usb",1512	.type		= POWER_SUPPLY_TYPE_USB,1513	.get_property	= smb347_get_property,1514	.properties	= smb347_properties,1515	.num_properties	= ARRAY_SIZE(smb347_properties),1516};1517 1518static const struct regulator_desc smb347_usb_vbus_regulator_desc = {1519	.name		= "smb347-usb-vbus",1520	.of_match	= of_match_ptr("usb-vbus"),1521	.ops		= &smb347_usb_vbus_regulator_ops,1522	.type		= REGULATOR_VOLTAGE,1523	.owner		= THIS_MODULE,1524	.enable_reg	= CMD_A,1525	.enable_mask	= CMD_A_OTG_ENABLED,1526	.enable_val	= CMD_A_OTG_ENABLED,1527	.fixed_uV	= 5000000,1528	.n_voltages	= 1,1529};1530 1531static int smb347_probe(struct i2c_client *client)1532{1533	const struct i2c_device_id *id = i2c_client_get_device_id(client);1534	struct power_supply_config mains_usb_cfg = {};1535	struct regulator_config usb_rdev_cfg = {};1536	struct device *dev = &client->dev;1537	struct smb347_charger *smb;1538	int ret;1539 1540	smb = devm_kzalloc(dev, sizeof(*smb), GFP_KERNEL);1541	if (!smb)1542		return -ENOMEM;1543	smb->dev = &client->dev;1544	smb->id = id->driver_data;1545	i2c_set_clientdata(client, smb);1546 1547	smb347_dt_parse_dev_info(smb);1548	if (!smb->use_mains && !smb->use_usb)1549		return -EINVAL;1550 1551	smb->regmap = devm_regmap_init_i2c(client, &smb347_regmap);1552	if (IS_ERR(smb->regmap))1553		return PTR_ERR(smb->regmap);1554 1555	mains_usb_cfg.drv_data = smb;1556	mains_usb_cfg.of_node = dev->of_node;1557	if (smb->use_mains) {1558		smb->mains = devm_power_supply_register(dev, &smb347_mains_desc,1559							&mains_usb_cfg);1560		if (IS_ERR(smb->mains))1561			return PTR_ERR(smb->mains);1562	}1563 1564	if (smb->use_usb) {1565		smb->usb = devm_power_supply_register(dev, &smb347_usb_desc,1566						      &mains_usb_cfg);1567		if (IS_ERR(smb->usb))1568			return PTR_ERR(smb->usb);1569	}1570 1571	ret = smb347_get_battery_info(smb);1572	if (ret)1573		return ret;1574 1575	ret = smb347_hw_init(smb);1576	if (ret < 0)1577		return ret;1578 1579	ret = smb347_irq_init(smb, client);1580	if (ret)1581		return ret;1582 1583	usb_rdev_cfg.dev = dev;1584	usb_rdev_cfg.driver_data = smb;1585	usb_rdev_cfg.regmap = smb->regmap;1586 1587	smb->usb_rdev = devm_regulator_register(dev,1588						&smb347_usb_vbus_regulator_desc,1589						&usb_rdev_cfg);1590	if (IS_ERR(smb->usb_rdev)) {1591		smb347_irq_disable(smb);1592		return PTR_ERR(smb->usb_rdev);1593	}1594 1595	return 0;1596}1597 1598static void smb347_remove(struct i2c_client *client)1599{1600	struct smb347_charger *smb = i2c_get_clientdata(client);1601 1602	smb347_usb_vbus_regulator_disable(smb->usb_rdev);1603	smb347_irq_disable(smb);1604}1605 1606static void smb347_shutdown(struct i2c_client *client)1607{1608	smb347_remove(client);1609}1610 1611static const struct i2c_device_id smb347_id[] = {1612	{ "smb345", SMB345 },1613	{ "smb347", SMB347 },1614	{ "smb358", SMB358 },1615	{ },1616};1617MODULE_DEVICE_TABLE(i2c, smb347_id);1618 1619static const struct of_device_id smb3xx_of_match[] = {1620	{ .compatible = "summit,smb345" },1621	{ .compatible = "summit,smb347" },1622	{ .compatible = "summit,smb358" },1623	{ },1624};1625MODULE_DEVICE_TABLE(of, smb3xx_of_match);1626 1627static struct i2c_driver smb347_driver = {1628	.driver = {1629		.name = "smb347",1630		.of_match_table = smb3xx_of_match,1631	},1632	.probe = smb347_probe,1633	.remove = smb347_remove,1634	.shutdown = smb347_shutdown,1635	.id_table = smb347_id,1636};1637module_i2c_driver(smb347_driver);1638 1639MODULE_AUTHOR("Bruce E. Robertson <bruce.e.robertson@intel.com>");1640MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");1641MODULE_DESCRIPTION("SMB347 battery charger driver");1642MODULE_LICENSE("GPL");1643