From 072de836f53be56a70cecf70b43ae43b7ce17376 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Mon, 11 Dec 2023 10:08:36 +0000
Subject: [PATCH] mk-rootfs.sh
---
kernel/drivers/power/supply/bq25700_charger.c | 536 ++++++++++++++++++++++++++++++++--------------------------
1 files changed, 296 insertions(+), 240 deletions(-)
diff --git a/kernel/drivers/power/supply/bq25700_charger.c b/kernel/drivers/power/supply/bq25700_charger.c
index 5b2a516..7109613 100644
--- a/kernel/drivers/power/supply/bq25700_charger.c
+++ b/kernel/drivers/power/supply/bq25700_charger.c
@@ -1,18 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* TI BQ257000 charger driver
+
+ * Copyright (c) 2021 Rockchip Electronics Co. Ltd.
*
- * Copyright (C) 2016 Rockchip Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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 FR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
+ * Author: shengfeixu <xsf@rock-chips.com>
*/
#include <linux/power/bq25700-charge.h>
@@ -22,6 +14,7 @@
#include <linux/mfd/core.h>
#include <linux/module.h>
#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
#include <linux/of_device.h>
#include <linux/delay.h>
#include <linux/usb/phy.h>
@@ -54,6 +47,7 @@
#define MAX_CHARGEVOLTAGE 16800000
#define MAX_CHARGECURRETNT 8128000
#define MAX_OTGVOLTAGE 20800000
+#define MIN_OTGVOLTAGE 4280000
#define MAX_OTGCURRENT 6350000
enum bq25700_fields {
@@ -168,27 +162,24 @@
bool charger_health_valid;
bool battery_health_valid;
bool battery_status_valid;
-
+ int automode;
+ struct notifier_block nb;
+ struct bq2570x_platform_data plat_data;
+ struct device_node *notify_node;
struct workqueue_struct *usb_charger_wq;
struct workqueue_struct *dc_charger_wq;
struct workqueue_struct *finish_sig_wq;
struct delayed_work usb_work;
- struct delayed_work pd_work;
struct delayed_work host_work;
struct delayed_work discnt_work;
struct delayed_work usb_work1;
- struct delayed_work pd_work1;
struct delayed_work host_work1;
struct delayed_work discnt_work1;
struct delayed_work irq_work;
struct notifier_block cable_cg_nb;
- struct notifier_block cable_pd_nb;
struct notifier_block cable_host_nb;
- struct notifier_block cable_discnt_nb;
struct notifier_block cable_cg_nb1;
- struct notifier_block cable_pd_nb1;
struct notifier_block cable_host_nb1;
- struct notifier_block cable_discnt_nb1;
struct extcon_dev *cable_edev;
struct extcon_dev *cable_edev_1;
int typec0_status;
@@ -199,6 +190,7 @@
struct gpio_desc *typec1_discharge_io;
struct gpio_desc *otg_mode_en_io;
+ struct regulator_dev *otg_vbus_reg;
struct regmap *regmap;
struct regmap_field *rmap_fields[F_MAX_FIELDS];
int chip_id;
@@ -515,7 +507,13 @@
u32 size;
};
-static const union {
+static const struct bq25700_range sc8886_otg_range = {
+ .min = 1280000,
+ .max = 20800000,
+ .step = 128000,
+};
+
+static union {
struct bq25700_range rt;
struct bq25700_lookup lt;
} bq25700_tables[] = {
@@ -816,7 +814,7 @@
return 0;
}
-ssize_t bq25700_charge_info_show(struct device *dev,
+static ssize_t bq25700_charge_info_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct bq25700_device *charger = dev_get_drvdata(dev);
@@ -944,12 +942,25 @@
dev_err(charger->dev, "ti,input-current is error\n");
return -ENODEV;
}
- if ((props[i].tbl_id == TBL_OTGVOL) &&
- (property > MAX_OTGVOLTAGE)) {
- dev_err(charger->dev, "ti,ti,otg-voltage is error\n");
- return -ENODEV;
+ if (props[i].tbl_id == TBL_OTGVOL) {
+ if (of_device_is_compatible(charger->dev->of_node,
+ "southchip,sc8886")) {
+ bq25700_tables[TBL_OTGVOL].rt = sc8886_otg_range;
+
+ if (property < MIN_OTGVOLTAGE) {
+ dev_err(charger->dev,
+ "ti,otg-voltage is error");
+ return -ENODEV;
+ }
+ }
+
+ if (property > MAX_OTGVOLTAGE) {
+ dev_err(charger->dev, "ti,otg-voltage is error\n");
+ return -ENODEV;
+ };
}
- if ((props[i].tbl_id == TBL_OTGVOL) &&
+
+ if ((props[i].tbl_id == TBL_OTGCUR) &&
(property > MAX_OTGCURRENT)) {
dev_err(charger->dev, "ti,otg-current is error\n");
return -ENODEV;
@@ -1231,6 +1242,7 @@
psy_cfg.supplied_to = bq25700_charger_supplied_to;
psy_cfg.num_supplicants = ARRAY_SIZE(bq25700_charger_supplied_to);
+ psy_cfg.of_node = charger->dev->of_node;
charger->supply_charger =
power_supply_register(charger->dev,
@@ -1238,6 +1250,71 @@
&psy_cfg);
return PTR_ERR_OR_ZERO(charger->supply_charger);
+}
+
+static void bq25700_discnt(struct bq25700_device *charger, enum tpyec_port_t port);
+
+static int bq2570x_pd_notifier_call(struct notifier_block *nb,
+ unsigned long val, void *v)
+{
+ struct bq25700_device *bq =
+ container_of(nb, struct bq25700_device, nb);
+ struct power_supply *psy = v;
+ union power_supply_propval prop;
+ struct bq25700_state state;
+ int ret;
+ int vol_idx, cur_idx, chr_idx;
+
+ if (val != PSY_EVENT_PROP_CHANGED)
+ return NOTIFY_OK;
+
+ /* Ignore event if it was not send by notify_node/notify_device */
+ if (bq->notify_node) {
+ if (!psy->dev.parent ||
+ psy->dev.parent->of_node != bq->notify_node)
+ return NOTIFY_OK;
+ } else if (bq->plat_data.notify_device) {
+ if (strcmp(psy->desc->name, bq->plat_data.notify_device) != 0)
+ return NOTIFY_OK;
+ }
+
+ ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_ONLINE, &prop);
+ if (ret != 0)
+ return NOTIFY_OK;
+ /* online=0: USB out */
+ if (prop.intval == 0) {
+ queue_delayed_work(bq->usb_charger_wq, &bq->discnt_work,
+ msecs_to_jiffies(10));
+ return NOTIFY_OK;
+ }
+
+ ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_CURRENT_NOW, &prop);
+ if (ret != 0)
+ return NOTIFY_OK;
+ if (prop.intval > 0) {
+ cur_idx = bq25700_find_idx(prop.intval, TBL_INPUTCUR);
+ ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ &prop);
+ if (ret != 0)
+ return NOTIFY_OK;
+ vol_idx = bq25700_find_idx((prop.intval - 1280000 - 3200000), TBL_INPUTVOL);
+ ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_CURRENT_NOW,
+ &prop);
+ if (ret != 0)
+ return NOTIFY_OK;
+ chr_idx = bq25700_find_idx(prop.intval, TBL_ICHG);
+
+ bq25700_field_write(bq, INPUT_CURRENT, cur_idx);
+ bq25700_field_write(bq, INPUT_VOLTAGE, vol_idx);
+ bq25700_field_write(bq, CHARGE_CURRENT, chr_idx);
+ dev_info(bq->dev, "INPUT_CURRENT:%d, INPUT_VOLTAGE:%d, CHARGE_CURRENT:%d\n",
+ cur_idx, vol_idx, chr_idx);
+
+ bq25700_get_chip_state(bq, &state);
+ bq->state = state;
+ power_supply_changed(bq->supply_charger);
+ }
+ return NOTIFY_OK;
}
static irqreturn_t bq25700_irq_handler_thread(int irq, void *private)
@@ -1304,101 +1381,6 @@
msleep(20);
if (!IS_ERR_OR_NULL(charger->typec1_discharge_io))
gpiod_direction_output(charger->typec1_discharge_io, 0);
-}
-
-static void bq25700_pd_connect(struct bq25700_device *charger,
- struct extcon_dev *edev,
- enum tpyec_port_t port)
-{
- union extcon_property_value prop_val;
- struct bq25700_state state;
- int ret;
- int vol, cur;
- int vol_idx, cur_idx;
- int i;
-
- if (charger->typec0_status == USB_STATUS_PD ||
- charger->typec1_status == USB_STATUS_PD)
- return;
-
- if (extcon_get_state(edev, EXTCON_CHG_USB_FAST) > 0) {
- ret = extcon_get_property(edev, EXTCON_CHG_USB_FAST,
- EXTCON_PROP_USB_TYPEC_POLARITY,
- &prop_val);
- DBG("usb pd charge...\n");
- vol = prop_val.intval & 0xffff;
- cur = prop_val.intval >> 15;
- if (ret == 0) {
- if (port == USB_TYPEC_0) {
- charger->typec0_status = USB_STATUS_PD;
- bq25700_enable_typec0(charger);
- } else {
- charger->typec1_status = USB_STATUS_PD;
- bq25700_enable_typec1(charger);
- }
-
- i = 0;
- while (!bq25700_field_read(charger, AC_STAT) && i < 5) {
- msleep(1000);
- i++;
- }
- vol_idx = bq25700_find_idx((vol - 1280) * 1000,
- TBL_INPUTVOL);
- cur_idx = bq25700_find_idx(cur * 1000, TBL_INPUTCUR);
- bq25700_field_write(charger, INPUT_VOLTAGE, vol_idx);
- bq25700_field_write(charger, INPUT_CURRENT, cur_idx);
- bq25700_field_write(charger, CHARGE_CURRENT,
- charger->init_data.ichg);
- }
-
- bq25700_get_chip_state(charger, &state);
- charger->state = state;
- power_supply_changed(charger->supply_charger);
- }
-}
-
-static void bq25700_pd_evt_worker(struct work_struct *work)
-{
- struct bq25700_device *charger = container_of(work,
- struct bq25700_device, pd_work.work);
- struct extcon_dev *edev = charger->cable_edev;
-
- bq25700_pd_connect(charger, edev, USB_TYPEC_0);
-}
-
-static void bq25700_pd_evt_worker1(struct work_struct *work)
-{
- struct bq25700_device *charger = container_of(work,
- struct bq25700_device, pd_work1.work);
- struct extcon_dev *edev = charger->cable_edev_1;
-
- bq25700_pd_connect(charger, edev, USB_TYPEC_1);
-}
-
-static int bq25700_pd_evt_notifier(struct notifier_block *nb,
- unsigned long event,
- void *ptr)
-{
- struct bq25700_device *charger =
- container_of(nb, struct bq25700_device, cable_pd_nb);
-
- queue_delayed_work(charger->usb_charger_wq, &charger->pd_work,
- msecs_to_jiffies(10));
-
- return NOTIFY_DONE;
-}
-
-static int bq25700_pd_evt_notifier1(struct notifier_block *nb,
- unsigned long event,
- void *ptr)
-{
- struct bq25700_device *charger =
- container_of(nb, struct bq25700_device, cable_pd_nb1);
-
- queue_delayed_work(charger->usb_charger_wq, &charger->pd_work1,
- msecs_to_jiffies(10));
-
- return NOTIFY_DONE;
}
static void bq25700_charger_evt_handel(struct bq25700_device *charger,
@@ -1481,6 +1463,7 @@
struct bq25700_device *charger = container_of(work,
struct bq25700_device, usb_work.work);
struct extcon_dev *edev = charger->cable_edev;
+
if (charger->usb_bc == 0)
bq25700_charger_evt_handel(charger, edev, USB_TYPEC_0);
else
@@ -1522,24 +1505,25 @@
return NOTIFY_DONE;
}
+static void bq25700_set_otg_vbus(struct bq25700_device *charger, bool enable)
+{
+ DBG("OTG %s\n", enable ? "enable" : "disable");
+
+ if (!IS_ERR_OR_NULL(charger->otg_mode_en_io))
+ gpiod_direction_output(charger->otg_mode_en_io, enable);
+ bq25700_field_write(charger, EN_OTG, enable);
+}
+
static void bq25700_host_evt_worker(struct work_struct *work)
{
struct bq25700_device *charger =
container_of(work, struct bq25700_device, host_work.work);
struct extcon_dev *edev = charger->cable_edev;
- /* Determine charger type */
- if (extcon_get_state(edev, EXTCON_USB_VBUS_EN) > 0) {
- if (!IS_ERR_OR_NULL(charger->otg_mode_en_io))
- gpiod_direction_output(charger->otg_mode_en_io, 1);
- bq25700_field_write(charger, EN_OTG, 1);
- DBG("OTG enable\n");
- } else if (extcon_get_state(edev, EXTCON_USB_VBUS_EN) == 0) {
- if (!IS_ERR_OR_NULL(charger->otg_mode_en_io))
- gpiod_direction_output(charger->otg_mode_en_io, 0);
- bq25700_field_write(charger, EN_OTG, 0);
- DBG("OTG disable\n");
- }
+ if (extcon_get_state(edev, EXTCON_USB_VBUS_EN) > 0)
+ bq25700_set_otg_vbus(charger, true);
+ else if (extcon_get_state(edev, EXTCON_USB_VBUS_EN) == 0)
+ bq25700_set_otg_vbus(charger, false);
}
static void bq25700_host_evt_worker1(struct work_struct *work)
@@ -1548,18 +1532,10 @@
container_of(work, struct bq25700_device, host_work1.work);
struct extcon_dev *edev = charger->cable_edev_1;
- /* Determine charger type */
- if (extcon_get_state(edev, EXTCON_USB_VBUS_EN) > 0) {
- if (!IS_ERR_OR_NULL(charger->otg_mode_en_io))
- gpiod_direction_output(charger->otg_mode_en_io, 1);
- bq25700_field_write(charger, EN_OTG, 1);
- DBG("OTG enable\n");
- } else if (extcon_get_state(edev, EXTCON_USB_VBUS_EN) == 0) {
- if (!IS_ERR_OR_NULL(charger->otg_mode_en_io))
- gpiod_direction_output(charger->otg_mode_en_io, 0);
- bq25700_field_write(charger, EN_OTG, 0);
- DBG("OTG disable\n");
- }
+ if (extcon_get_state(edev, EXTCON_USB_VBUS_EN) > 0)
+ bq25700_set_otg_vbus(charger, true);
+ else if (extcon_get_state(edev, EXTCON_USB_VBUS_EN) == 0)
+ bq25700_set_otg_vbus(charger, false);
}
static int bq25700_host_evt_notifier(struct notifier_block *nb,
@@ -1619,42 +1595,6 @@
discnt_work.work);
bq25700_discnt(charger, USB_TYPEC_0);
-}
-
-static void bq25700_discnt_evt_worker1(struct work_struct *work)
-{
- struct bq25700_device *charger = container_of(work,
- struct bq25700_device,
- discnt_work1.work);
- bq25700_discnt(charger, USB_TYPEC_1);
-}
-
-static int bq25700_discnt_evt_notfier(struct notifier_block *nb,
- unsigned long event,
- void *ptr)
-{
- struct bq25700_device *charger =
- container_of(nb, struct bq25700_device, cable_discnt_nb);
-
- queue_delayed_work(charger->usb_charger_wq,
- &charger->discnt_work,
- msecs_to_jiffies(0));
-
- return NOTIFY_DONE;
-}
-
-static int bq25700_discnt_evt_notfier1(struct notifier_block *nb,
- unsigned long event,
- void *ptr)
-{
- struct bq25700_device *charger =
- container_of(nb, struct bq25700_device, cable_discnt_nb1);
-
- queue_delayed_work(charger->usb_charger_wq,
- &charger->discnt_work1,
- msecs_to_jiffies(0));
-
- return NOTIFY_DONE;
}
static int bq25700_register_cg_extcon(struct bq25700_device *charger,
@@ -1731,60 +1671,61 @@
return 0;
}
-static int bq25700_register_discnt_nb(struct bq25700_device *charger)
-{
- int ret;
-
- /* Register discnt usb */
- if (charger->cable_edev) {
- INIT_DELAYED_WORK(&charger->discnt_work,
- bq25700_discnt_evt_worker);
- charger->cable_discnt_nb.notifier_call =
- bq25700_discnt_evt_notfier;
- ret = extcon_register_notifier(charger->cable_edev,
- EXTCON_USB,
- &charger->cable_discnt_nb);
- if (ret < 0) {
- dev_err(charger->dev,
- "failed to register notifier for HOST\n");
- return ret;
- }
- }
-
- if (charger->cable_edev_1) {
- INIT_DELAYED_WORK(&charger->discnt_work1,
- bq25700_discnt_evt_worker1);
- charger->cable_discnt_nb1.notifier_call =
- bq25700_discnt_evt_notfier1;
- ret = extcon_register_notifier(charger->cable_edev_1,
- EXTCON_USB,
- &charger->cable_discnt_nb1);
- if (ret < 0) {
- dev_err(charger->dev,
- "failed to register notifier for HOST\n");
- return ret;
- }
- }
-
- return 0;
-}
-
static int bq25700_register_pd_nb(struct bq25700_device *charger)
{
- if (charger->cable_edev) {
- INIT_DELAYED_WORK(&charger->pd_work, bq25700_pd_evt_worker);
- charger->cable_pd_nb.notifier_call = bq25700_pd_evt_notifier;
- extcon_register_notifier(charger->cable_edev,
- EXTCON_CHG_USB_FAST,
- &charger->cable_pd_nb);
+ struct power_supply *notify_psy = NULL;
+ int vol_idx, cur_idx;
+ int ret;
+ union power_supply_propval prop;
+
+ if (charger->notify_node || charger->plat_data.notify_device) {
+ INIT_DELAYED_WORK(&charger->discnt_work,
+ bq25700_discnt_evt_worker);
+ charger->nb.notifier_call = bq2570x_pd_notifier_call;
+ ret = power_supply_reg_notifier(&charger->nb);
+ if (ret) {
+ dev_err(charger->dev, "failed to reg notifier: %d\n", ret);
+ return ret;
+ }
+ charger->automode = 1;
+ dev_info(charger->dev, "automode supported, waiting for events\n");
+ } else {
+ charger->automode = -1;
+ dev_info(charger->dev, "automode not supported\n");
}
- if (charger->cable_edev_1) {
- INIT_DELAYED_WORK(&charger->pd_work1, bq25700_pd_evt_worker1);
- charger->cable_pd_nb1.notifier_call = bq25700_pd_evt_notifier1;
- extcon_register_notifier(charger->cable_edev_1,
- EXTCON_CHG_USB_FAST,
- &charger->cable_pd_nb1);
+ if (charger->nb.notifier_call) {
+ if (charger->dev->of_node) {
+ notify_psy = power_supply_get_by_phandle(charger->dev->of_node,
+ "ti,usb-charger-detection");
+ if (IS_ERR_OR_NULL(notify_psy)) {
+ dev_info(charger->dev, "bq25700 notify_psy is error\n");
+ notify_psy = NULL;
+ }
+ } else if (charger->plat_data.notify_device) {
+ notify_psy = power_supply_get_by_name(
+ charger->plat_data.notify_device);
+ }
+ }
+
+ if (notify_psy) {
+ ret = power_supply_get_property(notify_psy,
+ POWER_SUPPLY_PROP_CURRENT_MAX, &prop);
+ if (ret != 0)
+ return ret;
+ ret = power_supply_get_property(notify_psy,
+ POWER_SUPPLY_PROP_VOLTAGE_MAX, &prop);
+ if (ret != 0)
+ return ret;
+
+ cur_idx = bq25700_find_idx(prop.intval, TBL_INPUTCUR);
+ vol_idx = bq25700_find_idx((prop.intval - 1280000 - 3200000), TBL_INPUTVOL);
+ bq25700_field_write(charger, INPUT_CURRENT, cur_idx);
+ bq25700_field_write(charger, INPUT_VOLTAGE, vol_idx);
+ bq25700_field_write(charger, CHARGE_CURRENT,
+ charger->init_data.ichg);
+ dev_info(charger->dev, "INPUT_CURRENT:%d, INPUT_VOLTAGE:%d, CHARGE_CURRENT:%d\n",
+ cur_idx, vol_idx, charger->init_data.ichg);
}
return 0;
@@ -1800,7 +1741,7 @@
charger->cable_host_nb.notifier_call =
bq25700_host_evt_notifier;
ret = extcon_register_notifier(charger->cable_edev,
- EXTCON_USB_HOST,
+ EXTCON_USB_VBUS_EN,
&charger->cable_host_nb);
if (ret < 0) {
dev_err(charger->dev,
@@ -1815,7 +1756,7 @@
charger->cable_host_nb1.notifier_call =
bq25700_host_evt_notifier1;
ret = extcon_register_notifier(charger->cable_edev_1,
- EXTCON_USB_HOST,
+ EXTCON_USB_VBUS_EN,
&charger->cable_host_nb1);
if (ret < 0) {
dev_err(charger->dev,
@@ -1823,6 +1764,77 @@
return -1;
}
}
+
+ return 0;
+}
+
+static int bq25700_otg_vbus_enable(struct regulator_dev *dev)
+{
+ struct bq25700_device *charger = rdev_get_drvdata(dev);
+
+ bq25700_set_otg_vbus(charger, true);
+
+ return 0;
+}
+
+static int bq25700_otg_vbus_disable(struct regulator_dev *dev)
+{
+ struct bq25700_device *charger = rdev_get_drvdata(dev);
+
+ bq25700_set_otg_vbus(charger, false);
+
+ return 0;
+}
+
+static int bq25700_otg_vbus_is_enabled(struct regulator_dev *dev)
+{
+ struct bq25700_device *charger = rdev_get_drvdata(dev);
+ u8 val;
+ int gpio_status = 1;
+
+ val = bq25700_field_read(charger, EN_OTG);
+ if (!IS_ERR_OR_NULL(charger->otg_mode_en_io))
+ gpio_status = gpiod_get_value(charger->otg_mode_en_io);
+
+ return val && gpio_status ? 1 : 0;
+}
+
+static const struct regulator_ops bq25700_otg_vbus_ops = {
+ .enable = bq25700_otg_vbus_enable,
+ .disable = bq25700_otg_vbus_disable,
+ .is_enabled = bq25700_otg_vbus_is_enabled,
+};
+
+static const struct regulator_desc bq25700_otg_vbus_desc = {
+ .name = "otg-vbus",
+ .of_match = "otg-vbus",
+ .regulators_node = of_match_ptr("regulators"),
+ .owner = THIS_MODULE,
+ .ops = &bq25700_otg_vbus_ops,
+ .type = REGULATOR_VOLTAGE,
+ .fixed_uV = 5000000,
+ .n_voltages = 1,
+};
+
+static int bq25700_register_otg_vbus_regulator(struct bq25700_device *charger)
+{
+ struct device_node *np;
+ struct regulator_config config = { };
+
+ np = of_get_child_by_name(charger->dev->of_node, "regulators");
+ if (!np) {
+ dev_warn(charger->dev, "cannot find regulators node\n");
+ return -ENXIO;
+ }
+
+ config.dev = charger->dev;
+ config.driver_data = charger;
+
+ charger->otg_vbus_reg = devm_regulator_register(charger->dev,
+ &bq25700_otg_vbus_desc,
+ &config);
+ if (IS_ERR(charger->otg_vbus_reg))
+ return PTR_ERR(charger->otg_vbus_reg);
return 0;
}
@@ -1854,21 +1866,31 @@
} else {
charger->cable_edev_1 = edev1;
}
+ /*set power_on input current*/
+ bq25700_field_write(charger, INPUT_CURRENT,
+ charger->init_data.input_current_sdp);
+
if (!charger->pd_charge_only)
bq25700_register_cg_nb(charger);
- bq25700_register_host_nb(charger);
- bq25700_register_discnt_nb(charger);
+
+ if (bq25700_register_otg_vbus_regulator(charger) < 0) {
+ dev_warn(charger->dev,
+ "Cannot register otg vbus regulator\n");
+ charger->otg_vbus_reg = NULL;
+ bq25700_register_host_nb(charger);
+ }
+
bq25700_register_pd_nb(charger);
if (charger->cable_edev) {
- schedule_delayed_work(&charger->host_work, 0);
- schedule_delayed_work(&charger->pd_work, 0);
+ if (!charger->otg_vbus_reg)
+ schedule_delayed_work(&charger->host_work, 0);
if (!charger->pd_charge_only)
schedule_delayed_work(&charger->usb_work, 0);
}
if (charger->cable_edev_1) {
- schedule_delayed_work(&charger->host_work1, 0);
- schedule_delayed_work(&charger->pd_work1, 0);
+ if (!charger->otg_vbus_reg)
+ schedule_delayed_work(&charger->host_work1, 0);
if (!charger->pd_charge_only)
schedule_delayed_work(&charger->usb_work1, 0);
}
@@ -1918,7 +1940,11 @@
charger->usb_bc = 0;
else
charger->usb_bc = 1;
+ of_node_put(temp_np);
+ if (np)
+ charger->notify_node = of_parse_phandle(np,
+ "ti,usb-charger-detection", 0);
return 0;
}
@@ -1944,6 +1970,8 @@
charger->dev = dev;
charger_np = of_find_compatible_node(NULL, NULL, "ti,bq25700");
+ if (!charger_np)
+ charger_np = of_find_compatible_node(NULL, NULL, "southchip,sc8885");
if (charger_np) {
charger->regmap = devm_regmap_init_i2c(client,
&bq25700_regmap_config);
@@ -2006,6 +2034,20 @@
return -ENODEV;
}
+ /*
+ * Make sure battery online, otherwise, writing INPUT_CURRENT and
+ * CHARGE_CURRENT would make system power off
+ */
+ if (of_parse_phandle(charger->dev->of_node, "ti,battery", 0)) {
+ if (IS_ERR_OR_NULL(power_supply_get_by_phandle(
+ charger->dev->of_node,
+ "ti,battery"))) {
+ dev_info(charger->dev, "No battery found\n");
+ return -EPROBE_DEFER;
+ }
+ dev_info(charger->dev, "Battery found\n");
+ }
+
ret = bq25700_hw_init(charger);
if (ret < 0) {
dev_err(dev, "Cannot initialize the chip.\n");
@@ -2044,7 +2086,7 @@
return ret;
}
-void bq25700_shutdown(struct i2c_client *client)
+static void bq25700_shutdown(struct i2c_client *client)
{
int vol_idx;
struct bq25700_device *charger = i2c_get_clientdata(client);
@@ -2053,16 +2095,28 @@
bq25700_field_write(charger, INPUT_VOLTAGE, vol_idx);
bq25700_field_write(charger, INPUT_CURRENT,
charger->init_data.input_current_sdp);
+
+ if (!bq25700_field_read(charger, AC_STAT))
+ bq25700_field_write(charger, EN_LWPWR, 1);
}
#ifdef CONFIG_PM_SLEEP
static int bq25700_pm_suspend(struct device *dev)
{
+ struct bq25700_device *charger = dev_get_drvdata(dev);
+
+ if (!bq25700_field_read(charger, AC_STAT))
+ bq25700_field_write(charger, EN_LWPWR, 1);
+
return 0;
}
static int bq25700_pm_resume(struct device *dev)
{
+ struct bq25700_device *charger = dev_get_drvdata(dev);
+
+ bq25700_field_write(charger, EN_LWPWR, 0);
+
return 0;
}
#endif
@@ -2079,6 +2133,8 @@
static const struct of_device_id bq25700_of_match[] = {
{ .compatible = "ti,bq25700", },
{ .compatible = "ti,bq25703", },
+ { .compatible = "southchip,sc8885", },
+ { .compatible = "southchip,sc8886", },
{ },
};
MODULE_DEVICE_TABLE(of, bq25700_of_match);
--
Gitblit v1.6.2