Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d19eac45 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: qpnp-power-on : avoid overriding value of boot_reason"

parents 271d6821 bc76024c
Loading
Loading
Loading
Loading
+5 −0
Original line number Original line Diff line number Diff line
@@ -56,6 +56,10 @@ Optional properties:
				reset through qcom,system-reset property.
				reset through qcom,system-reset property.
				This should not be defined along with the
				This should not be defined along with the
				qcom,system-reset property.
				qcom,system-reset property.
- qcom,store-hard-reset-reason	Boolean property which if set will store the hardware
				reset reason to SOFT_RB_SPARE register of the core PMIC
				PON peripheral.



All the below properties are in the sub-node section (properties of the child
All the below properties are in the sub-node section (properties of the child
node).
node).
@@ -113,6 +117,7 @@ Example:
		qcom,s3-debounce = <32>;
		qcom,s3-debounce = <32>;
		qcom,s3-src = "resin";
		qcom,s3-src = "resin";
		qcom,clear-warm-reset;
		qcom,clear-warm-reset;
		qcom,store-hard-reset-reason;


		qcom,pon_1 {
		qcom,pon_1 {
			qcom,pon-type = <0>;
			qcom,pon-type = <0>;
+65 −1
Original line number Original line Diff line number Diff line
@@ -27,6 +27,11 @@
#include <linux/log2.h>
#include <linux/log2.h>
#include <linux/qpnp/power-on.h>
#include <linux/qpnp/power-on.h>


#define CREATE_MASK(NUM_BITS, POS) \
	((unsigned char) (((1 << (NUM_BITS)) - 1) << (POS)))
#define PON_MASK(MSB_BIT, LSB_BIT) \
	CREATE_MASK(MSB_BIT - LSB_BIT + 1, LSB_BIT)

#define PMIC_VER_8941           0x01
#define PMIC_VER_8941           0x01
#define PMIC_VERSION_REG        0x0105
#define PMIC_VERSION_REG        0x0105
#define PMIC_VERSION_REV4_REG   0x0103
#define PMIC_VERSION_REV4_REG   0x0103
@@ -68,6 +73,7 @@
#define QPNP_PON_S3_DBC_CTL(base)		(base + 0x75)
#define QPNP_PON_S3_DBC_CTL(base)		(base + 0x75)
#define QPNP_PON_TRIGGER_EN(base)		(base + 0x80)
#define QPNP_PON_TRIGGER_EN(base)		(base + 0x80)
#define QPNP_PON_XVDD_RB_SPARE(base)		(base + 0x8E)
#define QPNP_PON_XVDD_RB_SPARE(base)		(base + 0x8E)
#define QPNP_PON_SOFT_RB_SPARE(base)		(base + 0x8F)
#define QPNP_PON_SEC_ACCESS(base)		(base + 0xD0)
#define QPNP_PON_SEC_ACCESS(base)		(base + 0xD0)


#define QPNP_PON_SEC_UNLOCK			0xA5
#define QPNP_PON_SEC_UNLOCK			0xA5
@@ -101,6 +107,7 @@
#define QPNP_PON_S3_SRC_KPDPWR_AND_RESIN	2
#define QPNP_PON_S3_SRC_KPDPWR_AND_RESIN	2
#define QPNP_PON_S3_SRC_KPDPWR_OR_RESIN		3
#define QPNP_PON_S3_SRC_KPDPWR_OR_RESIN		3
#define QPNP_PON_S3_SRC_MASK			0x3
#define QPNP_PON_S3_SRC_MASK			0x3
#define QPNP_PON_HARD_RESET_MASK		PON_MASK(7, 5)


#define QPNP_PON_UVLO_DLOAD_EN		BIT(7)
#define QPNP_PON_UVLO_DLOAD_EN		BIT(7)


@@ -160,6 +167,7 @@ struct qpnp_pon {
	u8 warm_reset_reason1;
	u8 warm_reset_reason1;
	u8 warm_reset_reason2;
	u8 warm_reset_reason2;
	bool is_spon;
	bool is_spon;
	bool store_hard_reset_reason;
};
};


static struct qpnp_pon *sys_reset_dev;
static struct qpnp_pon *sys_reset_dev;
@@ -235,6 +243,56 @@ qpnp_pon_masked_write(struct qpnp_pon *pon, u16 addr, u8 mask, u8 val)
	return rc;
	return rc;
}
}


/**
 * qpnp_pon_set_restart_reason - Store device restart reason in PMIC register.
 *
 * Returns = 0 if PMIC feature is not available or store restart reason
 * successfully.
 * Returns > 0 for errors
 *
 * This function is used to store device restart reason in PMIC register.
 * It checks here to see if the restart reason register has been specified.
 * If it hasn't, this function should immediately return 0
 */
int qpnp_pon_set_restart_reason(enum pon_restart_reason reason)
{
	int rc = 0;
	struct qpnp_pon *pon = sys_reset_dev;

	if (!pon)
		return 0;

	if (!pon->store_hard_reset_reason)
		return 0;

	rc = qpnp_pon_masked_write(pon, QPNP_PON_SOFT_RB_SPARE(pon->base),
					PON_MASK(7, 5), (reason << 5));
	if (rc)
		dev_err(&pon->spmi->dev,
				"Unable to write to addr=%x, rc(%d)\n",
				QPNP_PON_SOFT_RB_SPARE(pon->base), rc);
	return rc;
}
EXPORT_SYMBOL(qpnp_pon_set_restart_reason);

/*
 * qpnp_pon_check_hard_reset_stored - Checks if the PMIC need to
 * store hard reset reason.
 *
 * Returns true if reset reason can be stored, false if it cannot be stored
 *
 */
bool qpnp_pon_check_hard_reset_stored(void)
{
	struct qpnp_pon *pon = sys_reset_dev;

	if (!pon)
		return false;

	return pon->store_hard_reset_reason;
}
EXPORT_SYMBOL(qpnp_pon_check_hard_reset_stored);

static int qpnp_pon_set_dbc(struct qpnp_pon *pon, u32 delay)
static int qpnp_pon_set_dbc(struct qpnp_pon *pon, u32 delay)
{
{
	int rc = 0;
	int rc = 0;
@@ -1564,7 +1622,6 @@ static int qpnp_pon_probe(struct spmi_device *spmi)
		return rc;
		return rc;
	}
	}


	boot_reason = ffs(pon_sts);


	index = ffs(pon_sts) - 1;
	index = ffs(pon_sts) - 1;
	cold_boot = !qpnp_pon_is_warm_reset();
	cold_boot = !qpnp_pon_is_warm_reset();
@@ -1720,8 +1777,15 @@ static int qpnp_pon_probe(struct spmi_device *spmi)
		list_add(&pon->list, &spon_dev_list);
		list_add(&pon->list, &spon_dev_list);
		mutex_unlock(&spon_list_mutex);
		mutex_unlock(&spon_list_mutex);
		pon->is_spon = true;
		pon->is_spon = true;
	} else {
		boot_reason = ffs(pon_sts);
	}
	}


	/* config whether store the hard reset reason */
	pon->store_hard_reset_reason = of_property_read_bool(
					spmi->dev.of_node,
					"qcom,store-hard-reset-reason");

	qpnp_pon_debugfs_init(spmi);
	qpnp_pon_debugfs_init(spmi);
	return 0;
	return 0;
}
}
+225 −2
Original line number Original line Diff line number Diff line
@@ -100,6 +100,15 @@ enum pmic_subtype {
	PMI8950		= 17,
	PMI8950		= 17,
};
};


enum wa_flags {
	IADC_GAIN_COMP_WA = BIT(0),
};

enum current_sense_type {
	INTERNAL_CURRENT_SENSE,
	EXTERNAL_CURRENT_SENSE,
};

struct fg_mem_setting {
struct fg_mem_setting {
	u16	address;
	u16	address;
	u8	offset;
	u8	offset;
@@ -151,6 +160,12 @@ struct fg_cyc_ctr_data {
	struct mutex		lock;
	struct mutex		lock;
};
};


struct fg_iadc_comp_data {
	u8			dfl_gain_reg[2];
	bool			gain_active;
	int64_t			dfl_gain;
};

/* FG_MEMIF setting index */
/* FG_MEMIF setting index */
enum fg_mem_setting_index {
enum fg_mem_setting_index {
	FG_MEM_SOFT_COLD = 0,
	FG_MEM_SOFT_COLD = 0,
@@ -373,6 +388,7 @@ struct fg_chip {
	u16			vbat_adc_addr;
	u16			vbat_adc_addr;
	u16			ibat_adc_addr;
	u16			ibat_adc_addr;
	u16			tp_rev_addr;
	u16			tp_rev_addr;
	u32			wa_flag;
	atomic_t		memif_user_cnt;
	atomic_t		memif_user_cnt;
	struct fg_irq		soc_irq[FG_SOC_IRQ_COUNT];
	struct fg_irq		soc_irq[FG_SOC_IRQ_COUNT];
	struct fg_irq		batt_irq[FG_BATT_IRQ_COUNT];
	struct fg_irq		batt_irq[FG_BATT_IRQ_COUNT];
@@ -394,6 +410,7 @@ struct fg_chip {
	struct work_struct	sysfs_restart_work;
	struct work_struct	sysfs_restart_work;
	struct work_struct	init_work;
	struct work_struct	init_work;
	struct work_struct	charge_full_work;
	struct work_struct	charge_full_work;
	struct work_struct	gain_comp_work;
	struct power_supply	*batt_psy;
	struct power_supply	*batt_psy;
	struct power_supply	*usb_psy;
	struct power_supply	*usb_psy;
	struct power_supply	*dc_psy;
	struct power_supply	*dc_psy;
@@ -401,6 +418,7 @@ struct fg_chip {
	struct fg_wakeup_source	profile_wakeup_source;
	struct fg_wakeup_source	profile_wakeup_source;
	struct fg_wakeup_source	empty_check_wakeup_source;
	struct fg_wakeup_source	empty_check_wakeup_source;
	struct fg_wakeup_source	resume_soc_wakeup_source;
	struct fg_wakeup_source	resume_soc_wakeup_source;
	struct fg_wakeup_source	gain_comp_wakeup_source;
	bool			first_profile_loaded;
	bool			first_profile_loaded;
	struct fg_wakeup_source	update_temp_wakeup_source;
	struct fg_wakeup_source	update_temp_wakeup_source;
	struct fg_wakeup_source	update_sram_wakeup_source;
	struct fg_wakeup_source	update_sram_wakeup_source;
@@ -417,6 +435,8 @@ struct fg_chip {
	bool			vbat_low_irq_enabled;
	bool			vbat_low_irq_enabled;
	bool			charge_full;
	bool			charge_full;
	bool			hold_soc_while_full;
	bool			hold_soc_while_full;
	bool			input_present;
	bool			otg_present;
	struct delayed_work	update_jeita_setting;
	struct delayed_work	update_jeita_setting;
	struct delayed_work	update_sram_data;
	struct delayed_work	update_sram_data;
	struct delayed_work	update_temp_work;
	struct delayed_work	update_temp_work;
@@ -449,9 +469,12 @@ struct fg_chip {
	struct fg_rslow_data	rslow_comp;
	struct fg_rslow_data	rslow_comp;
	/* cycle counter */
	/* cycle counter */
	struct fg_cyc_ctr_data	cyc_ctr;
	struct fg_cyc_ctr_data	cyc_ctr;
	/* iadc compensation */
	struct fg_iadc_comp_data iadc_comp_data;
	/* interleaved memory access */
	/* interleaved memory access */
	u16			*offset;
	u16			*offset;
	bool			ima_supported;
	bool			ima_supported;
	bool			init_done;
};
};


/* FG_MEMIF DEBUGFS structures */
/* FG_MEMIF DEBUGFS structures */
@@ -1876,6 +1899,8 @@ static int64_t twos_compliment_extend(int64_t val, int nbytes)
	return val;
	return val;
}
}


#define LSB_24B_NUMRTR		596046
#define LSB_24B_DENMTR		1000000
#define LSB_16B_NUMRTR		152587
#define LSB_16B_NUMRTR		152587
#define LSB_16B_DENMTR		1000
#define LSB_16B_DENMTR		1000
#define LSB_8B		9800
#define LSB_8B		9800
@@ -3021,6 +3046,19 @@ static bool is_input_present(struct fg_chip *chip)
	return is_usb_present(chip) || is_dc_present(chip);
	return is_usb_present(chip) || is_dc_present(chip);
}
}


static bool is_otg_present(struct fg_chip *chip)
{
	union power_supply_propval prop = {0,};

	if (!chip->usb_psy)
		chip->usb_psy = power_supply_get_by_name("usb");

	if (chip->usb_psy)
		chip->usb_psy->get_property(chip->usb_psy,
				POWER_SUPPLY_PROP_USB_OTG, &prop);
	return prop.intval != 0;
}

static void status_change_work(struct work_struct *work)
static void status_change_work(struct work_struct *work)
{
{
	struct fg_chip *chip = container_of(work,
	struct fg_chip *chip = container_of(work,
@@ -3073,6 +3111,26 @@ static void status_change_work(struct work_struct *work)
	}
	}
}
}


/*
 * Check for change in the status of input or OTG and schedule
 * IADC gain compensation work.
 */
static void check_gain_compensation(struct fg_chip *chip)
{
	bool input_present = is_input_present(chip);
	bool otg_present = is_otg_present(chip);

	if ((chip->wa_flag & IADC_GAIN_COMP_WA)
		&& ((chip->input_present ^ input_present)
			|| (chip->otg_present ^ otg_present))) {
		fg_stay_awake(&chip->gain_comp_wakeup_source);
		chip->input_present = input_present;
		chip->otg_present = otg_present;
		cancel_work_sync(&chip->gain_comp_work);
		schedule_work(&chip->gain_comp_work);
	}
}

static int fg_power_set_property(struct power_supply *psy,
static int fg_power_set_property(struct power_supply *psy,
				  enum power_supply_property psp,
				  enum power_supply_property psp,
				  const union power_supply_propval *val)
				  const union power_supply_propval *val)
@@ -3095,6 +3153,7 @@ static int fg_power_set_property(struct power_supply *psy,
		chip->prev_status = chip->status;
		chip->prev_status = chip->status;
		chip->status = val->intval;
		chip->status = val->intval;
		schedule_work(&chip->status_change_work);
		schedule_work(&chip->status_change_work);
		check_gain_compensation(chip);
		break;
		break;
	case POWER_SUPPLY_PROP_HEALTH:
	case POWER_SUPPLY_PROP_HEALTH:
		chip->health = val->intval;
		chip->health = val->intval;
@@ -3242,6 +3301,96 @@ static void update_esr_value(struct work_struct *work)
	}
	}
}
}


#define TEMP_COUNTER_REG	0x580
#define VBAT_FILTERED_OFFSET	1
#define GAIN_REG		0x424
#define GAIN_OFFSET		1
#define K_VCOR_REG		0x484
#define DEF_GAIN_OFFSET		2
#define PICO_UNIT		0xE8D4A51000LL
#define ATTO_UNIT		0xDE0B6B3A7640000LL
#define VBAT_REF		3800000

/*
 * IADC Gain compensation steps:
 * If Input/OTG absent:
 *	- read VBAT_FILTERED, KVCOR, GAIN
 *	- calculate the gain compensation using following formula:
 *	  gain = (1 + gain) * (1 + kvcor * (vbat_filtered - 3800000)) - 1;
 * else
 *	- reset to the default gain compensation
 */
static void iadc_gain_comp_work(struct work_struct *work)
{
	u8 reg[4];
	int rc;
	uint64_t vbat_filtered;
	int64_t gain, kvcor, temp, numerator;
	struct fg_chip *chip = container_of(work, struct fg_chip,
							gain_comp_work);
	bool input_present = is_input_present(chip);
	bool otg_present = is_otg_present(chip);

	if (!chip->init_done)
		goto done;

	if (!input_present && !otg_present) {
		/* read VBAT_FILTERED */
		rc = fg_mem_read(chip, reg, TEMP_COUNTER_REG, 3,
						VBAT_FILTERED_OFFSET, 0);
		if (rc) {
			pr_err("Failed to read VBAT: rc=%d\n", rc);
			goto done;
		}
		temp = (reg[2] << 16) | (reg[1] << 8) | reg[0];
		vbat_filtered = div_u64((u64)temp * LSB_24B_NUMRTR,
						LSB_24B_DENMTR);

		/* read K_VCOR */
		rc = fg_mem_read(chip, reg, K_VCOR_REG, 2, 0, 0);
		if (rc) {
			pr_err("Failed to KVCOR rc=%d\n", rc);
			goto done;
		}
		kvcor = half_float(reg);

		/* calculate gain */
		numerator = (MICRO_UNIT + chip->iadc_comp_data.dfl_gain)
			* (PICO_UNIT + kvcor * (vbat_filtered - VBAT_REF))
			- ATTO_UNIT;
		gain = div64_s64(numerator, PICO_UNIT);

		/* write back gain */
		half_float_to_buffer(gain, reg);
		rc = fg_mem_write(chip, reg, GAIN_REG, 2, GAIN_OFFSET, 0);
		if (rc) {
			pr_err("Failed to write gain reg rc=%d\n", rc);
			goto done;
		}

		if (fg_debug_mask & FG_STATUS)
			pr_info("IADC gain update [%x %x]\n", reg[1], reg[0]);
		chip->iadc_comp_data.gain_active = true;
	} else {
		/* reset gain register */
		rc = fg_mem_write(chip, chip->iadc_comp_data.dfl_gain_reg,
						GAIN_REG, GAIN_OFFSET, 2, 0);
		if (rc) {
			pr_err("unable to write gain comp: %d\n", rc);
			goto done;
		}

		if (fg_debug_mask & FG_STATUS)
			pr_info("IADC gain reset [%x %x]\n",
					chip->iadc_comp_data.dfl_gain_reg[1],
					chip->iadc_comp_data.dfl_gain_reg[0]);
		chip->iadc_comp_data.gain_active = false;
	}

done:
	fg_relax(&chip->gain_comp_wakeup_source);
}

#define BATT_MISSING_STS BIT(6)
#define BATT_MISSING_STS BIT(6)
static bool is_battery_missing(struct fg_chip *chip)
static bool is_battery_missing(struct fg_chip *chip)
{
{
@@ -3385,6 +3534,12 @@ static irqreturn_t fg_soc_irq_handler(int irq, void *_chip)
	schedule_work(&chip->update_esr_work);
	schedule_work(&chip->update_esr_work);
	if (chip->charge_full)
	if (chip->charge_full)
		schedule_work(&chip->charge_full_work);
		schedule_work(&chip->charge_full_work);
	if (chip->wa_flag & IADC_GAIN_COMP_WA
			&& chip->iadc_comp_data.gain_active) {
		fg_stay_awake(&chip->resume_soc_wakeup_source);
		schedule_work(&chip->gain_comp_work);
	}

	return IRQ_HANDLED;
	return IRQ_HANDLED;
}
}


@@ -4435,9 +4590,9 @@ static int fg_of_init(struct fg_chip *chip)
			fg_sense_type = sense_type;
			fg_sense_type = sense_type;


		if (fg_debug_mask & FG_STATUS) {
		if (fg_debug_mask & FG_STATUS) {
			if (fg_sense_type == 0)
			if (fg_sense_type == INTERNAL_CURRENT_SENSE)
				pr_info("Using internal sense\n");
				pr_info("Using internal sense\n");
			else if (fg_sense_type == 1)
			else if (fg_sense_type == EXTERNAL_CURRENT_SENSE)
				pr_info("Using external sense\n");
				pr_info("Using external sense\n");
			else
			else
				pr_info("Using default sense\n");
				pr_info("Using default sense\n");
@@ -4650,6 +4805,7 @@ static void fg_cleanup(struct fg_chip *chip)
	cancel_work_sync(&chip->cycle_count_work);
	cancel_work_sync(&chip->cycle_count_work);
	cancel_work_sync(&chip->update_esr_work);
	cancel_work_sync(&chip->update_esr_work);
	cancel_work_sync(&chip->sysfs_restart_work);
	cancel_work_sync(&chip->sysfs_restart_work);
	cancel_work_sync(&chip->gain_comp_work);
	cancel_work_sync(&chip->init_work);
	cancel_work_sync(&chip->init_work);
	cancel_work_sync(&chip->charge_full_work);
	cancel_work_sync(&chip->charge_full_work);
	power_supply_unregister(&chip->bms_psy);
	power_supply_unregister(&chip->bms_psy);
@@ -4664,6 +4820,7 @@ static void fg_cleanup(struct fg_chip *chip)
	wakeup_source_trash(&chip->profile_wakeup_source.source);
	wakeup_source_trash(&chip->profile_wakeup_source.source);
	wakeup_source_trash(&chip->update_temp_wakeup_source.source);
	wakeup_source_trash(&chip->update_temp_wakeup_source.source);
	wakeup_source_trash(&chip->update_sram_wakeup_source.source);
	wakeup_source_trash(&chip->update_sram_wakeup_source.source);
	wakeup_source_trash(&chip->gain_comp_wakeup_source.source);
}
}


static int fg_remove(struct spmi_device *spmi)
static int fg_remove(struct spmi_device *spmi)
@@ -5301,11 +5458,16 @@ static int fg_hw_init(struct fg_chip *chip)
		break;
		break;
	case PMI8950:
	case PMI8950:
		rc = fg_8950_hw_init(chip);
		rc = fg_8950_hw_init(chip);
		/* Setup workaround flag based on PMIC type */
		if (fg_sense_type == INTERNAL_CURRENT_SENSE)
			chip->wa_flag |= IADC_GAIN_COMP_WA;
		break;
		break;
	}
	}
	if (rc)
	if (rc)
		pr_err("Unable to initialize PMIC specific FG HW rc=%d\n", rc);
		pr_err("Unable to initialize PMIC specific FG HW rc=%d\n", rc);


	pr_debug("wa_flag=0x%x\n", chip->wa_flag);

	return rc;
	return rc;
}
}


@@ -5399,6 +5561,7 @@ static int fg_detect_pmic_type(struct fg_chip *chip)


static void delayed_init_work(struct work_struct *work)
static void delayed_init_work(struct work_struct *work)
{
{
	u8 reg[2];
	int rc;
	int rc;
	struct fg_chip *chip = container_of(work,
	struct fg_chip *chip = container_of(work,
				struct fg_chip,
				struct fg_chip,
@@ -5430,7 +5593,62 @@ static void delayed_init_work(struct work_struct *work)
	if (!chip->use_otp_profile)
	if (!chip->use_otp_profile)
		schedule_work(&chip->batt_profile_init);
		schedule_work(&chip->batt_profile_init);


	if (chip->wa_flag & IADC_GAIN_COMP_WA) {
		/* read default gain config */
		rc = fg_mem_read(chip, reg, K_VCOR_REG, 2, DEF_GAIN_OFFSET, 0);
		if (rc) {
			pr_err("Failed to read default gain rc=%d\n", rc);
			goto done;
		}

		if (reg[1] || reg[0]) {
			/*
			 * Default gain register has valid value:
			 * - write to gain register.
			 */
			rc = fg_mem_write(chip, reg, GAIN_REG, 2,
							GAIN_OFFSET, 0);
			if (rc) {
				pr_err("Failed to write gain rc=%d\n", rc);
				goto done;
			}
		} else {
			/*
			 * Default gain register is invalid:
			 * - read gain register for default gain value
			 * - write to default gain register.
			 */
			rc = fg_mem_read(chip, reg, GAIN_REG, 2,
							GAIN_OFFSET, 0);
			if (rc) {
				pr_err("Failed to read gain rc=%d\n", rc);
				goto done;
			}
			rc = fg_mem_write(chip, reg, K_VCOR_REG, 2,
							DEF_GAIN_OFFSET, 0);
			if (rc) {
				pr_err("Failed to write default gain rc=%d\n",
									rc);
				goto done;
			}
		}

		chip->iadc_comp_data.dfl_gain_reg[0] = reg[0];
		chip->iadc_comp_data.dfl_gain_reg[1] = reg[1];
		chip->iadc_comp_data.dfl_gain = half_float(reg);
		chip->input_present = is_input_present(chip);
		chip->otg_present = is_otg_present(chip);
		chip->init_done = true;

		pr_debug("IADC gain initial config reg_val 0x%x%x gain %lld\n",
			       reg[1], reg[0], chip->iadc_comp_data.dfl_gain);
	}

	pr_debug("FG: HW_init success\n");
	pr_debug("FG: HW_init success\n");

	return;
done:
	fg_cleanup(chip);
}
}


static int fg_probe(struct spmi_device *spmi)
static int fg_probe(struct spmi_device *spmi)
@@ -5473,6 +5691,8 @@ static int fg_probe(struct spmi_device *spmi)
			"qpnp_fg_update_sram");
			"qpnp_fg_update_sram");
	wakeup_source_init(&chip->resume_soc_wakeup_source.source,
	wakeup_source_init(&chip->resume_soc_wakeup_source.source,
			"qpnp_fg_set_resume_soc");
			"qpnp_fg_set_resume_soc");
	wakeup_source_init(&chip->gain_comp_wakeup_source.source,
			"qpnp_fg_gain_comp");
	mutex_init(&chip->rw_lock);
	mutex_init(&chip->rw_lock);
	mutex_init(&chip->cyc_ctr.lock);
	mutex_init(&chip->cyc_ctr.lock);
	mutex_init(&chip->learning_data.learning_lock);
	mutex_init(&chip->learning_data.learning_lock);
@@ -5494,6 +5714,7 @@ static int fg_probe(struct spmi_device *spmi)
	INIT_WORK(&chip->sysfs_restart_work, sysfs_restart_work);
	INIT_WORK(&chip->sysfs_restart_work, sysfs_restart_work);
	INIT_WORK(&chip->init_work, delayed_init_work);
	INIT_WORK(&chip->init_work, delayed_init_work);
	INIT_WORK(&chip->charge_full_work, charge_full_work);
	INIT_WORK(&chip->charge_full_work, charge_full_work);
	INIT_WORK(&chip->gain_comp_work, iadc_gain_comp_work);
	alarm_init(&chip->fg_cap_learning_alarm, ALARM_BOOTTIME,
	alarm_init(&chip->fg_cap_learning_alarm, ALARM_BOOTTIME,
			fg_cap_learning_alarm_cb);
			fg_cap_learning_alarm_cb);
	init_completion(&chip->sram_access_granted);
	init_completion(&chip->sram_access_granted);
@@ -5645,6 +5866,7 @@ cancel_work:
	cancel_work_sync(&chip->update_esr_work);
	cancel_work_sync(&chip->update_esr_work);
	cancel_work_sync(&chip->rslow_comp_work);
	cancel_work_sync(&chip->rslow_comp_work);
	cancel_work_sync(&chip->sysfs_restart_work);
	cancel_work_sync(&chip->sysfs_restart_work);
	cancel_work_sync(&chip->gain_comp_work);
	cancel_work_sync(&chip->init_work);
	cancel_work_sync(&chip->init_work);
	cancel_work_sync(&chip->charge_full_work);
	cancel_work_sync(&chip->charge_full_work);
of_init_fail:
of_init_fail:
@@ -5659,6 +5881,7 @@ of_init_fail:
	wakeup_source_trash(&chip->profile_wakeup_source.source);
	wakeup_source_trash(&chip->profile_wakeup_source.source);
	wakeup_source_trash(&chip->update_temp_wakeup_source.source);
	wakeup_source_trash(&chip->update_temp_wakeup_source.source);
	wakeup_source_trash(&chip->update_sram_wakeup_source.source);
	wakeup_source_trash(&chip->update_sram_wakeup_source.source);
	wakeup_source_trash(&chip->gain_comp_wakeup_source.source);
	return rc;
	return rc;
}
}


+14 −7
Original line number Original line Diff line number Diff line
@@ -264,6 +264,7 @@ enum pmic_subtype {
enum smbchg_wa {
enum smbchg_wa {
	SMBCHG_AICL_DEGLITCH_WA = BIT(0),
	SMBCHG_AICL_DEGLITCH_WA = BIT(0),
	SMBCHG_HVDCP_9V_EN_WA	= BIT(1),
	SMBCHG_HVDCP_9V_EN_WA	= BIT(1),
	SMBCHG_USB100_WA = BIT(2),
};
};


enum print_reason {
enum print_reason {
@@ -741,6 +742,10 @@ static int get_prop_batt_status(struct smbchg_chip *chip)
	u8 reg = 0, chg_type;
	u8 reg = 0, chg_type;
	bool charger_present, chg_inhibit;
	bool charger_present, chg_inhibit;


	charger_present = is_usb_present(chip) | is_dc_present(chip);
	if (!charger_present)
		return POWER_SUPPLY_STATUS_DISCHARGING;

	rc = smbchg_read(chip, &reg, chip->chgr_base + RT_STS, 1);
	rc = smbchg_read(chip, &reg, chip->chgr_base + RT_STS, 1);
	if (rc < 0) {
	if (rc < 0) {
		dev_err(chip->dev, "Unable to read RT_STS rc = %d\n", rc);
		dev_err(chip->dev, "Unable to read RT_STS rc = %d\n", rc);
@@ -750,10 +755,6 @@ static int get_prop_batt_status(struct smbchg_chip *chip)
	if (reg & BAT_TCC_REACHED_BIT)
	if (reg & BAT_TCC_REACHED_BIT)
		return POWER_SUPPLY_STATUS_FULL;
		return POWER_SUPPLY_STATUS_FULL;


	charger_present = is_usb_present(chip) | is_dc_present(chip);
	if (!charger_present)
		return POWER_SUPPLY_STATUS_DISCHARGING;

	chg_inhibit = reg & CHG_INHIBIT_BIT;
	chg_inhibit = reg & CHG_INHIBIT_BIT;
	if (chg_inhibit)
	if (chg_inhibit)
		return POWER_SUPPLY_STATUS_FULL;
		return POWER_SUPPLY_STATUS_FULL;
@@ -1420,6 +1421,10 @@ static int smbchg_set_usb_current_max(struct smbchg_chip *chip,


	switch (usb_supply_type) {
	switch (usb_supply_type) {
	case POWER_SUPPLY_TYPE_USB:
	case POWER_SUPPLY_TYPE_USB:
		if ((current_ma < CURRENT_150_MA) &&
				(chip->wa_flags & SMBCHG_USB100_WA))
			current_ma = CURRENT_150_MA;

		if (current_ma < CURRENT_150_MA) {
		if (current_ma < CURRENT_150_MA) {
			/* force 100mA */
			/* force 100mA */
			rc = smbchg_sec_masked_write(chip,
			rc = smbchg_sec_masked_write(chip,
@@ -6629,10 +6634,12 @@ static int smbchg_wa_config(struct smbchg_chip *chip)
	case PMI8994:
	case PMI8994:
		chip->wa_flags |= SMBCHG_AICL_DEGLITCH_WA;
		chip->wa_flags |= SMBCHG_AICL_DEGLITCH_WA;
	case PMI8950:
	case PMI8950:
		if (pmic_rev_id->rev4 < 2) /* PMI8950 1.0 */
		if (pmic_rev_id->rev4 < 2) /* PMI8950 1.0 */ {
			chip->wa_flags |= SMBCHG_AICL_DEGLITCH_WA;
			chip->wa_flags |= SMBCHG_AICL_DEGLITCH_WA;
		else	/* rev > PMI8950 v1.0 */
		} else	{ /* rev > PMI8950 v1.0 */
			chip->wa_flags |= SMBCHG_HVDCP_9V_EN_WA;
			chip->wa_flags |= SMBCHG_HVDCP_9V_EN_WA
					| SMBCHG_USB100_WA;
		}
		break;
		break;
	default:
	default:
		pr_err("PMIC subtype %d not supported, WA flags not set\n",
		pr_err("PMIC subtype %d not supported, WA flags not set\n",
+23 −0
Original line number Original line Diff line number Diff line
@@ -1117,12 +1117,35 @@ static int cpr_regulator_get_voltage(struct regulator_dev *rdev)
	return cpr_vreg->corner;
	return cpr_vreg->corner;
}
}


/**
 * cpr_regulator_list_corner_voltage() - return the ceiling voltage mapped to
 *			the specified voltage corner
 * @rdev:		Regulator device pointer for the cpr-regulator
 * @corner:		Voltage corner
 *
 * This function is passed as a callback function into the regulator ops that
 * are registered for each cpr-regulator device.
 *
 * Return: voltage value in microvolts or -EINVAL if the corner is out of range
 */
static int cpr_regulator_list_corner_voltage(struct regulator_dev *rdev,
		int corner)
{
	struct cpr_regulator *cpr_vreg = rdev_get_drvdata(rdev);

	if (corner >= CPR_CORNER_MIN && corner <= cpr_vreg->num_corners)
		return cpr_vreg->ceiling_volt[corner];
	else
		return -EINVAL;
}

static struct regulator_ops cpr_corner_ops = {
static struct regulator_ops cpr_corner_ops = {
	.enable			= cpr_regulator_enable,
	.enable			= cpr_regulator_enable,
	.disable		= cpr_regulator_disable,
	.disable		= cpr_regulator_disable,
	.is_enabled		= cpr_regulator_is_enabled,
	.is_enabled		= cpr_regulator_is_enabled,
	.set_voltage		= cpr_regulator_set_voltage_op,
	.set_voltage		= cpr_regulator_set_voltage_op,
	.get_voltage		= cpr_regulator_get_voltage,
	.get_voltage		= cpr_regulator_get_voltage,
	.list_corner_voltage	= cpr_regulator_list_corner_voltage,
};
};


#ifdef CONFIG_PM
#ifdef CONFIG_PM
Loading