power_supply: bq25700: support charge-dect interrupt wakeup system
[firefly-linux-kernel-4.4.55.git] / drivers / power / bq25700_charger.c
index d87f173340b1e83021225794634d20d5804d3598..fca588c6c7b036161e3b0f4546581350d69bcfa3 100644 (file)
  *
  */
 
+#include <linux/power/bq25700-charge.h>
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/mfd/core.h>
 #include <linux/module.h>
 #include <linux/regmap.h>
@@ -29,6 +31,7 @@
 #include <linux/power_supply.h>
 #include <linux/gpio.h>
 #include <linux/of_gpio.h>
+#include <linux/rk_keys.h>
 
 static int dbg_enable;
 module_param_named(dbg_level, dbg_enable, int, 0644);
@@ -375,7 +378,7 @@ static const union {
 } bq25700_tables[] = {
        /* range tables */
        [TBL_ICHG] =    { .rt = {0,       8128000, 64000} },
-       /* uA */
+       /* uV */
        [TBL_CHGMAX] = { .rt = {0, 19200000, 16000} },
        /* uV  max charge voltage*/
        [TBL_INPUTVOL] = { .rt = {3200000, 19520000, 64000} },
@@ -425,6 +428,8 @@ static const struct regmap_config bq25700_regmap_config = {
        .val_format_endian = REGMAP_ENDIAN_LITTLE,
 };
 
+static struct bq25700_device *bq25700_charger;
+
 static int bq25700_field_read(struct bq25700_device *charger,
                              enum bq25700_fields field_id)
 {
@@ -623,6 +628,31 @@ static u32 bq25700_find_idx(u32 value, enum bq25700_table_ids id)
        return idx - 1;
 }
 
+void bq25700_charger_set_current(unsigned long event,
+                                int current_value)
+{
+       int idx;
+
+       if (!bq25700_charger) {
+               pr_err("[%s,%d] bq25700_charger is null\n", __func__, __LINE__);
+               return;
+       }
+       switch (event) {
+       case CHARGER_CURRENT_EVENT:
+               idx = bq25700_find_idx(current_value, TBL_ICHG);
+               bq25700_field_write(bq25700_charger, CHARGE_CURRENT, idx);
+               break;
+
+       case INPUT_CURRENT_EVENT:
+               idx = bq25700_find_idx(current_value, TBL_INPUTCUR);
+               bq25700_field_write(bq25700_charger, INPUT_CURRENT, idx);
+               break;
+
+       default:
+               return;
+       }
+}
+
 static int bq25700_fw_read_u32_props(struct bq25700_device *charger)
 {
        int ret;
@@ -995,18 +1025,18 @@ static int bq25700_power_supply_init(struct bq25700_device *charger)
 static irqreturn_t bq25700_irq_handler_thread(int irq, void *private)
 {
        struct bq25700_device *charger = private;
-       int ret;
-       struct bq25700_state state;
-
-       ret = bq25700_get_chip_state(charger, &state);
-       if (ret < 0)
-               goto handled;
+       int irq_flag;
 
-       charger->state = state;
-
-       power_supply_changed(charger->supply_charger);
+       if (bq25700_field_read(charger, AC_STAT)) {
+               irq_flag = IRQF_TRIGGER_LOW;
+       } else {
+               irq_flag = IRQF_TRIGGER_HIGH;
+               bq25700_field_write(charger, INPUT_CURRENT,
+                                   charger->init_data.input_current_sdp);
+       }
+       irq_set_irq_type(irq, irq_flag | IRQF_ONESHOT);
+       rk_send_wakeup_key();
 
-handled:
        return IRQ_HANDLED;
 }
 
@@ -1609,6 +1639,7 @@ static int bq25700_probe(struct i2c_client *client,
        struct bq25700_device *charger;
        int ret = 0;
        u32 i = 0;
+       int irq_flag;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA))
                return -EIO;
@@ -1675,14 +1706,24 @@ static int bq25700_probe(struct i2c_client *client,
                dev_err(dev, "No irq resource found.\n");
                return client->irq;
        }
+
+       if (bq25700_field_read(charger, AC_STAT))
+               irq_flag = IRQF_TRIGGER_LOW;
+       else
+               irq_flag = IRQF_TRIGGER_HIGH;
+
+       device_init_wakeup(dev, 1);
+
        ret = devm_request_threaded_irq(dev, client->irq, NULL,
                                        bq25700_irq_handler_thread,
-                                       IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+                                       irq_flag | IRQF_ONESHOT,
                                        "bq25700_irq", charger);
        if (ret)
                goto irq_fail;
+       enable_irq_wake(client->irq);
 
        bq25700_power_supply_init(charger);
+       bq25700_charger = charger;
 
 irq_fail:
        return ret;