#include <linux/hwmon.h>
 #include <linux/iio/iio.h>
 #include <linux/toshiba.h>
+#include <acpi/battery.h>
 #include <acpi/video.h>
 
 MODULE_AUTHOR("John Belmonte");
 };
 #endif
 
+/* ACPI battery hooking */
+static ssize_t charge_control_end_threshold_show(struct device *device,
+                                                struct device_attribute *attr,
+                                                char *buf)
+{
+       u32 state;
+       int status;
+
+       if (toshiba_acpi == NULL) {
+               pr_err("Toshiba ACPI object invalid\n");
+               return -ENODEV;
+       }
+
+       status = toshiba_battery_charge_mode_get(toshiba_acpi, &state);
+
+       if (status != 0)
+               return status;
+
+       if (state == 1)
+               return sprintf(buf, "80\n");
+       else
+               return sprintf(buf, "100\n");
+}
+
+static ssize_t charge_control_end_threshold_store(struct device *dev,
+                                                 struct device_attribute *attr,
+                                                 const char *buf,
+                                                 size_t count)
+{
+       u32 value;
+       int rval;
+
+       if (toshiba_acpi == NULL) {
+               pr_err("Toshiba ACPI object invalid\n");
+               return -ENODEV;
+       }
+
+       rval = kstrtou32(buf, 10, &value);
+       if (rval)
+               return rval;
+
+       if (value < 1 || value > 100)
+               return -EINVAL;
+       rval = toshiba_battery_charge_mode_set(toshiba_acpi,
+                                              (value < 90) ? 1 : 0);
+       if (rval < 0)
+               return rval;
+       else
+               return count;
+}
+
+static DEVICE_ATTR_RW(charge_control_end_threshold);
+
+static struct attribute *toshiba_acpi_battery_attrs[] = {
+       &dev_attr_charge_control_end_threshold.attr,
+       NULL,
+};
+
+ATTRIBUTE_GROUPS(toshiba_acpi_battery);
+
+static int toshiba_acpi_battery_add(struct power_supply *battery)
+{
+       if (toshiba_acpi == NULL) {
+               pr_err("Init order issue\n");
+               return -ENODEV;
+       }
+       if (!toshiba_acpi->battery_charge_mode_supported)
+               return -ENODEV;
+       if (device_add_groups(&battery->dev, toshiba_acpi_battery_groups))
+               return -ENODEV;
+       return 0;
+}
+
+static int toshiba_acpi_battery_remove(struct power_supply *battery)
+{
+       device_remove_groups(&battery->dev, toshiba_acpi_battery_groups);
+       return 0;
+}
+
+static struct acpi_battery_hook battery_hook = {
+       .add_battery = toshiba_acpi_battery_add,
+       .remove_battery = toshiba_acpi_battery_remove,
+       .name = "Toshiba Battery Extension",
+};
+
 static void print_supported_features(struct toshiba_acpi_dev *dev)
 {
        pr_info("Supported laptop features:");
                rfkill_destroy(dev->wwan_rfk);
        }
 
+       if (dev->battery_charge_mode_supported)
+               battery_hook_unregister(&battery_hook);
+
        if (toshiba_acpi)
                toshiba_acpi = NULL;
 
 
        toshiba_acpi = dev;
 
+       /*
+        * As the battery hook relies on the static variable toshiba_acpi being
+        * set, this must be done after toshiba_acpi is assigned.
+        */
+       if (dev->battery_charge_mode_supported)
+               battery_hook_register(&battery_hook);
+
        return 0;
 
 error: