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

Commit 815c8456 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "power: smblite: Add snapshot of SMBLITE driver and its dependencies"

parents 37fbddf5 dc02da1f
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -34,6 +34,18 @@ config QPNP_SMB5
	  To compile this driver as a module, choose M here: the
	  module will be called qpnp-smb5-main.

config QPNP_SMBLITE
	tristate "SMBLITE Battery Charger"
	depends on MFD_SPMI_PMIC
	help
	  Say Y to enable support for the SMBLITE charging peripheral.
	  The QPNP SMBLITE charger driver supports the charger peripheral
	  present in the chip.
	  The power supply framework is used to communicate battery and
	  usb properties to userspace and other driver consumers such
	  as fuel gauge and USB.
	  VBUS regulator is registered for supporting OTG.

config SMB1398_CHARGER
	tristate "SMB1398 power supply framework based driver"
	depends on MFD_I2C_PMIC && IIO
+1 −0
Original line number Diff line number Diff line
@@ -7,3 +7,4 @@ qcom-qpnp-qg-y += qpnp-qg.o battery-profile-loader.o pmic-voter.o qg-util.o qg-s
obj-$(CONFIG_SMB1398_CHARGER)           += qcom-smb1398-charger.o
qcom-smb1398-charger-y += smb1398-charger.o pmic-voter.o
obj-$(CONFIG_SMB1355_SLAVE_CHARGER)	+= smb1355-charger.o pmic-voter.o
obj-$(CONFIG_QPNP_SMBLITE)	        += step-chg-jeita.o battery.o qpnp-smblite.o smblite-lib.o pmic-voter.o storm-watch.o schgm-falshlite.o
+2119 −0

File added.

Preview size limit exceeded, changes collapsed.

+220 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2018, 2020 The Linux Foundation. All rights reserved.
 */

#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 "smblite-lib.h"
#include "schgm-flashlite.h"

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

irqreturn_t schgm_flashlite_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_flashlite_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 = smblite_lib_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_flashlite_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 = smblite_lib_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_flashlite_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;
	}
}

bool is_flashlite_active(struct smb_charger *chg)
{
	return chg->flash_active ? true : false;
}

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

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

	rc = smblite_lib_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 = smblite_lib_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 = smblite_lib_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;
}

void schgm_flashlite_torch_priority(struct smb_charger *chg,
					enum torch_mode mode)
{
	int rc;
	u8 reg;

	if ((mode != TORCH_BOOST_MODE) && (mode != TORCH_BUCK_MODE))
		return;

	reg = mode;
	rc = smblite_lib_masked_write(chg, SCHGM_TORCH_PRIORITY_CONTROL_REG,
					TORCH_PRIORITY_CONTROL_BIT, reg);
	if (rc < 0)
		pr_err("Couldn't configure Torch priority control rc=%d\n",
				rc);

	pr_debug("Torch priority changed to: %d\n", mode);
}

int schgm_flashlite_config_usbin_collapse(struct smb_charger *chg, bool enable)
{
	return smblite_lib_masked_write(chg, SCHG_L_FLASH_FLASH_FAULT_CFG,
				CFG_FLASH_USB_COLLAPSE_BIT, enable ?
				CFG_FLASH_USB_COLLAPSE_BIT : 0);
}

int schgm_flashlite_init(struct smb_charger *chg)
{
	int rc;
	u8 reg, mask;

	schgm_flashlite_parse_dt(chg);

	if (chg->wa_flags & FLASH_DIE_TEMP_DERATE_WA) {
		mask = TEMP_DIE_REG_L_DERATE_EN_BIT |
				TEMP_DIE_REG_H_DERATE_EN_BIT;
		rc = smblite_lib_masked_write(chg, SCHGM_FLASH_CONTROL_REG,
				mask, 0);
		if (rc < 0)
			pr_err("Couldn't disable die-temp derate rc=%d\n", rc);
	}

	if (chg->flash_derating_soc != -EINVAL) {
		rc = smblite_lib_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 = smblite_lib_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->flash_derating_soc != -EINVAL)
				|| (chg->flash_disable_soc != -EINVAL)) {
		/* Check if SOC based derating/disable is enabled */
		rc = smblite_lib_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;
}
+59 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2018, 2020 The Linux Foundation. All rights reserved.
 */

#ifndef __SCHGM_FLASHLITE_H__
#define __SCHGM_FLASHLITE_H__

#include <linux/bitops.h>

#define SCHGM_FLASH_BASE			0xA600

#define SCHGM_FLASH_STATUS_2_REG		(SCHGM_FLASH_BASE + 0x07)
#define VREG_OK_BIT				BIT(4)

#define SCHGM_FLASH_STATUS_3_REG		(SCHGM_FLASH_BASE + 0x08)
#define FLASH_STATE_MASK			GENMASK(2, 0)
#define FLASH_ERROR_VAL				0x7

#define SCHGM_FLASH_INT_RT_STS_REG		(SCHGM_FLASH_BASE + 0x10)

#define SCHGM_FLASH_STATUS_5_REG		(SCHGM_FLASH_BASE + 0x0B)

#define SCHGM_FLASH_S2_LATCH_RESET_CMD_REG	(SCHGM_FLASH_BASE + 0x44)
#define FLASH_S2_LATCH_RESET_BIT		BIT(0)

#define SCHGM_FLASH_CONTROL_REG			(SCHGM_FLASH_BASE + 0x60)
#define SOC_LOW_FOR_FLASH_EN_BIT		BIT(7)
#define TEMP_DIE_REG_H_DERATE_EN_BIT		BIT(3)
#define TEMP_DIE_REG_L_DERATE_EN_BIT		BIT(2)

#define SCHGM_TORCH_PRIORITY_CONTROL_REG	(SCHGM_FLASH_BASE + 0x63)
#define TORCH_PRIORITY_CONTROL_BIT		BIT(0)

#define SCHG_L_FLASH_FLASH_FAULT_CFG		(SCHGM_FLASH_BASE + 0x64)
#define CFG_FLASH_USB_COLLAPSE_BIT		BIT(7)

#define SCHGM_SOC_BASED_FLASH_DERATE_TH_CFG_REG	(SCHGM_FLASH_BASE + 0x67)

#define SCHGM_SOC_BASED_FLASH_DISABLE_TH_CFG_REG \
						(SCHGM_FLASH_BASE + 0x68)

enum torch_mode {
	TORCH_BUCK_MODE = 0,
	TORCH_BOOST_MODE,
};

int schgm_flashlite_get_vreg_ok(struct smb_charger *chg, int *val);
void schgm_flashlite_torch_priority(struct smb_charger *chg,
					enum torch_mode mode);
int schgm_flashlite_config_usbin_collapse(struct smb_charger *chg,
						bool enable);
int schgm_flashlite_init(struct smb_charger *chg);
bool is_flashlite_active(struct smb_charger *chg);

irqreturn_t schgm_flashlite_default_irq_handler(int irq, void *data);
irqreturn_t schgm_flashlite_ilim2_irq_handler(int irq, void *data);
irqreturn_t schgm_flashlite_state_change_irq_handler(int irq, void *data);
#endif /* __SCHGM_FLASHLITE_H__ */
Loading