[PATCH v3 1/2] power: supply: add sbs-charger driver

2016-11-24 Thread Nicolas Saenz Julienne
This adds support for sbs-charger compilant chips as defined here:
http://sbs-forum.org/specs/sbc110.pdf

This was tested on a arm board connected to an LTC41000 battery charger
chip.

Signed-off-by: Nicolas Saenz Julienne 
---
 v2 -> v3:
 - add readable_reg() function to regmap config
 - update compatible strings with part number

 v1 -> v2:
 - add spec link in header
 - use proper gpio/interrupt interface
 - update regmap configuration (max register & endianness)
 - dropped oldschool .supplied_to assignments
 - use devm_* APIs
 drivers/power/supply/Kconfig   |   6 +
 drivers/power/supply/Makefile  |   1 +
 drivers/power/supply/sbs-charger.c | 275 +
 3 files changed, 282 insertions(+)
 create mode 100644 drivers/power/supply/sbs-charger.c

diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index 76806a0..42877ff 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -164,6 +164,12 @@ config BATTERY_SBS
  Say Y to include support for SBS battery driver for SBS-compliant
  gas gauges.
 
+config CHARGER_SBS
+tristate "SBS Compliant charger"
+depends on I2C
+help
+ Say Y to include support for SBS compilant battery chargers.
+
 config BATTERY_BQ27XXX
tristate "BQ27xxx battery driver"
help
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
index 36c599d..06d9ef5 100644
--- a/drivers/power/supply/Makefile
+++ b/drivers/power/supply/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_BATTERY_COLLIE)  += collie_battery.o
 obj-$(CONFIG_BATTERY_IPAQ_MICRO) += ipaq_micro_battery.o
 obj-$(CONFIG_BATTERY_WM97XX)   += wm97xx_battery.o
 obj-$(CONFIG_BATTERY_SBS)  += sbs-battery.o
+obj-$(CONFIG_CHARGER_SBS)  += sbs-charger.o
 obj-$(CONFIG_BATTERY_BQ27XXX)  += bq27xxx_battery.o
 obj-$(CONFIG_BATTERY_BQ27XXX_I2C) += bq27xxx_battery_i2c.o
 obj-$(CONFIG_BATTERY_DA9030)   += da9030_battery.o
diff --git a/drivers/power/supply/sbs-charger.c 
b/drivers/power/supply/sbs-charger.c
new file mode 100644
index 000..2c4cd45
--- /dev/null
+++ b/drivers/power/supply/sbs-charger.c
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2016, Prodys S.L.
+ *
+ * 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 adds support for sbs-charger compilant chips as defined here:
+ * http://sbs-forum.org/specs/sbc110.pdf
+ *
+ * Implemetation based on sbs-battery.c
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define SBS_CHARGER_REG_SPEC_INFO  0x11
+#define SBS_CHARGER_REG_STATUS 0x13
+#define SBS_CHARGER_REG_ALARM_WARNING  0x16
+
+#define SBS_CHARGER_STATUS_CHARGE_INHIBITEDBIT(1)
+#define SBS_CHARGER_STATUS_RES_COLDBIT(9)
+#define SBS_CHARGER_STATUS_RES_HOT BIT(10)
+#define SBS_CHARGER_STATUS_BATTERY_PRESENT BIT(14)
+#define SBS_CHARGER_STATUS_AC_PRESENT  BIT(15)
+
+#define SBS_CHARGER_POLL_TIME  500
+
+struct sbs_info {
+   struct i2c_client   *client;
+   struct power_supply *power_supply;
+   struct regmap   *regmap;
+   struct delayed_work work;
+   unsigned intlast_state;
+};
+
+static int sbs_get_property(struct power_supply *psy,
+   enum power_supply_property psp,
+   union power_supply_propval *val)
+{
+   struct sbs_info *chip = power_supply_get_drvdata(psy);
+   unsigned int reg;
+
+   reg = chip->last_state;
+
+   switch (psp) {
+   case POWER_SUPPLY_PROP_PRESENT:
+   val->intval = !!(reg & SBS_CHARGER_STATUS_BATTERY_PRESENT);
+   break;
+
+   case POWER_SUPPLY_PROP_ONLINE:
+   val->intval = !!(reg & SBS_CHARGER_STATUS_AC_PRESENT);
+   break;
+
+   case POWER_SUPPLY_PROP_STATUS:
+   val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
+
+   if (!(reg & SBS_CHARGER_STATUS_BATTERY_PRESENT))
+   val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+   else if (reg & SBS_CHARGER_STATUS_AC_PRESENT &&
+!(reg & SBS_CHARGER_STATUS_CHARGE_INHIBITED))
+   val->intval = POWER_SUPPLY_STATUS_CHARGING;
+   else
+   val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+
+   break;
+
+   case POWER_SUPPLY_PROP_HEALTH:
+   if (reg & SBS_CHARGER_STATUS_RES_COLD)
+   val->intval = POWER_SUPPLY_HEALTH_COLD;
+   if (reg & SBS_CHARGER_STATUS_RES_HOT)
+   val->intval = 

[PATCH v3 1/2] power: supply: add sbs-charger driver

2016-11-24 Thread Nicolas Saenz Julienne
This adds support for sbs-charger compilant chips as defined here:
http://sbs-forum.org/specs/sbc110.pdf

This was tested on a arm board connected to an LTC41000 battery charger
chip.

Signed-off-by: Nicolas Saenz Julienne 
---
 v2 -> v3:
 - add readable_reg() function to regmap config
 - update compatible strings with part number

 v1 -> v2:
 - add spec link in header
 - use proper gpio/interrupt interface
 - update regmap configuration (max register & endianness)
 - dropped oldschool .supplied_to assignments
 - use devm_* APIs
 drivers/power/supply/Kconfig   |   6 +
 drivers/power/supply/Makefile  |   1 +
 drivers/power/supply/sbs-charger.c | 275 +
 3 files changed, 282 insertions(+)
 create mode 100644 drivers/power/supply/sbs-charger.c

diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index 76806a0..42877ff 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -164,6 +164,12 @@ config BATTERY_SBS
  Say Y to include support for SBS battery driver for SBS-compliant
  gas gauges.
 
+config CHARGER_SBS
+tristate "SBS Compliant charger"
+depends on I2C
+help
+ Say Y to include support for SBS compilant battery chargers.
+
 config BATTERY_BQ27XXX
tristate "BQ27xxx battery driver"
help
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
index 36c599d..06d9ef5 100644
--- a/drivers/power/supply/Makefile
+++ b/drivers/power/supply/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_BATTERY_COLLIE)  += collie_battery.o
 obj-$(CONFIG_BATTERY_IPAQ_MICRO) += ipaq_micro_battery.o
 obj-$(CONFIG_BATTERY_WM97XX)   += wm97xx_battery.o
 obj-$(CONFIG_BATTERY_SBS)  += sbs-battery.o
+obj-$(CONFIG_CHARGER_SBS)  += sbs-charger.o
 obj-$(CONFIG_BATTERY_BQ27XXX)  += bq27xxx_battery.o
 obj-$(CONFIG_BATTERY_BQ27XXX_I2C) += bq27xxx_battery_i2c.o
 obj-$(CONFIG_BATTERY_DA9030)   += da9030_battery.o
diff --git a/drivers/power/supply/sbs-charger.c 
b/drivers/power/supply/sbs-charger.c
new file mode 100644
index 000..2c4cd45
--- /dev/null
+++ b/drivers/power/supply/sbs-charger.c
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2016, Prodys S.L.
+ *
+ * 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 adds support for sbs-charger compilant chips as defined here:
+ * http://sbs-forum.org/specs/sbc110.pdf
+ *
+ * Implemetation based on sbs-battery.c
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define SBS_CHARGER_REG_SPEC_INFO  0x11
+#define SBS_CHARGER_REG_STATUS 0x13
+#define SBS_CHARGER_REG_ALARM_WARNING  0x16
+
+#define SBS_CHARGER_STATUS_CHARGE_INHIBITEDBIT(1)
+#define SBS_CHARGER_STATUS_RES_COLDBIT(9)
+#define SBS_CHARGER_STATUS_RES_HOT BIT(10)
+#define SBS_CHARGER_STATUS_BATTERY_PRESENT BIT(14)
+#define SBS_CHARGER_STATUS_AC_PRESENT  BIT(15)
+
+#define SBS_CHARGER_POLL_TIME  500
+
+struct sbs_info {
+   struct i2c_client   *client;
+   struct power_supply *power_supply;
+   struct regmap   *regmap;
+   struct delayed_work work;
+   unsigned intlast_state;
+};
+
+static int sbs_get_property(struct power_supply *psy,
+   enum power_supply_property psp,
+   union power_supply_propval *val)
+{
+   struct sbs_info *chip = power_supply_get_drvdata(psy);
+   unsigned int reg;
+
+   reg = chip->last_state;
+
+   switch (psp) {
+   case POWER_SUPPLY_PROP_PRESENT:
+   val->intval = !!(reg & SBS_CHARGER_STATUS_BATTERY_PRESENT);
+   break;
+
+   case POWER_SUPPLY_PROP_ONLINE:
+   val->intval = !!(reg & SBS_CHARGER_STATUS_AC_PRESENT);
+   break;
+
+   case POWER_SUPPLY_PROP_STATUS:
+   val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
+
+   if (!(reg & SBS_CHARGER_STATUS_BATTERY_PRESENT))
+   val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+   else if (reg & SBS_CHARGER_STATUS_AC_PRESENT &&
+!(reg & SBS_CHARGER_STATUS_CHARGE_INHIBITED))
+   val->intval = POWER_SUPPLY_STATUS_CHARGING;
+   else
+   val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+
+   break;
+
+   case POWER_SUPPLY_PROP_HEALTH:
+   if (reg & SBS_CHARGER_STATUS_RES_COLD)
+   val->intval = POWER_SUPPLY_HEALTH_COLD;
+   if (reg & SBS_CHARGER_STATUS_RES_HOT)
+   val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
+