diff options
-rw-r--r-- | drivers/edp/sysedp_batmon_calc.c | 118 | ||||
-rw-r--r-- | drivers/edp/sysedp_internal.h | 1 | ||||
-rw-r--r-- | drivers/edp/sysedp_sysfs.c | 4 |
3 files changed, 117 insertions, 6 deletions
diff --git a/drivers/edp/sysedp_batmon_calc.c b/drivers/edp/sysedp_batmon_calc.c index feb961eb7142..c0625853bd68 100644 --- a/drivers/edp/sysedp_batmon_calc.c +++ b/drivers/edp/sysedp_batmon_calc.c @@ -31,9 +31,14 @@ static struct sysedp_batmon_calc_platform_data *pdata; static struct delayed_work work; static struct power_supply *psy; -static int esr; + int (*get_ocv)(unsigned int capacity); +static struct kobject batmon_kobj; + +/* ratio between user-space ESR setting and look-up-table based ESR value */ +static int user_esr_ratio = 100; + static int psy_get_property(enum power_supply_property psp, int *val) { union power_supply_propval pv; @@ -152,7 +157,7 @@ static int psy_ocv_from_lut(unsigned int capacity) q->ocv); } -static int calc_esr(int capacity, int temp) +static int lookup_esr(int capacity, int temp) { struct sysedp_batmon_rbat_lut *lut = pdata->rbat_lut; int ret = pdata->r_const; @@ -162,6 +167,14 @@ static int calc_esr(int capacity, int temp) return ret; } +static int calc_esr(int capacity, int temp) +{ + int esr; + esr = lookup_esr(capacity, temp); + esr = esr * user_esr_ratio / 100; + return esr; +} + /* calculate maximum allowed current (in mA) limited by equivalent * series resistance (esr) */ static s64 calc_ibat_esr(s64 ocv, s64 esr) @@ -203,8 +216,7 @@ static s64 calc_pbat(s64 ocv, s64 ibat, s64 esr) static unsigned int calc_avail_budget(void) { - unsigned int capacity; - int temp; + int esr, capacity, temp; s64 ocv; s64 ibat_esr; s64 ibat; @@ -552,6 +564,102 @@ static void of_batmon_calc_get_pdata(struct platform_device *pdev, return; } +struct batmon_attribute { + struct attribute attr; + ssize_t (*show)(char *buf); + ssize_t (*store)(const char *buf, size_t count); +}; + +static ssize_t esr_show(char *s) +{ + int capacity, temp, esr; + + capacity = psy_capacity(); + temp = psy_temp(); + esr = calc_esr(capacity, temp); + esr /= 1000; /* to mOhm */ + + return sprintf(s, "%d\n", esr); +} + +static ssize_t esr_store(const char *s, size_t count) +{ + int mohm, capacity, temp; + int lut_esr; + int n; + + n = sscanf(s, "%d %d %d", &mohm, &capacity, &temp); + if (n != 1 && n != 3) + return -EINVAL; + if (mohm <= 0) + return -EINVAL; + + if (n != 3) { + capacity = psy_capacity(); + temp = psy_temp(); + } else { + if (capacity < 0 || capacity > 100) + return -EINVAL; + } + + lut_esr = lookup_esr(capacity, temp); + if (!lut_esr) + return -EINVAL; + + user_esr_ratio = DIV_ROUND_CLOSEST(100 * 1000 * mohm, lut_esr); + + cancel_delayed_work_sync(&work); + schedule_delayed_work(&work, 0); + + return count; +} + +static struct batmon_attribute attr_esr = + __ATTR(esr, 0660, esr_show, esr_store); + +static struct attribute *batmon_attrs[] = { + &attr_esr.attr, + NULL +}; + +static ssize_t batmon_attr_show(struct kobject *kobj, + struct attribute *_attr, char *buf) +{ + ssize_t r = -EINVAL; + struct batmon_attribute *attr; + attr = container_of(_attr, struct batmon_attribute, attr); + if (attr && attr->show) + r = attr->show(buf); + return r; +} + +static ssize_t batmon_attr_store(struct kobject *kobj, struct attribute *_attr, + const char *buf, size_t count) +{ + ssize_t r = -EINVAL; + struct batmon_attribute *attr; + attr = container_of(_attr, struct batmon_attribute, attr); + if (attr && attr->store) + r = attr->store(buf, count); + return r; +} + +static const struct sysfs_ops batmon_sysfs_ops = { + .show = batmon_attr_show, + .store = batmon_attr_store, +}; + +static struct kobj_type ktype_batmon = { + .sysfs_ops = &batmon_sysfs_ops, + .default_attrs = batmon_attrs, +}; + +static int init_sysfs(void) +{ + return kobject_init_and_add(&batmon_kobj, &ktype_batmon, + &sysedp_kobj, "batmon"); +} + static int batmon_probe(struct platform_device *pdev) { int i; @@ -586,6 +694,8 @@ static int batmon_probe(struct platform_device *pdev) if (init_ocv_reader()) return -EFAULT; + init_sysfs(); + INIT_DEFERRABLE_WORK(&work, batmon_update); schedule_delayed_work(&work, 0); diff --git a/drivers/edp/sysedp_internal.h b/drivers/edp/sysedp_internal.h index cb725ac1d3c3..5f9e4dffb318 100644 --- a/drivers/edp/sysedp_internal.h +++ b/drivers/edp/sysedp_internal.h @@ -29,6 +29,7 @@ extern unsigned int avail_budget; extern unsigned int consumer_sum; extern struct list_head registered_consumers; extern struct mutex sysedp_lock; +extern struct kobject sysedp_kobj; static inline unsigned int _cur_level(struct sysedp_consumer *c) { diff --git a/drivers/edp/sysedp_sysfs.c b/drivers/edp/sysedp_sysfs.c index 21e536bdb271..d0be34ca602a 100644 --- a/drivers/edp/sysedp_sysfs.c +++ b/drivers/edp/sysedp_sysfs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -23,7 +23,7 @@ #include <trace/events/sysedp.h> #include "sysedp_internal.h" -static struct kobject sysedp_kobj; +struct kobject sysedp_kobj; static struct kset *consumers_kset; struct sysedp_consumer_attribute { |