diff options
author | Linux Build Service Account <lnxbuild@localhost> | 2017-02-25 01:09:27 -0800 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2017-02-25 01:09:27 -0800 |
commit | 8f0acd2665ff73b990d1e72aa8b95e9472b25578 (patch) | |
tree | 167cff861c2e90bb63a3fb0c0e628455d0dd61b4 | |
parent | 44ab13e7e1cba45eba3b70d7ad811f21aa9e36d3 (diff) | |
parent | 473bc7a3245795bc3a6b834196b8c4f8078c37d5 (diff) |
Merge "regulator: qpnp-labibb: Add support for notifier callback"
-rw-r--r-- | Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt | 2 | ||||
-rw-r--r-- | drivers/regulator/qpnp-labibb-regulator.c | 59 | ||||
-rw-r--r-- | include/linux/regulator/qpnp-labibb-regulator.h | 23 |
3 files changed, 84 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt b/Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt index d08ca957c954..c9cfc889faba 100644 --- a/Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt @@ -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: diff --git a/drivers/regulator/qpnp-labibb-regulator.c b/drivers/regulator/qpnp-labibb-regulator.c index cf8f00085a0c..dbe2a08f1776 100644 --- a/drivers/regulator/qpnp-labibb-regulator.c +++ b/drivers/regulator/qpnp-labibb-regulator.c @@ -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; } diff --git a/include/linux/regulator/qpnp-labibb-regulator.h b/include/linux/regulator/qpnp-labibb-regulator.h new file mode 100644 index 000000000000..247069507fd9 --- /dev/null +++ b/include/linux/regulator/qpnp-labibb-regulator.h @@ -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 |