regulator: qpnp-oledb: Add lab_vreg_ok notifier callback
OLEDB driver needs the LAB_VREG_OK status to program the PD_CTL register after the oledb module is enabled. As this status register is not accessible from the OLEDB driver, register a notifier callback with LABIBB driver to get LAB_VREG_OK status. Change-Id: I85009688a2accb6246135d22e08ee21fb8296f62 Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
This commit is contained in:
parent
9147c318e6
commit
c3cd3d3174
2 changed files with 195 additions and 27 deletions
|
@ -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).
|
||||
|
|
|
@ -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[] = {
|
||||
|
|
Loading…
Add table
Reference in a new issue