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

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

Merge "regulator: qpnp-oledb: Add lab_vreg_ok notifier callback"

parents 2779284a c3cd3d31
Loading
Loading
Loading
Loading
+37 −23
Original line number Diff line number Diff line
@@ -44,12 +44,12 @@ Required Node Structure
	Value type: <bool>
	Definition: Enables the voltage programming through SWIRE signal.

 qcom,ext-pin-control
- qcom,ext-pin-control
	Usage:      optional
	Value type: <bool>
	Definition: Configures the OLED module to be enabled by a external pin.

 qcom,dynamic-ext-pinctl-config
- qcom,dynamic-ext-pinctl-config
	Usage:      optional
	Value type: <bool>
	Definition:  Used to dynamically enable/disable the OLEDB module
@@ -57,13 +57,27 @@ Required Node Structure
		     rail.  This property is applicable only if qcom,ext-pin-ctl
		     property is specified and it is specific to PM660A.

 qcom,pbs-control
- qcom,force-pd-control
	Usage:      optional
	Value type: <bool>
	Definition:  Used to enable the pull down control forcibly via SPMI by
		     disabling the pull down configuration done by hardware
		     automatically through SWIRE pulses.

- qcom,pbs-client
	Usage:      optional
	Value type: <phandle>
	Definition:  Used to send the PBS trigger to the specified PBS client.
		     This property is applicable only if qcom,force-pd-control
		     property is specified.

- qcom,pbs-control
	Usage:      optional
	Value type: <bool>
	Definition: PMIC PBS logic directly configures the output voltage update
		    and pull down control.

 qcom,oledb-init-voltage-mv
- qcom,oledb-init-voltage-mv
	Usage:      optional
	Value type: <u32>
	Definition: Sets the AVDD bias voltage (in mV) when the module is
@@ -71,53 +85,53 @@ Required Node Structure
		    property is not specified. Supported values are from 5.0V
		    to 8.1V with a step of 100mV.

qcom,oledb-default-voltage-mv
- qcom,oledb-default-voltage-mv
	Usage:      optional
	Value type: <u32>
	Definition: Sets the default AVDD bias voltage (in mV) before module
		    enable. Supported values are from 5.0V to 8.1V with the
		    step of 100mV.

qcom,bias-gen-warmup-delay-ns
- qcom,bias-gen-warmup-delay-ns
	Usage:      optional
	Value type: <u32>
	Definition: Bias generator warm-up time (ns). Supported values are
		    6700, 13300, 267000, 534000.

qcom,peak-curr-limit-ma
- qcom,peak-curr-limit-ma
	Usage:      optional
	Value type: <u32>
	Definition: Peak current limit (in mA). Supported values are 115, 265,
		    415, 570, 720, 870, 1020, 1170.

qcom,pull-down-enable
- qcom,pull-down-enable
	Usage:      optional
	Value type: <u32>
	Definition: Pull down configuration of OLEDB.
		    1 - Enable pull-down
		    0 - Disable pull-down

qcom,negative-curr-limit-enable
- qcom,negative-curr-limit-enable
	Usage:      optional
	Value type: <u32>
	Definition: negative current limit enable/disable.
			1 = enable negative current limit
			0 = disable negative current limit

qcom,negative-curr-limit-ma
- qcom,negative-curr-limit-ma
	Usage:      optional
	Value type: <u32>
	Definition: Negative current limit (in mA). Supported values are
		    170, 300, 420, 550.

qcom,enable-short-circuit
- qcom,enable-short-circuit
	Usage:      optional
	Value type: <u32>
	Definition: Short circuit protection enable/disable.
			1 = enable short circuit protection
			0 = disable short circuit protection

qcom,short-circuit-dbnc-time
- qcom,short-circuit-dbnc-time
	usage:      optional
	Value type: <u32>
	Definitioan: Short circuit debounce time (in Fsw). Supported
@@ -126,26 +140,26 @@ qcom,short-circuit-dbnc-time
Fast precharge properties:
-------------------------

qcom,fast-precharge-ppulse-enable
- qcom,fast-precharge-ppulse-enable
	usage:      optional
	Value type: <u32>
	Definitioan: Fast precharge pfet pulsing enable/disable.
			1 = enable fast precharge pfet pulsing
			0 = disable fast precharge pfet pulsing

qcom,precharge-debounce-time-ms
- qcom,precharge-debounce-time-ms
	usage:      optional
	Value type: <u32>
	Definitioan: Fast precharge debounce time (in ms). Supported
		     values are 1, 2, 4, 8.

qcom,precharge-pulse-period-us
- qcom,precharge-pulse-period-us
	usage:      optional
	Value type: <u32>
	Definitioan: Fast precharge pulse period (in us). Supported
		     values are 3, 6, 9, 12.

qcom,precharge-pulse-on-time-us
- qcom,precharge-pulse-on-time-us
	usage:      optional
	Value type: <u32>
	Definitioan: Fast precharge pulse on time (in ns). Supported
@@ -154,20 +168,20 @@ qcom,precharge-pulse-on-time-us
Pulse Skip Modulation (PSM) properties:
--------------------------------------

qcom,psm-enable
- qcom,psm-enable
	Usage:      optional
	Value type: <u32>
	Definition: Pulse Skip Modulation mode.
		    1 - Enable PSM mode
		    0 - Disable PSM mode

qcom,psm-hys-mv
- qcom,psm-hys-mv
	Usage:      optional
	Value type: <u32>
	Definition: PSM hysterysis voltage (in mV).
		    Supported values are 13mV and 26mV.

qcom,psm-vref-mv
- qcom,psm-vref-mv
	Usage:      optional
	Value type: <u32>
	Definition: Reference voltage(in mV) control for PSM comparator.
@@ -177,26 +191,26 @@ qcom,psm-vref-mv
Pulse Frequency Modulation (PFM) properties:
-------------------------------------------

qcom,pfm-enable
- qcom,pfm-enable
	Usage:      optional
	Value type: <u32>
	Definition: Pulse Frequency Modulation mode.
		    1 - Enable PFM mode
		    0 - Disable PFM mode

qcom,pfm-hys-mv
- qcom,pfm-hys-mv
	Usage:      optional
	Value type: <u32>
	Definition: PFM hysterysis voltage (in mV).
		    Supported values are 13mV and 26mV.

qcom,pfm-curr-limit-ma
- qcom,pfm-curr-limit-ma
	Usage:      optional
	Value type: <u32>
	Definition: PFM current limit (in mA).
		    Supported values are 130, 200, 270, 340.

qcom,pfm-off-time-ns
- qcom,pfm-off-time-ns
	Usage:      optional
	Value type: <u32>
	Definition: NFET off time at PFM (in ns).
+158 −4
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/notifier.h>
#include <linux/of.h>
#include <linux/regmap.h>
#include <linux/spmi.h>
@@ -24,6 +25,8 @@
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/of_regulator.h>
#include <linux/regulator/qpnp-labibb-regulator.h>
#include <linux/qpnp/qpnp-pbs.h>

#define QPNP_OLEDB_REGULATOR_DRIVER_NAME	"qcom,qpnp-oledb-regulator"
#define OLEDB_VOUT_STEP_MV				100
@@ -91,6 +94,12 @@
#define OLEDB_ENABLE_NLIMIT_BIT_SHIFT			7
#define OLEDB_NLIMIT_PGM_MASK				GENMASK(1, 0)

#define OLEDB_SPARE_CTL					0xE9
#define OLEDB_FORCE_PD_CTL_SPARE_BIT			BIT(7)

#define OLEDB_PD_PBS_TRIGGER_BIT			BIT(0)

#define OLEDB_SEC_UNLOCK_CODE				0xA5
#define OLEDB_PSM_HYS_CTRL_MIN				13
#define OLEDB_PSM_HYS_CTRL_MAX				26

@@ -150,6 +159,9 @@ struct qpnp_oledb {
	struct qpnp_oledb_psm_ctl		psm_ctl;
	struct qpnp_oledb_pfm_ctl		pfm_ctl;
	struct qpnp_oledb_fast_precharge_ctl	fast_prechg_ctl;
	struct notifier_block			oledb_nb;
	struct mutex				bus_lock;
	struct device_node			*pbs_dev_node;

	u32					base;
	u8					mod_enable;
@@ -168,6 +180,7 @@ struct qpnp_oledb {
	bool					ext_pin_control;
	bool					dynamic_ext_pinctl_config;
	bool					pbs_control;
	bool					force_pd_control;
};

static const u16 oledb_warmup_dly_ns[] = {6700, 13300, 26700, 53400};
@@ -184,11 +197,13 @@ static int qpnp_oledb_read(struct qpnp_oledb *oledb, u32 address,
	int rc = 0;
	struct platform_device *pdev = oledb->pdev;

	mutex_lock(&oledb->bus_lock);
	rc = regmap_bulk_read(oledb->regmap, address, val, count);
	if (rc)
		pr_err("Failed to read address=0x%02x sid=0x%02x rc=%d\n",
			address, to_spmi_device(pdev->dev.parent)->usid, rc);

	mutex_unlock(&oledb->bus_lock);
	return rc;
}

@@ -197,6 +212,7 @@ static int qpnp_oledb_masked_write(struct qpnp_oledb *oledb,
{
	int rc;

	mutex_lock(&oledb->bus_lock);
	rc = regmap_update_bits(oledb->regmap, address, mask, val);
	if (rc < 0)
		pr_err("Failed to write address 0x%04X, rc = %d\n",
@@ -205,6 +221,31 @@ static int qpnp_oledb_masked_write(struct qpnp_oledb *oledb,
		pr_debug("Wrote 0x%02X to addr 0x%04X\n",
			val, address);

	mutex_unlock(&oledb->bus_lock);
	return rc;
}

#define OLEDB_SEC_ACCESS	0xD0
static int qpnp_oledb_sec_masked_write(struct qpnp_oledb *oledb, u16 address,
							 u8 mask, u8 val)
{
	int rc = 0;
	u8 sec_val = OLEDB_SEC_UNLOCK_CODE;
	u16 sec_reg_addr = (address & 0xFF00) | OLEDB_SEC_ACCESS;

	mutex_lock(&oledb->bus_lock);
	rc = regmap_write(oledb->regmap, sec_reg_addr, sec_val);
	if (rc < 0) {
		pr_err("register %x failed rc = %d\n", sec_reg_addr, rc);
		goto error;
	}

	rc = regmap_update_bits(oledb->regmap, address, mask, val);
	if (rc < 0)
		pr_err("spmi write failed: addr=%03X, rc=%d\n", address, rc);

error:
	mutex_unlock(&oledb->bus_lock);
	return rc;
}

@@ -214,6 +255,7 @@ static int qpnp_oledb_write(struct qpnp_oledb *oledb, u16 address, u8 *val,
	int rc = 0;
	struct platform_device *pdev = oledb->pdev;

	mutex_lock(&oledb->bus_lock);
	rc = regmap_bulk_write(oledb->regmap, address, val, count);
	if (rc)
		pr_err("Failed to write address=0x%02x sid=0x%02x rc=%d\n",
@@ -222,7 +264,8 @@ static int qpnp_oledb_write(struct qpnp_oledb *oledb, u16 address, u8 *val,
		pr_debug("Wrote 0x%02X to addr 0x%04X\n",
			*val, address);

	return 0;
	mutex_unlock(&oledb->bus_lock);
	return rc;
}

static int qpnp_oledb_regulator_enable(struct regulator_dev *rdev)
@@ -285,6 +328,8 @@ static int qpnp_oledb_regulator_enable(struct regulator_dev *rdev)
static int qpnp_oledb_regulator_disable(struct regulator_dev *rdev)
{
	int rc = 0;
	u8 trigger_bitmap = OLEDB_PD_PBS_TRIGGER_BIT;
	u8 val;

	struct qpnp_oledb *oledb  = rdev_get_drvdata(rdev);

@@ -314,6 +359,27 @@ static int qpnp_oledb_regulator_disable(struct regulator_dev *rdev)
		pr_debug("Register-control mode, module disabled\n");
	}

	if (oledb->force_pd_control) {
		rc = qpnp_oledb_read(oledb, oledb->base + OLEDB_SPARE_CTL,
						&val, 1);
		if (rc < 0) {
			pr_err("Failed to read OLEDB_SPARE_CTL rc=%d\n", rc);
			return rc;
		}

		if (val & OLEDB_FORCE_PD_CTL_SPARE_BIT) {
			rc = qpnp_pbs_trigger_event(oledb->pbs_dev_node,
							trigger_bitmap);
			if (rc < 0) {
				pr_err("Failed to trigger the PBS sequence\n");
				return rc;
			}
			pr_debug("PBS event triggered\n");
		} else {
			pr_debug("OLEDB_SPARE_CTL register bit not set\n");
		}
	}

	oledb->mod_enable = false;

	return rc;
@@ -1034,6 +1100,18 @@ static int qpnp_oledb_parse_dt(struct qpnp_oledb *oledb)
	oledb->pbs_control =
			of_property_read_bool(of_node, "qcom,pbs-control");

	oledb->force_pd_control =
			of_property_read_bool(of_node, "qcom,force-pd-control");

	if (oledb->force_pd_control) {
		oledb->pbs_dev_node = of_parse_phandle(of_node,
						"qcom,pbs-client", 0);
		if (!oledb->pbs_dev_node) {
			pr_err("Missing qcom,pbs-client property\n");
			return -EINVAL;
		}
	}

	oledb->current_voltage = -EINVAL;
	rc = of_property_read_u32(of_node, "qcom,oledb-init-voltage-mv",
						&oledb->current_voltage);
@@ -1116,6 +1194,52 @@ static int qpnp_oledb_parse_dt(struct qpnp_oledb *oledb)
	return rc;
}

static int qpnp_oledb_force_pulldown_config(struct qpnp_oledb *oledb)
{
	int rc = 0;
	u8 val;

	rc = qpnp_oledb_sec_masked_write(oledb, oledb->base +
		    OLEDB_SPARE_CTL, OLEDB_FORCE_PD_CTL_SPARE_BIT, 0);
	if (rc < 0) {
		pr_err("Failed to write SPARE_CTL rc=%d\n", rc);
		return rc;
	}

	val = 1;
	rc = qpnp_oledb_write(oledb, oledb->base + OLEDB_PD_CTL,
							&val, 1);
	if (rc < 0) {
		pr_err("Failed to write PD_CTL rc=%d\n", rc);
		return rc;
	}

	rc = qpnp_oledb_masked_write(oledb, oledb->base +
		OLEDB_SWIRE_CONTROL, OLEDB_EN_SWIRE_PD_UPD_BIT, 0);
	if (rc < 0)
		pr_err("Failed to write SWIRE_CTL for pbs mode rc=%d\n",
					rc);

	return rc;
}

static int qpnp_labibb_notifier_cb(struct notifier_block *nb,
					unsigned long action, void *data)
{
	int rc = 0;
	struct qpnp_oledb *oledb = container_of(nb, struct qpnp_oledb,
								oledb_nb);

	if (action == LAB_VREG_OK) {
		/* Disable SWIRE pull down control and enable via spmi mode */
		rc = qpnp_oledb_force_pulldown_config(oledb);
		if (rc < 0)
			return NOTIFY_STOP;
	}

	return NOTIFY_OK;
}

static int qpnp_oledb_regulator_probe(struct platform_device *pdev)
{
	int rc = 0;
@@ -1143,6 +1267,7 @@ static int qpnp_oledb_regulator_probe(struct platform_device *pdev)
		return rc;
	}

	mutex_init(&(oledb->bus_lock));
	oledb->base = val;
	rc = qpnp_oledb_parse_dt(oledb);
	if (rc < 0) {
@@ -1156,18 +1281,47 @@ static int qpnp_oledb_regulator_probe(struct platform_device *pdev)
		return rc;
	}

	if (oledb->force_pd_control) {
		oledb->oledb_nb.notifier_call = qpnp_labibb_notifier_cb;
		rc = qpnp_labibb_notifier_register(&oledb->oledb_nb);
		if (rc < 0) {
			pr_err("Failed to register qpnp_labibb_notifier_cb\n");
			return rc;
		}
	}

	rc = qpnp_oledb_register_regulator(oledb);
	if (!rc)
		pr_info("OLEDB registered successfully, ext_pin_en=%d mod_en=%d cuurent_voltage=%d mV\n",
	if (rc < 0) {
		pr_err("Failed to register regulator rc=%d\n", rc);
		goto out;
	}
	pr_info("OLEDB registered successfully, ext_pin_en=%d mod_en=%d current_voltage=%d mV\n",
			oledb->ext_pin_control, oledb->mod_enable,
						oledb->current_voltage);
	return 0;

out:
	if (oledb->force_pd_control) {
		rc  = qpnp_labibb_notifier_unregister(&oledb->oledb_nb);
		if (rc < 0)
			pr_err("Failed to unregister lab_vreg_ok notifier\n");
	}

	return rc;
}

static int qpnp_oledb_regulator_remove(struct platform_device *pdev)
{
	return 0;
	int rc = 0;
	struct qpnp_oledb *oledb = platform_get_drvdata(pdev);

	if (oledb->force_pd_control) {
		rc  = qpnp_labibb_notifier_unregister(&oledb->oledb_nb);
		if (rc < 0)
			pr_err("Failed to unregister lab_vreg_ok notifier\n");
	}

	return rc;
}

const struct of_device_id qpnp_oledb_regulator_match_table[] = {