Merge "regulator: qpnp-labibb: Add support for notifier callback"
This commit is contained in:
commit
8f0acd2665
3 changed files with 84 additions and 0 deletions
|
@ -149,6 +149,8 @@ LAB subnode optional properties:
|
||||||
already. If it it not specified, then
|
already. If it it not specified, then
|
||||||
output voltage can be configured to
|
output voltage can be configured to
|
||||||
any value in the allowed limit.
|
any value in the allowed limit.
|
||||||
|
- qcom,notify-lab-vreg-ok-sts: A boolean property which upon set will
|
||||||
|
poll and notify the lab_vreg_ok status.
|
||||||
|
|
||||||
Following properties are available only for PM660A:
|
Following properties are available only for PM660A:
|
||||||
|
|
||||||
|
|
|
@ -19,16 +19,19 @@
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/regmap.h>
|
#include <linux/regmap.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <linux/notifier.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/of_device.h>
|
#include <linux/of_device.h>
|
||||||
#include <linux/of_irq.h>
|
#include <linux/of_irq.h>
|
||||||
#include <linux/spmi.h>
|
#include <linux/spmi.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
|
#include <linux/workqueue.h>
|
||||||
#include <linux/regulator/driver.h>
|
#include <linux/regulator/driver.h>
|
||||||
#include <linux/regulator/machine.h>
|
#include <linux/regulator/machine.h>
|
||||||
#include <linux/regulator/of_regulator.h>
|
#include <linux/regulator/of_regulator.h>
|
||||||
#include <linux/qpnp/qpnp-revid.h>
|
#include <linux/qpnp/qpnp-revid.h>
|
||||||
|
#include <linux/regulator/qpnp-labibb-regulator.h>
|
||||||
|
|
||||||
#define QPNP_LABIBB_REGULATOR_DRIVER_NAME "qcom,qpnp-labibb-regulator"
|
#define QPNP_LABIBB_REGULATOR_DRIVER_NAME "qcom,qpnp-labibb-regulator"
|
||||||
|
|
||||||
|
@ -594,6 +597,7 @@ struct qpnp_labibb {
|
||||||
const struct lab_ver_ops *lab_ver_ops;
|
const struct lab_ver_ops *lab_ver_ops;
|
||||||
struct mutex bus_mutex;
|
struct mutex bus_mutex;
|
||||||
enum qpnp_labibb_mode mode;
|
enum qpnp_labibb_mode mode;
|
||||||
|
struct work_struct lab_vreg_ok_work;
|
||||||
bool standalone;
|
bool standalone;
|
||||||
bool ttw_en;
|
bool ttw_en;
|
||||||
bool in_ttw_mode;
|
bool in_ttw_mode;
|
||||||
|
@ -603,10 +607,13 @@ struct qpnp_labibb {
|
||||||
bool ttw_force_lab_on;
|
bool ttw_force_lab_on;
|
||||||
bool skip_2nd_swire_cmd;
|
bool skip_2nd_swire_cmd;
|
||||||
bool pfm_enable;
|
bool pfm_enable;
|
||||||
|
bool notify_lab_vreg_ok_sts;
|
||||||
u32 swire_2nd_cmd_delay;
|
u32 swire_2nd_cmd_delay;
|
||||||
u32 swire_ibb_ps_enable_delay;
|
u32 swire_ibb_ps_enable_delay;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static RAW_NOTIFIER_HEAD(labibb_notifier);
|
||||||
|
|
||||||
struct ibb_ver_ops {
|
struct ibb_ver_ops {
|
||||||
int (*set_default_voltage)(struct qpnp_labibb *labibb,
|
int (*set_default_voltage)(struct qpnp_labibb *labibb,
|
||||||
bool use_default);
|
bool use_default);
|
||||||
|
@ -2124,6 +2131,36 @@ static int qpnp_labibb_regulator_ttw_mode_exit(struct qpnp_labibb *labibb)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void qpnp_lab_vreg_notifier_work(struct work_struct *work)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
u16 retries = 1000, dly = 5000;
|
||||||
|
u8 val;
|
||||||
|
struct qpnp_labibb *labibb = container_of(work, struct qpnp_labibb,
|
||||||
|
lab_vreg_ok_work);
|
||||||
|
|
||||||
|
while (retries--) {
|
||||||
|
rc = qpnp_labibb_read(labibb, labibb->lab_base +
|
||||||
|
REG_LAB_STATUS1, &val, 1);
|
||||||
|
if (rc < 0) {
|
||||||
|
pr_err("read register %x failed rc = %d\n",
|
||||||
|
REG_LAB_STATUS1, rc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (val & LAB_STATUS1_VREG_OK) {
|
||||||
|
raw_notifier_call_chain(&labibb_notifier,
|
||||||
|
LAB_VREG_OK, NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
usleep_range(dly, dly + 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!retries)
|
||||||
|
pr_err("LAB_VREG_OK not set, failed to notify\n");
|
||||||
|
}
|
||||||
|
|
||||||
static int qpnp_labibb_regulator_enable(struct qpnp_labibb *labibb)
|
static int qpnp_labibb_regulator_enable(struct qpnp_labibb *labibb)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
@ -2326,6 +2363,9 @@ static int qpnp_lab_regulator_enable(struct regulator_dev *rdev)
|
||||||
labibb->lab_vreg.vreg_enabled = 1;
|
labibb->lab_vreg.vreg_enabled = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (labibb->notify_lab_vreg_ok_sts)
|
||||||
|
schedule_work(&labibb->lab_vreg_ok_work);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2578,6 +2618,9 @@ static int register_qpnp_lab_regulator(struct qpnp_labibb *labibb,
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
labibb->notify_lab_vreg_ok_sts = of_property_read_bool(of_node,
|
||||||
|
"qcom,notify-lab-vreg-ok-sts");
|
||||||
|
|
||||||
rc = of_property_read_u32(of_node, "qcom,qpnp-lab-soft-start",
|
rc = of_property_read_u32(of_node, "qcom,qpnp-lab-soft-start",
|
||||||
&(labibb->lab_vreg.soft_start));
|
&(labibb->lab_vreg.soft_start));
|
||||||
if (!rc) {
|
if (!rc) {
|
||||||
|
@ -3817,6 +3860,8 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev)
|
||||||
goto fail_registration;
|
goto fail_registration;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INIT_WORK(&labibb->lab_vreg_ok_work, qpnp_lab_vreg_notifier_work);
|
||||||
dev_set_drvdata(&pdev->dev, labibb);
|
dev_set_drvdata(&pdev->dev, labibb);
|
||||||
pr_info("LAB/IBB registered successfully, lab_vreg enable=%d ibb_vreg enable=%d swire_control=%d\n",
|
pr_info("LAB/IBB registered successfully, lab_vreg enable=%d ibb_vreg enable=%d swire_control=%d\n",
|
||||||
labibb->lab_vreg.vreg_enabled,
|
labibb->lab_vreg.vreg_enabled,
|
||||||
|
@ -3834,6 +3879,18 @@ fail_registration:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int qpnp_labibb_notifier_register(struct notifier_block *nb)
|
||||||
|
{
|
||||||
|
return raw_notifier_chain_register(&labibb_notifier, nb);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(qpnp_labibb_notifier_register);
|
||||||
|
|
||||||
|
int qpnp_labibb_notifier_unregister(struct notifier_block *nb)
|
||||||
|
{
|
||||||
|
return raw_notifier_chain_unregister(&labibb_notifier, nb);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(qpnp_labibb_notifier_unregister);
|
||||||
|
|
||||||
static int qpnp_labibb_regulator_remove(struct platform_device *pdev)
|
static int qpnp_labibb_regulator_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct qpnp_labibb *labibb = dev_get_drvdata(&pdev->dev);
|
struct qpnp_labibb *labibb = dev_get_drvdata(&pdev->dev);
|
||||||
|
@ -3843,6 +3900,8 @@ static int qpnp_labibb_regulator_remove(struct platform_device *pdev)
|
||||||
regulator_unregister(labibb->lab_vreg.rdev);
|
regulator_unregister(labibb->lab_vreg.rdev);
|
||||||
if (labibb->ibb_vreg.rdev)
|
if (labibb->ibb_vreg.rdev)
|
||||||
regulator_unregister(labibb->ibb_vreg.rdev);
|
regulator_unregister(labibb->ibb_vreg.rdev);
|
||||||
|
|
||||||
|
cancel_work_sync(&labibb->lab_vreg_ok_work);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
23
include/linux/regulator/qpnp-labibb-regulator.h
Normal file
23
include/linux/regulator/qpnp-labibb-regulator.h
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
/* Copyright (c) 2017 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _QPNP_LABIBB_REGULATOR_H
|
||||||
|
#define _QPNP_LABIBB_REGULATOR_H
|
||||||
|
|
||||||
|
enum labibb_notify_event {
|
||||||
|
LAB_VREG_OK = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
int qpnp_labibb_notifier_register(struct notifier_block *nb);
|
||||||
|
int qpnp_labibb_notifier_unregister(struct notifier_block *nb);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Add table
Reference in a new issue