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

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

Merge "ARM: dts: msm: add SCHGM_FLASH in charger device for PMI632"

parents f07ebd86 3ee6df65
Loading
Loading
Loading
Loading
+47 −0
Original line number Original line Diff line number Diff line
@@ -164,6 +164,32 @@ Charger specific properties:
		to be get from these properties defined in battery profile:
		to be get from these properties defined in battery profile:
		qcom,step-chg-ranges, qcom,jeita-fcc-ranges, qcom,jeita-fv-ranges.
		qcom,step-chg-ranges, qcom,jeita-fcc-ranges, qcom,jeita-fv-ranges.


- qcom,flash-derating-soc
  Usage:      optional
  Value type: <u32>
  Definition: SOC threshold in percentage below which hardware will start
		derating flash. This is only applicable to certain PMICs like
		PMI632 which has SCHGM_FLASH peripheral.

- qcom,flash-disable-soc
  Usage:      optional
  Value type: <u32>
  Definition: SOC threshold in percentage below which hardware will disable
		flash. This is only applicable to certain PMICs like PMI632
		which has SCHGM_FLASH peripheral.

- qcom,headroom-mode
  Usage:      optional
  Value type: <u32>
  Definition: Specifies flash hardware headroom management policy. The
		possible values are:
		<0>: Fixed mode, constant 5V at flash input.
		<1>: Adaptive mode allows charger output voltage to be
		dynamically controlled by the flash module based on the
		required flash headroom.
		This is only applicable to certain PMICs like PMI632 which
		has SCHGM_FLASH peripheral.

=============================================
=============================================
Second Level Nodes - SMB5 Charger Peripherals
Second Level Nodes - SMB5 Charger Peripherals
=============================================
=============================================
@@ -301,4 +327,25 @@ pmi8998_charger: qcom,qpnp-smb5 {
					"temperature-change",
					"temperature-change",
					"switcher-power-ok";
					"switcher-power-ok";
	};
	};

	qcom,schgm-flash@a600 {
		reg = <0xa600 0x100>;
		interrupts =	<0x2 0xa6 0x0 IRQ_TYPE_NONE>,
				<0x2 0xa6 0x1 IRQ_TYPE_NONE>,
				<0x2 0xa6 0x2 IRQ_TYPE_NONE>,
				<0x2 0xa6 0x3 IRQ_TYPE_NONE>,
				<0x2 0xa6 0x4 IRQ_TYPE_NONE>,
				<0x2 0xa6 0x5 IRQ_TYPE_NONE>,
				<0x2 0xa6 0x6 IRQ_TYPE_NONE>,
				<0x2 0xa6 0x7 IRQ_TYPE_NONE>;

		interrupt-names =	"flash-en",
					"torch-req",
					"flash-state-change",
					"vout-up",
					"vout-down",
					"ilim1-s1",
					"ilim2-s2",
					"vreg-ok";
	};
};
};
+14 −0
Original line number Original line Diff line number Diff line
@@ -355,6 +355,20 @@
						  "temp-change-smb";
						  "temp-change-smb";
			};
			};


			qcom,schgm-flash@a600 {
				reg = <0xa600 0x100>;
				interrupts =
					<0x2 0xa6 0x2 IRQ_TYPE_EDGE_RISING>,
					<0x2 0xa6 0x5 IRQ_TYPE_EDGE_RISING>,
					<0x2 0xa6 0x6 IRQ_TYPE_EDGE_RISING>,
					<0x2 0xa6 0x7 IRQ_TYPE_EDGE_BOTH>;

				interrupt-names = "flash-state-change",
						"ilim1-s1",
						"ilim2-s2",
						"vreg-ok";
			};

			smb5_vbus: qcom,smb5-vbus {
			smb5_vbus: qcom,smb5-vbus {
				regulator-name = "smb5-vbus";
				regulator-name = "smb5-vbus";
			};
			};
+1 −1
Original line number Original line Diff line number Diff line
@@ -9,4 +9,4 @@ obj-$(CONFIG_SMB138X_CHARGER) += step-chg-jeita.o smb138x-charger.o smb-lib.o pm
obj-$(CONFIG_QPNP_QG)		+= qpnp-qg.o pmic-voter.o qg-util.o qg-soc.o qg-sdam.o qg-battery-profile.o qg-profile-lib.o
obj-$(CONFIG_QPNP_QG)		+= qpnp-qg.o pmic-voter.o qg-util.o qg-soc.o qg-sdam.o qg-battery-profile.o qg-profile-lib.o
obj-$(CONFIG_QPNP_QNOVO)	+= qpnp-qnovo.o battery.o
obj-$(CONFIG_QPNP_QNOVO)	+= qpnp-qnovo.o battery.o
obj-$(CONFIG_QPNP_TYPEC)	+= qpnp-typec.o
obj-$(CONFIG_QPNP_TYPEC)	+= qpnp-typec.o
obj-$(CONFIG_QPNP_SMB5)		+= step-chg-jeita.o battery.o qpnp-smb5.o smb5-lib.o pmic-voter.o storm-watch.o
obj-$(CONFIG_QPNP_SMB5)		+= step-chg-jeita.o battery.o qpnp-smb5.o smb5-lib.o pmic-voter.o storm-watch.o schgm-flash.o
+63 −0
Original line number Original line Diff line number Diff line
@@ -27,6 +27,7 @@
#include <linux/pmic-voter.h>
#include <linux/pmic-voter.h>
#include "smb5-reg.h"
#include "smb5-reg.h"
#include "smb5-lib.h"
#include "smb5-lib.h"
#include "schgm-flash.h"


static struct smb_params smb5_pmi632_params = {
static struct smb_params smb5_pmi632_params = {
	.fcc			= {
	.fcc			= {
@@ -371,6 +372,7 @@ static enum power_supply_property smb5_usb_props[] = {
	POWER_SUPPLY_PROP_SDP_CURRENT_MAX,
	POWER_SUPPLY_PROP_SDP_CURRENT_MAX,
	POWER_SUPPLY_PROP_CONNECTOR_TYPE,
	POWER_SUPPLY_PROP_CONNECTOR_TYPE,
	POWER_SUPPLY_PROP_VOLTAGE_MAX,
	POWER_SUPPLY_PROP_VOLTAGE_MAX,
	POWER_SUPPLY_PROP_SCOPE,
};
};


static int smb5_usb_get_prop(struct power_supply *psy,
static int smb5_usb_get_prop(struct power_supply *psy,
@@ -379,6 +381,7 @@ static int smb5_usb_get_prop(struct power_supply *psy,
{
{
	struct smb5 *chip = power_supply_get_drvdata(psy);
	struct smb5 *chip = power_supply_get_drvdata(psy);
	struct smb_charger *chg = &chip->chg;
	struct smb_charger *chg = &chip->chg;
	union power_supply_propval pval;
	int rc = 0;
	int rc = 0;


	switch (psp) {
	switch (psp) {
@@ -476,6 +479,15 @@ static int smb5_usb_get_prop(struct power_supply *psy,
	case POWER_SUPPLY_PROP_CONNECTOR_TYPE:
	case POWER_SUPPLY_PROP_CONNECTOR_TYPE:
		val->intval = chg->connector_type;
		val->intval = chg->connector_type;
		break;
		break;
	case POWER_SUPPLY_PROP_SCOPE:
		val->intval = POWER_SUPPLY_SCOPE_UNKNOWN;
		rc = smblib_get_prop_usb_present(chg, &pval);
		if (rc < 0)
			break;
		val->intval = pval.intval ? POWER_SUPPLY_SCOPE_DEVICE
				: chg->otg_present ? POWER_SUPPLY_SCOPE_SYSTEM
						: POWER_SUPPLY_SCOPE_UNKNOWN;
		break;
	default:
	default:
		pr_err("get prop %d is not supported in usb\n", psp);
		pr_err("get prop %d is not supported in usb\n", psp);
		rc = -EINVAL;
		rc = -EINVAL;
@@ -701,6 +713,8 @@ static enum power_supply_property smb5_usb_main_props[] = {
	POWER_SUPPLY_PROP_INPUT_VOLTAGE_SETTLED,
	POWER_SUPPLY_PROP_INPUT_VOLTAGE_SETTLED,
	POWER_SUPPLY_PROP_FCC_DELTA,
	POWER_SUPPLY_PROP_FCC_DELTA,
	POWER_SUPPLY_PROP_CURRENT_MAX,
	POWER_SUPPLY_PROP_CURRENT_MAX,
	POWER_SUPPLY_PROP_FLASH_ACTIVE,
	POWER_SUPPLY_PROP_FLASH_TRIGGER,
};
};


static int smb5_usb_main_get_prop(struct power_supply *psy,
static int smb5_usb_main_get_prop(struct power_supply *psy,
@@ -734,6 +748,12 @@ static int smb5_usb_main_get_prop(struct power_supply *psy,
	case POWER_SUPPLY_PROP_CURRENT_MAX:
	case POWER_SUPPLY_PROP_CURRENT_MAX:
		rc = smblib_get_icl_current(chg, &val->intval);
		rc = smblib_get_icl_current(chg, &val->intval);
		break;
		break;
	case POWER_SUPPLY_PROP_FLASH_ACTIVE:
		val->intval = chg->flash_active;
		break;
	case POWER_SUPPLY_PROP_FLASH_TRIGGER:
		rc = schgm_flash_get_vreg_ok(chg, &val->intval);
		break;
	default:
	default:
		pr_debug("get prop %d is not supported in usb-main\n", psp);
		pr_debug("get prop %d is not supported in usb-main\n", psp);
		rc = -EINVAL;
		rc = -EINVAL;
@@ -765,6 +785,9 @@ static int smb5_usb_main_set_prop(struct power_supply *psy,
	case POWER_SUPPLY_PROP_CURRENT_MAX:
	case POWER_SUPPLY_PROP_CURRENT_MAX:
		rc = smblib_set_icl_current(chg, val->intval);
		rc = smblib_set_icl_current(chg, val->intval);
		break;
		break;
	case POWER_SUPPLY_PROP_FLASH_ACTIVE:
		chg->flash_active = val->intval;
		break;
	default:
	default:
		pr_err("set prop %d is not supported\n", psp);
		pr_err("set prop %d is not supported\n", psp);
		rc = -EINVAL;
		rc = -EINVAL;
@@ -1367,6 +1390,13 @@ static int smb5_init_hw(struct smb5 *chip)
					: POWER_SUPPLY_CONNECTOR_TYPEC;
					: POWER_SUPPLY_CONNECTOR_TYPEC;
	pr_debug("Connector type=%s\n", type ? "Micro USB" : "TypeC");
	pr_debug("Connector type=%s\n", type ? "Micro USB" : "TypeC");


	/*
	 * PMI632 based hw init:
	 * - Initialize flash module for PMI632
	 */
	if (chg->smb_version == PMI632_SUBTYPE)
		schgm_flash_init(chg);

	smblib_rerun_apsd_if_required(chg);
	smblib_rerun_apsd_if_required(chg);


	/* vote 0mA on usb_icl for non battery platforms */
	/* vote 0mA on usb_icl for non battery platforms */
@@ -1829,6 +1859,39 @@ static struct smb_irq_info smb5_irqs[] = {
		.name		= "temp-change-smb",
		.name		= "temp-change-smb",
		.handler	= default_irq_handler,
		.handler	= default_irq_handler,
	},
	},
	/* FLASH */
	[VREG_OK_IRQ] = {
		.name		= "vreg-ok",
		.handler	= schgm_flash_default_irq_handler,
	},
	[ILIM_S2_IRQ] = {
		.name		= "ilim2-s2",
		.handler	= schgm_flash_ilim2_irq_handler,
	},
	[ILIM_S1_IRQ] = {
		.name		= "ilim1-s1",
		.handler	= schgm_flash_default_irq_handler,
	},
	[VOUT_DOWN_IRQ] = {
		.name		= "vout-down",
		.handler	= schgm_flash_default_irq_handler,
	},
	[VOUT_UP_IRQ] = {
		.name		= "vout-up",
		.handler	= schgm_flash_default_irq_handler,
	},
	[FLASH_STATE_CHANGE_IRQ] = {
		.name		= "flash-state-change",
		.handler	= schgm_flash_state_change_irq_handler,
	},
	[TORCH_REQ_IRQ] = {
		.name		= "torch-req",
		.handler	= schgm_flash_default_irq_handler,
	},
	[FLASH_EN_IRQ] = {
		.name		= "flash-en",
		.handler	= schgm_flash_default_irq_handler,
	},
};
};


static int smb5_get_irq_index_byname(const char *irq_name)
static int smb5_get_irq_index_byname(const char *irq_name)
+216 −0
Original line number Original line Diff line number Diff line
/* Copyright (c) 2018 The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#define pr_fmt(fmt) "SCHG-FLASH: %s: " fmt, __func__

#include <linux/device.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/power_supply.h>
#include <linux/interrupt.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/printk.h>
#include <linux/pmic-voter.h>
#include "smb5-lib.h"
#include "schgm-flash.h"

#define IS_BETWEEN(left, right, value) \
		(((left) >= (right) && (left) >= (value) \
			&& (value) >= (right)) \
		|| ((left) <= (right) && (left) <= (value) \
			&& (value) <= (right)))

irqreturn_t schgm_flash_default_irq_handler(int irq, void *data)
{
	struct smb_irq_data *irq_data = data;

	pr_debug("IRQ: %s\n", irq_data->name);

	return IRQ_HANDLED;
}

irqreturn_t schgm_flash_ilim2_irq_handler(int irq, void *data)
{
	struct smb_irq_data *irq_data = data;
	struct smb_charger *chg = irq_data->parent_data;
	int rc;

	rc = smblib_write(chg, SCHGM_FLASH_S2_LATCH_RESET_CMD_REG,
				FLASH_S2_LATCH_RESET_BIT);
	if (rc < 0)
		pr_err("Couldn't reset S2_LATCH reset rc=%d\n", rc);

	return IRQ_HANDLED;
}

irqreturn_t schgm_flash_state_change_irq_handler(int irq, void *data)
{
	struct smb_irq_data *irq_data = data;
	struct smb_charger *chg = irq_data->parent_data;
	int rc;
	u8 reg;

	rc = smblib_read(chg, SCHGM_FLASH_STATUS_3_REG, &reg);
	if (rc < 0)
		pr_err("Couldn't read flash status_3 rc=%d\n", rc);
	else
		pr_debug("Flash status changed state=[%x]\n",
					(reg && FLASH_STATE_MASK));

	return IRQ_HANDLED;
}

#define FIXED_MODE		0
#define ADAPTIVE_MODE		1
static void schgm_flash_parse_dt(struct smb_charger *chg)
{
	struct device_node *node = chg->dev->of_node;
	u32 val;
	int rc;

	chg->flash_derating_soc = -EINVAL;
	rc = of_property_read_u32(node, "qcom,flash-derating-soc", &val);
	if (!rc) {
		if (IS_BETWEEN(0, 100, val))
			chg->flash_derating_soc = (val * 255) / 100;
	}

	chg->flash_disable_soc = -EINVAL;
	rc = of_property_read_u32(node, "qcom,flash-disable-soc", &val);
	if (!rc) {
		if (IS_BETWEEN(0, 100, val))
			chg->flash_disable_soc = (val * 255) / 100;
	}

	chg->headroom_mode = -EINVAL;
	rc = of_property_read_u32(node, "qcom,headroom-mode", &val);
	if (!rc) {
		if (IS_BETWEEN(FIXED_MODE, ADAPTIVE_MODE, val))
			chg->headroom_mode = val;
	}
}

int schgm_flash_get_vreg_ok(struct smb_charger *chg, int *val)
{
	int rc, vreg_state;
	u8 stat = 0;

	if (!chg->flash_init_done)
		return -EPERM;

	rc = smblib_read(chg, SCHGM_FLASH_STATUS_2_REG, &stat);
	if (rc < 0) {
		pr_err("Couldn't read FLASH STATUS_2 rc=%d\n", rc);
		return rc;
	}
	vreg_state = !!(stat & VREG_OK_BIT);

	/* If VREG_OK is not set check for flash error */
	if (!vreg_state) {
		rc = smblib_read(chg, SCHGM_FLASH_STATUS_3_REG, &stat);
		if (rc < 0) {
			pr_err("Couldn't read FLASH_STATUS_3 rc=%d\n", rc);
			return rc;
		}
		if ((stat & FLASH_STATE_MASK) == FLASH_ERROR_VAL) {
			vreg_state = -EFAULT;
			rc = smblib_read(chg, SCHGM_FLASH_STATUS_5_REG,
					&stat);
			if (rc < 0) {
				pr_err("Couldn't read FLASH_STATUS_5 rc=%d\n",
						rc);
				return rc;
			}
			pr_debug("Flash error: status=%x\n", stat);
		}
	}

	/*
	 * val can be one of the following:
	 * 1		- VREG_OK is set.
	 * 0		- VREG_OK is 0 but no Flash error.
	 * -EFAULT	- Flash Error is set.
	 */
	*val = vreg_state;

	return 0;
}

int schgm_flash_init(struct smb_charger *chg)
{
	int rc;
	u8 reg;

	schgm_flash_parse_dt(chg);

	if (chg->flash_derating_soc != -EINVAL) {
		rc = smblib_write(chg, SCHGM_SOC_BASED_FLASH_DERATE_TH_CFG_REG,
					chg->flash_derating_soc);
		if (rc < 0) {
			pr_err("Couldn't configure SOC for flash derating rc=%d\n",
					rc);
			return rc;
		}
	}

	if (chg->flash_disable_soc != -EINVAL) {
		rc = smblib_write(chg, SCHGM_SOC_BASED_FLASH_DISABLE_TH_CFG_REG,
					chg->flash_disable_soc);
		if (rc < 0) {
			pr_err("Couldn't configure SOC for flash disable rc=%d\n",
					rc);
			return rc;
		}
	}

	if (chg->headroom_mode != -EINVAL) {
		/*
		 * configure headroom management policy for
		 * flash and torch mode.
		 */
		reg = (chg->headroom_mode == FIXED_MODE)
					? FORCE_FLASH_BOOST_5V_BIT : 0;
		rc = smblib_write(chg, SCHGM_FORCE_BOOST_CONTROL, reg);
		if (rc < 0) {
			pr_err("Couldn't write force boost control reg rc=%d\n",
					rc);
			return rc;
		}

		reg = (chg->headroom_mode == FIXED_MODE)
					? TORCH_PRIORITY_CONTROL_BIT : 0;
		rc = smblib_write(chg, SCHGM_TORCH_PRIORITY_CONTROL, reg);
		if (rc < 0) {
			pr_err("Couldn't force 5V boost in torch mode rc=%d\n",
					rc);
			return rc;
		}
	}

	if ((chg->flash_derating_soc != -EINVAL)
				|| (chg->flash_disable_soc != -EINVAL)) {
		/* Check if SOC based derating/disable is enabled */
		rc = smblib_read(chg, SCHGM_FLASH_CONTROL_REG, &reg);
		if (rc < 0) {
			pr_err("Couldn't read flash control reg rc=%d\n", rc);
			return rc;
		}
		if (!(reg & SOC_LOW_FOR_FLASH_EN_BIT))
			pr_warn("Soc based flash derating not enabled\n");
	}

	chg->flash_init_done = true;

	return 0;
}
Loading