Merge "regulator: qpnp-labibb: Add support for notifier callback"

This commit is contained in:
Linux Build Service Account 2017-02-25 01:09:27 -08:00 committed by Gerrit - the friendly Code Review server
commit 8f0acd2665
3 changed files with 84 additions and 0 deletions

View file

@ -149,6 +149,8 @@ LAB subnode optional properties:
already. If it it not specified, then
output voltage can be configured to
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:

View file

@ -19,16 +19,19 @@
#include <linux/kernel.h>
#include <linux/regmap.h>
#include <linux/module.h>
#include <linux/notifier.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/spmi.h>
#include <linux/platform_device.h>
#include <linux/string.h>
#include <linux/workqueue.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/of_regulator.h>
#include <linux/qpnp/qpnp-revid.h>
#include <linux/regulator/qpnp-labibb-regulator.h>
#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;
struct mutex bus_mutex;
enum qpnp_labibb_mode mode;
struct work_struct lab_vreg_ok_work;
bool standalone;
bool ttw_en;
bool in_ttw_mode;
@ -603,10 +607,13 @@ struct qpnp_labibb {
bool ttw_force_lab_on;
bool skip_2nd_swire_cmd;
bool pfm_enable;
bool notify_lab_vreg_ok_sts;
u32 swire_2nd_cmd_delay;
u32 swire_ibb_ps_enable_delay;
};
static RAW_NOTIFIER_HEAD(labibb_notifier);
struct ibb_ver_ops {
int (*set_default_voltage)(struct qpnp_labibb *labibb,
bool use_default);
@ -2124,6 +2131,36 @@ static int qpnp_labibb_regulator_ttw_mode_exit(struct qpnp_labibb *labibb)
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)
{
int rc;
@ -2326,6 +2363,9 @@ static int qpnp_lab_regulator_enable(struct regulator_dev *rdev)
labibb->lab_vreg.vreg_enabled = 1;
}
if (labibb->notify_lab_vreg_ok_sts)
schedule_work(&labibb->lab_vreg_ok_work);
return 0;
}
@ -2578,6 +2618,9 @@ static int register_qpnp_lab_regulator(struct qpnp_labibb *labibb,
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",
&(labibb->lab_vreg.soft_start));
if (!rc) {
@ -3817,6 +3860,8 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev)
goto fail_registration;
}
}
INIT_WORK(&labibb->lab_vreg_ok_work, qpnp_lab_vreg_notifier_work);
dev_set_drvdata(&pdev->dev, labibb);
pr_info("LAB/IBB registered successfully, lab_vreg enable=%d ibb_vreg enable=%d swire_control=%d\n",
labibb->lab_vreg.vreg_enabled,
@ -3834,6 +3879,18 @@ fail_registration:
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)
{
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);
if (labibb->ibb_vreg.rdev)
regulator_unregister(labibb->ibb_vreg.rdev);
cancel_work_sync(&labibb->lab_vreg_ok_work);
}
return 0;
}

View 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