summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorDavide Garberi <dade.garberi@gmail.com>2019-08-21 03:23:03 +0200
committerMichael Bestas <mkbestas@lineageos.org>2020-05-01 17:02:33 +0300
commit6abc14f74a4e924d00b2919e7dd3cf2921a3c8bd (patch)
treeb78f3ed1a830626a343accb4888cb8f2ceb1ca7d /drivers
parent1727d33f3c9f948ef8f3b9b5034e46ef0a11e123 (diff)
iio: qcom-rradc: Import xiaomi tulip changes
* Modified ifdef style and config name to MACH_XIAOMI_TULIP Change-Id: I6d270520ffd7b52d36d7657d1c53b6fb5a48cefb Signed-off-by: Isaac Chen <tingyi364@gmail.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/iio/adc/qcom-rradc.c136
1 files changed, 136 insertions, 0 deletions
diff --git a/drivers/iio/adc/qcom-rradc.c b/drivers/iio/adc/qcom-rradc.c
index b3aa73f1a5a1..62153b8a8594 100644
--- a/drivers/iio/adc/qcom-rradc.c
+++ b/drivers/iio/adc/qcom-rradc.c
@@ -199,6 +199,10 @@
#define FG_RR_TP_REV_VERSION2 29
#define FG_RR_TP_REV_VERSION3 32
+#ifdef CONFIG_MACH_XIAOMI_TULIP
+int rradc_die = 0;
+#endif
+
/*
* The channel number is not a physical index in hardware,
* rather it's a list of supported channels and an index to
@@ -236,6 +240,13 @@ struct rradc_chip {
struct pmic_revid_data *pmic_fab_id;
int volt;
struct power_supply *usb_trig;
+#ifdef CONFIG_MACH_XIAOMI_TULIP
+ struct power_supply *batt_psy;
+ struct power_supply *bms_psy;
+ struct notifier_block nb;
+ bool conv_cbk;
+ struct work_struct psy_notify_work;
+#endif
};
struct rradc_channels {
@@ -680,6 +691,30 @@ static const struct rradc_channels rradc_chans[] = {
FG_ADC_RR_AUX_THERM_STS)
};
+#ifdef CONFIG_MACH_XIAOMI_TULIP
+static bool rradc_is_batt_psy_available(struct rradc_chip *chip)
+{
+ if (!chip->batt_psy)
+ chip->batt_psy = power_supply_get_by_name("battery");
+
+ if (!chip->batt_psy)
+ return false;
+
+ return true;
+}
+
+static bool rradc_is_bms_psy_available(struct rradc_chip *chip)
+{
+ if (!chip->bms_psy)
+ chip->bms_psy = power_supply_get_by_name("bms");
+
+ if (!chip->bms_psy)
+ return false;
+
+ return true;
+}
+#endif
+
static int rradc_enable_continuous_mode(struct rradc_chip *chip)
{
int rc = 0;
@@ -749,6 +784,9 @@ static int rradc_check_status_ready_with_retry(struct rradc_chip *chip,
struct rradc_chan_prop *prop, u8 *buf, u16 status)
{
int rc = 0, retry_cnt = 0, mask = 0;
+#ifdef CONFIG_MACH_XIAOMI_TULIP
+ union power_supply_propval pval = {0, };
+#endif
switch (prop->channel) {
case RR_ADC_BATT_ID:
@@ -784,8 +822,31 @@ static int rradc_check_status_ready_with_retry(struct rradc_chip *chip,
}
}
+#ifdef CONFIG_MACH_XIAOMI_TULIP
+ if ((retry_cnt >= FG_RR_CONV_MAX_RETRY_CNT) &&
+ ((prop->channel != RR_ADC_DCIN_V) ||
+ (prop->channel != RR_ADC_DCIN_I))) {
+ pr_err("rradc is hung, Proceed to recovery\n");
+ if (rradc_is_bms_psy_available(chip)) {
+ rc = power_supply_set_property(chip->bms_psy,
+ POWER_SUPPLY_PROP_FG_RESET_CLOCK,
+ &pval);
+ if (rc < 0) {
+ pr_err("Couldn't reset FG clock rc=%d\n", rc);
+ return rc;
+ }
+ } else {
+ pr_err("Error obtaining bms power supply\n");
+ rc = -EINVAL;
+ }
+ } else {
+ if (retry_cnt >= FG_RR_CONV_MAX_RETRY_CNT)
+ rc = -ENODATA;
+ }
+#else
if (retry_cnt >= FG_RR_CONV_MAX_RETRY_CNT)
rc = -ENODATA;
+#endif
return rc;
}
@@ -1073,6 +1134,66 @@ static int rradc_read_raw(struct iio_dev *indio_dev,
return rc;
}
+#ifdef CONFIG_MACH_XIAOMI_TULIP
+static void psy_notify_work(struct work_struct *work)
+{
+ struct rradc_chip *chip = container_of(work,
+ struct rradc_chip, psy_notify_work);
+
+ struct rradc_chan_prop *prop;
+ union power_supply_propval pval = {0, };
+ u16 adc_code;
+ int rc = 0;
+
+ if (rradc_is_batt_psy_available(chip)) {
+ rc = power_supply_get_property(chip->batt_psy,
+ POWER_SUPPLY_PROP_STATUS, &pval);
+ if (rc < 0) {
+ pr_err("Error obtaining battery status, rc=%d\n", rc);
+ }
+
+ if (pval.intval == POWER_SUPPLY_STATUS_CHARGING) {
+ chip->conv_cbk = true;
+ prop = &chip->chan_props[RR_ADC_USBIN_V];
+ rc = rradc_do_conversion(chip, prop, &adc_code);
+ if (rc == -ENODATA) {
+ pr_err("rradc is hung, Proceed to recovery\n");
+ rradc_die = 1;
+ if (rradc_is_bms_psy_available(chip)) {
+ rc = power_supply_set_property
+ (chip->bms_psy,
+ POWER_SUPPLY_PROP_FG_RESET_CLOCK,
+ &pval);
+ if (rc < 0) {
+ pr_err("Couldn't reset FG clock rc=%d\n", rc);
+ }
+ } else {
+ pr_err("Error obtaining bms power supply");
+ }
+ }
+ }
+ } else {
+ pr_err("Error obtaining battery power supply");
+ }
+ chip->conv_cbk = false;
+ pm_relax(chip->dev);
+}
+
+static int rradc_psy_notifier_cb(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ struct power_supply *psy = data;
+ struct rradc_chip *chip = container_of(nb, struct rradc_chip, nb);
+
+ if (strcmp(psy->desc->name, "battery") == 0) {
+ pm_stay_awake(chip->dev);
+ schedule_work(&chip->psy_notify_work);
+ }
+
+ return NOTIFY_OK;
+}
+#endif
+
static const struct iio_info rradc_info = {
.read_raw = &rradc_read_raw,
.driver_module = THIS_MODULE,
@@ -1180,6 +1301,21 @@ static int rradc_probe(struct platform_device *pdev)
indio_dev->channels = chip->iio_chans;
indio_dev->num_channels = chip->nchannels;
+#ifdef CONFIG_MACH_XIAOMI_TULIP
+ chip->batt_psy = power_supply_get_by_name("battery");
+ if (!chip->batt_psy)
+ pr_debug("Error obtaining battery power supply\n");
+
+ chip->bms_psy = power_supply_get_by_name("bms");
+ if (!chip->bms_psy)
+ pr_debug("Error obtaining bms power supply\n");
+
+ chip->nb.notifier_call = rradc_psy_notifier_cb;
+ rc = power_supply_reg_notifier(&chip->nb);
+ if (rc < 0)
+ pr_err("Error registering psy notifier rc = %d\n", rc);
+ INIT_WORK(&chip->psy_notify_work, psy_notify_work);
+#endif
chip->usb_trig = power_supply_get_by_name("usb");
if (!chip->usb_trig)
pr_debug("Error obtaining usb power supply\n");