[PATCH] [RFC] security: smack: Add support automatic Smack labeling

2015-08-26 Thread Jonghwa Lee
Smack labeling is always done in user space, not in kernel space.
Because kernel can't know which node or preocess should has the certain label
and it shouldn't be neither. Therefore there is a distinct time gap between
file creation and the labeling which might be about few miliseconds or even
indefinite period. This unavoidable and imprecise time gap produces unintended
Smack denial time to time. If it guerantees that labeling is done before any
other access, the time gap doesn't make matter. However if not, the system
will suffer from false alarm.

I've already exeperienced the situation with specific cases.
Mostly, it happens with devtmpfs where udevd applies xattr with defined udev
rules. When kernel module is loaded, device node is newly created and it sends
uevent and notification to processes in wait. However, somtimes uevent may be
handled lately then other processes's access. So, Smack module checks the
authority with uninitialized label, and prohibits the access even the access
authority exists in Smack rule.

At the first time of encounting the problem, I tries to fix the system and user
process to prevent the accesses in ahead of labeling but it wasn't the solution.
Performance is degraded because of compulsory delay.

Another candidate of solution is given label from kernel side.
However, kernel should not be aware of the label, the string, and the
relationship between specific node and label. So I left it in user space.

Label is still given from user space. Kernel only checks there is a pre-assigned
labeling rule for the node. If so, the file will acquire the label as default at
the creation. A file is created with pre-assigend label as like it's done
automatically. So it's called 'Auto Smack labeling'

Pre-assigned label can be given via additional file, 'autolabel' in smackfs.

   echo ' ' > /sys/fs/smackfs/autolabel

The label only activates when the file isn't created yet. If file already
exists, then just add the label relationship to table and deactivate it.
When the label is applied, it'll also be deactivated. The label turns to be
enabled again only when the file is removed.

This is a candidate of solution for the specific problem, and might be buggy or
hamful for system-wide security. So I gently request your opinion for more clear
and wise solution for the case that I faced.

Jonghwa Lee (1):
  security: smack: Add support automatic Smack labeling

 security/smack/Kconfig |   11 
 security/smack/smack.h |   23 
 security/smack/smack_lsm.c |   66 +
 security/smack/smackfs.c   |  136 
 4 files changed, 236 insertions(+)

-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] security: smack: Add support automatic Smack labeling

2015-08-26 Thread Jonghwa Lee
Current Smack object's label is always given by userspace.
So there might be a certain gap between the time of file creation
and the time of applying actual label. And because of the time gap,
it results unintended Smack denial time to time.

If accessing a file occurs ahead of labeling, Smack module will check
the authority with uninitialized label and will prohibit the access
as a result. It shouldn't be happened labeling is done in proper time.

For the case that system can't gueratee that Smack labeling is done
before any other accesses to newly created file, this patch introdues
new interface called 'Automatic Smack labling'.

The label can be defined before file creation with absolute path.
Then, when target file is created in generic manner, the pre-defined
label is applied automatically at once.

Pre-defined label format follows below form.



And it can add new entry to autolabel table via 'autolabel' in smackfs.

   echo ' ' > /sys/fs/smackfs/autolabel

To view entries of autolabel table,

   $cat /sys/fs/smackfs/autolabel
   /dev/device00 Label:A 
   /run/userfile0 Label:B 

Signed-off-by: Jonghwa Lee 
---
 security/smack/Kconfig |   11 
 security/smack/smack.h |   23 
 security/smack/smack_lsm.c |   66 +
 security/smack/smackfs.c   |  136 
 4 files changed, 236 insertions(+)

diff --git a/security/smack/Kconfig b/security/smack/Kconfig
index 271adae..002aa01 100644
--- a/security/smack/Kconfig
+++ b/security/smack/Kconfig
@@ -30,6 +30,17 @@ config SECURITY_SMACK_BRINGUP
  "permissive" mode of other systems.
  If you are unsure how to answer this question, answer N.
 
+config SECURITY_SMACK_AUTOLABEL
+   bool "Enable Automatic Smack Labeling"
+   depends on SECURITY_SMACK
+   default n
+   help
+ To remove out the gap between file creation and actual labeling,
+ this option gives the additional interface for automatic labeling.
+ With this option enabled, a file will posseses the assigned label
+ in autolabel table at creation.
+ If you are unsure how to answer this question, answer N.
+
 config SECURITY_SMACK_NETFILTER
bool "Packet marking using secmarks for netfilter"
depends on SECURITY_SMACK
diff --git a/security/smack/smack.h b/security/smack/smack.h
index fff0c61..8b7ee83 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -24,6 +24,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /*
  * Use IPv6 port labeling if IPv6 is enabled and secmarks
@@ -106,6 +107,9 @@ struct inode_smack {
struct smack_known  *smk_inode; /* label of the fso */
struct smack_known  *smk_task;  /* label of the task */
struct smack_known  *smk_mmap;  /* label of the mmap domain */
+#ifdef CONFIG_SECURITY_SMACK_AUTOLABEL
+   struct smack_auto_label *smk_auto;
+#endif
struct mutexsmk_lock;   /* initialization lock */
int smk_flags;  /* smack inode flags */
 };
@@ -480,4 +484,23 @@ static inline void smk_ad_setfield_u_net_sk(struct 
smk_audit_info *a,
 }
 #endif
 
+#ifdef CONFIG_SECURITY_SMACK_AUTOLABEL
+struct smack_auto_label {
+   bool disabled;
+   char *fpath;
+   struct list_head entry;
+   struct smack_known *label;
+   struct inode *inode;
+};
+
+extern struct list_head smack_autolabel_list;
+extern struct mutex smack_autolabel_lock;
+
+extern struct smack_known *smk_inode_bind_autolabel(struct inode *);
+extern void smk_inode_unbind_autolabel(struct inode *);
+#else
+#define smk_inode_bind_autolabel(inode)NULL
+#define smk_inode_unbind_autolabel(inode)  do { } while (0)
+#endif /* CONFIG_SECURITY_SMACK_AUTOLABEL */
+
 #endif  /* _SECURITY_SMACK_H */
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 996c889..851e8b4 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -249,6 +249,65 @@ static int smk_bu_credfile(const struct cred *cred, struct 
file *file,
 #define smk_bu_credfile(cred, file, mode, RC) (RC)
 #endif
 
+#ifdef CONFIG_SECURITY_SMACK_AUTOLABEL
+/**
+ * smk_inode_bind_autolabel - Check assigned label for this inode
+ * @ip : the object of inode
+ *
+ * Return pre-assigned smack_known when exists, NULL if not.
+ */
+struct smack_known *smk_inode_bind_autolabel(struct inode *ip)
+{
+   struct smack_auto_label *smk_auto;
+   struct inode_smack *isp;
+   struct smack_known *smk = NULL;
+   struct path p;
+
+   if (list_empty(_autolabel_list))
+   goto out;
+
+   mutex_lock(_autolabel_lock);
+   list_for_each_entry(smk_auto, _autolabel_list, entry) {
+   if (smk_auto->disabled)
+   continue;
+
+   if (!smk_auto->inode) {
+   if (kern_path(smk_auto->fpath, 0, )

[PATCH] [RFC] security: smack: Add support automatic Smack labeling

2015-08-26 Thread Jonghwa Lee
Smack labeling is always done in user space, not in kernel space.
Because kernel can't know which node or preocess should has the certain label
and it shouldn't be neither. Therefore there is a distinct time gap between
file creation and the labeling which might be about few miliseconds or even
indefinite period. This unavoidable and imprecise time gap produces unintended
Smack denial time to time. If it guerantees that labeling is done before any
other access, the time gap doesn't make matter. However if not, the system
will suffer from false alarm.

I've already exeperienced the situation with specific cases.
Mostly, it happens with devtmpfs where udevd applies xattr with defined udev
rules. When kernel module is loaded, device node is newly created and it sends
uevent and notification to processes in wait. However, somtimes uevent may be
handled lately then other processes's access. So, Smack module checks the
authority with uninitialized label, and prohibits the access even the access
authority exists in Smack rule.

At the first time of encounting the problem, I tries to fix the system and user
process to prevent the accesses in ahead of labeling but it wasn't the solution.
Performance is degraded because of compulsory delay.

Another candidate of solution is given label from kernel side.
However, kernel should not be aware of the label, the string, and the
relationship between specific node and label. So I left it in user space.

Label is still given from user space. Kernel only checks there is a pre-assigned
labeling rule for the node. If so, the file will acquire the label as default at
the creation. A file is created with pre-assigend label as like it's done
automatically. So it's called 'Auto Smack labeling'

Pre-assigned label can be given via additional file, 'autolabel' in smackfs.

   echo 'File path Smack Label'  /sys/fs/smackfs/autolabel

The label only activates when the file isn't created yet. If file already
exists, then just add the label relationship to table and deactivate it.
When the label is applied, it'll also be deactivated. The label turns to be
enabled again only when the file is removed.

This is a candidate of solution for the specific problem, and might be buggy or
hamful for system-wide security. So I gently request your opinion for more clear
and wise solution for the case that I faced.

Jonghwa Lee (1):
  security: smack: Add support automatic Smack labeling

 security/smack/Kconfig |   11 
 security/smack/smack.h |   23 
 security/smack/smack_lsm.c |   66 +
 security/smack/smackfs.c   |  136 
 4 files changed, 236 insertions(+)

-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] security: smack: Add support automatic Smack labeling

2015-08-26 Thread Jonghwa Lee
Current Smack object's label is always given by userspace.
So there might be a certain gap between the time of file creation
and the time of applying actual label. And because of the time gap,
it results unintended Smack denial time to time.

If accessing a file occurs ahead of labeling, Smack module will check
the authority with uninitialized label and will prohibit the access
as a result. It shouldn't be happened labeling is done in proper time.

For the case that system can't gueratee that Smack labeling is done
before any other accesses to newly created file, this patch introdues
new interface called 'Automatic Smack labling'.

The label can be defined before file creation with absolute path.
Then, when target file is created in generic manner, the pre-defined
label is applied automatically at once.

Pre-defined label format follows below form.

   File path Smack Label

And it can add new entry to autolabel table via 'autolabel' in smackfs.

   echo 'File path Smack Label'  /sys/fs/smackfs/autolabel

To view entries of autolabel table,

   $cat /sys/fs/smackfs/autolabel
   /dev/device00 Label:A enabled
   /run/userfile0 Label:B disabled

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 security/smack/Kconfig |   11 
 security/smack/smack.h |   23 
 security/smack/smack_lsm.c |   66 +
 security/smack/smackfs.c   |  136 
 4 files changed, 236 insertions(+)

diff --git a/security/smack/Kconfig b/security/smack/Kconfig
index 271adae..002aa01 100644
--- a/security/smack/Kconfig
+++ b/security/smack/Kconfig
@@ -30,6 +30,17 @@ config SECURITY_SMACK_BRINGUP
  permissive mode of other systems.
  If you are unsure how to answer this question, answer N.
 
+config SECURITY_SMACK_AUTOLABEL
+   bool Enable Automatic Smack Labeling
+   depends on SECURITY_SMACK
+   default n
+   help
+ To remove out the gap between file creation and actual labeling,
+ this option gives the additional interface for automatic labeling.
+ With this option enabled, a file will posseses the assigned label
+ in autolabel table at creation.
+ If you are unsure how to answer this question, answer N.
+
 config SECURITY_SMACK_NETFILTER
bool Packet marking using secmarks for netfilter
depends on SECURITY_SMACK
diff --git a/security/smack/smack.h b/security/smack/smack.h
index fff0c61..8b7ee83 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -24,6 +24,7 @@
 #include linux/list.h
 #include linux/rculist.h
 #include linux/lsm_audit.h
+#include linux/namei.h
 
 /*
  * Use IPv6 port labeling if IPv6 is enabled and secmarks
@@ -106,6 +107,9 @@ struct inode_smack {
struct smack_known  *smk_inode; /* label of the fso */
struct smack_known  *smk_task;  /* label of the task */
struct smack_known  *smk_mmap;  /* label of the mmap domain */
+#ifdef CONFIG_SECURITY_SMACK_AUTOLABEL
+   struct smack_auto_label *smk_auto;
+#endif
struct mutexsmk_lock;   /* initialization lock */
int smk_flags;  /* smack inode flags */
 };
@@ -480,4 +484,23 @@ static inline void smk_ad_setfield_u_net_sk(struct 
smk_audit_info *a,
 }
 #endif
 
+#ifdef CONFIG_SECURITY_SMACK_AUTOLABEL
+struct smack_auto_label {
+   bool disabled;
+   char *fpath;
+   struct list_head entry;
+   struct smack_known *label;
+   struct inode *inode;
+};
+
+extern struct list_head smack_autolabel_list;
+extern struct mutex smack_autolabel_lock;
+
+extern struct smack_known *smk_inode_bind_autolabel(struct inode *);
+extern void smk_inode_unbind_autolabel(struct inode *);
+#else
+#define smk_inode_bind_autolabel(inode)NULL
+#define smk_inode_unbind_autolabel(inode)  do { } while (0)
+#endif /* CONFIG_SECURITY_SMACK_AUTOLABEL */
+
 #endif  /* _SECURITY_SMACK_H */
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 996c889..851e8b4 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -249,6 +249,65 @@ static int smk_bu_credfile(const struct cred *cred, struct 
file *file,
 #define smk_bu_credfile(cred, file, mode, RC) (RC)
 #endif
 
+#ifdef CONFIG_SECURITY_SMACK_AUTOLABEL
+/**
+ * smk_inode_bind_autolabel - Check assigned label for this inode
+ * @ip : the object of inode
+ *
+ * Return pre-assigned smack_known when exists, NULL if not.
+ */
+struct smack_known *smk_inode_bind_autolabel(struct inode *ip)
+{
+   struct smack_auto_label *smk_auto;
+   struct inode_smack *isp;
+   struct smack_known *smk = NULL;
+   struct path p;
+
+   if (list_empty(smack_autolabel_list))
+   goto out;
+
+   mutex_lock(smack_autolabel_lock);
+   list_for_each_entry(smk_auto, smack_autolabel_list, entry) {
+   if (smk_auto-disabled)
+   continue

[PATCH V3 04/11] power: charger-manager: Remove deprecated function, cm_notify_event().

2014-12-19 Thread Jonghwa Lee
cm_notify_event() is introduced to get event associated with battery status
externally, but no one had been used. Moreover it makes charger manager
driver more complicated. This patch tries to drop the function and all data
related to simplify the driver.

Signed-off-by: Jonghwa Lee 
---
 .../bindings/power_supply/charger-manager.txt  |1 -
 drivers/power/charger-manager.c|  196 +---
 include/linux/power/charger-manager.h  |   19 +-
 3 files changed, 8 insertions(+), 208 deletions(-)

diff --git a/Documentation/devicetree/bindings/power_supply/charger-manager.txt 
b/Documentation/devicetree/bindings/power_supply/charger-manager.txt
index ec4fe9d..827576e 100644
--- a/Documentation/devicetree/bindings/power_supply/charger-manager.txt
+++ b/Documentation/devicetree/bindings/power_supply/charger-manager.txt
@@ -39,7 +39,6 @@ Example :
cm-poll-mode = <1>;
cm-poll-interval = <3>;
 
-   cm-fullbatt-vchkdrop-ms = <3>;
cm-fullbatt-vchkdrop-volt = <15>;
cm-fullbatt-soc = <100>;
 
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 8c76bce..5482661 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -410,25 +410,18 @@ static int try_charger_restart(struct charger_manager *cm)
 
 /**
  * fullbatt_vchk - Check voltage drop some times after "FULL" event.
- * @work: the work_struct appointing the function
  *
- * If a user has designated "fullbatt_vchkdrop_ms/uV" values with
+ * If a user has designated "fullbatt_vchkdrop_uV" values with
  * charger_desc, Charger Manager checks voltage drop after the battery
  * "FULL" event. It checks whether the voltage has dropped more than
  * fullbatt_vchkdrop_uV by calling this function after fullbatt_vchkrop_ms.
  */
-static void fullbatt_vchk(struct work_struct *work)
+static void fullbatt_vchk(struct charger_manager *cm)
 {
-   struct delayed_work *dwork = to_delayed_work(work);
-   struct charger_manager *cm = container_of(dwork,
-   struct charger_manager, fullbatt_vchk_work);
struct charger_desc *desc = cm->desc;
int batt_uV, err, diff;
 
-   /* remove the appointment for fullbatt_vchk */
-   cm->fullbatt_vchk_jiffies_at = 0;
-
-   if (!desc->fullbatt_vchkdrop_uV || !desc->fullbatt_vchkdrop_ms)
+   if (!desc->fullbatt_vchkdrop_uV)
return;
 
err = get_batt_uV(cm, _uV);
@@ -585,7 +578,7 @@ static bool _cm_monitor(struct charger_manager *cm)
 */
} else if (!cm->emergency_stop && is_ext_pwr_online(cm) &&
!cm->charger_enabled) {
-   fullbatt_vchk(>fullbatt_vchk_work.work);
+   fullbatt_vchk(cm);
 
/*
 * Check whether fully charged state to protect overcharge
@@ -598,7 +591,7 @@ static bool _cm_monitor(struct charger_manager *cm)
 
try_charger_enable(cm, false);
 
-   fullbatt_vchk(>fullbatt_vchk_work.work);
+   fullbatt_vchk(cm);
} else {
cm->emergency_stop = 0;
if (is_ext_pwr_online(cm)) {
@@ -700,66 +693,6 @@ static void cm_monitor_poller(struct work_struct *work)
schedule_work(_polling);
 }
 
-/**
- * fullbatt_handler - Event handler for CM_EVENT_BATT_FULL
- * @cm: the Charger Manager representing the battery.
- */
-static void fullbatt_handler(struct charger_manager *cm)
-{
-   struct charger_desc *desc = cm->desc;
-
-   if (!desc->fullbatt_vchkdrop_uV || !desc->fullbatt_vchkdrop_ms)
-   goto out;
-
-   if (cm_suspended)
-   device_set_wakeup_capable(cm->dev, true);
-
-   mod_delayed_work(cm_wq, >fullbatt_vchk_work,
-msecs_to_jiffies(desc->fullbatt_vchkdrop_ms));
-   cm->fullbatt_vchk_jiffies_at = jiffies + msecs_to_jiffies(
-  desc->fullbatt_vchkdrop_ms);
-
-   if (cm->fullbatt_vchk_jiffies_at == 0)
-   cm->fullbatt_vchk_jiffies_at = 1;
-
-out:
-   dev_info(cm->dev, "EVENT_HANDLE: Battery Fully Charged\n");
-   power_supply_changed(>charger_psy);
-}
-
-/**
- * battout_handler - Event handler for CM_EVENT_BATT_OUT
- * @cm: the Charger Manager representing the battery.
- */
-static void battout_handler(struct charger_manager *cm)
-{
-   if (cm_suspended)
-   device_set_wakeup_capable(cm->dev, true);
-
-   if (!is_batt_present(cm)) {
-   dev_emerg(cm->dev, "Battery Pulled Out!\n");
-   power_supply_changed(>charger_psy);
-   } else {
-   power_supply_changed(>charger_psy);
-   }
-}
-
-/**
- * misc_event_handler - Handler for othe

[PATCH V3 01/11] power: charger-manager: Use alarmtimer for battery monitoring in suspend.

2014-12-19 Thread Jonghwa Lee
To guerantee proper charing and managing batteries even in suspend,
charger-manager has used rtc device with rtc framework interface.
However, it is better to use alarmtimer for cleaner and more appropriate
operation.
This patch makes driver to use alamtimer for polling work in suspend and
removes all deprecated codes related with using rtc interface.

Signed-off-by: Jonghwa Lee 
---
 drivers/power/Kconfig |2 +-
 drivers/power/charger-manager.c   |  288 ++---
 include/linux/power/charger-manager.h |   32 +---
 3 files changed, 84 insertions(+), 238 deletions(-)

diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 0108c2a..8ff2511 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -315,7 +315,7 @@ config CHARGER_GPIO
 
 config CHARGER_MANAGER
bool "Battery charger manager for multiple chargers"
-   depends on REGULATOR && RTC_CLASS
+   depends on REGULATOR
select EXTCON
help
   Say Y to enable charger-manager support, which allows multiple
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index ef8094a..22246b9 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -69,16 +69,11 @@ static LIST_HEAD(cm_list);
 static DEFINE_MUTEX(cm_list_mtx);
 
 /* About in-suspend (suspend-again) monitoring */
-static struct rtc_device *rtc_dev;
-/*
- * Backup RTC alarm
- * Save the wakeup alarm before entering suspend-to-RAM
- */
-static struct rtc_wkalrm rtc_wkalarm_save;
+static struct alarm *cm_timer;
+
 /* Backup RTC alarm time in terms of seconds since 01-01-1970 00:00:00 */
-static unsigned long rtc_wkalarm_save_time;
 static bool cm_suspended;
-static bool cm_rtc_set;
+static bool cm_timer_set;
 static unsigned long cm_suspend_duration_ms;
 
 /* About normal (not suspended) monitoring */
@@ -87,9 +82,6 @@ static unsigned long next_polling; /* Next appointed polling 
time */
 static struct workqueue_struct *cm_wq; /* init at driver add */
 static struct delayed_work cm_monitor_work; /* init at driver add */
 
-/* Global charger-manager description */
-static struct charger_global_desc *g_desc; /* init with setup_charger_manager 
*/
-
 /**
  * is_batt_present - See if the battery presents in place.
  * @cm: the Charger Manager representing the battery.
@@ -1047,10 +1039,13 @@ static bool cm_setup_timer(void)
 {
struct charger_manager *cm;
unsigned int wakeup_ms = UINT_MAX;
-   bool ret = false;
+   int timer_req = 0;
 
-   mutex_lock(_list_mtx);
+   if (time_after(next_polling, jiffies))
+   CM_MIN_VALID(wakeup_ms,
+   jiffies_to_msecs(next_polling - jiffies));
 
+   mutex_lock(_list_mtx);
list_for_each_entry(cm, _list, entry) {
unsigned int fbchk_ms = 0;
 
@@ -1070,162 +1065,38 @@ static bool cm_setup_timer(void)
/* Skip if polling is not required for this CM */
if (!is_polling_required(cm) && !cm->emergency_stop)
continue;
+   timer_req++;
if (cm->desc->polling_interval_ms == 0)
continue;
CM_MIN_VALID(wakeup_ms, cm->desc->polling_interval_ms);
}
-
mutex_unlock(_list_mtx);
 
-   if (wakeup_ms < UINT_MAX && wakeup_ms > 0) {
-   pr_info("Charger Manager wakeup timer: %u ms\n", wakeup_ms);
-   if (rtc_dev) {
-   struct rtc_wkalrm tmp;
-   unsigned long time, now;
-   unsigned long add = DIV_ROUND_UP(wakeup_ms, 1000);
-
-   /*
-* Set alarm with the polling interval (wakeup_ms)
-* except when rtc_wkalarm_save comes first.
-* However, the alarm time should be NOW +
-* CM_RTC_SMALL or later.
-*/
-   tmp.enabled = 1;
-   rtc_read_time(rtc_dev, );
-   rtc_tm_to_time(, );
-   if (add < CM_RTC_SMALL)
-   add = CM_RTC_SMALL;
-   time = now + add;
+   if (timer_req && cm_timer) {
+   ktime_t now, add;
 
-   ret = true;
+   /*
+* Set alarm with the polling interval (wakeup_ms)
+* The alarm time should be NOW + CM_RTC_SMALL or later.
+*/
+   if (wakeup_ms == UINT_MAX ||
+   wakeup_ms < CM_RTC_SMALL * MSEC_PER_SEC)
+   wakeup_ms = 2 * CM_RTC_SMALL * MSEC_PER_SEC;
 
-   if (rtc_wkalarm_save.enabled &&
-   rtc_wkalarm_save_time &&
-   rtc_wkalarm_sav

[PATCH V3 09/11] power: charger-manager: Not to start charging directly in cable nofitication.

2014-12-19 Thread Jonghwa Lee
This patch prevents direct charging control in cable notification.
It sets only input current limit according to cable type and yields charging
control to be done by cm_monitor() where charging management proceeds.
It may loose few ms to enable charging compared to before, even though it's
more important that charging is enabled always in safe context.

Signed-off-by: Jonghwa Lee 
---
 drivers/power/charger-manager.c |   12 ++--
 1 file changed, 2 insertions(+), 10 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 44cc19a..4f8b0e6 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -849,7 +849,8 @@ static void charger_extcon_work(struct work_struct *work)
cable->min_uA, cable->max_uA);
}
 
-   try_charger_enable(cable->cm, cable->attached);
+   cancel_delayed_work(_monitor_work);
+   queue_delayed_work(cm_wq, _monitor_work, 0);
 }
 
 /**
@@ -873,15 +874,6 @@ static int charger_extcon_notifier(struct notifier_block 
*self,
cable->attached = event;
 
/*
-* Setup monitoring to check battery state
-* when charger cable is attached.
-*/
-   if (cable->attached && is_polling_required(cable->cm)) {
-   cancel_work_sync(_polling);
-   schedule_work(_polling);
-   }
-
-   /*
 * Setup work for controlling charger(regulator)
 * according to charger cable.
 */
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V3 05/11] power: charger-manager: Fix to use CHARGE_NOW/FULL property correctly.

2014-12-19 Thread Jonghwa Lee
The POWER_SUPPLY_CHARGE_NOW/FULL property reflects battery's charges
in uAh unit, but charger-manager has been used it wrongly. This patch
makes it to use those propeties correctly and change to be optional.

Signed-off-by: Jonghwa Lee 
---
 drivers/power/charger-manager.c |   85 +--
 1 file changed, 28 insertions(+), 57 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 5482661..7bbaef6 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -796,35 +796,13 @@ static int charger_get_property(struct power_supply *psy,
val->intval = 0;
break;
case POWER_SUPPLY_PROP_CHARGE_FULL:
-   if (is_full_charged(cm))
-   val->intval = 1;
-   else
-   val->intval = 0;
-   ret = 0;
-   break;
case POWER_SUPPLY_PROP_CHARGE_NOW:
-   if (is_charging(cm)) {
-   fuel_gauge = power_supply_get_by_name(
-   cm->desc->psy_fuel_gauge);
-   if (!fuel_gauge) {
-   ret = -ENODEV;
-   break;
-   }
-
-   ret = fuel_gauge->get_property(fuel_gauge,
-   POWER_SUPPLY_PROP_CHARGE_NOW,
-   val);
-   if (ret) {
-   val->intval = 1;
-   ret = 0;
-   } else {
-   /* If CHARGE_NOW is supplied, use it */
-   val->intval = (val->intval > 0) ?
-   val->intval : 1;
-   }
-   } else {
-   val->intval = 0;
+   fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge);
+   if (!fuel_gauge) {
+   ret = -ENODEV;
+   break;
}
+   ret = fuel_gauge->get_property(fuel_gauge, psp, val);
break;
default:
return -EINVAL;
@@ -832,8 +810,7 @@ static int charger_get_property(struct power_supply *psy,
return ret;
 }
 
-#define NUM_CHARGER_PSY_OPTIONAL   (4)
-static enum power_supply_property default_charger_props[] = {
+static enum power_supply_property cm_default_props[] = {
/* Guaranteed to provide */
POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_HEALTH,
@@ -841,20 +818,21 @@ static enum power_supply_property default_charger_props[] 
= {
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_CAPACITY,
POWER_SUPPLY_PROP_ONLINE,
-   POWER_SUPPLY_PROP_CHARGE_FULL,
POWER_SUPPLY_PROP_TEMP,
-   /*
-* Optional properties are:
-* POWER_SUPPLY_PROP_CHARGE_NOW,
-* POWER_SUPPLY_PROP_CURRENT_NOW,
-*/
 };
 
+static enum power_supply_property cm_optional_props[] = {
+   POWER_SUPPLY_PROP_CHARGE_FULL,
+   POWER_SUPPLY_PROP_CHARGE_NOW,
+   POWER_SUPPLY_PROP_CURRENT_NOW,
+};
+
+#define CM_NUM_OF_PROPS\
+   (ARRAY_SIZE(cm_default_props) + ARRAY_SIZE(cm_optional_props))
+
 static struct power_supply psy_default = {
.name = "battery",
.type = POWER_SUPPLY_TYPE_BATTERY,
-   .properties = default_charger_props,
-   .num_properties = ARRAY_SIZE(default_charger_props),
.get_property = charger_get_property,
.no_thermal = true,
 };
@@ -1484,29 +1462,22 @@ static int charger_manager_probe(struct platform_device 
*pdev)
/* Allocate for psy properties because they may vary */
cm->charger_psy.properties = devm_kzalloc(>dev,
sizeof(enum power_supply_property)
-   * (ARRAY_SIZE(default_charger_props) +
-   NUM_CHARGER_PSY_OPTIONAL), GFP_KERNEL);
+   * CM_NUM_OF_PROPS, GFP_KERNEL);
if (!cm->charger_psy.properties)
return -ENOMEM;
 
-   memcpy(cm->charger_psy.properties, default_charger_props,
-   sizeof(enum power_supply_property) *
-   ARRAY_SIZE(default_charger_props));
-   cm->charger_psy.num_properties = psy_default.num_properties;
-
-   /* Find which optional psy-properties are available */
-   if (!fuel_gauge->get_property(fuel_gauge,
- POWER_SUPPLY_PROP_CHARGE_NOW, )) {
-   cm->charger_psy.properties[cm->charger_psy.num_properties] =
-   POWER_SUPPLY_PROP_CHARGE_NOW;
-   cm->charger_psy.num_properties++;
-   }
-   if (!fuel_gauge->get_propert

[PATCH V3 06/11] power: charger-manager: Concentrate scattered power_supply_changed() calls.

2014-12-19 Thread Jonghwa Lee
Current charger-manager calls power_suuply_changed() whenever charging
status is changed. This patch removes seperated power_supply_changed()
use and let it be called at end of try_charger_enable() function which
is called to set charging/discharging.

Signed-off-by: Jonghwa Lee 
---
 drivers/power/charger-manager.c |   18 ++
 1 file changed, 6 insertions(+), 12 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 7bbaef6..d29155d 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -382,8 +382,10 @@ static int try_charger_enable(struct charger_manager *cm, 
bool enable)
}
}
 
-   if (!err)
+   if (!err) {
cm->charger_enabled = enable;
+   power_supply_changed(>charger_psy);
+   }
 
return err;
 }
@@ -436,10 +438,8 @@ static void fullbatt_vchk(struct charger_manager *cm)
 
dev_info(cm->dev, "VBATT dropped %duV after full-batt\n", diff);
 
-   if (diff > desc->fullbatt_vchkdrop_uV) {
+   if (diff > desc->fullbatt_vchkdrop_uV)
try_charger_restart(cm);
-   power_supply_changed(>charger_psy);
-   }
 }
 
 /**
@@ -469,7 +469,6 @@ static int check_charging_duration(struct charger_manager 
*cm)
if (duration > desc->charging_max_duration_ms) {
dev_info(cm->dev, "Charging duration exceed %ums\n",
 desc->charging_max_duration_ms);
-   power_supply_changed(>charger_psy);
try_charger_enable(cm, false);
ret = true;
}
@@ -480,7 +479,6 @@ static int check_charging_duration(struct charger_manager 
*cm)
is_ext_pwr_online(cm)) {
dev_info(cm->dev, "Discharging duration exceed %ums\n",
 desc->discharging_max_duration_ms);
-   power_supply_changed(>charger_psy);
try_charger_enable(cm, true);
ret = true;
}
@@ -561,8 +559,7 @@ static bool _cm_monitor(struct charger_manager *cm)
 */
if (temp_alrt) {
cm->emergency_stop = temp_alrt;
-   if (!try_charger_enable(cm, false))
-   power_supply_changed(>charger_psy);
+   try_charger_enable(cm, false);
 
/*
 * Check whole charging duration and discharing duration
@@ -587,16 +584,13 @@ static bool _cm_monitor(struct charger_manager *cm)
} else if (!cm->emergency_stop && is_full_charged(cm) &&
cm->charger_enabled) {
dev_info(cm->dev, "EVENT_HANDLE: Battery Fully Charged\n");
-   power_supply_changed(>charger_psy);
-
try_charger_enable(cm, false);
 
fullbatt_vchk(cm);
} else {
cm->emergency_stop = 0;
if (is_ext_pwr_online(cm)) {
-   if (!try_charger_enable(cm, true))
-   power_supply_changed(>charger_psy);
+   try_charger_enable(cm, true);
}
}
 
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V3 0/11] Improve charger manager driver for optimized operation.

2014-12-19 Thread Jonghwa Lee
After charger manager's initially introduced, it has kept its codes without any
big change. However, the charger manager working operation isn't optimized and
it also has unused codes and non-generic interface. This series tries to make
charger manager more generic and maintainable with some fixes.

[Changes in V3]
- Add omitted patch '[1/11] Use alarmtimer for battery~' from v2 patch set.

[Changes in V2]
- Rebase patch series on latest of battery-2.6.git.
- Seperate 'power: charger-manager: Rearrange data and monitor ~' patch into
  several patches depends on its purpose.
- Add 2 patches related with polling mode.

Jonghwa Lee (11):
  power: charger-manager: Use alarmtimer for battery monitoring in
suspend.
  power: charger-manager: Use thermal subsystem interface only to get
temperature.
  power: charger-manager: Use power_supply_changed() not private
uevent.
  power: charger-manager: Remove deprecated function,
cm_notify_event().
  power: charger-manager: Fix to use CHARGE_NOW/FULL property
correctly.
  power: charger-manager: Concentrate scattered power_supply_changed()
calls.
  power: charger-manager: Get external power souce information only
from EXTCON.
  power: charger-manager: Make chraging decision focusing on battery
status.
  power: charger-manager: Not to start charging directly in cable
nofitication.
  power: charger-manager: Support different polling mode for sleep
state.
  power: charger-manager: Support to change polling rate in runtime.

 .../bindings/power_supply/charger-manager.txt  |1 -
 drivers/power/Kconfig  |3 +-
 drivers/power/charger-manager.c| 1026 ++--
 include/linux/power/charger-manager.h  |   66 +-
 4 files changed, 293 insertions(+), 803 deletions(-)

-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V3 02/11] power: charger-manager: Use thermal subsystem interface only to get temperature.

2014-12-19 Thread Jonghwa Lee
It drops the way of using power_supply interface to reference battery's
temperature. Then it tries to use thermal subsystem's only. This makes driver
more simple and also can remove ifdeferies.

Signed-off-by: Jonghwa Lee 
---
 drivers/power/Kconfig |1 +
 drivers/power/charger-manager.c   |  111 -
 include/linux/power/charger-manager.h |3 +-
 3 files changed, 27 insertions(+), 88 deletions(-)

diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 8ff2511..9ede4f2 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -316,6 +316,7 @@ config CHARGER_GPIO
 config CHARGER_MANAGER
bool "Battery charger manager for multiple chargers"
depends on REGULATOR
+   depends on THERMAL
select EXTCON
help
   Say Y to enable charger-manager support, which allows multiple
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 22246b9..71a3df7 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -28,13 +28,6 @@
 #include 
 #include 
 
-/*
- * Default termperature threshold for charging.
- * Every temperature units are in tenth of centigrade.
- */
-#define CM_DEFAULT_RECHARGE_TEMP_DIFF  50
-#define CM_DEFAULT_CHARGE_TEMP_MAX 500
-
 static const char * const default_event_names[] = {
[CM_EVENT_UNKNOWN] = "Unknown",
[CM_EVENT_BATT_FULL] = "Battery Full",
@@ -572,40 +565,18 @@ static int check_charging_duration(struct charger_manager 
*cm)
return ret;
 }
 
-static int cm_get_battery_temperature_by_psy(struct charger_manager *cm,
-   int *temp)
-{
-   struct power_supply *fuel_gauge;
-
-   fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge);
-   if (!fuel_gauge)
-   return -ENODEV;
-
-   return fuel_gauge->get_property(fuel_gauge,
-   POWER_SUPPLY_PROP_TEMP,
-   (union power_supply_propval *)temp);
-}
-
 static int cm_get_battery_temperature(struct charger_manager *cm,
int *temp)
 {
int ret;
 
-   if (!cm->desc->measure_battery_temp)
+   if (!cm->tzd_batt)
return -ENODEV;
 
-#ifdef CONFIG_THERMAL
-   if (cm->tzd_batt) {
-   ret = thermal_zone_get_temp(cm->tzd_batt, (unsigned long 
*)temp);
-   if (!ret)
-   /* Calibrate temperature unit */
-   *temp /= 100;
-   } else
-#endif
-   {
-   /* if-else continued from CONFIG_THERMAL */
-   ret = cm_get_battery_temperature_by_psy(cm, temp);
-   }
+   ret = thermal_zone_get_temp(cm->tzd_batt, (unsigned long *)temp);
+   if (!ret)
+   /* Calibrate temperature unit */
+   *temp /= 100;
 
return ret;
 }
@@ -1007,12 +978,11 @@ static enum power_supply_property 
default_charger_props[] = {
POWER_SUPPLY_PROP_CAPACITY,
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_CHARGE_FULL,
+   POWER_SUPPLY_PROP_TEMP,
/*
 * Optional properties are:
 * POWER_SUPPLY_PROP_CHARGE_NOW,
 * POWER_SUPPLY_PROP_CURRENT_NOW,
-* POWER_SUPPLY_PROP_TEMP, and
-* POWER_SUPPLY_PROP_TEMP_AMBIENT,
 */
 };
 
@@ -1417,49 +1387,6 @@ err:
return ret;
 }
 
-static int cm_init_thermal_data(struct charger_manager *cm,
-   struct power_supply *fuel_gauge)
-{
-   struct charger_desc *desc = cm->desc;
-   union power_supply_propval val;
-   int ret;
-
-   /* Verify whether fuel gauge provides battery temperature */
-   ret = fuel_gauge->get_property(fuel_gauge,
-   POWER_SUPPLY_PROP_TEMP, );
-
-   if (!ret) {
-   cm->charger_psy.properties[cm->charger_psy.num_properties] =
-   POWER_SUPPLY_PROP_TEMP;
-   cm->charger_psy.num_properties++;
-   cm->desc->measure_battery_temp = true;
-   }
-#ifdef CONFIG_THERMAL
-   if (ret && desc->thermal_zone) {
-   cm->tzd_batt =
-   thermal_zone_get_zone_by_name(desc->thermal_zone);
-   if (IS_ERR(cm->tzd_batt))
-   return PTR_ERR(cm->tzd_batt);
-
-   /* Use external thermometer */
-   cm->charger_psy.properties[cm->charger_psy.num_properties] =
-   POWER_SUPPLY_PROP_TEMP_AMBIENT;
-   cm->charger_psy.num_properties++;
-   cm->desc->measure_battery_temp = true;
-   ret = 0;
-   }
-#endif
-   if (cm->desc->measure_battery_temp) {
-   /* NOTICE : Default allowable minimum charge temperature is 0 */
-   if (

[PATCH V3 03/11] power: charger-manager: Use power_supply_changed() not private uevent.

2014-12-19 Thread Jonghwa Lee
Whenever battery status is changed, charger manager tries to trigger uevent
through private interface. This patch modifies it to use power_supply_changed()
since it belongs to power supply subsystem.

Signed-off-by: Jonghwa Lee 
---
 drivers/power/charger-manager.c |   91 +--
 1 file changed, 11 insertions(+), 80 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 71a3df7..8c76bce 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -28,18 +28,6 @@
 #include 
 #include 
 
-static const char * const default_event_names[] = {
-   [CM_EVENT_UNKNOWN] = "Unknown",
-   [CM_EVENT_BATT_FULL] = "Battery Full",
-   [CM_EVENT_BATT_IN] = "Battery Inserted",
-   [CM_EVENT_BATT_OUT] = "Battery Pulled Out",
-   [CM_EVENT_BATT_OVERHEAT] = "Battery Overheat",
-   [CM_EVENT_BATT_COLD] = "Battery Cold",
-   [CM_EVENT_EXT_PWR_IN_OUT] = "External Power Attach/Detach",
-   [CM_EVENT_CHG_START_STOP] = "Charging Start/Stop",
-   [CM_EVENT_OTHERS] = "Other battery events"
-};
-
 /*
  * Regard CM_JIFFIES_SMALL jiffies is small enough to ignore for
  * delayed works so that we can run delayed works with CM_JIFFIES_SMALL
@@ -56,8 +44,6 @@ static const char * const default_event_names[] = {
  */
 #define CM_RTC_SMALL   (2)
 
-#define UEVENT_BUF_SIZE32
-
 static LIST_HEAD(cm_list);
 static DEFINE_MUTEX(cm_list_mtx);
 
@@ -423,61 +409,6 @@ static int try_charger_restart(struct charger_manager *cm)
 }
 
 /**
- * uevent_notify - Let users know something has changed.
- * @cm: the Charger Manager representing the battery.
- * @event: the event string.
- *
- * If @event is null, it implies that uevent_notify is called
- * by resume function. When called in the resume function, cm_suspended
- * should be already reset to false in order to let uevent_notify
- * notify the recent event during the suspend to users. While
- * suspended, uevent_notify does not notify users, but tracks
- * events so that uevent_notify can notify users later after resumed.
- */
-static void uevent_notify(struct charger_manager *cm, const char *event)
-{
-   static char env_str[UEVENT_BUF_SIZE + 1] = "";
-   static char env_str_save[UEVENT_BUF_SIZE + 1] = "";
-
-   if (cm_suspended) {
-   /* Nothing in suspended-event buffer */
-   if (env_str_save[0] == 0) {
-   if (!strncmp(env_str, event, UEVENT_BUF_SIZE))
-   return; /* status not changed */
-   strncpy(env_str_save, event, UEVENT_BUF_SIZE);
-   return;
-   }
-
-   if (!strncmp(env_str_save, event, UEVENT_BUF_SIZE))
-   return; /* Duplicated. */
-   strncpy(env_str_save, event, UEVENT_BUF_SIZE);
-   return;
-   }
-
-   if (event == NULL) {
-   /* No messages pending */
-   if (!env_str_save[0])
-   return;
-
-   strncpy(env_str, env_str_save, UEVENT_BUF_SIZE);
-   kobject_uevent(>dev->kobj, KOBJ_CHANGE);
-   env_str_save[0] = 0;
-
-   return;
-   }
-
-   /* status not changed */
-   if (!strncmp(env_str, event, UEVENT_BUF_SIZE))
-   return;
-
-   /* save the status and notify the update */
-   strncpy(env_str, event, UEVENT_BUF_SIZE);
-   kobject_uevent(>dev->kobj, KOBJ_CHANGE);
-
-   dev_info(cm->dev, "%s\n", event);
-}
-
-/**
  * fullbatt_vchk - Check voltage drop some times after "FULL" event.
  * @work: the work_struct appointing the function
  *
@@ -514,7 +445,7 @@ static void fullbatt_vchk(struct work_struct *work)
 
if (diff > desc->fullbatt_vchkdrop_uV) {
try_charger_restart(cm);
-   uevent_notify(cm, "Recharging");
+   power_supply_changed(>charger_psy);
}
 }
 
@@ -545,7 +476,7 @@ static int check_charging_duration(struct charger_manager 
*cm)
if (duration > desc->charging_max_duration_ms) {
dev_info(cm->dev, "Charging duration exceed %ums\n",
 desc->charging_max_duration_ms);
-   uevent_notify(cm, "Discharging");
+   power_supply_changed(>charger_psy);
try_charger_enable(cm, false);
ret = true;
}
@@ -556,7 +487,7 @@ static int check_charging_duration(struct charger_manager 
*cm)
is_ext_pwr_online(cm)) {
dev_info(cm->dev, "Discharging duration exceed %ums\n",
 desc->discharging_m

[PATCH V3 08/11] power: charger-manager: Make chraging decision focusing on battery status.

2014-12-19 Thread Jonghwa Lee
In cm_monitor() where charging management starts, it checks various charging
condition sequentially to decide next charging operation. However, as it
follows sequential process, cascaded IF statements, it does some duplicated
jobs which is already done in previous stage. It results delay in decision
making. And moreover, starting point of charing is spreaded all around, so
it makes maintain codes and debugging difficult.

Both of problems mentioned above becomes clean if it manages battery charging
focusing on battery status not following sequential condition checking.
Now, cm_monitor() moves battery state diagram and does optimal operation for
current state. As a result, it reduces whole monitoring time almost in half.

Signed-off-by: Jonghwa Lee 
---
 drivers/power/charger-manager.c   |  177 +++--
 include/linux/power/charger-manager.h |3 +
 2 files changed, 62 insertions(+), 118 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index dc15436..44cc19a 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -249,6 +249,19 @@ static bool is_full_charged(struct charger_manager *cm)
if (!fuel_gauge)
return false;
 
+   /* Full, if it's over the fullbatt voltage */
+   if (desc->fullbatt_uV > 0) {
+   ret = get_batt_uV(cm, );
+   if (!ret) {
+   /* Battery is already full, checks voltage drop. */
+   if (cm->battery_status == POWER_SUPPLY_STATUS_FULL
+   && desc->fullbatt_vchkdrop_uV)
+   uV += desc->fullbatt_vchkdrop_uV;
+   if (uV >= desc->fullbatt_uV)
+   return true;
+   }
+   }
+
if (desc->fullbatt_full_capacity > 0) {
val.intval = 0;
 
@@ -259,13 +272,6 @@ static bool is_full_charged(struct charger_manager *cm)
return true;
}
 
-   /* Full, if it's over the fullbatt voltage */
-   if (desc->fullbatt_uV > 0) {
-   ret = get_batt_uV(cm, );
-   if (!ret && uV >= desc->fullbatt_uV)
-   return true;
-   }
-
/* Full, if the capacity is more than fullbatt_soc */
if (desc->fullbatt_soc > 0) {
val.intval = 0;
@@ -376,67 +382,13 @@ static int try_charger_enable(struct charger_manager *cm, 
bool enable)
}
}
 
-   if (!err) {
+   if (!err)
cm->charger_enabled = enable;
-   power_supply_changed(>charger_psy);
-   }
 
return err;
 }
 
 /**
- * try_charger_restart - Restart charging.
- * @cm: the Charger Manager representing the battery.
- *
- * Restart charging by turning off and on the charger.
- */
-static int try_charger_restart(struct charger_manager *cm)
-{
-   int err;
-
-   if (cm->emergency_stop)
-   return -EAGAIN;
-
-   err = try_charger_enable(cm, false);
-   if (err)
-   return err;
-
-   return try_charger_enable(cm, true);
-}
-
-/**
- * fullbatt_vchk - Check voltage drop some times after "FULL" event.
- *
- * If a user has designated "fullbatt_vchkdrop_uV" values with
- * charger_desc, Charger Manager checks voltage drop after the battery
- * "FULL" event. It checks whether the voltage has dropped more than
- * fullbatt_vchkdrop_uV by calling this function after fullbatt_vchkrop_ms.
- */
-static void fullbatt_vchk(struct charger_manager *cm)
-{
-   struct charger_desc *desc = cm->desc;
-   int batt_uV, err, diff;
-
-   if (!desc->fullbatt_vchkdrop_uV)
-   return;
-
-   err = get_batt_uV(cm, _uV);
-   if (err) {
-   dev_err(cm->dev, "%s: get_batt_uV error(%d)\n", __func__, err);
-   return;
-   }
-
-   diff = desc->fullbatt_uV - batt_uV;
-   if (diff < 0)
-   return;
-
-   dev_info(cm->dev, "VBATT dropped %duV after full-batt\n", diff);
-
-   if (diff > desc->fullbatt_vchkdrop_uV)
-   try_charger_restart(cm);
-}
-
-/**
  * check_charging_duration - Monitor charging/discharging duration
  * @cm: the Charger Manager representing the battery.
  *
@@ -463,17 +415,14 @@ static int check_charging_duration(struct charger_manager 
*cm)
if (duration > desc->charging_max_duration_ms) {
dev_info(cm->dev, "Charging duration exceed %ums\n",
 desc->charging_max_duration_ms);
-   try_charger_enable(cm, false);
ret = true;
}
-   } else if (is_ext_pwr_online(cm) && !cm->charger_enabled) {
+   } else if (c

[PATCH V3 07/11] power: charger-manager: Get external power souce information only from EXTCON.

2014-12-19 Thread Jonghwa Lee
When charger-manager checks whether external power source is available,
it gets information from charger IC driver. However, it's not correct source,
charger IC doesn't have responsibilty to give cable connection status.
The charger-manager already gets cable information from EXTCON susbsystem,
so it can re-use it.

Signed-off-by: Jonghwa Lee 
---
 drivers/power/charger-manager.c |   34 ++
 1 file changed, 14 insertions(+), 20 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index d29155d..dc15436 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -115,34 +115,28 @@ static bool is_batt_present(struct charger_manager *cm)
  * is_ext_pwr_online - See if an external power source is attached to charge
  * @cm: the Charger Manager representing the battery.
  *
- * Returns true if at least one of the chargers of the battery has an external
- * power source attached to charge the battery regardless of whether it is
- * actually charging or not.
+ * Returns true if there is external power source.
+ * Cable connection information is only obtained by EXTCON class notification.
  */
 static bool is_ext_pwr_online(struct charger_manager *cm)
 {
-   union power_supply_propval val;
-   struct power_supply *psy;
-   bool online = false;
-   int i, ret;
 
-   /* If at least one of them has one, it's yes. */
-   for (i = 0; cm->desc->psy_charger_stat[i]; i++) {
-   psy = power_supply_get_by_name(cm->desc->psy_charger_stat[i]);
-   if (!psy) {
-   dev_err(cm->dev, "Cannot find power supply \"%s\"\n",
-   cm->desc->psy_charger_stat[i]);
-   continue;
-   }
+   struct charger_desc *desc = cm->desc;
+   struct charger_regulator *regulators = desc->charger_regulators;
+   struct charger_cable *cables;
+   int i, j, num_cables;
 
-   ret = psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, );
-   if (ret == 0 && val.intval) {
-   online = true;
-   break;
+   /* If at least one of them has one, it's yes. */
+   for (i = 0; i < desc->num_charger_regulators; i++) {
+   cables = regulators[i].cables;
+   num_cables = regulators[i].num_cables;
+   for (j = 0; j < num_cables; j++) {
+   if (cables[j].attached)
+   return true;
}
}
 
-   return online;
+   return false;
 }
 
 /**
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V3 10/11] power: charger-manager: Support different polling mode for sleep state.

2014-12-19 Thread Jonghwa Lee
Add additional polling mode for sleep state to define different mode with
normal state. With this change, charger-manager can work differently in
normal state or sleep state. e.g, polling aways for normal and polling
only when charing for sleep. If there is no defined polling mode for
sleep state it just follows the normal state's.
In addition to, polling rate is still same in sleep.

Signed-off-by: Jonghwa Lee 
---
 drivers/power/charger-manager.c   |   20 +---
 include/linux/power/charger-manager.h |9 ++---
 2 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 4f8b0e6..f5787bc 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -291,7 +291,15 @@ static bool is_full_charged(struct charger_manager *cm)
  */
 static bool is_polling_required(struct charger_manager *cm)
 {
-   switch (cm->desc->polling_mode) {
+   enum polling_modes polling_mode;
+
+   if (cm_suspended
+   && cm->desc->poll_mode_sleep >= 0)
+   polling_mode = cm->desc->poll_mode_sleep;
+   else
+   polling_mode = cm->desc->poll_mode_normal;
+
+   switch (polling_mode) {
case CM_POLL_DISABLE:
return false;
case CM_POLL_ALWAYS:
@@ -302,7 +310,7 @@ static bool is_polling_required(struct charger_manager *cm)
return is_charging(cm);
default:
dev_warn(cm->dev, "Incorrect polling_mode (%d)\n",
-cm->desc->polling_mode);
+polling_mode);
}
 
return false;
@@ -1158,7 +1166,13 @@ static struct charger_desc *of_cm_parse_desc(struct 
device *dev)
of_property_read_string(np, "cm-name", >psy_name);
 
of_property_read_u32(np, "cm-poll-mode", _mode);
-   desc->polling_mode = poll_mode;
+   desc->poll_mode_normal = poll_mode;
+
+   /* Polling mode in sleep state */
+   if (!of_property_read_u32(np, "cm-poll-mode-sleep", _mode))
+   desc->poll_mode_sleep = poll_mode;
+   else
+   desc->poll_mode_sleep = -EINVAL;
 
of_property_read_u32(np, "cm-poll-interval",
>polling_interval_ms);
diff --git a/include/linux/power/charger-manager.h 
b/include/linux/power/charger-manager.h
index 37fb181..a30a0b6 100644
--- a/include/linux/power/charger-manager.h
+++ b/include/linux/power/charger-manager.h
@@ -131,8 +131,10 @@ struct charger_regulator {
 /**
  * struct charger_desc
  * @psy_name: the name of power-supply-class for charger manager
- * @polling_mode:
- * Determine which polling mode will be used
+ * @poll_mode_normal:
+ * Determine which polling mode will be used in normal state.
+ * @poll_mode_sleep:
+ * Determine which polling mode will be used in sleep state.
  * @fullbatt_vchkdrop_uV:
  * Check voltage drop after the battery is fully charged.
  * If it has dropped more than fullbatt_vchkdrop_uV
@@ -170,7 +172,8 @@ struct charger_regulator {
 struct charger_desc {
const char *psy_name;
 
-   enum polling_modes polling_mode;
+   enum polling_modes poll_mode_normal;
+   enum polling_modes poll_mode_sleep;
unsigned int polling_interval_ms;
 
unsigned int fullbatt_vchkdrop_uV;
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V3 11/11] power: charger-manager: Support to change polling rate in runtime.

2014-12-19 Thread Jonghwa Lee
Add 'polling_ms' sysfs node to change charger-manager's monitoring rate
in runtime. It can set only bigger than 2 jiffies (for 200 HZ system it
is 10 msecs.) as it's allowed for minimum poling rate in previous.
It resets poller and re-configure polling rate based on new input if next
polling time is far enough. Otherwise, it just waits expiration of timer
and new polling rate will affects the next scheduling.

Signed-off-by: Jonghwa Lee 
---
 drivers/power/charger-manager.c |   62 +++
 1 file changed, 62 insertions(+)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index f5787bc..a8cabf09 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -1054,6 +1054,63 @@ static ssize_t charger_externally_control_store(struct 
device *dev,
return count;
 }
 
+static ssize_t show_polling_ms(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   struct charger_manager *cm;
+   ssize_t len;
+
+   list_for_each_entry(cm, _list, entry)
+   if (cm->charger_psy.dev == dev)
+   break;
+
+   if (cm->charger_psy.dev != dev)
+   return -EINVAL;
+
+   len = sprintf(buf, "%d\n", cm->desc->polling_interval_ms);
+
+   return len;
+}
+
+static ssize_t store_polling_ms(struct device *dev,
+   struct device_attribute *attr, const char *buf,
+   size_t count)
+{
+   struct charger_manager *cm;
+   int polling_ms;
+   int ret;
+
+   ret = sscanf(buf, "%d", _ms);
+   if (ret < 0 )
+   return -EINVAL;
+
+   if (polling_ms < CM_JIFFIES_SMALL * MSEC_PER_SEC / HZ)
+   return -EINVAL;
+
+   list_for_each_entry(cm, _list, entry)
+   if (cm->charger_psy.dev == dev)
+   break;
+
+   if (cm->charger_psy.dev != dev)
+   return -ENODEV;
+
+   cm->desc->polling_interval_ms = polling_ms;
+
+   pr_info("Polling interval's changed to %u ms.\n",
+   cm->desc->polling_interval_ms);
+
+   if (next_polling - jiffies >
+   msecs_to_jiffies(cm->desc->polling_interval_ms)) {
+   pr_info("Reset poller now... \n");
+   cancel_delayed_work(_monitor_work);
+   schedule_work(_polling);
+   }
+
+   return count;
+}
+
+static DEVICE_ATTR(polling_ms, 0644, show_polling_ms, store_polling_ms);
+
 /**
  * charger_manager_register_sysfs - Register sysfs entry for each charger
  * @cm: the Charger Manager representing the battery.
@@ -1077,6 +1134,11 @@ static int charger_manager_register_sysfs(struct 
charger_manager *cm)
int ret = 0;
int i;
 
+   /* Create polling_ms sysfs node */
+   ret = device_create_file(cm->charger_psy.dev, _attr_polling_ms);
+   if (ret)
+   pr_err("Failed to create poling_ms sysfs node (%d)\n", ret);
+
/* Create sysfs entry to control charger(regulator) */
for (i = 0; i < desc->num_charger_regulators; i++) {
charger = >charger_regulators[i];
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V3 11/11] power: charger-manager: Support to change polling rate in runtime.

2014-12-19 Thread Jonghwa Lee
Add 'polling_ms' sysfs node to change charger-manager's monitoring rate
in runtime. It can set only bigger than 2 jiffies (for 200 HZ system it
is 10 msecs.) as it's allowed for minimum poling rate in previous.
It resets poller and re-configure polling rate based on new input if next
polling time is far enough. Otherwise, it just waits expiration of timer
and new polling rate will affects the next scheduling.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 drivers/power/charger-manager.c |   62 +++
 1 file changed, 62 insertions(+)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index f5787bc..a8cabf09 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -1054,6 +1054,63 @@ static ssize_t charger_externally_control_store(struct 
device *dev,
return count;
 }
 
+static ssize_t show_polling_ms(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   struct charger_manager *cm;
+   ssize_t len;
+
+   list_for_each_entry(cm, cm_list, entry)
+   if (cm-charger_psy.dev == dev)
+   break;
+
+   if (cm-charger_psy.dev != dev)
+   return -EINVAL;
+
+   len = sprintf(buf, %d\n, cm-desc-polling_interval_ms);
+
+   return len;
+}
+
+static ssize_t store_polling_ms(struct device *dev,
+   struct device_attribute *attr, const char *buf,
+   size_t count)
+{
+   struct charger_manager *cm;
+   int polling_ms;
+   int ret;
+
+   ret = sscanf(buf, %d, polling_ms);
+   if (ret  0 )
+   return -EINVAL;
+
+   if (polling_ms  CM_JIFFIES_SMALL * MSEC_PER_SEC / HZ)
+   return -EINVAL;
+
+   list_for_each_entry(cm, cm_list, entry)
+   if (cm-charger_psy.dev == dev)
+   break;
+
+   if (cm-charger_psy.dev != dev)
+   return -ENODEV;
+
+   cm-desc-polling_interval_ms = polling_ms;
+
+   pr_info(Polling interval's changed to %u ms.\n,
+   cm-desc-polling_interval_ms);
+
+   if (next_polling - jiffies 
+   msecs_to_jiffies(cm-desc-polling_interval_ms)) {
+   pr_info(Reset poller now... \n);
+   cancel_delayed_work(cm_monitor_work);
+   schedule_work(setup_polling);
+   }
+
+   return count;
+}
+
+static DEVICE_ATTR(polling_ms, 0644, show_polling_ms, store_polling_ms);
+
 /**
  * charger_manager_register_sysfs - Register sysfs entry for each charger
  * @cm: the Charger Manager representing the battery.
@@ -1077,6 +1134,11 @@ static int charger_manager_register_sysfs(struct 
charger_manager *cm)
int ret = 0;
int i;
 
+   /* Create polling_ms sysfs node */
+   ret = device_create_file(cm-charger_psy.dev, dev_attr_polling_ms);
+   if (ret)
+   pr_err(Failed to create poling_ms sysfs node (%d)\n, ret);
+
/* Create sysfs entry to control charger(regulator) */
for (i = 0; i  desc-num_charger_regulators; i++) {
charger = desc-charger_regulators[i];
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V3 10/11] power: charger-manager: Support different polling mode for sleep state.

2014-12-19 Thread Jonghwa Lee
Add additional polling mode for sleep state to define different mode with
normal state. With this change, charger-manager can work differently in
normal state or sleep state. e.g, polling aways for normal and polling
only when charing for sleep. If there is no defined polling mode for
sleep state it just follows the normal state's.
In addition to, polling rate is still same in sleep.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 drivers/power/charger-manager.c   |   20 +---
 include/linux/power/charger-manager.h |9 ++---
 2 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 4f8b0e6..f5787bc 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -291,7 +291,15 @@ static bool is_full_charged(struct charger_manager *cm)
  */
 static bool is_polling_required(struct charger_manager *cm)
 {
-   switch (cm-desc-polling_mode) {
+   enum polling_modes polling_mode;
+
+   if (cm_suspended
+cm-desc-poll_mode_sleep = 0)
+   polling_mode = cm-desc-poll_mode_sleep;
+   else
+   polling_mode = cm-desc-poll_mode_normal;
+
+   switch (polling_mode) {
case CM_POLL_DISABLE:
return false;
case CM_POLL_ALWAYS:
@@ -302,7 +310,7 @@ static bool is_polling_required(struct charger_manager *cm)
return is_charging(cm);
default:
dev_warn(cm-dev, Incorrect polling_mode (%d)\n,
-cm-desc-polling_mode);
+polling_mode);
}
 
return false;
@@ -1158,7 +1166,13 @@ static struct charger_desc *of_cm_parse_desc(struct 
device *dev)
of_property_read_string(np, cm-name, desc-psy_name);
 
of_property_read_u32(np, cm-poll-mode, poll_mode);
-   desc-polling_mode = poll_mode;
+   desc-poll_mode_normal = poll_mode;
+
+   /* Polling mode in sleep state */
+   if (!of_property_read_u32(np, cm-poll-mode-sleep, poll_mode))
+   desc-poll_mode_sleep = poll_mode;
+   else
+   desc-poll_mode_sleep = -EINVAL;
 
of_property_read_u32(np, cm-poll-interval,
desc-polling_interval_ms);
diff --git a/include/linux/power/charger-manager.h 
b/include/linux/power/charger-manager.h
index 37fb181..a30a0b6 100644
--- a/include/linux/power/charger-manager.h
+++ b/include/linux/power/charger-manager.h
@@ -131,8 +131,10 @@ struct charger_regulator {
 /**
  * struct charger_desc
  * @psy_name: the name of power-supply-class for charger manager
- * @polling_mode:
- * Determine which polling mode will be used
+ * @poll_mode_normal:
+ * Determine which polling mode will be used in normal state.
+ * @poll_mode_sleep:
+ * Determine which polling mode will be used in sleep state.
  * @fullbatt_vchkdrop_uV:
  * Check voltage drop after the battery is fully charged.
  * If it has dropped more than fullbatt_vchkdrop_uV
@@ -170,7 +172,8 @@ struct charger_regulator {
 struct charger_desc {
const char *psy_name;
 
-   enum polling_modes polling_mode;
+   enum polling_modes poll_mode_normal;
+   enum polling_modes poll_mode_sleep;
unsigned int polling_interval_ms;
 
unsigned int fullbatt_vchkdrop_uV;
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V3 07/11] power: charger-manager: Get external power souce information only from EXTCON.

2014-12-19 Thread Jonghwa Lee
When charger-manager checks whether external power source is available,
it gets information from charger IC driver. However, it's not correct source,
charger IC doesn't have responsibilty to give cable connection status.
The charger-manager already gets cable information from EXTCON susbsystem,
so it can re-use it.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 drivers/power/charger-manager.c |   34 ++
 1 file changed, 14 insertions(+), 20 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index d29155d..dc15436 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -115,34 +115,28 @@ static bool is_batt_present(struct charger_manager *cm)
  * is_ext_pwr_online - See if an external power source is attached to charge
  * @cm: the Charger Manager representing the battery.
  *
- * Returns true if at least one of the chargers of the battery has an external
- * power source attached to charge the battery regardless of whether it is
- * actually charging or not.
+ * Returns true if there is external power source.
+ * Cable connection information is only obtained by EXTCON class notification.
  */
 static bool is_ext_pwr_online(struct charger_manager *cm)
 {
-   union power_supply_propval val;
-   struct power_supply *psy;
-   bool online = false;
-   int i, ret;
 
-   /* If at least one of them has one, it's yes. */
-   for (i = 0; cm-desc-psy_charger_stat[i]; i++) {
-   psy = power_supply_get_by_name(cm-desc-psy_charger_stat[i]);
-   if (!psy) {
-   dev_err(cm-dev, Cannot find power supply \%s\\n,
-   cm-desc-psy_charger_stat[i]);
-   continue;
-   }
+   struct charger_desc *desc = cm-desc;
+   struct charger_regulator *regulators = desc-charger_regulators;
+   struct charger_cable *cables;
+   int i, j, num_cables;
 
-   ret = psy-get_property(psy, POWER_SUPPLY_PROP_ONLINE, val);
-   if (ret == 0  val.intval) {
-   online = true;
-   break;
+   /* If at least one of them has one, it's yes. */
+   for (i = 0; i  desc-num_charger_regulators; i++) {
+   cables = regulators[i].cables;
+   num_cables = regulators[i].num_cables;
+   for (j = 0; j  num_cables; j++) {
+   if (cables[j].attached)
+   return true;
}
}
 
-   return online;
+   return false;
 }
 
 /**
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V3 08/11] power: charger-manager: Make chraging decision focusing on battery status.

2014-12-19 Thread Jonghwa Lee
In cm_monitor() where charging management starts, it checks various charging
condition sequentially to decide next charging operation. However, as it
follows sequential process, cascaded IF statements, it does some duplicated
jobs which is already done in previous stage. It results delay in decision
making. And moreover, starting point of charing is spreaded all around, so
it makes maintain codes and debugging difficult.

Both of problems mentioned above becomes clean if it manages battery charging
focusing on battery status not following sequential condition checking.
Now, cm_monitor() moves battery state diagram and does optimal operation for
current state. As a result, it reduces whole monitoring time almost in half.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 drivers/power/charger-manager.c   |  177 +++--
 include/linux/power/charger-manager.h |3 +
 2 files changed, 62 insertions(+), 118 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index dc15436..44cc19a 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -249,6 +249,19 @@ static bool is_full_charged(struct charger_manager *cm)
if (!fuel_gauge)
return false;
 
+   /* Full, if it's over the fullbatt voltage */
+   if (desc-fullbatt_uV  0) {
+   ret = get_batt_uV(cm, uV);
+   if (!ret) {
+   /* Battery is already full, checks voltage drop. */
+   if (cm-battery_status == POWER_SUPPLY_STATUS_FULL
+desc-fullbatt_vchkdrop_uV)
+   uV += desc-fullbatt_vchkdrop_uV;
+   if (uV = desc-fullbatt_uV)
+   return true;
+   }
+   }
+
if (desc-fullbatt_full_capacity  0) {
val.intval = 0;
 
@@ -259,13 +272,6 @@ static bool is_full_charged(struct charger_manager *cm)
return true;
}
 
-   /* Full, if it's over the fullbatt voltage */
-   if (desc-fullbatt_uV  0) {
-   ret = get_batt_uV(cm, uV);
-   if (!ret  uV = desc-fullbatt_uV)
-   return true;
-   }
-
/* Full, if the capacity is more than fullbatt_soc */
if (desc-fullbatt_soc  0) {
val.intval = 0;
@@ -376,67 +382,13 @@ static int try_charger_enable(struct charger_manager *cm, 
bool enable)
}
}
 
-   if (!err) {
+   if (!err)
cm-charger_enabled = enable;
-   power_supply_changed(cm-charger_psy);
-   }
 
return err;
 }
 
 /**
- * try_charger_restart - Restart charging.
- * @cm: the Charger Manager representing the battery.
- *
- * Restart charging by turning off and on the charger.
- */
-static int try_charger_restart(struct charger_manager *cm)
-{
-   int err;
-
-   if (cm-emergency_stop)
-   return -EAGAIN;
-
-   err = try_charger_enable(cm, false);
-   if (err)
-   return err;
-
-   return try_charger_enable(cm, true);
-}
-
-/**
- * fullbatt_vchk - Check voltage drop some times after FULL event.
- *
- * If a user has designated fullbatt_vchkdrop_uV values with
- * charger_desc, Charger Manager checks voltage drop after the battery
- * FULL event. It checks whether the voltage has dropped more than
- * fullbatt_vchkdrop_uV by calling this function after fullbatt_vchkrop_ms.
- */
-static void fullbatt_vchk(struct charger_manager *cm)
-{
-   struct charger_desc *desc = cm-desc;
-   int batt_uV, err, diff;
-
-   if (!desc-fullbatt_vchkdrop_uV)
-   return;
-
-   err = get_batt_uV(cm, batt_uV);
-   if (err) {
-   dev_err(cm-dev, %s: get_batt_uV error(%d)\n, __func__, err);
-   return;
-   }
-
-   diff = desc-fullbatt_uV - batt_uV;
-   if (diff  0)
-   return;
-
-   dev_info(cm-dev, VBATT dropped %duV after full-batt\n, diff);
-
-   if (diff  desc-fullbatt_vchkdrop_uV)
-   try_charger_restart(cm);
-}
-
-/**
  * check_charging_duration - Monitor charging/discharging duration
  * @cm: the Charger Manager representing the battery.
  *
@@ -463,17 +415,14 @@ static int check_charging_duration(struct charger_manager 
*cm)
if (duration  desc-charging_max_duration_ms) {
dev_info(cm-dev, Charging duration exceed %ums\n,
 desc-charging_max_duration_ms);
-   try_charger_enable(cm, false);
ret = true;
}
-   } else if (is_ext_pwr_online(cm)  !cm-charger_enabled) {
+   } else if (cm-battery_status == POWER_SUPPLY_STATUS_NOT_CHARGING) {
duration = curr - cm-charging_end_time;
 
-   if (duration  desc-charging_max_duration_ms

[PATCH V3 02/11] power: charger-manager: Use thermal subsystem interface only to get temperature.

2014-12-19 Thread Jonghwa Lee
It drops the way of using power_supply interface to reference battery's
temperature. Then it tries to use thermal subsystem's only. This makes driver
more simple and also can remove ifdeferies.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 drivers/power/Kconfig |1 +
 drivers/power/charger-manager.c   |  111 -
 include/linux/power/charger-manager.h |3 +-
 3 files changed, 27 insertions(+), 88 deletions(-)

diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 8ff2511..9ede4f2 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -316,6 +316,7 @@ config CHARGER_GPIO
 config CHARGER_MANAGER
bool Battery charger manager for multiple chargers
depends on REGULATOR
+   depends on THERMAL
select EXTCON
help
   Say Y to enable charger-manager support, which allows multiple
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 22246b9..71a3df7 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -28,13 +28,6 @@
 #include linux/of.h
 #include linux/thermal.h
 
-/*
- * Default termperature threshold for charging.
- * Every temperature units are in tenth of centigrade.
- */
-#define CM_DEFAULT_RECHARGE_TEMP_DIFF  50
-#define CM_DEFAULT_CHARGE_TEMP_MAX 500
-
 static const char * const default_event_names[] = {
[CM_EVENT_UNKNOWN] = Unknown,
[CM_EVENT_BATT_FULL] = Battery Full,
@@ -572,40 +565,18 @@ static int check_charging_duration(struct charger_manager 
*cm)
return ret;
 }
 
-static int cm_get_battery_temperature_by_psy(struct charger_manager *cm,
-   int *temp)
-{
-   struct power_supply *fuel_gauge;
-
-   fuel_gauge = power_supply_get_by_name(cm-desc-psy_fuel_gauge);
-   if (!fuel_gauge)
-   return -ENODEV;
-
-   return fuel_gauge-get_property(fuel_gauge,
-   POWER_SUPPLY_PROP_TEMP,
-   (union power_supply_propval *)temp);
-}
-
 static int cm_get_battery_temperature(struct charger_manager *cm,
int *temp)
 {
int ret;
 
-   if (!cm-desc-measure_battery_temp)
+   if (!cm-tzd_batt)
return -ENODEV;
 
-#ifdef CONFIG_THERMAL
-   if (cm-tzd_batt) {
-   ret = thermal_zone_get_temp(cm-tzd_batt, (unsigned long 
*)temp);
-   if (!ret)
-   /* Calibrate temperature unit */
-   *temp /= 100;
-   } else
-#endif
-   {
-   /* if-else continued from CONFIG_THERMAL */
-   ret = cm_get_battery_temperature_by_psy(cm, temp);
-   }
+   ret = thermal_zone_get_temp(cm-tzd_batt, (unsigned long *)temp);
+   if (!ret)
+   /* Calibrate temperature unit */
+   *temp /= 100;
 
return ret;
 }
@@ -1007,12 +978,11 @@ static enum power_supply_property 
default_charger_props[] = {
POWER_SUPPLY_PROP_CAPACITY,
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_CHARGE_FULL,
+   POWER_SUPPLY_PROP_TEMP,
/*
 * Optional properties are:
 * POWER_SUPPLY_PROP_CHARGE_NOW,
 * POWER_SUPPLY_PROP_CURRENT_NOW,
-* POWER_SUPPLY_PROP_TEMP, and
-* POWER_SUPPLY_PROP_TEMP_AMBIENT,
 */
 };
 
@@ -1417,49 +1387,6 @@ err:
return ret;
 }
 
-static int cm_init_thermal_data(struct charger_manager *cm,
-   struct power_supply *fuel_gauge)
-{
-   struct charger_desc *desc = cm-desc;
-   union power_supply_propval val;
-   int ret;
-
-   /* Verify whether fuel gauge provides battery temperature */
-   ret = fuel_gauge-get_property(fuel_gauge,
-   POWER_SUPPLY_PROP_TEMP, val);
-
-   if (!ret) {
-   cm-charger_psy.properties[cm-charger_psy.num_properties] =
-   POWER_SUPPLY_PROP_TEMP;
-   cm-charger_psy.num_properties++;
-   cm-desc-measure_battery_temp = true;
-   }
-#ifdef CONFIG_THERMAL
-   if (ret  desc-thermal_zone) {
-   cm-tzd_batt =
-   thermal_zone_get_zone_by_name(desc-thermal_zone);
-   if (IS_ERR(cm-tzd_batt))
-   return PTR_ERR(cm-tzd_batt);
-
-   /* Use external thermometer */
-   cm-charger_psy.properties[cm-charger_psy.num_properties] =
-   POWER_SUPPLY_PROP_TEMP_AMBIENT;
-   cm-charger_psy.num_properties++;
-   cm-desc-measure_battery_temp = true;
-   ret = 0;
-   }
-#endif
-   if (cm-desc-measure_battery_temp) {
-   /* NOTICE : Default allowable minimum charge temperature is 0 */
-   if (!desc-temp_max)
-   desc-temp_max = CM_DEFAULT_CHARGE_TEMP_MAX;
-   if (!desc-temp_diff

[PATCH V3 03/11] power: charger-manager: Use power_supply_changed() not private uevent.

2014-12-19 Thread Jonghwa Lee
Whenever battery status is changed, charger manager tries to trigger uevent
through private interface. This patch modifies it to use power_supply_changed()
since it belongs to power supply subsystem.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 drivers/power/charger-manager.c |   91 +--
 1 file changed, 11 insertions(+), 80 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 71a3df7..8c76bce 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -28,18 +28,6 @@
 #include linux/of.h
 #include linux/thermal.h
 
-static const char * const default_event_names[] = {
-   [CM_EVENT_UNKNOWN] = Unknown,
-   [CM_EVENT_BATT_FULL] = Battery Full,
-   [CM_EVENT_BATT_IN] = Battery Inserted,
-   [CM_EVENT_BATT_OUT] = Battery Pulled Out,
-   [CM_EVENT_BATT_OVERHEAT] = Battery Overheat,
-   [CM_EVENT_BATT_COLD] = Battery Cold,
-   [CM_EVENT_EXT_PWR_IN_OUT] = External Power Attach/Detach,
-   [CM_EVENT_CHG_START_STOP] = Charging Start/Stop,
-   [CM_EVENT_OTHERS] = Other battery events
-};
-
 /*
  * Regard CM_JIFFIES_SMALL jiffies is small enough to ignore for
  * delayed works so that we can run delayed works with CM_JIFFIES_SMALL
@@ -56,8 +44,6 @@ static const char * const default_event_names[] = {
  */
 #define CM_RTC_SMALL   (2)
 
-#define UEVENT_BUF_SIZE32
-
 static LIST_HEAD(cm_list);
 static DEFINE_MUTEX(cm_list_mtx);
 
@@ -423,61 +409,6 @@ static int try_charger_restart(struct charger_manager *cm)
 }
 
 /**
- * uevent_notify - Let users know something has changed.
- * @cm: the Charger Manager representing the battery.
- * @event: the event string.
- *
- * If @event is null, it implies that uevent_notify is called
- * by resume function. When called in the resume function, cm_suspended
- * should be already reset to false in order to let uevent_notify
- * notify the recent event during the suspend to users. While
- * suspended, uevent_notify does not notify users, but tracks
- * events so that uevent_notify can notify users later after resumed.
- */
-static void uevent_notify(struct charger_manager *cm, const char *event)
-{
-   static char env_str[UEVENT_BUF_SIZE + 1] = ;
-   static char env_str_save[UEVENT_BUF_SIZE + 1] = ;
-
-   if (cm_suspended) {
-   /* Nothing in suspended-event buffer */
-   if (env_str_save[0] == 0) {
-   if (!strncmp(env_str, event, UEVENT_BUF_SIZE))
-   return; /* status not changed */
-   strncpy(env_str_save, event, UEVENT_BUF_SIZE);
-   return;
-   }
-
-   if (!strncmp(env_str_save, event, UEVENT_BUF_SIZE))
-   return; /* Duplicated. */
-   strncpy(env_str_save, event, UEVENT_BUF_SIZE);
-   return;
-   }
-
-   if (event == NULL) {
-   /* No messages pending */
-   if (!env_str_save[0])
-   return;
-
-   strncpy(env_str, env_str_save, UEVENT_BUF_SIZE);
-   kobject_uevent(cm-dev-kobj, KOBJ_CHANGE);
-   env_str_save[0] = 0;
-
-   return;
-   }
-
-   /* status not changed */
-   if (!strncmp(env_str, event, UEVENT_BUF_SIZE))
-   return;
-
-   /* save the status and notify the update */
-   strncpy(env_str, event, UEVENT_BUF_SIZE);
-   kobject_uevent(cm-dev-kobj, KOBJ_CHANGE);
-
-   dev_info(cm-dev, %s\n, event);
-}
-
-/**
  * fullbatt_vchk - Check voltage drop some times after FULL event.
  * @work: the work_struct appointing the function
  *
@@ -514,7 +445,7 @@ static void fullbatt_vchk(struct work_struct *work)
 
if (diff  desc-fullbatt_vchkdrop_uV) {
try_charger_restart(cm);
-   uevent_notify(cm, Recharging);
+   power_supply_changed(cm-charger_psy);
}
 }
 
@@ -545,7 +476,7 @@ static int check_charging_duration(struct charger_manager 
*cm)
if (duration  desc-charging_max_duration_ms) {
dev_info(cm-dev, Charging duration exceed %ums\n,
 desc-charging_max_duration_ms);
-   uevent_notify(cm, Discharging);
+   power_supply_changed(cm-charger_psy);
try_charger_enable(cm, false);
ret = true;
}
@@ -556,7 +487,7 @@ static int check_charging_duration(struct charger_manager 
*cm)
is_ext_pwr_online(cm)) {
dev_info(cm-dev, Discharging duration exceed %ums\n,
 desc-discharging_max_duration_ms);
-   uevent_notify(cm, Recharging);
+   power_supply_changed(cm-charger_psy);
try_charger_enable(cm, true

[PATCH V3 0/11] Improve charger manager driver for optimized operation.

2014-12-19 Thread Jonghwa Lee
After charger manager's initially introduced, it has kept its codes without any
big change. However, the charger manager working operation isn't optimized and
it also has unused codes and non-generic interface. This series tries to make
charger manager more generic and maintainable with some fixes.

[Changes in V3]
- Add omitted patch '[1/11] Use alarmtimer for battery~' from v2 patch set.

[Changes in V2]
- Rebase patch series on latest of battery-2.6.git.
- Seperate 'power: charger-manager: Rearrange data and monitor ~' patch into
  several patches depends on its purpose.
- Add 2 patches related with polling mode.

Jonghwa Lee (11):
  power: charger-manager: Use alarmtimer for battery monitoring in
suspend.
  power: charger-manager: Use thermal subsystem interface only to get
temperature.
  power: charger-manager: Use power_supply_changed() not private
uevent.
  power: charger-manager: Remove deprecated function,
cm_notify_event().
  power: charger-manager: Fix to use CHARGE_NOW/FULL property
correctly.
  power: charger-manager: Concentrate scattered power_supply_changed()
calls.
  power: charger-manager: Get external power souce information only
from EXTCON.
  power: charger-manager: Make chraging decision focusing on battery
status.
  power: charger-manager: Not to start charging directly in cable
nofitication.
  power: charger-manager: Support different polling mode for sleep
state.
  power: charger-manager: Support to change polling rate in runtime.

 .../bindings/power_supply/charger-manager.txt  |1 -
 drivers/power/Kconfig  |3 +-
 drivers/power/charger-manager.c| 1026 ++--
 include/linux/power/charger-manager.h  |   66 +-
 4 files changed, 293 insertions(+), 803 deletions(-)

-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V3 05/11] power: charger-manager: Fix to use CHARGE_NOW/FULL property correctly.

2014-12-19 Thread Jonghwa Lee
The POWER_SUPPLY_CHARGE_NOW/FULL property reflects battery's charges
in uAh unit, but charger-manager has been used it wrongly. This patch
makes it to use those propeties correctly and change to be optional.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 drivers/power/charger-manager.c |   85 +--
 1 file changed, 28 insertions(+), 57 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 5482661..7bbaef6 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -796,35 +796,13 @@ static int charger_get_property(struct power_supply *psy,
val-intval = 0;
break;
case POWER_SUPPLY_PROP_CHARGE_FULL:
-   if (is_full_charged(cm))
-   val-intval = 1;
-   else
-   val-intval = 0;
-   ret = 0;
-   break;
case POWER_SUPPLY_PROP_CHARGE_NOW:
-   if (is_charging(cm)) {
-   fuel_gauge = power_supply_get_by_name(
-   cm-desc-psy_fuel_gauge);
-   if (!fuel_gauge) {
-   ret = -ENODEV;
-   break;
-   }
-
-   ret = fuel_gauge-get_property(fuel_gauge,
-   POWER_SUPPLY_PROP_CHARGE_NOW,
-   val);
-   if (ret) {
-   val-intval = 1;
-   ret = 0;
-   } else {
-   /* If CHARGE_NOW is supplied, use it */
-   val-intval = (val-intval  0) ?
-   val-intval : 1;
-   }
-   } else {
-   val-intval = 0;
+   fuel_gauge = power_supply_get_by_name(cm-desc-psy_fuel_gauge);
+   if (!fuel_gauge) {
+   ret = -ENODEV;
+   break;
}
+   ret = fuel_gauge-get_property(fuel_gauge, psp, val);
break;
default:
return -EINVAL;
@@ -832,8 +810,7 @@ static int charger_get_property(struct power_supply *psy,
return ret;
 }
 
-#define NUM_CHARGER_PSY_OPTIONAL   (4)
-static enum power_supply_property default_charger_props[] = {
+static enum power_supply_property cm_default_props[] = {
/* Guaranteed to provide */
POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_HEALTH,
@@ -841,20 +818,21 @@ static enum power_supply_property default_charger_props[] 
= {
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_CAPACITY,
POWER_SUPPLY_PROP_ONLINE,
-   POWER_SUPPLY_PROP_CHARGE_FULL,
POWER_SUPPLY_PROP_TEMP,
-   /*
-* Optional properties are:
-* POWER_SUPPLY_PROP_CHARGE_NOW,
-* POWER_SUPPLY_PROP_CURRENT_NOW,
-*/
 };
 
+static enum power_supply_property cm_optional_props[] = {
+   POWER_SUPPLY_PROP_CHARGE_FULL,
+   POWER_SUPPLY_PROP_CHARGE_NOW,
+   POWER_SUPPLY_PROP_CURRENT_NOW,
+};
+
+#define CM_NUM_OF_PROPS\
+   (ARRAY_SIZE(cm_default_props) + ARRAY_SIZE(cm_optional_props))
+
 static struct power_supply psy_default = {
.name = battery,
.type = POWER_SUPPLY_TYPE_BATTERY,
-   .properties = default_charger_props,
-   .num_properties = ARRAY_SIZE(default_charger_props),
.get_property = charger_get_property,
.no_thermal = true,
 };
@@ -1484,29 +1462,22 @@ static int charger_manager_probe(struct platform_device 
*pdev)
/* Allocate for psy properties because they may vary */
cm-charger_psy.properties = devm_kzalloc(pdev-dev,
sizeof(enum power_supply_property)
-   * (ARRAY_SIZE(default_charger_props) +
-   NUM_CHARGER_PSY_OPTIONAL), GFP_KERNEL);
+   * CM_NUM_OF_PROPS, GFP_KERNEL);
if (!cm-charger_psy.properties)
return -ENOMEM;
 
-   memcpy(cm-charger_psy.properties, default_charger_props,
-   sizeof(enum power_supply_property) *
-   ARRAY_SIZE(default_charger_props));
-   cm-charger_psy.num_properties = psy_default.num_properties;
-
-   /* Find which optional psy-properties are available */
-   if (!fuel_gauge-get_property(fuel_gauge,
- POWER_SUPPLY_PROP_CHARGE_NOW, val)) {
-   cm-charger_psy.properties[cm-charger_psy.num_properties] =
-   POWER_SUPPLY_PROP_CHARGE_NOW;
-   cm-charger_psy.num_properties++;
-   }
-   if (!fuel_gauge-get_property(fuel_gauge,
- POWER_SUPPLY_PROP_CURRENT_NOW

[PATCH V3 06/11] power: charger-manager: Concentrate scattered power_supply_changed() calls.

2014-12-19 Thread Jonghwa Lee
Current charger-manager calls power_suuply_changed() whenever charging
status is changed. This patch removes seperated power_supply_changed()
use and let it be called at end of try_charger_enable() function which
is called to set charging/discharging.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 drivers/power/charger-manager.c |   18 ++
 1 file changed, 6 insertions(+), 12 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 7bbaef6..d29155d 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -382,8 +382,10 @@ static int try_charger_enable(struct charger_manager *cm, 
bool enable)
}
}
 
-   if (!err)
+   if (!err) {
cm-charger_enabled = enable;
+   power_supply_changed(cm-charger_psy);
+   }
 
return err;
 }
@@ -436,10 +438,8 @@ static void fullbatt_vchk(struct charger_manager *cm)
 
dev_info(cm-dev, VBATT dropped %duV after full-batt\n, diff);
 
-   if (diff  desc-fullbatt_vchkdrop_uV) {
+   if (diff  desc-fullbatt_vchkdrop_uV)
try_charger_restart(cm);
-   power_supply_changed(cm-charger_psy);
-   }
 }
 
 /**
@@ -469,7 +469,6 @@ static int check_charging_duration(struct charger_manager 
*cm)
if (duration  desc-charging_max_duration_ms) {
dev_info(cm-dev, Charging duration exceed %ums\n,
 desc-charging_max_duration_ms);
-   power_supply_changed(cm-charger_psy);
try_charger_enable(cm, false);
ret = true;
}
@@ -480,7 +479,6 @@ static int check_charging_duration(struct charger_manager 
*cm)
is_ext_pwr_online(cm)) {
dev_info(cm-dev, Discharging duration exceed %ums\n,
 desc-discharging_max_duration_ms);
-   power_supply_changed(cm-charger_psy);
try_charger_enable(cm, true);
ret = true;
}
@@ -561,8 +559,7 @@ static bool _cm_monitor(struct charger_manager *cm)
 */
if (temp_alrt) {
cm-emergency_stop = temp_alrt;
-   if (!try_charger_enable(cm, false))
-   power_supply_changed(cm-charger_psy);
+   try_charger_enable(cm, false);
 
/*
 * Check whole charging duration and discharing duration
@@ -587,16 +584,13 @@ static bool _cm_monitor(struct charger_manager *cm)
} else if (!cm-emergency_stop  is_full_charged(cm) 
cm-charger_enabled) {
dev_info(cm-dev, EVENT_HANDLE: Battery Fully Charged\n);
-   power_supply_changed(cm-charger_psy);
-
try_charger_enable(cm, false);
 
fullbatt_vchk(cm);
} else {
cm-emergency_stop = 0;
if (is_ext_pwr_online(cm)) {
-   if (!try_charger_enable(cm, true))
-   power_supply_changed(cm-charger_psy);
+   try_charger_enable(cm, true);
}
}
 
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V3 09/11] power: charger-manager: Not to start charging directly in cable nofitication.

2014-12-19 Thread Jonghwa Lee
This patch prevents direct charging control in cable notification.
It sets only input current limit according to cable type and yields charging
control to be done by cm_monitor() where charging management proceeds.
It may loose few ms to enable charging compared to before, even though it's
more important that charging is enabled always in safe context.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 drivers/power/charger-manager.c |   12 ++--
 1 file changed, 2 insertions(+), 10 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 44cc19a..4f8b0e6 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -849,7 +849,8 @@ static void charger_extcon_work(struct work_struct *work)
cable-min_uA, cable-max_uA);
}
 
-   try_charger_enable(cable-cm, cable-attached);
+   cancel_delayed_work(cm_monitor_work);
+   queue_delayed_work(cm_wq, cm_monitor_work, 0);
 }
 
 /**
@@ -873,15 +874,6 @@ static int charger_extcon_notifier(struct notifier_block 
*self,
cable-attached = event;
 
/*
-* Setup monitoring to check battery state
-* when charger cable is attached.
-*/
-   if (cable-attached  is_polling_required(cable-cm)) {
-   cancel_work_sync(setup_polling);
-   schedule_work(setup_polling);
-   }
-
-   /*
 * Setup work for controlling charger(regulator)
 * according to charger cable.
 */
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V3 01/11] power: charger-manager: Use alarmtimer for battery monitoring in suspend.

2014-12-19 Thread Jonghwa Lee
To guerantee proper charing and managing batteries even in suspend,
charger-manager has used rtc device with rtc framework interface.
However, it is better to use alarmtimer for cleaner and more appropriate
operation.
This patch makes driver to use alamtimer for polling work in suspend and
removes all deprecated codes related with using rtc interface.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 drivers/power/Kconfig |2 +-
 drivers/power/charger-manager.c   |  288 ++---
 include/linux/power/charger-manager.h |   32 +---
 3 files changed, 84 insertions(+), 238 deletions(-)

diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 0108c2a..8ff2511 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -315,7 +315,7 @@ config CHARGER_GPIO
 
 config CHARGER_MANAGER
bool Battery charger manager for multiple chargers
-   depends on REGULATOR  RTC_CLASS
+   depends on REGULATOR
select EXTCON
help
   Say Y to enable charger-manager support, which allows multiple
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index ef8094a..22246b9 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -69,16 +69,11 @@ static LIST_HEAD(cm_list);
 static DEFINE_MUTEX(cm_list_mtx);
 
 /* About in-suspend (suspend-again) monitoring */
-static struct rtc_device *rtc_dev;
-/*
- * Backup RTC alarm
- * Save the wakeup alarm before entering suspend-to-RAM
- */
-static struct rtc_wkalrm rtc_wkalarm_save;
+static struct alarm *cm_timer;
+
 /* Backup RTC alarm time in terms of seconds since 01-01-1970 00:00:00 */
-static unsigned long rtc_wkalarm_save_time;
 static bool cm_suspended;
-static bool cm_rtc_set;
+static bool cm_timer_set;
 static unsigned long cm_suspend_duration_ms;
 
 /* About normal (not suspended) monitoring */
@@ -87,9 +82,6 @@ static unsigned long next_polling; /* Next appointed polling 
time */
 static struct workqueue_struct *cm_wq; /* init at driver add */
 static struct delayed_work cm_monitor_work; /* init at driver add */
 
-/* Global charger-manager description */
-static struct charger_global_desc *g_desc; /* init with setup_charger_manager 
*/
-
 /**
  * is_batt_present - See if the battery presents in place.
  * @cm: the Charger Manager representing the battery.
@@ -1047,10 +1039,13 @@ static bool cm_setup_timer(void)
 {
struct charger_manager *cm;
unsigned int wakeup_ms = UINT_MAX;
-   bool ret = false;
+   int timer_req = 0;
 
-   mutex_lock(cm_list_mtx);
+   if (time_after(next_polling, jiffies))
+   CM_MIN_VALID(wakeup_ms,
+   jiffies_to_msecs(next_polling - jiffies));
 
+   mutex_lock(cm_list_mtx);
list_for_each_entry(cm, cm_list, entry) {
unsigned int fbchk_ms = 0;
 
@@ -1070,162 +1065,38 @@ static bool cm_setup_timer(void)
/* Skip if polling is not required for this CM */
if (!is_polling_required(cm)  !cm-emergency_stop)
continue;
+   timer_req++;
if (cm-desc-polling_interval_ms == 0)
continue;
CM_MIN_VALID(wakeup_ms, cm-desc-polling_interval_ms);
}
-
mutex_unlock(cm_list_mtx);
 
-   if (wakeup_ms  UINT_MAX  wakeup_ms  0) {
-   pr_info(Charger Manager wakeup timer: %u ms\n, wakeup_ms);
-   if (rtc_dev) {
-   struct rtc_wkalrm tmp;
-   unsigned long time, now;
-   unsigned long add = DIV_ROUND_UP(wakeup_ms, 1000);
-
-   /*
-* Set alarm with the polling interval (wakeup_ms)
-* except when rtc_wkalarm_save comes first.
-* However, the alarm time should be NOW +
-* CM_RTC_SMALL or later.
-*/
-   tmp.enabled = 1;
-   rtc_read_time(rtc_dev, tmp.time);
-   rtc_tm_to_time(tmp.time, now);
-   if (add  CM_RTC_SMALL)
-   add = CM_RTC_SMALL;
-   time = now + add;
+   if (timer_req  cm_timer) {
+   ktime_t now, add;
 
-   ret = true;
+   /*
+* Set alarm with the polling interval (wakeup_ms)
+* The alarm time should be NOW + CM_RTC_SMALL or later.
+*/
+   if (wakeup_ms == UINT_MAX ||
+   wakeup_ms  CM_RTC_SMALL * MSEC_PER_SEC)
+   wakeup_ms = 2 * CM_RTC_SMALL * MSEC_PER_SEC;
 
-   if (rtc_wkalarm_save.enabled 
-   rtc_wkalarm_save_time 
-   rtc_wkalarm_save_time  time) {
-   if (rtc_wkalarm_save_time  now + CM_RTC_SMALL

[PATCH V3 04/11] power: charger-manager: Remove deprecated function, cm_notify_event().

2014-12-19 Thread Jonghwa Lee
cm_notify_event() is introduced to get event associated with battery status
externally, but no one had been used. Moreover it makes charger manager
driver more complicated. This patch tries to drop the function and all data
related to simplify the driver.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 .../bindings/power_supply/charger-manager.txt  |1 -
 drivers/power/charger-manager.c|  196 +---
 include/linux/power/charger-manager.h  |   19 +-
 3 files changed, 8 insertions(+), 208 deletions(-)

diff --git a/Documentation/devicetree/bindings/power_supply/charger-manager.txt 
b/Documentation/devicetree/bindings/power_supply/charger-manager.txt
index ec4fe9d..827576e 100644
--- a/Documentation/devicetree/bindings/power_supply/charger-manager.txt
+++ b/Documentation/devicetree/bindings/power_supply/charger-manager.txt
@@ -39,7 +39,6 @@ Example :
cm-poll-mode = 1;
cm-poll-interval = 3;
 
-   cm-fullbatt-vchkdrop-ms = 3;
cm-fullbatt-vchkdrop-volt = 15;
cm-fullbatt-soc = 100;
 
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 8c76bce..5482661 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -410,25 +410,18 @@ static int try_charger_restart(struct charger_manager *cm)
 
 /**
  * fullbatt_vchk - Check voltage drop some times after FULL event.
- * @work: the work_struct appointing the function
  *
- * If a user has designated fullbatt_vchkdrop_ms/uV values with
+ * If a user has designated fullbatt_vchkdrop_uV values with
  * charger_desc, Charger Manager checks voltage drop after the battery
  * FULL event. It checks whether the voltage has dropped more than
  * fullbatt_vchkdrop_uV by calling this function after fullbatt_vchkrop_ms.
  */
-static void fullbatt_vchk(struct work_struct *work)
+static void fullbatt_vchk(struct charger_manager *cm)
 {
-   struct delayed_work *dwork = to_delayed_work(work);
-   struct charger_manager *cm = container_of(dwork,
-   struct charger_manager, fullbatt_vchk_work);
struct charger_desc *desc = cm-desc;
int batt_uV, err, diff;
 
-   /* remove the appointment for fullbatt_vchk */
-   cm-fullbatt_vchk_jiffies_at = 0;
-
-   if (!desc-fullbatt_vchkdrop_uV || !desc-fullbatt_vchkdrop_ms)
+   if (!desc-fullbatt_vchkdrop_uV)
return;
 
err = get_batt_uV(cm, batt_uV);
@@ -585,7 +578,7 @@ static bool _cm_monitor(struct charger_manager *cm)
 */
} else if (!cm-emergency_stop  is_ext_pwr_online(cm) 
!cm-charger_enabled) {
-   fullbatt_vchk(cm-fullbatt_vchk_work.work);
+   fullbatt_vchk(cm);
 
/*
 * Check whether fully charged state to protect overcharge
@@ -598,7 +591,7 @@ static bool _cm_monitor(struct charger_manager *cm)
 
try_charger_enable(cm, false);
 
-   fullbatt_vchk(cm-fullbatt_vchk_work.work);
+   fullbatt_vchk(cm);
} else {
cm-emergency_stop = 0;
if (is_ext_pwr_online(cm)) {
@@ -700,66 +693,6 @@ static void cm_monitor_poller(struct work_struct *work)
schedule_work(setup_polling);
 }
 
-/**
- * fullbatt_handler - Event handler for CM_EVENT_BATT_FULL
- * @cm: the Charger Manager representing the battery.
- */
-static void fullbatt_handler(struct charger_manager *cm)
-{
-   struct charger_desc *desc = cm-desc;
-
-   if (!desc-fullbatt_vchkdrop_uV || !desc-fullbatt_vchkdrop_ms)
-   goto out;
-
-   if (cm_suspended)
-   device_set_wakeup_capable(cm-dev, true);
-
-   mod_delayed_work(cm_wq, cm-fullbatt_vchk_work,
-msecs_to_jiffies(desc-fullbatt_vchkdrop_ms));
-   cm-fullbatt_vchk_jiffies_at = jiffies + msecs_to_jiffies(
-  desc-fullbatt_vchkdrop_ms);
-
-   if (cm-fullbatt_vchk_jiffies_at == 0)
-   cm-fullbatt_vchk_jiffies_at = 1;
-
-out:
-   dev_info(cm-dev, EVENT_HANDLE: Battery Fully Charged\n);
-   power_supply_changed(cm-charger_psy);
-}
-
-/**
- * battout_handler - Event handler for CM_EVENT_BATT_OUT
- * @cm: the Charger Manager representing the battery.
- */
-static void battout_handler(struct charger_manager *cm)
-{
-   if (cm_suspended)
-   device_set_wakeup_capable(cm-dev, true);
-
-   if (!is_batt_present(cm)) {
-   dev_emerg(cm-dev, Battery Pulled Out!\n);
-   power_supply_changed(cm-charger_psy);
-   } else {
-   power_supply_changed(cm-charger_psy);
-   }
-}
-
-/**
- * misc_event_handler - Handler for other evnets
- * @cm: the Charger Manager representing the battery.
- * @type: the Charger Manager representing the battery.
- */
-static void misc_event_handler(struct charger_manager *cm

[PATCH] arm64: psci: Support generic pm suspend withtout CPUIDLE subsystem's help.

2014-12-18 Thread Jonghwa Lee
Current psci's cpu_suspend callback can be used only when common cpu idle
configuration is enabled. However, it's also needed for system which only
uses generic pm suspend not cpu idle. This patch modifies psci driver to
support both of cases.

Signed-off-by: Jonghwa Lee 
---
 arch/arm64/kernel/psci.c |   41 +
 1 file changed, 29 insertions(+), 12 deletions(-)

diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c
index f1dbca7..06d5527 100644
--- a/arch/arm64/kernel/psci.c
+++ b/arch/arm64/kernel/psci.c
@@ -35,6 +35,13 @@
 #define PSCI_POWER_STATE_TYPE_STANDBY  0
 #define PSCI_POWER_STATE_TYPE_POWER_DOWN   1
 
+enum psci_affinity_level {
+   PSCI_AFFINITY_LEVEL_0,
+   PSCI_AFFINITY_LEVEL_1,
+   PSCI_AFFINITY_LEVEL_2,
+   PSCI_AFFINITY_LEVEL_3,
+};
+
 struct psci_power_state {
u16 id;
u8  type;
@@ -513,27 +520,37 @@ static int psci_suspend_finisher(unsigned long index)
 {
struct psci_power_state *state = __this_cpu_read(psci_power_state);
 
+   /* Generic PM suspend without CPUIDLE functionality */
+   if (!state) {
+   struct psci_power_state s = {
+   .affinity_level = PSCI_AFFINITY_LEVEL_3,
+   .type = PSCI_POWER_STATE_TYPE_POWER_DOWN,
+   };
+   return psci_ops.cpu_suspend(s, virt_to_phys(cpu_resume));
+   }
+
return psci_ops.cpu_suspend(state[index - 1],
virt_to_phys(cpu_resume));
 }
 
 static int __maybe_unused cpu_psci_cpu_suspend(unsigned long index)
 {
-   int ret;
struct psci_power_state *state = __this_cpu_read(psci_power_state);
-   /*
-* idle state index 0 corresponds to wfi, should never be called
-* from the cpu_suspend operations
-*/
-   if (WARN_ON_ONCE(!index))
-   return -EINVAL;
 
-   if (state[index - 1].type == PSCI_POWER_STATE_TYPE_STANDBY)
-   ret = psci_ops.cpu_suspend(state[index - 1], 0);
-   else
-   ret = __cpu_suspend(index, psci_suspend_finisher);
+   if (state) {
+   if (WARN_ON_ONCE(!index))
+   return -EINVAL;
+
+   /*
+* If idle state initialization is successfully done,
+* idle state index 0 corresponds to wfi, should never be
+* called from the cpu_suspend operations
+*/
+   if (state[index - 1].type == PSCI_POWER_STATE_TYPE_STANDBY)
+   return psci_ops.cpu_suspend(state[index - 1], 0);
+   }
 
-   return ret;
+   return __cpu_suspend(index, psci_suspend_finisher);
 }
 
 const struct cpu_operations cpu_psci_ops = {
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH RESEND v2 02/10] power: charger-manager: Use power_supply_changed() not private uevent.

2014-12-18 Thread Jonghwa Lee
Whenever battery status is changed, charger manager tries to trigger uevent
through private interface. This patch modifies it to use power_supply_changed()
since it belongs to power supply subsystem.

Signed-off-by: Jonghwa Lee 
---
 drivers/power/charger-manager.c |   91 +--
 1 file changed, 11 insertions(+), 80 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index b4b101c..33a1a4d 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -28,18 +28,6 @@
 #include 
 #include 
 
-static const char * const default_event_names[] = {
-   [CM_EVENT_UNKNOWN] = "Unknown",
-   [CM_EVENT_BATT_FULL] = "Battery Full",
-   [CM_EVENT_BATT_IN] = "Battery Inserted",
-   [CM_EVENT_BATT_OUT] = "Battery Pulled Out",
-   [CM_EVENT_BATT_OVERHEAT] = "Battery Overheat",
-   [CM_EVENT_BATT_COLD] = "Battery Cold",
-   [CM_EVENT_EXT_PWR_IN_OUT] = "External Power Attach/Detach",
-   [CM_EVENT_CHG_START_STOP] = "Charging Start/Stop",
-   [CM_EVENT_OTHERS] = "Other battery events"
-};
-
 /*
  * Regard CM_JIFFIES_SMALL jiffies is small enough to ignore for
  * delayed works so that we can run delayed works with CM_JIFFIES_SMALL
@@ -56,8 +44,6 @@ static const char * const default_event_names[] = {
  */
 #define CM_RTC_SMALL   (2)
 
-#define UEVENT_BUF_SIZE32
-
 static LIST_HEAD(cm_list);
 static DEFINE_MUTEX(cm_list_mtx);
 
@@ -423,61 +409,6 @@ static int try_charger_restart(struct charger_manager *cm)
 }
 
 /**
- * uevent_notify - Let users know something has changed.
- * @cm: the Charger Manager representing the battery.
- * @event: the event string.
- *
- * If @event is null, it implies that uevent_notify is called
- * by resume function. When called in the resume function, cm_suspended
- * should be already reset to false in order to let uevent_notify
- * notify the recent event during the suspend to users. While
- * suspended, uevent_notify does not notify users, but tracks
- * events so that uevent_notify can notify users later after resumed.
- */
-static void uevent_notify(struct charger_manager *cm, const char *event)
-{
-   static char env_str[UEVENT_BUF_SIZE + 1] = "";
-   static char env_str_save[UEVENT_BUF_SIZE + 1] = "";
-
-   if (cm_suspended) {
-   /* Nothing in suspended-event buffer */
-   if (env_str_save[0] == 0) {
-   if (!strncmp(env_str, event, UEVENT_BUF_SIZE))
-   return; /* status not changed */
-   strncpy(env_str_save, event, UEVENT_BUF_SIZE);
-   return;
-   }
-
-   if (!strncmp(env_str_save, event, UEVENT_BUF_SIZE))
-   return; /* Duplicated. */
-   strncpy(env_str_save, event, UEVENT_BUF_SIZE);
-   return;
-   }
-
-   if (event == NULL) {
-   /* No messages pending */
-   if (!env_str_save[0])
-   return;
-
-   strncpy(env_str, env_str_save, UEVENT_BUF_SIZE);
-   kobject_uevent(>dev->kobj, KOBJ_CHANGE);
-   env_str_save[0] = 0;
-
-   return;
-   }
-
-   /* status not changed */
-   if (!strncmp(env_str, event, UEVENT_BUF_SIZE))
-   return;
-
-   /* save the status and notify the update */
-   strncpy(env_str, event, UEVENT_BUF_SIZE);
-   kobject_uevent(>dev->kobj, KOBJ_CHANGE);
-
-   dev_info(cm->dev, "%s\n", event);
-}
-
-/**
  * fullbatt_vchk - Check voltage drop some times after "FULL" event.
  * @work: the work_struct appointing the function
  *
@@ -514,7 +445,7 @@ static void fullbatt_vchk(struct work_struct *work)
 
if (diff > desc->fullbatt_vchkdrop_uV) {
try_charger_restart(cm);
-   uevent_notify(cm, "Recharging");
+   power_supply_changed(>charger_psy);
}
 }
 
@@ -545,7 +476,7 @@ static int check_charging_duration(struct charger_manager 
*cm)
if (duration > desc->charging_max_duration_ms) {
dev_info(cm->dev, "Charging duration exceed %ums\n",
 desc->charging_max_duration_ms);
-   uevent_notify(cm, "Discharging");
+   power_supply_changed(>charger_psy);
try_charger_enable(cm, false);
ret = true;
}
@@ -556,7 +487,7 @@ static int check_charging_duration(struct charger_manager 
*cm)
is_ext_pwr_online(cm)) {
dev_info(cm->dev, "Discharging duration exceed %ums\n",
 desc->discharging_m

[PATCH RESEND v2 07/10] power: charger-manager: Make chraging decision focusing on battery status.

2014-12-18 Thread Jonghwa Lee
In cm_monitor() where charging management starts, it checks various charging
condition sequentially to decide next charging operation. However, as it
follows sequential process, cascaded IF statements, it does some duplicated
jobs which is already done in previous stage. It results delay in decision
making. And moreover, starting point of charing is spreaded all around, so
it makes maintain codes and debugging difficult.

Both of problems mentioned above becomes clean if it manages battery charging
focusing on battery status not following sequential condition checking.
Now, cm_monitor() moves battery state diagram and does optimal operation for
current state. As a result, it reduces whole monitoring time almost in half.

Signed-off-by: Jonghwa Lee 
---
 drivers/power/charger-manager.c   |  177 +++--
 include/linux/power/charger-manager.h |3 +
 2 files changed, 62 insertions(+), 118 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 172dfe5..065b92a 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -249,6 +249,19 @@ static bool is_full_charged(struct charger_manager *cm)
if (!fuel_gauge)
return false;
 
+   /* Full, if it's over the fullbatt voltage */
+   if (desc->fullbatt_uV > 0) {
+   ret = get_batt_uV(cm, );
+   if (!ret) {
+   /* Battery is already full, checks voltage drop. */
+   if (cm->battery_status == POWER_SUPPLY_STATUS_FULL
+   && desc->fullbatt_vchkdrop_uV)
+   uV += desc->fullbatt_vchkdrop_uV;
+   if (uV >= desc->fullbatt_uV)
+   return true;
+   }
+   }
+
if (desc->fullbatt_full_capacity > 0) {
val.intval = 0;
 
@@ -259,13 +272,6 @@ static bool is_full_charged(struct charger_manager *cm)
return true;
}
 
-   /* Full, if it's over the fullbatt voltage */
-   if (desc->fullbatt_uV > 0) {
-   ret = get_batt_uV(cm, );
-   if (!ret && uV >= desc->fullbatt_uV)
-   return true;
-   }
-
/* Full, if the capacity is more than fullbatt_soc */
if (desc->fullbatt_soc > 0) {
val.intval = 0;
@@ -376,67 +382,13 @@ static int try_charger_enable(struct charger_manager *cm, 
bool enable)
}
}
 
-   if (!err) {
+   if (!err)
cm->charger_enabled = enable;
-   power_supply_changed(>charger_psy);
-   }
 
return err;
 }
 
 /**
- * try_charger_restart - Restart charging.
- * @cm: the Charger Manager representing the battery.
- *
- * Restart charging by turning off and on the charger.
- */
-static int try_charger_restart(struct charger_manager *cm)
-{
-   int err;
-
-   if (cm->emergency_stop)
-   return -EAGAIN;
-
-   err = try_charger_enable(cm, false);
-   if (err)
-   return err;
-
-   return try_charger_enable(cm, true);
-}
-
-/**
- * fullbatt_vchk - Check voltage drop some times after "FULL" event.
- *
- * If a user has designated "fullbatt_vchkdrop_uV" values with
- * charger_desc, Charger Manager checks voltage drop after the battery
- * "FULL" event. It checks whether the voltage has dropped more than
- * fullbatt_vchkdrop_uV by calling this function after fullbatt_vchkrop_ms.
- */
-static void fullbatt_vchk(struct charger_manager *cm)
-{
-   struct charger_desc *desc = cm->desc;
-   int batt_uV, err, diff;
-
-   if (!desc->fullbatt_vchkdrop_uV)
-   return;
-
-   err = get_batt_uV(cm, _uV);
-   if (err) {
-   dev_err(cm->dev, "%s: get_batt_uV error(%d)\n", __func__, err);
-   return;
-   }
-
-   diff = desc->fullbatt_uV - batt_uV;
-   if (diff < 0)
-   return;
-
-   dev_info(cm->dev, "VBATT dropped %duV after full-batt\n", diff);
-
-   if (diff > desc->fullbatt_vchkdrop_uV)
-   try_charger_restart(cm);
-}
-
-/**
  * check_charging_duration - Monitor charging/discharging duration
  * @cm: the Charger Manager representing the battery.
  *
@@ -463,17 +415,14 @@ static int check_charging_duration(struct charger_manager 
*cm)
if (duration > desc->charging_max_duration_ms) {
dev_info(cm->dev, "Charging duration exceed %ums\n",
 desc->charging_max_duration_ms);
-   try_charger_enable(cm, false);
ret = true;
}
-   } else if (is_ext_pwr_online(cm) && !cm->charger_enabled) {
+   } else if (c

[PATCH RESEND v2 01/10] power: charger-manager: Use thermal subsystem interface only to get temperature.

2014-12-18 Thread Jonghwa Lee
It drops the way of using power_supply interface to reference battery's
temperature. Then it tries to use thermal subsystem's only. This makes driver
more simple and also can remove ifdeferies.

Signed-off-by: Jonghwa Lee 
---
 drivers/power/Kconfig |1 +
 drivers/power/charger-manager.c   |  113 -
 include/linux/power/charger-manager.h |3 +-
 3 files changed, 28 insertions(+), 89 deletions(-)

diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 8ff2511..115d153 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -317,6 +317,7 @@ config CHARGER_MANAGER
bool "Battery charger manager for multiple chargers"
depends on REGULATOR
select EXTCON
+   select THERMAL
help
   Say Y to enable charger-manager support, which allows multiple
   chargers attached to a battery and multiple batteries attached to a
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 22246b9..b4b101c 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -28,13 +28,6 @@
 #include 
 #include 
 
-/*
- * Default termperature threshold for charging.
- * Every temperature units are in tenth of centigrade.
- */
-#define CM_DEFAULT_RECHARGE_TEMP_DIFF  50
-#define CM_DEFAULT_CHARGE_TEMP_MAX 500
-
 static const char * const default_event_names[] = {
[CM_EVENT_UNKNOWN] = "Unknown",
[CM_EVENT_BATT_FULL] = "Battery Full",
@@ -572,40 +565,18 @@ static int check_charging_duration(struct charger_manager 
*cm)
return ret;
 }
 
-static int cm_get_battery_temperature_by_psy(struct charger_manager *cm,
-   int *temp)
-{
-   struct power_supply *fuel_gauge;
-
-   fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge);
-   if (!fuel_gauge)
-   return -ENODEV;
-
-   return fuel_gauge->get_property(fuel_gauge,
-   POWER_SUPPLY_PROP_TEMP,
-   (union power_supply_propval *)temp);
-}
-
 static int cm_get_battery_temperature(struct charger_manager *cm,
int *temp)
 {
int ret;
 
-   if (!cm->desc->measure_battery_temp)
+   if (!cm->tzd_batt)
return -ENODEV;
 
-#ifdef CONFIG_THERMAL
-   if (cm->tzd_batt) {
-   ret = thermal_zone_get_temp(cm->tzd_batt, (unsigned long 
*)temp);
-   if (!ret)
-   /* Calibrate temperature unit */
-   *temp /= 100;
-   } else
-#endif
-   {
-   /* if-else continued from CONFIG_THERMAL */
-   ret = cm_get_battery_temperature_by_psy(cm, temp);
-   }
+   ret = thermal_zone_get_temp(cm->tzd_batt, (unsigned long *)temp);
+   if (!ret)
+   /* Calibrate temperature unit */
+   *temp /= 100;
 
return ret;
 }
@@ -623,7 +594,7 @@ static int cm_check_thermal_status(struct charger_manager 
*cm)
 * occur hazadous result. We have to handle it
 * depending on battery type.
 */
-   dev_err(cm->dev, "Failed to get battery temperature\n");
+   dev_dbg(cm->dev, "Failed to get battery temperature\n");
return 0;
}
 
@@ -1007,12 +978,11 @@ static enum power_supply_property 
default_charger_props[] = {
POWER_SUPPLY_PROP_CAPACITY,
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_CHARGE_FULL,
+   POWER_SUPPLY_PROP_TEMP,
/*
 * Optional properties are:
 * POWER_SUPPLY_PROP_CHARGE_NOW,
 * POWER_SUPPLY_PROP_CURRENT_NOW,
-* POWER_SUPPLY_PROP_TEMP, and
-* POWER_SUPPLY_PROP_TEMP_AMBIENT,
 */
 };
 
@@ -1417,49 +1387,6 @@ err:
return ret;
 }
 
-static int cm_init_thermal_data(struct charger_manager *cm,
-   struct power_supply *fuel_gauge)
-{
-   struct charger_desc *desc = cm->desc;
-   union power_supply_propval val;
-   int ret;
-
-   /* Verify whether fuel gauge provides battery temperature */
-   ret = fuel_gauge->get_property(fuel_gauge,
-   POWER_SUPPLY_PROP_TEMP, );
-
-   if (!ret) {
-   cm->charger_psy.properties[cm->charger_psy.num_properties] =
-   POWER_SUPPLY_PROP_TEMP;
-   cm->charger_psy.num_properties++;
-   cm->desc->measure_battery_temp = true;
-   }
-#ifdef CONFIG_THERMAL
-   if (ret && desc->thermal_zone) {
-   cm->tzd_batt =
-   thermal_zone_get_zone_by_name(desc->thermal_zone);
-   if (IS_ERR(cm->tzd_batt))
-   return PTR_ERR(cm->tzd_ba

[PATCH RESEND v2 06/10] power: charger-manager: Get external power souce information only from EXTCON.

2014-12-18 Thread Jonghwa Lee
When charger-manager checks whether external power source is available,
it gets information from charger IC driver. However, it's not correct source,
charger IC doesn't have responsibilty to give cable connection status.
The charger-manager already gets cable information from EXTCON susbsystem,
so it can re-use it.

Signed-off-by: Jonghwa Lee 
---
 drivers/power/charger-manager.c |   34 ++
 1 file changed, 14 insertions(+), 20 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index bb44588..172dfe5 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -115,34 +115,28 @@ static bool is_batt_present(struct charger_manager *cm)
  * is_ext_pwr_online - See if an external power source is attached to charge
  * @cm: the Charger Manager representing the battery.
  *
- * Returns true if at least one of the chargers of the battery has an external
- * power source attached to charge the battery regardless of whether it is
- * actually charging or not.
+ * Returns true if there is external power source.
+ * Cable connection information is only obtained by EXTCON class notification.
  */
 static bool is_ext_pwr_online(struct charger_manager *cm)
 {
-   union power_supply_propval val;
-   struct power_supply *psy;
-   bool online = false;
-   int i, ret;
 
-   /* If at least one of them has one, it's yes. */
-   for (i = 0; cm->desc->psy_charger_stat[i]; i++) {
-   psy = power_supply_get_by_name(cm->desc->psy_charger_stat[i]);
-   if (!psy) {
-   dev_err(cm->dev, "Cannot find power supply \"%s\"\n",
-   cm->desc->psy_charger_stat[i]);
-   continue;
-   }
+   struct charger_desc *desc = cm->desc;
+   struct charger_regulator *regulators = desc->charger_regulators;
+   struct charger_cable *cables;
+   int i, j, num_cables;
 
-   ret = psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, );
-   if (ret == 0 && val.intval) {
-   online = true;
-   break;
+   /* If at least one of them has one, it's yes. */
+   for (i = 0; i < desc->num_charger_regulators; i++) {
+   cables = regulators[i].cables;
+   num_cables = regulators[i].num_cables;
+   for (j = 0; j < num_cables; j++) {
+   if (cables[j].attached)
+   return true;
}
}
 
-   return online;
+   return false;
 }
 
 /**
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH RESEND V2 0/10] Improve charger manager driver for optimized operation.

2014-12-18 Thread Jonghwa Lee
After charger manager's initially introduced, it has kept its codes without any
big change. However, the charger manager working operation isn't optimized and
it also has unused codes and non-generic interface. This series tries to make
charger manager more generic and maintainable with some fixes.

[Changes in V2]
- Rebase patch series on latest of battery-2.6.git.
- Seperate 'power: charger-manager: Rearrange data and monitor ~' patch into
  several patches depends on its purpose.
- Add 2 patches related with polling mode.

Jonghwa Lee (10):
  power: charger-manager: Use thermal subsystem interface only to get
temperature.
  power: charger-manager: Use power_supply_changed() not private
uevent.
  power: charger-manager: Remove deprecated function,
cm_notify_event().
  power: charger-manager: Fix to use CHARGE_NOW/FULL property
correctly.
  power: charger-manager: Concentrate scattered power_supply_changed()
calls.
  power: charger-manager: Get external power souce information only
from EXTCON.
  power: charger-manager: Make chraging decision focusing on battery
status.
  power: charger-manager: Not to start charging directly in cable
nofitication.
  power: charger-manager: Support different polling mode for sleep
state.
  power: charger-manager: Support to change polling rate in runtime.

 .../bindings/power_supply/charger-manager.txt  |1 -
 drivers/power/Kconfig  |1 +
 drivers/power/charger-manager.c|  758 ++--
 include/linux/power/charger-manager.h  |   34 +-
 4 files changed, 219 insertions(+), 575 deletions(-)

-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH RESEND v2 04/10] power: charger-manager: Fix to use CHARGE_NOW/FULL property correctly.

2014-12-18 Thread Jonghwa Lee
The POWER_SUPPLY_CHARGE_NOW/FULL property reflects battery's charges
in uAh unit, but charger-manager has been used it wrongly. This patch
makes it to use those propeties correctly and change to be optional.

Signed-off-by: Jonghwa Lee 
---
 drivers/power/charger-manager.c |   85 +--
 1 file changed, 28 insertions(+), 57 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 64fdaaf..687f109 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -796,35 +796,13 @@ static int charger_get_property(struct power_supply *psy,
val->intval = 0;
break;
case POWER_SUPPLY_PROP_CHARGE_FULL:
-   if (is_full_charged(cm))
-   val->intval = 1;
-   else
-   val->intval = 0;
-   ret = 0;
-   break;
case POWER_SUPPLY_PROP_CHARGE_NOW:
-   if (is_charging(cm)) {
-   fuel_gauge = power_supply_get_by_name(
-   cm->desc->psy_fuel_gauge);
-   if (!fuel_gauge) {
-   ret = -ENODEV;
-   break;
-   }
-
-   ret = fuel_gauge->get_property(fuel_gauge,
-   POWER_SUPPLY_PROP_CHARGE_NOW,
-   val);
-   if (ret) {
-   val->intval = 1;
-   ret = 0;
-   } else {
-   /* If CHARGE_NOW is supplied, use it */
-   val->intval = (val->intval > 0) ?
-   val->intval : 1;
-   }
-   } else {
-   val->intval = 0;
+   fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge);
+   if (!fuel_gauge) {
+   ret = -ENODEV;
+   break;
}
+   ret = fuel_gauge->get_property(fuel_gauge, psp, val);
break;
default:
return -EINVAL;
@@ -832,8 +810,7 @@ static int charger_get_property(struct power_supply *psy,
return ret;
 }
 
-#define NUM_CHARGER_PSY_OPTIONAL   (4)
-static enum power_supply_property default_charger_props[] = {
+static enum power_supply_property cm_default_props[] = {
/* Guaranteed to provide */
POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_HEALTH,
@@ -841,20 +818,21 @@ static enum power_supply_property default_charger_props[] 
= {
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_CAPACITY,
POWER_SUPPLY_PROP_ONLINE,
-   POWER_SUPPLY_PROP_CHARGE_FULL,
POWER_SUPPLY_PROP_TEMP,
-   /*
-* Optional properties are:
-* POWER_SUPPLY_PROP_CHARGE_NOW,
-* POWER_SUPPLY_PROP_CURRENT_NOW,
-*/
 };
 
+static enum power_supply_property cm_optional_props[] = {
+   POWER_SUPPLY_PROP_CHARGE_FULL,
+   POWER_SUPPLY_PROP_CHARGE_NOW,
+   POWER_SUPPLY_PROP_CURRENT_NOW,
+};
+
+#define CM_NUM_OF_PROPS\
+   (ARRAY_SIZE(cm_default_props) + ARRAY_SIZE(cm_optional_props))
+
 static struct power_supply psy_default = {
.name = "battery",
.type = POWER_SUPPLY_TYPE_BATTERY,
-   .properties = default_charger_props,
-   .num_properties = ARRAY_SIZE(default_charger_props),
.get_property = charger_get_property,
.no_thermal = true,
 };
@@ -1484,29 +1462,22 @@ static int charger_manager_probe(struct platform_device 
*pdev)
/* Allocate for psy properties because they may vary */
cm->charger_psy.properties = devm_kzalloc(>dev,
sizeof(enum power_supply_property)
-   * (ARRAY_SIZE(default_charger_props) +
-   NUM_CHARGER_PSY_OPTIONAL), GFP_KERNEL);
+   * CM_NUM_OF_PROPS, GFP_KERNEL);
if (!cm->charger_psy.properties)
return -ENOMEM;
 
-   memcpy(cm->charger_psy.properties, default_charger_props,
-   sizeof(enum power_supply_property) *
-   ARRAY_SIZE(default_charger_props));
-   cm->charger_psy.num_properties = psy_default.num_properties;
-
-   /* Find which optional psy-properties are available */
-   if (!fuel_gauge->get_property(fuel_gauge,
- POWER_SUPPLY_PROP_CHARGE_NOW, )) {
-   cm->charger_psy.properties[cm->charger_psy.num_properties] =
-   POWER_SUPPLY_PROP_CHARGE_NOW;
-   cm->charger_psy.num_properties++;
-   }
-   if (!fuel_gauge->get_propert

[PATCH RESEND v2 08/10] power: charger-manager: Not to start charging directly in cable nofitication.

2014-12-18 Thread Jonghwa Lee
This patch prevents direct charging control in cable notification.
It sets only input current limit according to cable type and yields charging
control to be done by cm_monitor() where charging management proceeds.
It may loose few ms to enable charging compared to before, even though it's
more important that charging is enabled always in safe context.

Signed-off-by: Jonghwa Lee 
---
 drivers/power/charger-manager.c |   12 ++--
 1 file changed, 2 insertions(+), 10 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 065b92a..1ccb9be 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -849,7 +849,8 @@ static void charger_extcon_work(struct work_struct *work)
cable->min_uA, cable->max_uA);
}
 
-   try_charger_enable(cable->cm, cable->attached);
+   cancel_delayed_work(_monitor_work);
+   queue_delayed_work(cm_wq, _monitor_work, 0);
 }
 
 /**
@@ -873,15 +874,6 @@ static int charger_extcon_notifier(struct notifier_block 
*self,
cable->attached = event;
 
/*
-* Setup monitoring to check battery state
-* when charger cable is attached.
-*/
-   if (cable->attached && is_polling_required(cable->cm)) {
-   cancel_work_sync(_polling);
-   schedule_work(_polling);
-   }
-
-   /*
 * Setup work for controlling charger(regulator)
 * according to charger cable.
 */
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH RESEND v2 05/10] power: charger-manager: Concentrate scattered power_supply_changed() calls.

2014-12-18 Thread Jonghwa Lee
Current charger-manager calls power_suuply_changed() whenever charging
status is changed. This patch removes seperated power_supply_changed()
use and let it be called at end of try_charger_enable() function which
is called to set charging/discharging.

Signed-off-by: Jonghwa Lee 
---
 drivers/power/charger-manager.c |   18 ++
 1 file changed, 6 insertions(+), 12 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 687f109..bb44588 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -382,8 +382,10 @@ static int try_charger_enable(struct charger_manager *cm, 
bool enable)
}
}
 
-   if (!err)
+   if (!err) {
cm->charger_enabled = enable;
+   power_supply_changed(>charger_psy);
+   }
 
return err;
 }
@@ -436,10 +438,8 @@ static void fullbatt_vchk(struct charger_manager *cm)
 
dev_info(cm->dev, "VBATT dropped %duV after full-batt\n", diff);
 
-   if (diff > desc->fullbatt_vchkdrop_uV) {
+   if (diff > desc->fullbatt_vchkdrop_uV)
try_charger_restart(cm);
-   power_supply_changed(>charger_psy);
-   }
 }
 
 /**
@@ -469,7 +469,6 @@ static int check_charging_duration(struct charger_manager 
*cm)
if (duration > desc->charging_max_duration_ms) {
dev_info(cm->dev, "Charging duration exceed %ums\n",
 desc->charging_max_duration_ms);
-   power_supply_changed(>charger_psy);
try_charger_enable(cm, false);
ret = true;
}
@@ -480,7 +479,6 @@ static int check_charging_duration(struct charger_manager 
*cm)
is_ext_pwr_online(cm)) {
dev_info(cm->dev, "Discharging duration exceed %ums\n",
 desc->discharging_max_duration_ms);
-   power_supply_changed(>charger_psy);
try_charger_enable(cm, true);
ret = true;
}
@@ -561,8 +559,7 @@ static bool _cm_monitor(struct charger_manager *cm)
 */
if (temp_alrt) {
cm->emergency_stop = temp_alrt;
-   if (!try_charger_enable(cm, false))
-   power_supply_changed(>charger_psy);
+   try_charger_enable(cm, false);
 
/*
 * Check whole charging duration and discharing duration
@@ -587,16 +584,13 @@ static bool _cm_monitor(struct charger_manager *cm)
} else if (!cm->emergency_stop && is_full_charged(cm) &&
cm->charger_enabled) {
dev_info(cm->dev, "EVENT_HANDLE: Battery Fully Charged\n");
-   power_supply_changed(>charger_psy);
-
try_charger_enable(cm, false);
 
fullbatt_vchk(cm);
} else {
cm->emergency_stop = 0;
if (is_ext_pwr_online(cm)) {
-   if (!try_charger_enable(cm, true))
-   power_supply_changed(>charger_psy);
+   try_charger_enable(cm, true);
}
}
 
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH RESEND v2 10/10] power: charger-manager: Support to change polling rate in runtime.

2014-12-18 Thread Jonghwa Lee
Add 'polling_ms' sysfs node to change charger-manager's monitoring rate
in runtime. It can set only bigger than 2 jiffies (for 200 HZ system it
is 10 msecs.) as it's allowed for minimum poling rate in previous.
It resets poller and re-configure polling rate based on new input if next
polling time is far enough. Otherwise, it just waits expiration of timer
and new polling rate will affects the next scheduling.

Signed-off-by: Jonghwa Lee 
---
 drivers/power/charger-manager.c |   62 +++
 1 file changed, 62 insertions(+)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 0a0834f..7a007f4 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -1054,6 +1054,63 @@ static ssize_t charger_externally_control_store(struct 
device *dev,
return count;
 }
 
+static ssize_t show_polling_ms(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   struct charger_manager *cm;
+   ssize_t len;
+
+   list_for_each_entry(cm, _list, entry)
+   if (cm->charger_psy.dev == dev)
+   break;
+
+   if (cm->charger_psy.dev != dev)
+   return -EINVAL;
+
+   len = sprintf(buf, "%d\n", cm->desc->polling_interval_ms);
+
+   return len;
+}
+
+static ssize_t store_polling_ms(struct device *dev,
+   struct device_attribute *attr, const char *buf,
+   size_t count)
+{
+   struct charger_manager *cm;
+   int polling_ms;
+   int ret;
+
+   ret = sscanf(buf, "%d", _ms);
+   if (ret < 0 )
+   return -EINVAL;
+
+   if (polling_ms < CM_JIFFIES_SMALL * MSEC_PER_SEC / HZ)
+   return -EINVAL;
+
+   list_for_each_entry(cm, _list, entry)
+   if (cm->charger_psy.dev == dev)
+   break;
+
+   if (cm->charger_psy.dev != dev)
+   return -ENODEV;
+
+   cm->desc->polling_interval_ms = polling_ms;
+
+   pr_info("Polling interval's changed to %u ms.\n",
+   cm->desc->polling_interval_ms);
+
+   if (next_polling - jiffies >
+   msecs_to_jiffies(cm->desc->polling_interval_ms)) {
+   pr_info("Reset poller now... \n");
+   cancel_delayed_work(_monitor_work);
+   schedule_work(_polling);
+   }
+
+   return count;
+}
+
+static DEVICE_ATTR(polling_ms, 0644, show_polling_ms, store_polling_ms);
+
 /**
  * charger_manager_register_sysfs - Register sysfs entry for each charger
  * @cm: the Charger Manager representing the battery.
@@ -1077,6 +1134,11 @@ static int charger_manager_register_sysfs(struct 
charger_manager *cm)
int ret = 0;
int i;
 
+   /* Create polling_ms sysfs node */
+   ret = device_create_file(cm->charger_psy.dev, _attr_polling_ms);
+   if (ret)
+   pr_err("Failed to create poling_ms sysfs node (%d)\n", ret);
+
/* Create sysfs entry to control charger(regulator) */
for (i = 0; i < desc->num_charger_regulators; i++) {
charger = >charger_regulators[i];
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH RESEND v2 03/10] power: charger-manager: Remove deprecated function, cm_notify_event().

2014-12-18 Thread Jonghwa Lee
cm_notify_event() is introduced to get event associated with battery status
externally, but no one had been used. Moreover it makes charger manager
driver more complicated. This patch tries to drop the function and all data
related to simplify the driver.

Signed-off-by: Jonghwa Lee 
---
 .../bindings/power_supply/charger-manager.txt  |1 -
 drivers/power/charger-manager.c|  196 +---
 include/linux/power/charger-manager.h  |   19 +-
 3 files changed, 8 insertions(+), 208 deletions(-)

diff --git a/Documentation/devicetree/bindings/power_supply/charger-manager.txt 
b/Documentation/devicetree/bindings/power_supply/charger-manager.txt
index 2b33750..767aaa5 100644
--- a/Documentation/devicetree/bindings/power_supply/charger-manager.txt
+++ b/Documentation/devicetree/bindings/power_supply/charger-manager.txt
@@ -39,7 +39,6 @@ Example :
cm-poll-mode = <1>;
cm-poll-interval = <3>;
 
-   cm-fullbatt-vchkdrop-ms = <3>;
cm-fullbatt-vchkdrop-volt = <15>;
cm-fullbatt-soc = <100>;
 
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 33a1a4d..64fdaaf 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -410,25 +410,18 @@ static int try_charger_restart(struct charger_manager *cm)
 
 /**
  * fullbatt_vchk - Check voltage drop some times after "FULL" event.
- * @work: the work_struct appointing the function
  *
- * If a user has designated "fullbatt_vchkdrop_ms/uV" values with
+ * If a user has designated "fullbatt_vchkdrop_uV" values with
  * charger_desc, Charger Manager checks voltage drop after the battery
  * "FULL" event. It checks whether the voltage has dropped more than
  * fullbatt_vchkdrop_uV by calling this function after fullbatt_vchkrop_ms.
  */
-static void fullbatt_vchk(struct work_struct *work)
+static void fullbatt_vchk(struct charger_manager *cm)
 {
-   struct delayed_work *dwork = to_delayed_work(work);
-   struct charger_manager *cm = container_of(dwork,
-   struct charger_manager, fullbatt_vchk_work);
struct charger_desc *desc = cm->desc;
int batt_uV, err, diff;
 
-   /* remove the appointment for fullbatt_vchk */
-   cm->fullbatt_vchk_jiffies_at = 0;
-
-   if (!desc->fullbatt_vchkdrop_uV || !desc->fullbatt_vchkdrop_ms)
+   if (!desc->fullbatt_vchkdrop_uV)
return;
 
err = get_batt_uV(cm, _uV);
@@ -585,7 +578,7 @@ static bool _cm_monitor(struct charger_manager *cm)
 */
} else if (!cm->emergency_stop && is_ext_pwr_online(cm) &&
!cm->charger_enabled) {
-   fullbatt_vchk(>fullbatt_vchk_work.work);
+   fullbatt_vchk(cm);
 
/*
 * Check whether fully charged state to protect overcharge
@@ -598,7 +591,7 @@ static bool _cm_monitor(struct charger_manager *cm)
 
try_charger_enable(cm, false);
 
-   fullbatt_vchk(>fullbatt_vchk_work.work);
+   fullbatt_vchk(cm);
} else {
cm->emergency_stop = 0;
if (is_ext_pwr_online(cm)) {
@@ -700,66 +693,6 @@ static void cm_monitor_poller(struct work_struct *work)
schedule_work(_polling);
 }
 
-/**
- * fullbatt_handler - Event handler for CM_EVENT_BATT_FULL
- * @cm: the Charger Manager representing the battery.
- */
-static void fullbatt_handler(struct charger_manager *cm)
-{
-   struct charger_desc *desc = cm->desc;
-
-   if (!desc->fullbatt_vchkdrop_uV || !desc->fullbatt_vchkdrop_ms)
-   goto out;
-
-   if (cm_suspended)
-   device_set_wakeup_capable(cm->dev, true);
-
-   mod_delayed_work(cm_wq, >fullbatt_vchk_work,
-msecs_to_jiffies(desc->fullbatt_vchkdrop_ms));
-   cm->fullbatt_vchk_jiffies_at = jiffies + msecs_to_jiffies(
-  desc->fullbatt_vchkdrop_ms);
-
-   if (cm->fullbatt_vchk_jiffies_at == 0)
-   cm->fullbatt_vchk_jiffies_at = 1;
-
-out:
-   dev_info(cm->dev, "EVENT_HANDLE: Battery Fully Charged\n");
-   power_supply_changed(>charger_psy);
-}
-
-/**
- * battout_handler - Event handler for CM_EVENT_BATT_OUT
- * @cm: the Charger Manager representing the battery.
- */
-static void battout_handler(struct charger_manager *cm)
-{
-   if (cm_suspended)
-   device_set_wakeup_capable(cm->dev, true);
-
-   if (!is_batt_present(cm)) {
-   dev_emerg(cm->dev, "Battery Pulled Out!\n");
-   power_supply_changed(>charger_psy);
-   } else {
-   power_supply_changed(>charger_psy);
-   }
-}
-
-/**
- * misc_event_handler - Handler for othe

[PATCH RESEND v2 09/10] power: charger-manager: Support different polling mode for sleep state.

2014-12-18 Thread Jonghwa Lee
Add additional polling mode for sleep state to define different mode with
normal state. With this change, charger-manager can work differently in
normal state or sleep state. e.g, polling aways for normal and polling
only when charing for sleep. If there is no defined polling mode for
sleep state it just follows the normal state's.
In addition to, polling rate is still same in sleep.

Signed-off-by: Jonghwa Lee 
---
 drivers/power/charger-manager.c   |   20 +---
 include/linux/power/charger-manager.h |9 ++---
 2 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 1ccb9be..0a0834f 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -291,7 +291,15 @@ static bool is_full_charged(struct charger_manager *cm)
  */
 static bool is_polling_required(struct charger_manager *cm)
 {
-   switch (cm->desc->polling_mode) {
+   enum polling_modes polling_mode;
+
+   if (cm_suspended
+   && cm->desc->poll_mode_sleep >= 0)
+   polling_mode = cm->desc->poll_mode_sleep;
+   else
+   polling_mode = cm->desc->poll_mode_normal;
+
+   switch (polling_mode) {
case CM_POLL_DISABLE:
return false;
case CM_POLL_ALWAYS:
@@ -302,7 +310,7 @@ static bool is_polling_required(struct charger_manager *cm)
return is_charging(cm);
default:
dev_warn(cm->dev, "Incorrect polling_mode (%d)\n",
-cm->desc->polling_mode);
+polling_mode);
}
 
return false;
@@ -1158,7 +1166,13 @@ static struct charger_desc *of_cm_parse_desc(struct 
device *dev)
of_property_read_string(np, "cm-name", >psy_name);
 
of_property_read_u32(np, "cm-poll-mode", _mode);
-   desc->polling_mode = poll_mode;
+   desc->poll_mode_normal = poll_mode;
+
+   /* Polling mode in sleep state */
+   if (!of_property_read_u32(np, "cm-poll-mode-sleep", _mode))
+   desc->poll_mode_sleep = poll_mode;
+   else
+   desc->poll_mode_sleep = -EINVAL;
 
of_property_read_u32(np, "cm-poll-interval",
>polling_interval_ms);
diff --git a/include/linux/power/charger-manager.h 
b/include/linux/power/charger-manager.h
index 37fb181..a30a0b6 100644
--- a/include/linux/power/charger-manager.h
+++ b/include/linux/power/charger-manager.h
@@ -131,8 +131,10 @@ struct charger_regulator {
 /**
  * struct charger_desc
  * @psy_name: the name of power-supply-class for charger manager
- * @polling_mode:
- * Determine which polling mode will be used
+ * @poll_mode_normal:
+ * Determine which polling mode will be used in normal state.
+ * @poll_mode_sleep:
+ * Determine which polling mode will be used in sleep state.
  * @fullbatt_vchkdrop_uV:
  * Check voltage drop after the battery is fully charged.
  * If it has dropped more than fullbatt_vchkdrop_uV
@@ -170,7 +172,8 @@ struct charger_regulator {
 struct charger_desc {
const char *psy_name;
 
-   enum polling_modes polling_mode;
+   enum polling_modes poll_mode_normal;
+   enum polling_modes poll_mode_sleep;
unsigned int polling_interval_ms;
 
unsigned int fullbatt_vchkdrop_uV;
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH RESEND v2 10/10] power: charger-manager: Support to change polling rate in runtime.

2014-12-18 Thread Jonghwa Lee
Add 'polling_ms' sysfs node to change charger-manager's monitoring rate
in runtime. It can set only bigger than 2 jiffies (for 200 HZ system it
is 10 msecs.) as it's allowed for minimum poling rate in previous.
It resets poller and re-configure polling rate based on new input if next
polling time is far enough. Otherwise, it just waits expiration of timer
and new polling rate will affects the next scheduling.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 drivers/power/charger-manager.c |   62 +++
 1 file changed, 62 insertions(+)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 0a0834f..7a007f4 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -1054,6 +1054,63 @@ static ssize_t charger_externally_control_store(struct 
device *dev,
return count;
 }
 
+static ssize_t show_polling_ms(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   struct charger_manager *cm;
+   ssize_t len;
+
+   list_for_each_entry(cm, cm_list, entry)
+   if (cm-charger_psy.dev == dev)
+   break;
+
+   if (cm-charger_psy.dev != dev)
+   return -EINVAL;
+
+   len = sprintf(buf, %d\n, cm-desc-polling_interval_ms);
+
+   return len;
+}
+
+static ssize_t store_polling_ms(struct device *dev,
+   struct device_attribute *attr, const char *buf,
+   size_t count)
+{
+   struct charger_manager *cm;
+   int polling_ms;
+   int ret;
+
+   ret = sscanf(buf, %d, polling_ms);
+   if (ret  0 )
+   return -EINVAL;
+
+   if (polling_ms  CM_JIFFIES_SMALL * MSEC_PER_SEC / HZ)
+   return -EINVAL;
+
+   list_for_each_entry(cm, cm_list, entry)
+   if (cm-charger_psy.dev == dev)
+   break;
+
+   if (cm-charger_psy.dev != dev)
+   return -ENODEV;
+
+   cm-desc-polling_interval_ms = polling_ms;
+
+   pr_info(Polling interval's changed to %u ms.\n,
+   cm-desc-polling_interval_ms);
+
+   if (next_polling - jiffies 
+   msecs_to_jiffies(cm-desc-polling_interval_ms)) {
+   pr_info(Reset poller now... \n);
+   cancel_delayed_work(cm_monitor_work);
+   schedule_work(setup_polling);
+   }
+
+   return count;
+}
+
+static DEVICE_ATTR(polling_ms, 0644, show_polling_ms, store_polling_ms);
+
 /**
  * charger_manager_register_sysfs - Register sysfs entry for each charger
  * @cm: the Charger Manager representing the battery.
@@ -1077,6 +1134,11 @@ static int charger_manager_register_sysfs(struct 
charger_manager *cm)
int ret = 0;
int i;
 
+   /* Create polling_ms sysfs node */
+   ret = device_create_file(cm-charger_psy.dev, dev_attr_polling_ms);
+   if (ret)
+   pr_err(Failed to create poling_ms sysfs node (%d)\n, ret);
+
/* Create sysfs entry to control charger(regulator) */
for (i = 0; i  desc-num_charger_regulators; i++) {
charger = desc-charger_regulators[i];
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH RESEND v2 03/10] power: charger-manager: Remove deprecated function, cm_notify_event().

2014-12-18 Thread Jonghwa Lee
cm_notify_event() is introduced to get event associated with battery status
externally, but no one had been used. Moreover it makes charger manager
driver more complicated. This patch tries to drop the function and all data
related to simplify the driver.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 .../bindings/power_supply/charger-manager.txt  |1 -
 drivers/power/charger-manager.c|  196 +---
 include/linux/power/charger-manager.h  |   19 +-
 3 files changed, 8 insertions(+), 208 deletions(-)

diff --git a/Documentation/devicetree/bindings/power_supply/charger-manager.txt 
b/Documentation/devicetree/bindings/power_supply/charger-manager.txt
index 2b33750..767aaa5 100644
--- a/Documentation/devicetree/bindings/power_supply/charger-manager.txt
+++ b/Documentation/devicetree/bindings/power_supply/charger-manager.txt
@@ -39,7 +39,6 @@ Example :
cm-poll-mode = 1;
cm-poll-interval = 3;
 
-   cm-fullbatt-vchkdrop-ms = 3;
cm-fullbatt-vchkdrop-volt = 15;
cm-fullbatt-soc = 100;
 
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 33a1a4d..64fdaaf 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -410,25 +410,18 @@ static int try_charger_restart(struct charger_manager *cm)
 
 /**
  * fullbatt_vchk - Check voltage drop some times after FULL event.
- * @work: the work_struct appointing the function
  *
- * If a user has designated fullbatt_vchkdrop_ms/uV values with
+ * If a user has designated fullbatt_vchkdrop_uV values with
  * charger_desc, Charger Manager checks voltage drop after the battery
  * FULL event. It checks whether the voltage has dropped more than
  * fullbatt_vchkdrop_uV by calling this function after fullbatt_vchkrop_ms.
  */
-static void fullbatt_vchk(struct work_struct *work)
+static void fullbatt_vchk(struct charger_manager *cm)
 {
-   struct delayed_work *dwork = to_delayed_work(work);
-   struct charger_manager *cm = container_of(dwork,
-   struct charger_manager, fullbatt_vchk_work);
struct charger_desc *desc = cm-desc;
int batt_uV, err, diff;
 
-   /* remove the appointment for fullbatt_vchk */
-   cm-fullbatt_vchk_jiffies_at = 0;
-
-   if (!desc-fullbatt_vchkdrop_uV || !desc-fullbatt_vchkdrop_ms)
+   if (!desc-fullbatt_vchkdrop_uV)
return;
 
err = get_batt_uV(cm, batt_uV);
@@ -585,7 +578,7 @@ static bool _cm_monitor(struct charger_manager *cm)
 */
} else if (!cm-emergency_stop  is_ext_pwr_online(cm) 
!cm-charger_enabled) {
-   fullbatt_vchk(cm-fullbatt_vchk_work.work);
+   fullbatt_vchk(cm);
 
/*
 * Check whether fully charged state to protect overcharge
@@ -598,7 +591,7 @@ static bool _cm_monitor(struct charger_manager *cm)
 
try_charger_enable(cm, false);
 
-   fullbatt_vchk(cm-fullbatt_vchk_work.work);
+   fullbatt_vchk(cm);
} else {
cm-emergency_stop = 0;
if (is_ext_pwr_online(cm)) {
@@ -700,66 +693,6 @@ static void cm_monitor_poller(struct work_struct *work)
schedule_work(setup_polling);
 }
 
-/**
- * fullbatt_handler - Event handler for CM_EVENT_BATT_FULL
- * @cm: the Charger Manager representing the battery.
- */
-static void fullbatt_handler(struct charger_manager *cm)
-{
-   struct charger_desc *desc = cm-desc;
-
-   if (!desc-fullbatt_vchkdrop_uV || !desc-fullbatt_vchkdrop_ms)
-   goto out;
-
-   if (cm_suspended)
-   device_set_wakeup_capable(cm-dev, true);
-
-   mod_delayed_work(cm_wq, cm-fullbatt_vchk_work,
-msecs_to_jiffies(desc-fullbatt_vchkdrop_ms));
-   cm-fullbatt_vchk_jiffies_at = jiffies + msecs_to_jiffies(
-  desc-fullbatt_vchkdrop_ms);
-
-   if (cm-fullbatt_vchk_jiffies_at == 0)
-   cm-fullbatt_vchk_jiffies_at = 1;
-
-out:
-   dev_info(cm-dev, EVENT_HANDLE: Battery Fully Charged\n);
-   power_supply_changed(cm-charger_psy);
-}
-
-/**
- * battout_handler - Event handler for CM_EVENT_BATT_OUT
- * @cm: the Charger Manager representing the battery.
- */
-static void battout_handler(struct charger_manager *cm)
-{
-   if (cm_suspended)
-   device_set_wakeup_capable(cm-dev, true);
-
-   if (!is_batt_present(cm)) {
-   dev_emerg(cm-dev, Battery Pulled Out!\n);
-   power_supply_changed(cm-charger_psy);
-   } else {
-   power_supply_changed(cm-charger_psy);
-   }
-}
-
-/**
- * misc_event_handler - Handler for other evnets
- * @cm: the Charger Manager representing the battery.
- * @type: the Charger Manager representing the battery.
- */
-static void misc_event_handler(struct charger_manager *cm

[PATCH RESEND v2 09/10] power: charger-manager: Support different polling mode for sleep state.

2014-12-18 Thread Jonghwa Lee
Add additional polling mode for sleep state to define different mode with
normal state. With this change, charger-manager can work differently in
normal state or sleep state. e.g, polling aways for normal and polling
only when charing for sleep. If there is no defined polling mode for
sleep state it just follows the normal state's.
In addition to, polling rate is still same in sleep.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 drivers/power/charger-manager.c   |   20 +---
 include/linux/power/charger-manager.h |9 ++---
 2 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 1ccb9be..0a0834f 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -291,7 +291,15 @@ static bool is_full_charged(struct charger_manager *cm)
  */
 static bool is_polling_required(struct charger_manager *cm)
 {
-   switch (cm-desc-polling_mode) {
+   enum polling_modes polling_mode;
+
+   if (cm_suspended
+cm-desc-poll_mode_sleep = 0)
+   polling_mode = cm-desc-poll_mode_sleep;
+   else
+   polling_mode = cm-desc-poll_mode_normal;
+
+   switch (polling_mode) {
case CM_POLL_DISABLE:
return false;
case CM_POLL_ALWAYS:
@@ -302,7 +310,7 @@ static bool is_polling_required(struct charger_manager *cm)
return is_charging(cm);
default:
dev_warn(cm-dev, Incorrect polling_mode (%d)\n,
-cm-desc-polling_mode);
+polling_mode);
}
 
return false;
@@ -1158,7 +1166,13 @@ static struct charger_desc *of_cm_parse_desc(struct 
device *dev)
of_property_read_string(np, cm-name, desc-psy_name);
 
of_property_read_u32(np, cm-poll-mode, poll_mode);
-   desc-polling_mode = poll_mode;
+   desc-poll_mode_normal = poll_mode;
+
+   /* Polling mode in sleep state */
+   if (!of_property_read_u32(np, cm-poll-mode-sleep, poll_mode))
+   desc-poll_mode_sleep = poll_mode;
+   else
+   desc-poll_mode_sleep = -EINVAL;
 
of_property_read_u32(np, cm-poll-interval,
desc-polling_interval_ms);
diff --git a/include/linux/power/charger-manager.h 
b/include/linux/power/charger-manager.h
index 37fb181..a30a0b6 100644
--- a/include/linux/power/charger-manager.h
+++ b/include/linux/power/charger-manager.h
@@ -131,8 +131,10 @@ struct charger_regulator {
 /**
  * struct charger_desc
  * @psy_name: the name of power-supply-class for charger manager
- * @polling_mode:
- * Determine which polling mode will be used
+ * @poll_mode_normal:
+ * Determine which polling mode will be used in normal state.
+ * @poll_mode_sleep:
+ * Determine which polling mode will be used in sleep state.
  * @fullbatt_vchkdrop_uV:
  * Check voltage drop after the battery is fully charged.
  * If it has dropped more than fullbatt_vchkdrop_uV
@@ -170,7 +172,8 @@ struct charger_regulator {
 struct charger_desc {
const char *psy_name;
 
-   enum polling_modes polling_mode;
+   enum polling_modes poll_mode_normal;
+   enum polling_modes poll_mode_sleep;
unsigned int polling_interval_ms;
 
unsigned int fullbatt_vchkdrop_uV;
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH RESEND v2 05/10] power: charger-manager: Concentrate scattered power_supply_changed() calls.

2014-12-18 Thread Jonghwa Lee
Current charger-manager calls power_suuply_changed() whenever charging
status is changed. This patch removes seperated power_supply_changed()
use and let it be called at end of try_charger_enable() function which
is called to set charging/discharging.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 drivers/power/charger-manager.c |   18 ++
 1 file changed, 6 insertions(+), 12 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 687f109..bb44588 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -382,8 +382,10 @@ static int try_charger_enable(struct charger_manager *cm, 
bool enable)
}
}
 
-   if (!err)
+   if (!err) {
cm-charger_enabled = enable;
+   power_supply_changed(cm-charger_psy);
+   }
 
return err;
 }
@@ -436,10 +438,8 @@ static void fullbatt_vchk(struct charger_manager *cm)
 
dev_info(cm-dev, VBATT dropped %duV after full-batt\n, diff);
 
-   if (diff  desc-fullbatt_vchkdrop_uV) {
+   if (diff  desc-fullbatt_vchkdrop_uV)
try_charger_restart(cm);
-   power_supply_changed(cm-charger_psy);
-   }
 }
 
 /**
@@ -469,7 +469,6 @@ static int check_charging_duration(struct charger_manager 
*cm)
if (duration  desc-charging_max_duration_ms) {
dev_info(cm-dev, Charging duration exceed %ums\n,
 desc-charging_max_duration_ms);
-   power_supply_changed(cm-charger_psy);
try_charger_enable(cm, false);
ret = true;
}
@@ -480,7 +479,6 @@ static int check_charging_duration(struct charger_manager 
*cm)
is_ext_pwr_online(cm)) {
dev_info(cm-dev, Discharging duration exceed %ums\n,
 desc-discharging_max_duration_ms);
-   power_supply_changed(cm-charger_psy);
try_charger_enable(cm, true);
ret = true;
}
@@ -561,8 +559,7 @@ static bool _cm_monitor(struct charger_manager *cm)
 */
if (temp_alrt) {
cm-emergency_stop = temp_alrt;
-   if (!try_charger_enable(cm, false))
-   power_supply_changed(cm-charger_psy);
+   try_charger_enable(cm, false);
 
/*
 * Check whole charging duration and discharing duration
@@ -587,16 +584,13 @@ static bool _cm_monitor(struct charger_manager *cm)
} else if (!cm-emergency_stop  is_full_charged(cm) 
cm-charger_enabled) {
dev_info(cm-dev, EVENT_HANDLE: Battery Fully Charged\n);
-   power_supply_changed(cm-charger_psy);
-
try_charger_enable(cm, false);
 
fullbatt_vchk(cm);
} else {
cm-emergency_stop = 0;
if (is_ext_pwr_online(cm)) {
-   if (!try_charger_enable(cm, true))
-   power_supply_changed(cm-charger_psy);
+   try_charger_enable(cm, true);
}
}
 
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH RESEND v2 08/10] power: charger-manager: Not to start charging directly in cable nofitication.

2014-12-18 Thread Jonghwa Lee
This patch prevents direct charging control in cable notification.
It sets only input current limit according to cable type and yields charging
control to be done by cm_monitor() where charging management proceeds.
It may loose few ms to enable charging compared to before, even though it's
more important that charging is enabled always in safe context.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 drivers/power/charger-manager.c |   12 ++--
 1 file changed, 2 insertions(+), 10 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 065b92a..1ccb9be 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -849,7 +849,8 @@ static void charger_extcon_work(struct work_struct *work)
cable-min_uA, cable-max_uA);
}
 
-   try_charger_enable(cable-cm, cable-attached);
+   cancel_delayed_work(cm_monitor_work);
+   queue_delayed_work(cm_wq, cm_monitor_work, 0);
 }
 
 /**
@@ -873,15 +874,6 @@ static int charger_extcon_notifier(struct notifier_block 
*self,
cable-attached = event;
 
/*
-* Setup monitoring to check battery state
-* when charger cable is attached.
-*/
-   if (cable-attached  is_polling_required(cable-cm)) {
-   cancel_work_sync(setup_polling);
-   schedule_work(setup_polling);
-   }
-
-   /*
 * Setup work for controlling charger(regulator)
 * according to charger cable.
 */
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH RESEND v2 06/10] power: charger-manager: Get external power souce information only from EXTCON.

2014-12-18 Thread Jonghwa Lee
When charger-manager checks whether external power source is available,
it gets information from charger IC driver. However, it's not correct source,
charger IC doesn't have responsibilty to give cable connection status.
The charger-manager already gets cable information from EXTCON susbsystem,
so it can re-use it.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 drivers/power/charger-manager.c |   34 ++
 1 file changed, 14 insertions(+), 20 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index bb44588..172dfe5 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -115,34 +115,28 @@ static bool is_batt_present(struct charger_manager *cm)
  * is_ext_pwr_online - See if an external power source is attached to charge
  * @cm: the Charger Manager representing the battery.
  *
- * Returns true if at least one of the chargers of the battery has an external
- * power source attached to charge the battery regardless of whether it is
- * actually charging or not.
+ * Returns true if there is external power source.
+ * Cable connection information is only obtained by EXTCON class notification.
  */
 static bool is_ext_pwr_online(struct charger_manager *cm)
 {
-   union power_supply_propval val;
-   struct power_supply *psy;
-   bool online = false;
-   int i, ret;
 
-   /* If at least one of them has one, it's yes. */
-   for (i = 0; cm-desc-psy_charger_stat[i]; i++) {
-   psy = power_supply_get_by_name(cm-desc-psy_charger_stat[i]);
-   if (!psy) {
-   dev_err(cm-dev, Cannot find power supply \%s\\n,
-   cm-desc-psy_charger_stat[i]);
-   continue;
-   }
+   struct charger_desc *desc = cm-desc;
+   struct charger_regulator *regulators = desc-charger_regulators;
+   struct charger_cable *cables;
+   int i, j, num_cables;
 
-   ret = psy-get_property(psy, POWER_SUPPLY_PROP_ONLINE, val);
-   if (ret == 0  val.intval) {
-   online = true;
-   break;
+   /* If at least one of them has one, it's yes. */
+   for (i = 0; i  desc-num_charger_regulators; i++) {
+   cables = regulators[i].cables;
+   num_cables = regulators[i].num_cables;
+   for (j = 0; j  num_cables; j++) {
+   if (cables[j].attached)
+   return true;
}
}
 
-   return online;
+   return false;
 }
 
 /**
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH RESEND V2 0/10] Improve charger manager driver for optimized operation.

2014-12-18 Thread Jonghwa Lee
After charger manager's initially introduced, it has kept its codes without any
big change. However, the charger manager working operation isn't optimized and
it also has unused codes and non-generic interface. This series tries to make
charger manager more generic and maintainable with some fixes.

[Changes in V2]
- Rebase patch series on latest of battery-2.6.git.
- Seperate 'power: charger-manager: Rearrange data and monitor ~' patch into
  several patches depends on its purpose.
- Add 2 patches related with polling mode.

Jonghwa Lee (10):
  power: charger-manager: Use thermal subsystem interface only to get
temperature.
  power: charger-manager: Use power_supply_changed() not private
uevent.
  power: charger-manager: Remove deprecated function,
cm_notify_event().
  power: charger-manager: Fix to use CHARGE_NOW/FULL property
correctly.
  power: charger-manager: Concentrate scattered power_supply_changed()
calls.
  power: charger-manager: Get external power souce information only
from EXTCON.
  power: charger-manager: Make chraging decision focusing on battery
status.
  power: charger-manager: Not to start charging directly in cable
nofitication.
  power: charger-manager: Support different polling mode for sleep
state.
  power: charger-manager: Support to change polling rate in runtime.

 .../bindings/power_supply/charger-manager.txt  |1 -
 drivers/power/Kconfig  |1 +
 drivers/power/charger-manager.c|  758 ++--
 include/linux/power/charger-manager.h  |   34 +-
 4 files changed, 219 insertions(+), 575 deletions(-)

-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH RESEND v2 04/10] power: charger-manager: Fix to use CHARGE_NOW/FULL property correctly.

2014-12-18 Thread Jonghwa Lee
The POWER_SUPPLY_CHARGE_NOW/FULL property reflects battery's charges
in uAh unit, but charger-manager has been used it wrongly. This patch
makes it to use those propeties correctly and change to be optional.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 drivers/power/charger-manager.c |   85 +--
 1 file changed, 28 insertions(+), 57 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 64fdaaf..687f109 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -796,35 +796,13 @@ static int charger_get_property(struct power_supply *psy,
val-intval = 0;
break;
case POWER_SUPPLY_PROP_CHARGE_FULL:
-   if (is_full_charged(cm))
-   val-intval = 1;
-   else
-   val-intval = 0;
-   ret = 0;
-   break;
case POWER_SUPPLY_PROP_CHARGE_NOW:
-   if (is_charging(cm)) {
-   fuel_gauge = power_supply_get_by_name(
-   cm-desc-psy_fuel_gauge);
-   if (!fuel_gauge) {
-   ret = -ENODEV;
-   break;
-   }
-
-   ret = fuel_gauge-get_property(fuel_gauge,
-   POWER_SUPPLY_PROP_CHARGE_NOW,
-   val);
-   if (ret) {
-   val-intval = 1;
-   ret = 0;
-   } else {
-   /* If CHARGE_NOW is supplied, use it */
-   val-intval = (val-intval  0) ?
-   val-intval : 1;
-   }
-   } else {
-   val-intval = 0;
+   fuel_gauge = power_supply_get_by_name(cm-desc-psy_fuel_gauge);
+   if (!fuel_gauge) {
+   ret = -ENODEV;
+   break;
}
+   ret = fuel_gauge-get_property(fuel_gauge, psp, val);
break;
default:
return -EINVAL;
@@ -832,8 +810,7 @@ static int charger_get_property(struct power_supply *psy,
return ret;
 }
 
-#define NUM_CHARGER_PSY_OPTIONAL   (4)
-static enum power_supply_property default_charger_props[] = {
+static enum power_supply_property cm_default_props[] = {
/* Guaranteed to provide */
POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_HEALTH,
@@ -841,20 +818,21 @@ static enum power_supply_property default_charger_props[] 
= {
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_CAPACITY,
POWER_SUPPLY_PROP_ONLINE,
-   POWER_SUPPLY_PROP_CHARGE_FULL,
POWER_SUPPLY_PROP_TEMP,
-   /*
-* Optional properties are:
-* POWER_SUPPLY_PROP_CHARGE_NOW,
-* POWER_SUPPLY_PROP_CURRENT_NOW,
-*/
 };
 
+static enum power_supply_property cm_optional_props[] = {
+   POWER_SUPPLY_PROP_CHARGE_FULL,
+   POWER_SUPPLY_PROP_CHARGE_NOW,
+   POWER_SUPPLY_PROP_CURRENT_NOW,
+};
+
+#define CM_NUM_OF_PROPS\
+   (ARRAY_SIZE(cm_default_props) + ARRAY_SIZE(cm_optional_props))
+
 static struct power_supply psy_default = {
.name = battery,
.type = POWER_SUPPLY_TYPE_BATTERY,
-   .properties = default_charger_props,
-   .num_properties = ARRAY_SIZE(default_charger_props),
.get_property = charger_get_property,
.no_thermal = true,
 };
@@ -1484,29 +1462,22 @@ static int charger_manager_probe(struct platform_device 
*pdev)
/* Allocate for psy properties because they may vary */
cm-charger_psy.properties = devm_kzalloc(pdev-dev,
sizeof(enum power_supply_property)
-   * (ARRAY_SIZE(default_charger_props) +
-   NUM_CHARGER_PSY_OPTIONAL), GFP_KERNEL);
+   * CM_NUM_OF_PROPS, GFP_KERNEL);
if (!cm-charger_psy.properties)
return -ENOMEM;
 
-   memcpy(cm-charger_psy.properties, default_charger_props,
-   sizeof(enum power_supply_property) *
-   ARRAY_SIZE(default_charger_props));
-   cm-charger_psy.num_properties = psy_default.num_properties;
-
-   /* Find which optional psy-properties are available */
-   if (!fuel_gauge-get_property(fuel_gauge,
- POWER_SUPPLY_PROP_CHARGE_NOW, val)) {
-   cm-charger_psy.properties[cm-charger_psy.num_properties] =
-   POWER_SUPPLY_PROP_CHARGE_NOW;
-   cm-charger_psy.num_properties++;
-   }
-   if (!fuel_gauge-get_property(fuel_gauge,
- POWER_SUPPLY_PROP_CURRENT_NOW

[PATCH RESEND v2 07/10] power: charger-manager: Make chraging decision focusing on battery status.

2014-12-18 Thread Jonghwa Lee
In cm_monitor() where charging management starts, it checks various charging
condition sequentially to decide next charging operation. However, as it
follows sequential process, cascaded IF statements, it does some duplicated
jobs which is already done in previous stage. It results delay in decision
making. And moreover, starting point of charing is spreaded all around, so
it makes maintain codes and debugging difficult.

Both of problems mentioned above becomes clean if it manages battery charging
focusing on battery status not following sequential condition checking.
Now, cm_monitor() moves battery state diagram and does optimal operation for
current state. As a result, it reduces whole monitoring time almost in half.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 drivers/power/charger-manager.c   |  177 +++--
 include/linux/power/charger-manager.h |3 +
 2 files changed, 62 insertions(+), 118 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 172dfe5..065b92a 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -249,6 +249,19 @@ static bool is_full_charged(struct charger_manager *cm)
if (!fuel_gauge)
return false;
 
+   /* Full, if it's over the fullbatt voltage */
+   if (desc-fullbatt_uV  0) {
+   ret = get_batt_uV(cm, uV);
+   if (!ret) {
+   /* Battery is already full, checks voltage drop. */
+   if (cm-battery_status == POWER_SUPPLY_STATUS_FULL
+desc-fullbatt_vchkdrop_uV)
+   uV += desc-fullbatt_vchkdrop_uV;
+   if (uV = desc-fullbatt_uV)
+   return true;
+   }
+   }
+
if (desc-fullbatt_full_capacity  0) {
val.intval = 0;
 
@@ -259,13 +272,6 @@ static bool is_full_charged(struct charger_manager *cm)
return true;
}
 
-   /* Full, if it's over the fullbatt voltage */
-   if (desc-fullbatt_uV  0) {
-   ret = get_batt_uV(cm, uV);
-   if (!ret  uV = desc-fullbatt_uV)
-   return true;
-   }
-
/* Full, if the capacity is more than fullbatt_soc */
if (desc-fullbatt_soc  0) {
val.intval = 0;
@@ -376,67 +382,13 @@ static int try_charger_enable(struct charger_manager *cm, 
bool enable)
}
}
 
-   if (!err) {
+   if (!err)
cm-charger_enabled = enable;
-   power_supply_changed(cm-charger_psy);
-   }
 
return err;
 }
 
 /**
- * try_charger_restart - Restart charging.
- * @cm: the Charger Manager representing the battery.
- *
- * Restart charging by turning off and on the charger.
- */
-static int try_charger_restart(struct charger_manager *cm)
-{
-   int err;
-
-   if (cm-emergency_stop)
-   return -EAGAIN;
-
-   err = try_charger_enable(cm, false);
-   if (err)
-   return err;
-
-   return try_charger_enable(cm, true);
-}
-
-/**
- * fullbatt_vchk - Check voltage drop some times after FULL event.
- *
- * If a user has designated fullbatt_vchkdrop_uV values with
- * charger_desc, Charger Manager checks voltage drop after the battery
- * FULL event. It checks whether the voltage has dropped more than
- * fullbatt_vchkdrop_uV by calling this function after fullbatt_vchkrop_ms.
- */
-static void fullbatt_vchk(struct charger_manager *cm)
-{
-   struct charger_desc *desc = cm-desc;
-   int batt_uV, err, diff;
-
-   if (!desc-fullbatt_vchkdrop_uV)
-   return;
-
-   err = get_batt_uV(cm, batt_uV);
-   if (err) {
-   dev_err(cm-dev, %s: get_batt_uV error(%d)\n, __func__, err);
-   return;
-   }
-
-   diff = desc-fullbatt_uV - batt_uV;
-   if (diff  0)
-   return;
-
-   dev_info(cm-dev, VBATT dropped %duV after full-batt\n, diff);
-
-   if (diff  desc-fullbatt_vchkdrop_uV)
-   try_charger_restart(cm);
-}
-
-/**
  * check_charging_duration - Monitor charging/discharging duration
  * @cm: the Charger Manager representing the battery.
  *
@@ -463,17 +415,14 @@ static int check_charging_duration(struct charger_manager 
*cm)
if (duration  desc-charging_max_duration_ms) {
dev_info(cm-dev, Charging duration exceed %ums\n,
 desc-charging_max_duration_ms);
-   try_charger_enable(cm, false);
ret = true;
}
-   } else if (is_ext_pwr_online(cm)  !cm-charger_enabled) {
+   } else if (cm-battery_status == POWER_SUPPLY_STATUS_NOT_CHARGING) {
duration = curr - cm-charging_end_time;
 
-   if (duration  desc-charging_max_duration_ms

[PATCH RESEND v2 01/10] power: charger-manager: Use thermal subsystem interface only to get temperature.

2014-12-18 Thread Jonghwa Lee
It drops the way of using power_supply interface to reference battery's
temperature. Then it tries to use thermal subsystem's only. This makes driver
more simple and also can remove ifdeferies.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 drivers/power/Kconfig |1 +
 drivers/power/charger-manager.c   |  113 -
 include/linux/power/charger-manager.h |3 +-
 3 files changed, 28 insertions(+), 89 deletions(-)

diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 8ff2511..115d153 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -317,6 +317,7 @@ config CHARGER_MANAGER
bool Battery charger manager for multiple chargers
depends on REGULATOR
select EXTCON
+   select THERMAL
help
   Say Y to enable charger-manager support, which allows multiple
   chargers attached to a battery and multiple batteries attached to a
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 22246b9..b4b101c 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -28,13 +28,6 @@
 #include linux/of.h
 #include linux/thermal.h
 
-/*
- * Default termperature threshold for charging.
- * Every temperature units are in tenth of centigrade.
- */
-#define CM_DEFAULT_RECHARGE_TEMP_DIFF  50
-#define CM_DEFAULT_CHARGE_TEMP_MAX 500
-
 static const char * const default_event_names[] = {
[CM_EVENT_UNKNOWN] = Unknown,
[CM_EVENT_BATT_FULL] = Battery Full,
@@ -572,40 +565,18 @@ static int check_charging_duration(struct charger_manager 
*cm)
return ret;
 }
 
-static int cm_get_battery_temperature_by_psy(struct charger_manager *cm,
-   int *temp)
-{
-   struct power_supply *fuel_gauge;
-
-   fuel_gauge = power_supply_get_by_name(cm-desc-psy_fuel_gauge);
-   if (!fuel_gauge)
-   return -ENODEV;
-
-   return fuel_gauge-get_property(fuel_gauge,
-   POWER_SUPPLY_PROP_TEMP,
-   (union power_supply_propval *)temp);
-}
-
 static int cm_get_battery_temperature(struct charger_manager *cm,
int *temp)
 {
int ret;
 
-   if (!cm-desc-measure_battery_temp)
+   if (!cm-tzd_batt)
return -ENODEV;
 
-#ifdef CONFIG_THERMAL
-   if (cm-tzd_batt) {
-   ret = thermal_zone_get_temp(cm-tzd_batt, (unsigned long 
*)temp);
-   if (!ret)
-   /* Calibrate temperature unit */
-   *temp /= 100;
-   } else
-#endif
-   {
-   /* if-else continued from CONFIG_THERMAL */
-   ret = cm_get_battery_temperature_by_psy(cm, temp);
-   }
+   ret = thermal_zone_get_temp(cm-tzd_batt, (unsigned long *)temp);
+   if (!ret)
+   /* Calibrate temperature unit */
+   *temp /= 100;
 
return ret;
 }
@@ -623,7 +594,7 @@ static int cm_check_thermal_status(struct charger_manager 
*cm)
 * occur hazadous result. We have to handle it
 * depending on battery type.
 */
-   dev_err(cm-dev, Failed to get battery temperature\n);
+   dev_dbg(cm-dev, Failed to get battery temperature\n);
return 0;
}
 
@@ -1007,12 +978,11 @@ static enum power_supply_property 
default_charger_props[] = {
POWER_SUPPLY_PROP_CAPACITY,
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_CHARGE_FULL,
+   POWER_SUPPLY_PROP_TEMP,
/*
 * Optional properties are:
 * POWER_SUPPLY_PROP_CHARGE_NOW,
 * POWER_SUPPLY_PROP_CURRENT_NOW,
-* POWER_SUPPLY_PROP_TEMP, and
-* POWER_SUPPLY_PROP_TEMP_AMBIENT,
 */
 };
 
@@ -1417,49 +1387,6 @@ err:
return ret;
 }
 
-static int cm_init_thermal_data(struct charger_manager *cm,
-   struct power_supply *fuel_gauge)
-{
-   struct charger_desc *desc = cm-desc;
-   union power_supply_propval val;
-   int ret;
-
-   /* Verify whether fuel gauge provides battery temperature */
-   ret = fuel_gauge-get_property(fuel_gauge,
-   POWER_SUPPLY_PROP_TEMP, val);
-
-   if (!ret) {
-   cm-charger_psy.properties[cm-charger_psy.num_properties] =
-   POWER_SUPPLY_PROP_TEMP;
-   cm-charger_psy.num_properties++;
-   cm-desc-measure_battery_temp = true;
-   }
-#ifdef CONFIG_THERMAL
-   if (ret  desc-thermal_zone) {
-   cm-tzd_batt =
-   thermal_zone_get_zone_by_name(desc-thermal_zone);
-   if (IS_ERR(cm-tzd_batt))
-   return PTR_ERR(cm-tzd_batt);
-
-   /* Use external thermometer */
-   cm-charger_psy.properties[cm-charger_psy.num_properties

[PATCH RESEND v2 02/10] power: charger-manager: Use power_supply_changed() not private uevent.

2014-12-18 Thread Jonghwa Lee
Whenever battery status is changed, charger manager tries to trigger uevent
through private interface. This patch modifies it to use power_supply_changed()
since it belongs to power supply subsystem.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 drivers/power/charger-manager.c |   91 +--
 1 file changed, 11 insertions(+), 80 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index b4b101c..33a1a4d 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -28,18 +28,6 @@
 #include linux/of.h
 #include linux/thermal.h
 
-static const char * const default_event_names[] = {
-   [CM_EVENT_UNKNOWN] = Unknown,
-   [CM_EVENT_BATT_FULL] = Battery Full,
-   [CM_EVENT_BATT_IN] = Battery Inserted,
-   [CM_EVENT_BATT_OUT] = Battery Pulled Out,
-   [CM_EVENT_BATT_OVERHEAT] = Battery Overheat,
-   [CM_EVENT_BATT_COLD] = Battery Cold,
-   [CM_EVENT_EXT_PWR_IN_OUT] = External Power Attach/Detach,
-   [CM_EVENT_CHG_START_STOP] = Charging Start/Stop,
-   [CM_EVENT_OTHERS] = Other battery events
-};
-
 /*
  * Regard CM_JIFFIES_SMALL jiffies is small enough to ignore for
  * delayed works so that we can run delayed works with CM_JIFFIES_SMALL
@@ -56,8 +44,6 @@ static const char * const default_event_names[] = {
  */
 #define CM_RTC_SMALL   (2)
 
-#define UEVENT_BUF_SIZE32
-
 static LIST_HEAD(cm_list);
 static DEFINE_MUTEX(cm_list_mtx);
 
@@ -423,61 +409,6 @@ static int try_charger_restart(struct charger_manager *cm)
 }
 
 /**
- * uevent_notify - Let users know something has changed.
- * @cm: the Charger Manager representing the battery.
- * @event: the event string.
- *
- * If @event is null, it implies that uevent_notify is called
- * by resume function. When called in the resume function, cm_suspended
- * should be already reset to false in order to let uevent_notify
- * notify the recent event during the suspend to users. While
- * suspended, uevent_notify does not notify users, but tracks
- * events so that uevent_notify can notify users later after resumed.
- */
-static void uevent_notify(struct charger_manager *cm, const char *event)
-{
-   static char env_str[UEVENT_BUF_SIZE + 1] = ;
-   static char env_str_save[UEVENT_BUF_SIZE + 1] = ;
-
-   if (cm_suspended) {
-   /* Nothing in suspended-event buffer */
-   if (env_str_save[0] == 0) {
-   if (!strncmp(env_str, event, UEVENT_BUF_SIZE))
-   return; /* status not changed */
-   strncpy(env_str_save, event, UEVENT_BUF_SIZE);
-   return;
-   }
-
-   if (!strncmp(env_str_save, event, UEVENT_BUF_SIZE))
-   return; /* Duplicated. */
-   strncpy(env_str_save, event, UEVENT_BUF_SIZE);
-   return;
-   }
-
-   if (event == NULL) {
-   /* No messages pending */
-   if (!env_str_save[0])
-   return;
-
-   strncpy(env_str, env_str_save, UEVENT_BUF_SIZE);
-   kobject_uevent(cm-dev-kobj, KOBJ_CHANGE);
-   env_str_save[0] = 0;
-
-   return;
-   }
-
-   /* status not changed */
-   if (!strncmp(env_str, event, UEVENT_BUF_SIZE))
-   return;
-
-   /* save the status and notify the update */
-   strncpy(env_str, event, UEVENT_BUF_SIZE);
-   kobject_uevent(cm-dev-kobj, KOBJ_CHANGE);
-
-   dev_info(cm-dev, %s\n, event);
-}
-
-/**
  * fullbatt_vchk - Check voltage drop some times after FULL event.
  * @work: the work_struct appointing the function
  *
@@ -514,7 +445,7 @@ static void fullbatt_vchk(struct work_struct *work)
 
if (diff  desc-fullbatt_vchkdrop_uV) {
try_charger_restart(cm);
-   uevent_notify(cm, Recharging);
+   power_supply_changed(cm-charger_psy);
}
 }
 
@@ -545,7 +476,7 @@ static int check_charging_duration(struct charger_manager 
*cm)
if (duration  desc-charging_max_duration_ms) {
dev_info(cm-dev, Charging duration exceed %ums\n,
 desc-charging_max_duration_ms);
-   uevent_notify(cm, Discharging);
+   power_supply_changed(cm-charger_psy);
try_charger_enable(cm, false);
ret = true;
}
@@ -556,7 +487,7 @@ static int check_charging_duration(struct charger_manager 
*cm)
is_ext_pwr_online(cm)) {
dev_info(cm-dev, Discharging duration exceed %ums\n,
 desc-discharging_max_duration_ms);
-   uevent_notify(cm, Recharging);
+   power_supply_changed(cm-charger_psy);
try_charger_enable(cm, true

[PATCH] arm64: psci: Support generic pm suspend withtout CPUIDLE subsystem's help.

2014-12-18 Thread Jonghwa Lee
Current psci's cpu_suspend callback can be used only when common cpu idle
configuration is enabled. However, it's also needed for system which only
uses generic pm suspend not cpu idle. This patch modifies psci driver to
support both of cases.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 arch/arm64/kernel/psci.c |   41 +
 1 file changed, 29 insertions(+), 12 deletions(-)

diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c
index f1dbca7..06d5527 100644
--- a/arch/arm64/kernel/psci.c
+++ b/arch/arm64/kernel/psci.c
@@ -35,6 +35,13 @@
 #define PSCI_POWER_STATE_TYPE_STANDBY  0
 #define PSCI_POWER_STATE_TYPE_POWER_DOWN   1
 
+enum psci_affinity_level {
+   PSCI_AFFINITY_LEVEL_0,
+   PSCI_AFFINITY_LEVEL_1,
+   PSCI_AFFINITY_LEVEL_2,
+   PSCI_AFFINITY_LEVEL_3,
+};
+
 struct psci_power_state {
u16 id;
u8  type;
@@ -513,27 +520,37 @@ static int psci_suspend_finisher(unsigned long index)
 {
struct psci_power_state *state = __this_cpu_read(psci_power_state);
 
+   /* Generic PM suspend without CPUIDLE functionality */
+   if (!state) {
+   struct psci_power_state s = {
+   .affinity_level = PSCI_AFFINITY_LEVEL_3,
+   .type = PSCI_POWER_STATE_TYPE_POWER_DOWN,
+   };
+   return psci_ops.cpu_suspend(s, virt_to_phys(cpu_resume));
+   }
+
return psci_ops.cpu_suspend(state[index - 1],
virt_to_phys(cpu_resume));
 }
 
 static int __maybe_unused cpu_psci_cpu_suspend(unsigned long index)
 {
-   int ret;
struct psci_power_state *state = __this_cpu_read(psci_power_state);
-   /*
-* idle state index 0 corresponds to wfi, should never be called
-* from the cpu_suspend operations
-*/
-   if (WARN_ON_ONCE(!index))
-   return -EINVAL;
 
-   if (state[index - 1].type == PSCI_POWER_STATE_TYPE_STANDBY)
-   ret = psci_ops.cpu_suspend(state[index - 1], 0);
-   else
-   ret = __cpu_suspend(index, psci_suspend_finisher);
+   if (state) {
+   if (WARN_ON_ONCE(!index))
+   return -EINVAL;
+
+   /*
+* If idle state initialization is successfully done,
+* idle state index 0 corresponds to wfi, should never be
+* called from the cpu_suspend operations
+*/
+   if (state[index - 1].type == PSCI_POWER_STATE_TYPE_STANDBY)
+   return psci_ops.cpu_suspend(state[index - 1], 0);
+   }
 
-   return ret;
+   return __cpu_suspend(index, psci_suspend_finisher);
 }
 
 const struct cpu_operations cpu_psci_ops = {
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 04/10] power: charger-manager: Fix to use CHARGE_NOW/FULL property correctly.

2014-10-30 Thread Jonghwa Lee
The POWER_SUPPLY_CHARGE_NOW/FULL property reflects battery's charges
in uAh unit, but charger-manager has been used it wrongly. This patch
makes it to use those propeties correctly and change to be optional.

Signed-off-by: Jonghwa Lee 
---
 drivers/power/charger-manager.c |   85 +--
 1 file changed, 28 insertions(+), 57 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 64fdaaf..687f109 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -796,35 +796,13 @@ static int charger_get_property(struct power_supply *psy,
val->intval = 0;
break;
case POWER_SUPPLY_PROP_CHARGE_FULL:
-   if (is_full_charged(cm))
-   val->intval = 1;
-   else
-   val->intval = 0;
-   ret = 0;
-   break;
case POWER_SUPPLY_PROP_CHARGE_NOW:
-   if (is_charging(cm)) {
-   fuel_gauge = power_supply_get_by_name(
-   cm->desc->psy_fuel_gauge);
-   if (!fuel_gauge) {
-   ret = -ENODEV;
-   break;
-   }
-
-   ret = fuel_gauge->get_property(fuel_gauge,
-   POWER_SUPPLY_PROP_CHARGE_NOW,
-   val);
-   if (ret) {
-   val->intval = 1;
-   ret = 0;
-   } else {
-   /* If CHARGE_NOW is supplied, use it */
-   val->intval = (val->intval > 0) ?
-   val->intval : 1;
-   }
-   } else {
-   val->intval = 0;
+   fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge);
+   if (!fuel_gauge) {
+   ret = -ENODEV;
+   break;
}
+   ret = fuel_gauge->get_property(fuel_gauge, psp, val);
break;
default:
return -EINVAL;
@@ -832,8 +810,7 @@ static int charger_get_property(struct power_supply *psy,
return ret;
 }
 
-#define NUM_CHARGER_PSY_OPTIONAL   (4)
-static enum power_supply_property default_charger_props[] = {
+static enum power_supply_property cm_default_props[] = {
/* Guaranteed to provide */
POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_HEALTH,
@@ -841,20 +818,21 @@ static enum power_supply_property default_charger_props[] 
= {
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_CAPACITY,
POWER_SUPPLY_PROP_ONLINE,
-   POWER_SUPPLY_PROP_CHARGE_FULL,
POWER_SUPPLY_PROP_TEMP,
-   /*
-* Optional properties are:
-* POWER_SUPPLY_PROP_CHARGE_NOW,
-* POWER_SUPPLY_PROP_CURRENT_NOW,
-*/
 };
 
+static enum power_supply_property cm_optional_props[] = {
+   POWER_SUPPLY_PROP_CHARGE_FULL,
+   POWER_SUPPLY_PROP_CHARGE_NOW,
+   POWER_SUPPLY_PROP_CURRENT_NOW,
+};
+
+#define CM_NUM_OF_PROPS\
+   (ARRAY_SIZE(cm_default_props) + ARRAY_SIZE(cm_optional_props))
+
 static struct power_supply psy_default = {
.name = "battery",
.type = POWER_SUPPLY_TYPE_BATTERY,
-   .properties = default_charger_props,
-   .num_properties = ARRAY_SIZE(default_charger_props),
.get_property = charger_get_property,
.no_thermal = true,
 };
@@ -1484,29 +1462,22 @@ static int charger_manager_probe(struct platform_device 
*pdev)
/* Allocate for psy properties because they may vary */
cm->charger_psy.properties = devm_kzalloc(>dev,
sizeof(enum power_supply_property)
-   * (ARRAY_SIZE(default_charger_props) +
-   NUM_CHARGER_PSY_OPTIONAL), GFP_KERNEL);
+   * CM_NUM_OF_PROPS, GFP_KERNEL);
if (!cm->charger_psy.properties)
return -ENOMEM;
 
-   memcpy(cm->charger_psy.properties, default_charger_props,
-   sizeof(enum power_supply_property) *
-   ARRAY_SIZE(default_charger_props));
-   cm->charger_psy.num_properties = psy_default.num_properties;
-
-   /* Find which optional psy-properties are available */
-   if (!fuel_gauge->get_property(fuel_gauge,
- POWER_SUPPLY_PROP_CHARGE_NOW, )) {
-   cm->charger_psy.properties[cm->charger_psy.num_properties] =
-   POWER_SUPPLY_PROP_CHARGE_NOW;
-   cm->charger_psy.num_properties++;
-   }
-   if (!fuel_gauge->get_propert

[PATCH 05/10] power: charger-manager: Concentrate scattered power_supply_changed() calls.

2014-10-30 Thread Jonghwa Lee
Current charger-manager calls power_suuply_changed() whenever charging
status is changed. This patch removes seperated power_supply_changed()
use and let it be called at end of try_charger_enable() function which
is called to set charging/discharging.

Signed-off-by: Jonghwa Lee 
---
 drivers/power/charger-manager.c |   18 ++
 1 file changed, 6 insertions(+), 12 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 687f109..bb44588 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -382,8 +382,10 @@ static int try_charger_enable(struct charger_manager *cm, 
bool enable)
}
}
 
-   if (!err)
+   if (!err) {
cm->charger_enabled = enable;
+   power_supply_changed(>charger_psy);
+   }
 
return err;
 }
@@ -436,10 +438,8 @@ static void fullbatt_vchk(struct charger_manager *cm)
 
dev_info(cm->dev, "VBATT dropped %duV after full-batt\n", diff);
 
-   if (diff > desc->fullbatt_vchkdrop_uV) {
+   if (diff > desc->fullbatt_vchkdrop_uV)
try_charger_restart(cm);
-   power_supply_changed(>charger_psy);
-   }
 }
 
 /**
@@ -469,7 +469,6 @@ static int check_charging_duration(struct charger_manager 
*cm)
if (duration > desc->charging_max_duration_ms) {
dev_info(cm->dev, "Charging duration exceed %ums\n",
 desc->charging_max_duration_ms);
-   power_supply_changed(>charger_psy);
try_charger_enable(cm, false);
ret = true;
}
@@ -480,7 +479,6 @@ static int check_charging_duration(struct charger_manager 
*cm)
is_ext_pwr_online(cm)) {
dev_info(cm->dev, "Discharging duration exceed %ums\n",
 desc->discharging_max_duration_ms);
-   power_supply_changed(>charger_psy);
try_charger_enable(cm, true);
ret = true;
}
@@ -561,8 +559,7 @@ static bool _cm_monitor(struct charger_manager *cm)
 */
if (temp_alrt) {
cm->emergency_stop = temp_alrt;
-   if (!try_charger_enable(cm, false))
-   power_supply_changed(>charger_psy);
+   try_charger_enable(cm, false);
 
/*
 * Check whole charging duration and discharing duration
@@ -587,16 +584,13 @@ static bool _cm_monitor(struct charger_manager *cm)
} else if (!cm->emergency_stop && is_full_charged(cm) &&
cm->charger_enabled) {
dev_info(cm->dev, "EVENT_HANDLE: Battery Fully Charged\n");
-   power_supply_changed(>charger_psy);
-
try_charger_enable(cm, false);
 
fullbatt_vchk(cm);
} else {
cm->emergency_stop = 0;
if (is_ext_pwr_online(cm)) {
-   if (!try_charger_enable(cm, true))
-   power_supply_changed(>charger_psy);
+   try_charger_enable(cm, true);
}
}
 
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 02/10] power: charger-manager: Use power_supply_changed() not private uevent.

2014-10-30 Thread Jonghwa Lee
Whenever battery status is changed, charger manager tries to trigger uevent
through private interface. This patch modifies it to use power_supply_changed()
since it belongs to power supply subsystem.

Signed-off-by: Jonghwa Lee 
---
 drivers/power/charger-manager.c |   91 +--
 1 file changed, 11 insertions(+), 80 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index b4b101c..33a1a4d 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -28,18 +28,6 @@
 #include 
 #include 
 
-static const char * const default_event_names[] = {
-   [CM_EVENT_UNKNOWN] = "Unknown",
-   [CM_EVENT_BATT_FULL] = "Battery Full",
-   [CM_EVENT_BATT_IN] = "Battery Inserted",
-   [CM_EVENT_BATT_OUT] = "Battery Pulled Out",
-   [CM_EVENT_BATT_OVERHEAT] = "Battery Overheat",
-   [CM_EVENT_BATT_COLD] = "Battery Cold",
-   [CM_EVENT_EXT_PWR_IN_OUT] = "External Power Attach/Detach",
-   [CM_EVENT_CHG_START_STOP] = "Charging Start/Stop",
-   [CM_EVENT_OTHERS] = "Other battery events"
-};
-
 /*
  * Regard CM_JIFFIES_SMALL jiffies is small enough to ignore for
  * delayed works so that we can run delayed works with CM_JIFFIES_SMALL
@@ -56,8 +44,6 @@ static const char * const default_event_names[] = {
  */
 #define CM_RTC_SMALL   (2)
 
-#define UEVENT_BUF_SIZE32
-
 static LIST_HEAD(cm_list);
 static DEFINE_MUTEX(cm_list_mtx);
 
@@ -423,61 +409,6 @@ static int try_charger_restart(struct charger_manager *cm)
 }
 
 /**
- * uevent_notify - Let users know something has changed.
- * @cm: the Charger Manager representing the battery.
- * @event: the event string.
- *
- * If @event is null, it implies that uevent_notify is called
- * by resume function. When called in the resume function, cm_suspended
- * should be already reset to false in order to let uevent_notify
- * notify the recent event during the suspend to users. While
- * suspended, uevent_notify does not notify users, but tracks
- * events so that uevent_notify can notify users later after resumed.
- */
-static void uevent_notify(struct charger_manager *cm, const char *event)
-{
-   static char env_str[UEVENT_BUF_SIZE + 1] = "";
-   static char env_str_save[UEVENT_BUF_SIZE + 1] = "";
-
-   if (cm_suspended) {
-   /* Nothing in suspended-event buffer */
-   if (env_str_save[0] == 0) {
-   if (!strncmp(env_str, event, UEVENT_BUF_SIZE))
-   return; /* status not changed */
-   strncpy(env_str_save, event, UEVENT_BUF_SIZE);
-   return;
-   }
-
-   if (!strncmp(env_str_save, event, UEVENT_BUF_SIZE))
-   return; /* Duplicated. */
-   strncpy(env_str_save, event, UEVENT_BUF_SIZE);
-   return;
-   }
-
-   if (event == NULL) {
-   /* No messages pending */
-   if (!env_str_save[0])
-   return;
-
-   strncpy(env_str, env_str_save, UEVENT_BUF_SIZE);
-   kobject_uevent(>dev->kobj, KOBJ_CHANGE);
-   env_str_save[0] = 0;
-
-   return;
-   }
-
-   /* status not changed */
-   if (!strncmp(env_str, event, UEVENT_BUF_SIZE))
-   return;
-
-   /* save the status and notify the update */
-   strncpy(env_str, event, UEVENT_BUF_SIZE);
-   kobject_uevent(>dev->kobj, KOBJ_CHANGE);
-
-   dev_info(cm->dev, "%s\n", event);
-}
-
-/**
  * fullbatt_vchk - Check voltage drop some times after "FULL" event.
  * @work: the work_struct appointing the function
  *
@@ -514,7 +445,7 @@ static void fullbatt_vchk(struct work_struct *work)
 
if (diff > desc->fullbatt_vchkdrop_uV) {
try_charger_restart(cm);
-   uevent_notify(cm, "Recharging");
+   power_supply_changed(>charger_psy);
}
 }
 
@@ -545,7 +476,7 @@ static int check_charging_duration(struct charger_manager 
*cm)
if (duration > desc->charging_max_duration_ms) {
dev_info(cm->dev, "Charging duration exceed %ums\n",
 desc->charging_max_duration_ms);
-   uevent_notify(cm, "Discharging");
+   power_supply_changed(>charger_psy);
try_charger_enable(cm, false);
ret = true;
}
@@ -556,7 +487,7 @@ static int check_charging_duration(struct charger_manager 
*cm)
is_ext_pwr_online(cm)) {
dev_info(cm->dev, "Discharging duration exceed %ums\n",
 desc->discharging_m

[PATCH 01/10] power: charger-manager: Use thermal subsystem interface only to get temperature.

2014-10-30 Thread Jonghwa Lee
It drops the way of using power_supply interface to reference battery's
temperature. Then it tries to use thermal subsystem's only. This makes driver
more simple and also can remove ifdeferies.

Signed-off-by: Jonghwa Lee 
---
 drivers/power/Kconfig |1 +
 drivers/power/charger-manager.c   |  113 -
 include/linux/power/charger-manager.h |3 +-
 3 files changed, 28 insertions(+), 89 deletions(-)

diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 8ff2511..115d153 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -317,6 +317,7 @@ config CHARGER_MANAGER
bool "Battery charger manager for multiple chargers"
depends on REGULATOR
select EXTCON
+   select THERMAL
help
   Say Y to enable charger-manager support, which allows multiple
   chargers attached to a battery and multiple batteries attached to a
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 22246b9..b4b101c 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -28,13 +28,6 @@
 #include 
 #include 
 
-/*
- * Default termperature threshold for charging.
- * Every temperature units are in tenth of centigrade.
- */
-#define CM_DEFAULT_RECHARGE_TEMP_DIFF  50
-#define CM_DEFAULT_CHARGE_TEMP_MAX 500
-
 static const char * const default_event_names[] = {
[CM_EVENT_UNKNOWN] = "Unknown",
[CM_EVENT_BATT_FULL] = "Battery Full",
@@ -572,40 +565,18 @@ static int check_charging_duration(struct charger_manager 
*cm)
return ret;
 }
 
-static int cm_get_battery_temperature_by_psy(struct charger_manager *cm,
-   int *temp)
-{
-   struct power_supply *fuel_gauge;
-
-   fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge);
-   if (!fuel_gauge)
-   return -ENODEV;
-
-   return fuel_gauge->get_property(fuel_gauge,
-   POWER_SUPPLY_PROP_TEMP,
-   (union power_supply_propval *)temp);
-}
-
 static int cm_get_battery_temperature(struct charger_manager *cm,
int *temp)
 {
int ret;
 
-   if (!cm->desc->measure_battery_temp)
+   if (!cm->tzd_batt)
return -ENODEV;
 
-#ifdef CONFIG_THERMAL
-   if (cm->tzd_batt) {
-   ret = thermal_zone_get_temp(cm->tzd_batt, (unsigned long 
*)temp);
-   if (!ret)
-   /* Calibrate temperature unit */
-   *temp /= 100;
-   } else
-#endif
-   {
-   /* if-else continued from CONFIG_THERMAL */
-   ret = cm_get_battery_temperature_by_psy(cm, temp);
-   }
+   ret = thermal_zone_get_temp(cm->tzd_batt, (unsigned long *)temp);
+   if (!ret)
+   /* Calibrate temperature unit */
+   *temp /= 100;
 
return ret;
 }
@@ -623,7 +594,7 @@ static int cm_check_thermal_status(struct charger_manager 
*cm)
 * occur hazadous result. We have to handle it
 * depending on battery type.
 */
-   dev_err(cm->dev, "Failed to get battery temperature\n");
+   dev_dbg(cm->dev, "Failed to get battery temperature\n");
return 0;
}
 
@@ -1007,12 +978,11 @@ static enum power_supply_property 
default_charger_props[] = {
POWER_SUPPLY_PROP_CAPACITY,
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_CHARGE_FULL,
+   POWER_SUPPLY_PROP_TEMP,
/*
 * Optional properties are:
 * POWER_SUPPLY_PROP_CHARGE_NOW,
 * POWER_SUPPLY_PROP_CURRENT_NOW,
-* POWER_SUPPLY_PROP_TEMP, and
-* POWER_SUPPLY_PROP_TEMP_AMBIENT,
 */
 };
 
@@ -1417,49 +1387,6 @@ err:
return ret;
 }
 
-static int cm_init_thermal_data(struct charger_manager *cm,
-   struct power_supply *fuel_gauge)
-{
-   struct charger_desc *desc = cm->desc;
-   union power_supply_propval val;
-   int ret;
-
-   /* Verify whether fuel gauge provides battery temperature */
-   ret = fuel_gauge->get_property(fuel_gauge,
-   POWER_SUPPLY_PROP_TEMP, );
-
-   if (!ret) {
-   cm->charger_psy.properties[cm->charger_psy.num_properties] =
-   POWER_SUPPLY_PROP_TEMP;
-   cm->charger_psy.num_properties++;
-   cm->desc->measure_battery_temp = true;
-   }
-#ifdef CONFIG_THERMAL
-   if (ret && desc->thermal_zone) {
-   cm->tzd_batt =
-   thermal_zone_get_zone_by_name(desc->thermal_zone);
-   if (IS_ERR(cm->tzd_batt))
-   return PTR_ERR(cm->tzd_ba

[PATCH 03/10] power: charger-manager: Remove deprecated function, cm_notify_event().

2014-10-30 Thread Jonghwa Lee
cm_notify_event() is introduced to get event associated with battery status
externally, but no one had been used. Moreover it makes charger manager
driver more complicated. This patch tries to drop the function and all data
related to simplify the driver.

Signed-off-by: Jonghwa Lee 
---
 .../bindings/power_supply/charger-manager.txt  |1 -
 drivers/power/charger-manager.c|  196 +---
 include/linux/power/charger-manager.h  |   19 +-
 3 files changed, 8 insertions(+), 208 deletions(-)

diff --git a/Documentation/devicetree/bindings/power_supply/charger-manager.txt 
b/Documentation/devicetree/bindings/power_supply/charger-manager.txt
index 2b33750..767aaa5 100644
--- a/Documentation/devicetree/bindings/power_supply/charger-manager.txt
+++ b/Documentation/devicetree/bindings/power_supply/charger-manager.txt
@@ -39,7 +39,6 @@ Example :
cm-poll-mode = <1>;
cm-poll-interval = <3>;
 
-   cm-fullbatt-vchkdrop-ms = <3>;
cm-fullbatt-vchkdrop-volt = <15>;
cm-fullbatt-soc = <100>;
 
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 33a1a4d..64fdaaf 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -410,25 +410,18 @@ static int try_charger_restart(struct charger_manager *cm)
 
 /**
  * fullbatt_vchk - Check voltage drop some times after "FULL" event.
- * @work: the work_struct appointing the function
  *
- * If a user has designated "fullbatt_vchkdrop_ms/uV" values with
+ * If a user has designated "fullbatt_vchkdrop_uV" values with
  * charger_desc, Charger Manager checks voltage drop after the battery
  * "FULL" event. It checks whether the voltage has dropped more than
  * fullbatt_vchkdrop_uV by calling this function after fullbatt_vchkrop_ms.
  */
-static void fullbatt_vchk(struct work_struct *work)
+static void fullbatt_vchk(struct charger_manager *cm)
 {
-   struct delayed_work *dwork = to_delayed_work(work);
-   struct charger_manager *cm = container_of(dwork,
-   struct charger_manager, fullbatt_vchk_work);
struct charger_desc *desc = cm->desc;
int batt_uV, err, diff;
 
-   /* remove the appointment for fullbatt_vchk */
-   cm->fullbatt_vchk_jiffies_at = 0;
-
-   if (!desc->fullbatt_vchkdrop_uV || !desc->fullbatt_vchkdrop_ms)
+   if (!desc->fullbatt_vchkdrop_uV)
return;
 
err = get_batt_uV(cm, _uV);
@@ -585,7 +578,7 @@ static bool _cm_monitor(struct charger_manager *cm)
 */
} else if (!cm->emergency_stop && is_ext_pwr_online(cm) &&
!cm->charger_enabled) {
-   fullbatt_vchk(>fullbatt_vchk_work.work);
+   fullbatt_vchk(cm);
 
/*
 * Check whether fully charged state to protect overcharge
@@ -598,7 +591,7 @@ static bool _cm_monitor(struct charger_manager *cm)
 
try_charger_enable(cm, false);
 
-   fullbatt_vchk(>fullbatt_vchk_work.work);
+   fullbatt_vchk(cm);
} else {
cm->emergency_stop = 0;
if (is_ext_pwr_online(cm)) {
@@ -700,66 +693,6 @@ static void cm_monitor_poller(struct work_struct *work)
schedule_work(_polling);
 }
 
-/**
- * fullbatt_handler - Event handler for CM_EVENT_BATT_FULL
- * @cm: the Charger Manager representing the battery.
- */
-static void fullbatt_handler(struct charger_manager *cm)
-{
-   struct charger_desc *desc = cm->desc;
-
-   if (!desc->fullbatt_vchkdrop_uV || !desc->fullbatt_vchkdrop_ms)
-   goto out;
-
-   if (cm_suspended)
-   device_set_wakeup_capable(cm->dev, true);
-
-   mod_delayed_work(cm_wq, >fullbatt_vchk_work,
-msecs_to_jiffies(desc->fullbatt_vchkdrop_ms));
-   cm->fullbatt_vchk_jiffies_at = jiffies + msecs_to_jiffies(
-  desc->fullbatt_vchkdrop_ms);
-
-   if (cm->fullbatt_vchk_jiffies_at == 0)
-   cm->fullbatt_vchk_jiffies_at = 1;
-
-out:
-   dev_info(cm->dev, "EVENT_HANDLE: Battery Fully Charged\n");
-   power_supply_changed(>charger_psy);
-}
-
-/**
- * battout_handler - Event handler for CM_EVENT_BATT_OUT
- * @cm: the Charger Manager representing the battery.
- */
-static void battout_handler(struct charger_manager *cm)
-{
-   if (cm_suspended)
-   device_set_wakeup_capable(cm->dev, true);
-
-   if (!is_batt_present(cm)) {
-   dev_emerg(cm->dev, "Battery Pulled Out!\n");
-   power_supply_changed(>charger_psy);
-   } else {
-   power_supply_changed(>charger_psy);
-   }
-}
-
-/**
- * misc_event_handler - Handler for othe

[PATCH 08/10] power: charger-manager: Not to start charging directly in cable nofitication.

2014-10-30 Thread Jonghwa Lee
This patch prevents direct charging control in cable notification.
It sets only input current limit according to cable type and yields charging
control to be done by cm_monitor() where charging management proceeds.
It may loose few ms to enable charging compared to before, even though it's
more important that charging is enabled always in safe context.

Signed-off-by: Jonghwa Lee 
---
 drivers/power/charger-manager.c |   12 ++--
 1 file changed, 2 insertions(+), 10 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 065b92a..1ccb9be 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -849,7 +849,8 @@ static void charger_extcon_work(struct work_struct *work)
cable->min_uA, cable->max_uA);
}
 
-   try_charger_enable(cable->cm, cable->attached);
+   cancel_delayed_work(_monitor_work);
+   queue_delayed_work(cm_wq, _monitor_work, 0);
 }
 
 /**
@@ -873,15 +874,6 @@ static int charger_extcon_notifier(struct notifier_block 
*self,
cable->attached = event;
 
/*
-* Setup monitoring to check battery state
-* when charger cable is attached.
-*/
-   if (cable->attached && is_polling_required(cable->cm)) {
-   cancel_work_sync(_polling);
-   schedule_work(_polling);
-   }
-
-   /*
 * Setup work for controlling charger(regulator)
 * according to charger cable.
 */
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 07/10] power: charger-manager: Make chraging decision focusing on battery status.

2014-10-30 Thread Jonghwa Lee
In cm_monitor() where charging management starts, it checks various charging
condition sequentially to decide next charging operation. However, as it
follows sequential process, cascaded IF statements, it does some duplicated
jobs which is already done in previous stage. It results delay in decision
making. And moreover, starting point of charing is spreaded all around, so
it makes maintain codes and debugging difficult.

Both of problems mentioned above becomes clean if it manages battery charging
focusing on battery status not following sequential condition checking.
Now, cm_monitor() moves battery state diagram and does optimal operation for
current state. As a result, it reduces whole monitoring time almost in half.

Signed-off-by: Jonghwa Lee 
---
 drivers/power/charger-manager.c   |  177 +++--
 include/linux/power/charger-manager.h |3 +
 2 files changed, 62 insertions(+), 118 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 172dfe5..065b92a 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -249,6 +249,19 @@ static bool is_full_charged(struct charger_manager *cm)
if (!fuel_gauge)
return false;
 
+   /* Full, if it's over the fullbatt voltage */
+   if (desc->fullbatt_uV > 0) {
+   ret = get_batt_uV(cm, );
+   if (!ret) {
+   /* Battery is already full, checks voltage drop. */
+   if (cm->battery_status == POWER_SUPPLY_STATUS_FULL
+   && desc->fullbatt_vchkdrop_uV)
+   uV += desc->fullbatt_vchkdrop_uV;
+   if (uV >= desc->fullbatt_uV)
+   return true;
+   }
+   }
+
if (desc->fullbatt_full_capacity > 0) {
val.intval = 0;
 
@@ -259,13 +272,6 @@ static bool is_full_charged(struct charger_manager *cm)
return true;
}
 
-   /* Full, if it's over the fullbatt voltage */
-   if (desc->fullbatt_uV > 0) {
-   ret = get_batt_uV(cm, );
-   if (!ret && uV >= desc->fullbatt_uV)
-   return true;
-   }
-
/* Full, if the capacity is more than fullbatt_soc */
if (desc->fullbatt_soc > 0) {
val.intval = 0;
@@ -376,67 +382,13 @@ static int try_charger_enable(struct charger_manager *cm, 
bool enable)
}
}
 
-   if (!err) {
+   if (!err)
cm->charger_enabled = enable;
-   power_supply_changed(>charger_psy);
-   }
 
return err;
 }
 
 /**
- * try_charger_restart - Restart charging.
- * @cm: the Charger Manager representing the battery.
- *
- * Restart charging by turning off and on the charger.
- */
-static int try_charger_restart(struct charger_manager *cm)
-{
-   int err;
-
-   if (cm->emergency_stop)
-   return -EAGAIN;
-
-   err = try_charger_enable(cm, false);
-   if (err)
-   return err;
-
-   return try_charger_enable(cm, true);
-}
-
-/**
- * fullbatt_vchk - Check voltage drop some times after "FULL" event.
- *
- * If a user has designated "fullbatt_vchkdrop_uV" values with
- * charger_desc, Charger Manager checks voltage drop after the battery
- * "FULL" event. It checks whether the voltage has dropped more than
- * fullbatt_vchkdrop_uV by calling this function after fullbatt_vchkrop_ms.
- */
-static void fullbatt_vchk(struct charger_manager *cm)
-{
-   struct charger_desc *desc = cm->desc;
-   int batt_uV, err, diff;
-
-   if (!desc->fullbatt_vchkdrop_uV)
-   return;
-
-   err = get_batt_uV(cm, _uV);
-   if (err) {
-   dev_err(cm->dev, "%s: get_batt_uV error(%d)\n", __func__, err);
-   return;
-   }
-
-   diff = desc->fullbatt_uV - batt_uV;
-   if (diff < 0)
-   return;
-
-   dev_info(cm->dev, "VBATT dropped %duV after full-batt\n", diff);
-
-   if (diff > desc->fullbatt_vchkdrop_uV)
-   try_charger_restart(cm);
-}
-
-/**
  * check_charging_duration - Monitor charging/discharging duration
  * @cm: the Charger Manager representing the battery.
  *
@@ -463,17 +415,14 @@ static int check_charging_duration(struct charger_manager 
*cm)
if (duration > desc->charging_max_duration_ms) {
dev_info(cm->dev, "Charging duration exceed %ums\n",
 desc->charging_max_duration_ms);
-   try_charger_enable(cm, false);
ret = true;
}
-   } else if (is_ext_pwr_online(cm) && !cm->charger_enabled) {
+   } else if (c

[PATCH V2 0/10] Improve charger manager driver for optimized operation.

2014-10-30 Thread Jonghwa Lee
After charger manager's initially introduced, it has kept its codes without any
big change. However, the charger manager working operation isn't optimized and
it also has unused codes and non-generic interface. This series tries to make
charger manager more generic and maintainable with some fixes.

[Changes in V2]
- Rebase patch series on latest of battery-2.6.git.
- Seperate 'power: charger-manager: Rearrange data and monitor ~' patch into
  several patches depends on its purpose.
- Add 2 patches related with polling mode.

Jonghwa Lee (10):
  power: charger-manager: Use thermal subsystem interface only to get
temperature.
  power: charger-manager: Use power_supply_changed() not private
uevent.
  power: charger-manager: Remove deprecated function,
cm_notify_event().
  power: charger-manager: Fix to use CHARGE_NOW/FULL property
correctly.
  power: charger-manager: Concentrate scattered power_supply_changed()
calls.
  power: charger-manager: Get external power souce information only
from EXTCON.
  power: charger-manager: Make chraging decision focusing on battery
status.
  power: charger-manager: Not to start charging directly in cable
nofitication.
  power: charger-manager: Support different polling mode for sleep
state.
  power: charger-manager: Support to change polling rate in runtime.

 .../bindings/power_supply/charger-manager.txt  |1 -
 drivers/power/Kconfig  |1 +
 drivers/power/charger-manager.c|  758 ++--
 include/linux/power/charger-manager.h  |   34 +-
 4 files changed, 219 insertions(+), 575 deletions(-)

-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 09/10] power: charger-manager: Support different polling mode for sleep state.

2014-10-30 Thread Jonghwa Lee
Add additional polling mode for sleep state to define different mode with
normal state. With this change, charger-manager can work differently in
normal state or sleep state. e.g, polling aways for normal and polling
only when charing for sleep. If there is no defined polling mode for
sleep state it just follows the normal state's.
In addition to, polling rate is still same in sleep.

Signed-off-by: Jonghwa Lee 
---
 drivers/power/charger-manager.c   |   20 +---
 include/linux/power/charger-manager.h |9 ++---
 2 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 1ccb9be..0a0834f 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -291,7 +291,15 @@ static bool is_full_charged(struct charger_manager *cm)
  */
 static bool is_polling_required(struct charger_manager *cm)
 {
-   switch (cm->desc->polling_mode) {
+   enum polling_modes polling_mode;
+
+   if (cm_suspended
+   && cm->desc->poll_mode_sleep >= 0)
+   polling_mode = cm->desc->poll_mode_sleep;
+   else
+   polling_mode = cm->desc->poll_mode_normal;
+
+   switch (polling_mode) {
case CM_POLL_DISABLE:
return false;
case CM_POLL_ALWAYS:
@@ -302,7 +310,7 @@ static bool is_polling_required(struct charger_manager *cm)
return is_charging(cm);
default:
dev_warn(cm->dev, "Incorrect polling_mode (%d)\n",
-cm->desc->polling_mode);
+polling_mode);
}
 
return false;
@@ -1158,7 +1166,13 @@ static struct charger_desc *of_cm_parse_desc(struct 
device *dev)
of_property_read_string(np, "cm-name", >psy_name);
 
of_property_read_u32(np, "cm-poll-mode", _mode);
-   desc->polling_mode = poll_mode;
+   desc->poll_mode_normal = poll_mode;
+
+   /* Polling mode in sleep state */
+   if (!of_property_read_u32(np, "cm-poll-mode-sleep", _mode))
+   desc->poll_mode_sleep = poll_mode;
+   else
+   desc->poll_mode_sleep = -EINVAL;
 
of_property_read_u32(np, "cm-poll-interval",
>polling_interval_ms);
diff --git a/include/linux/power/charger-manager.h 
b/include/linux/power/charger-manager.h
index 37fb181..a30a0b6 100644
--- a/include/linux/power/charger-manager.h
+++ b/include/linux/power/charger-manager.h
@@ -131,8 +131,10 @@ struct charger_regulator {
 /**
  * struct charger_desc
  * @psy_name: the name of power-supply-class for charger manager
- * @polling_mode:
- * Determine which polling mode will be used
+ * @poll_mode_normal:
+ * Determine which polling mode will be used in normal state.
+ * @poll_mode_sleep:
+ * Determine which polling mode will be used in sleep state.
  * @fullbatt_vchkdrop_uV:
  * Check voltage drop after the battery is fully charged.
  * If it has dropped more than fullbatt_vchkdrop_uV
@@ -170,7 +172,8 @@ struct charger_regulator {
 struct charger_desc {
const char *psy_name;
 
-   enum polling_modes polling_mode;
+   enum polling_modes poll_mode_normal;
+   enum polling_modes poll_mode_sleep;
unsigned int polling_interval_ms;
 
unsigned int fullbatt_vchkdrop_uV;
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 06/10] power: charger-manager: Get external power souce information only from EXTCON.

2014-10-30 Thread Jonghwa Lee
When charger-manager checks whether external power source is available,
it gets information from charger IC driver. However, it's not correct source,
charger IC doesn't have responsibilty to give cable connection status.
The charger-manager already gets cable information from EXTCON susbsystem,
so it can re-use it.

Signed-off-by: Jonghwa Lee 
---
 drivers/power/charger-manager.c |   34 ++
 1 file changed, 14 insertions(+), 20 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index bb44588..172dfe5 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -115,34 +115,28 @@ static bool is_batt_present(struct charger_manager *cm)
  * is_ext_pwr_online - See if an external power source is attached to charge
  * @cm: the Charger Manager representing the battery.
  *
- * Returns true if at least one of the chargers of the battery has an external
- * power source attached to charge the battery regardless of whether it is
- * actually charging or not.
+ * Returns true if there is external power source.
+ * Cable connection information is only obtained by EXTCON class notification.
  */
 static bool is_ext_pwr_online(struct charger_manager *cm)
 {
-   union power_supply_propval val;
-   struct power_supply *psy;
-   bool online = false;
-   int i, ret;
 
-   /* If at least one of them has one, it's yes. */
-   for (i = 0; cm->desc->psy_charger_stat[i]; i++) {
-   psy = power_supply_get_by_name(cm->desc->psy_charger_stat[i]);
-   if (!psy) {
-   dev_err(cm->dev, "Cannot find power supply \"%s\"\n",
-   cm->desc->psy_charger_stat[i]);
-   continue;
-   }
+   struct charger_desc *desc = cm->desc;
+   struct charger_regulator *regulators = desc->charger_regulators;
+   struct charger_cable *cables;
+   int i, j, num_cables;
 
-   ret = psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, );
-   if (ret == 0 && val.intval) {
-   online = true;
-   break;
+   /* If at least one of them has one, it's yes. */
+   for (i = 0; i < desc->num_charger_regulators; i++) {
+   cables = regulators[i].cables;
+   num_cables = regulators[i].num_cables;
+   for (j = 0; j < num_cables; j++) {
+   if (cables[j].attached)
+   return true;
}
}
 
-   return online;
+   return false;
 }
 
 /**
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 10/10] power: charger-manager: Support to change polling rate in runtime.

2014-10-30 Thread Jonghwa Lee
Add 'polling_ms' sysfs node to change charger-manager's monitoring rate
in runtime. It can set only bigger than 2 jiffies (for 200 HZ system it
is 10 msecs.) as it's allowed for minimum poling rate in previous.
It resets poller and re-configure polling rate based on new input if next
polling time is far enough. Otherwise, it just waits expiration of timer
and new polling rate will affects the next scheduling.

Signed-off-by: Jonghwa Lee 
---
 drivers/power/charger-manager.c |   62 +++
 1 file changed, 62 insertions(+)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 0a0834f..7a007f4 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -1054,6 +1054,63 @@ static ssize_t charger_externally_control_store(struct 
device *dev,
return count;
 }
 
+static ssize_t show_polling_ms(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   struct charger_manager *cm;
+   ssize_t len;
+
+   list_for_each_entry(cm, _list, entry)
+   if (cm->charger_psy.dev == dev)
+   break;
+
+   if (cm->charger_psy.dev != dev)
+   return -EINVAL;
+
+   len = sprintf(buf, "%d\n", cm->desc->polling_interval_ms);
+
+   return len;
+}
+
+static ssize_t store_polling_ms(struct device *dev,
+   struct device_attribute *attr, const char *buf,
+   size_t count)
+{
+   struct charger_manager *cm;
+   int polling_ms;
+   int ret;
+
+   ret = sscanf(buf, "%d", _ms);
+   if (ret < 0 )
+   return -EINVAL;
+
+   if (polling_ms < CM_JIFFIES_SMALL * MSEC_PER_SEC / HZ)
+   return -EINVAL;
+
+   list_for_each_entry(cm, _list, entry)
+   if (cm->charger_psy.dev == dev)
+   break;
+
+   if (cm->charger_psy.dev != dev)
+   return -ENODEV;
+
+   cm->desc->polling_interval_ms = polling_ms;
+
+   pr_info("Polling interval's changed to %u ms.\n",
+   cm->desc->polling_interval_ms);
+
+   if (next_polling - jiffies >
+   msecs_to_jiffies(cm->desc->polling_interval_ms)) {
+   pr_info("Reset poller now... \n");
+   cancel_delayed_work(_monitor_work);
+   schedule_work(_polling);
+   }
+
+   return count;
+}
+
+static DEVICE_ATTR(polling_ms, 0644, show_polling_ms, store_polling_ms);
+
 /**
  * charger_manager_register_sysfs - Register sysfs entry for each charger
  * @cm: the Charger Manager representing the battery.
@@ -1077,6 +1134,11 @@ static int charger_manager_register_sysfs(struct 
charger_manager *cm)
int ret = 0;
int i;
 
+   /* Create polling_ms sysfs node */
+   ret = device_create_file(cm->charger_psy.dev, _attr_polling_ms);
+   if (ret)
+   pr_err("Failed to create poling_ms sysfs node (%d)\n", ret);
+
/* Create sysfs entry to control charger(regulator) */
for (i = 0; i < desc->num_charger_regulators; i++) {
charger = >charger_regulators[i];
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 10/10] power: charger-manager: Support to change polling rate in runtime.

2014-10-30 Thread Jonghwa Lee
Add 'polling_ms' sysfs node to change charger-manager's monitoring rate
in runtime. It can set only bigger than 2 jiffies (for 200 HZ system it
is 10 msecs.) as it's allowed for minimum poling rate in previous.
It resets poller and re-configure polling rate based on new input if next
polling time is far enough. Otherwise, it just waits expiration of timer
and new polling rate will affects the next scheduling.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 drivers/power/charger-manager.c |   62 +++
 1 file changed, 62 insertions(+)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 0a0834f..7a007f4 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -1054,6 +1054,63 @@ static ssize_t charger_externally_control_store(struct 
device *dev,
return count;
 }
 
+static ssize_t show_polling_ms(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   struct charger_manager *cm;
+   ssize_t len;
+
+   list_for_each_entry(cm, cm_list, entry)
+   if (cm-charger_psy.dev == dev)
+   break;
+
+   if (cm-charger_psy.dev != dev)
+   return -EINVAL;
+
+   len = sprintf(buf, %d\n, cm-desc-polling_interval_ms);
+
+   return len;
+}
+
+static ssize_t store_polling_ms(struct device *dev,
+   struct device_attribute *attr, const char *buf,
+   size_t count)
+{
+   struct charger_manager *cm;
+   int polling_ms;
+   int ret;
+
+   ret = sscanf(buf, %d, polling_ms);
+   if (ret  0 )
+   return -EINVAL;
+
+   if (polling_ms  CM_JIFFIES_SMALL * MSEC_PER_SEC / HZ)
+   return -EINVAL;
+
+   list_for_each_entry(cm, cm_list, entry)
+   if (cm-charger_psy.dev == dev)
+   break;
+
+   if (cm-charger_psy.dev != dev)
+   return -ENODEV;
+
+   cm-desc-polling_interval_ms = polling_ms;
+
+   pr_info(Polling interval's changed to %u ms.\n,
+   cm-desc-polling_interval_ms);
+
+   if (next_polling - jiffies 
+   msecs_to_jiffies(cm-desc-polling_interval_ms)) {
+   pr_info(Reset poller now... \n);
+   cancel_delayed_work(cm_monitor_work);
+   schedule_work(setup_polling);
+   }
+
+   return count;
+}
+
+static DEVICE_ATTR(polling_ms, 0644, show_polling_ms, store_polling_ms);
+
 /**
  * charger_manager_register_sysfs - Register sysfs entry for each charger
  * @cm: the Charger Manager representing the battery.
@@ -1077,6 +1134,11 @@ static int charger_manager_register_sysfs(struct 
charger_manager *cm)
int ret = 0;
int i;
 
+   /* Create polling_ms sysfs node */
+   ret = device_create_file(cm-charger_psy.dev, dev_attr_polling_ms);
+   if (ret)
+   pr_err(Failed to create poling_ms sysfs node (%d)\n, ret);
+
/* Create sysfs entry to control charger(regulator) */
for (i = 0; i  desc-num_charger_regulators; i++) {
charger = desc-charger_regulators[i];
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 09/10] power: charger-manager: Support different polling mode for sleep state.

2014-10-30 Thread Jonghwa Lee
Add additional polling mode for sleep state to define different mode with
normal state. With this change, charger-manager can work differently in
normal state or sleep state. e.g, polling aways for normal and polling
only when charing for sleep. If there is no defined polling mode for
sleep state it just follows the normal state's.
In addition to, polling rate is still same in sleep.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 drivers/power/charger-manager.c   |   20 +---
 include/linux/power/charger-manager.h |9 ++---
 2 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 1ccb9be..0a0834f 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -291,7 +291,15 @@ static bool is_full_charged(struct charger_manager *cm)
  */
 static bool is_polling_required(struct charger_manager *cm)
 {
-   switch (cm-desc-polling_mode) {
+   enum polling_modes polling_mode;
+
+   if (cm_suspended
+cm-desc-poll_mode_sleep = 0)
+   polling_mode = cm-desc-poll_mode_sleep;
+   else
+   polling_mode = cm-desc-poll_mode_normal;
+
+   switch (polling_mode) {
case CM_POLL_DISABLE:
return false;
case CM_POLL_ALWAYS:
@@ -302,7 +310,7 @@ static bool is_polling_required(struct charger_manager *cm)
return is_charging(cm);
default:
dev_warn(cm-dev, Incorrect polling_mode (%d)\n,
-cm-desc-polling_mode);
+polling_mode);
}
 
return false;
@@ -1158,7 +1166,13 @@ static struct charger_desc *of_cm_parse_desc(struct 
device *dev)
of_property_read_string(np, cm-name, desc-psy_name);
 
of_property_read_u32(np, cm-poll-mode, poll_mode);
-   desc-polling_mode = poll_mode;
+   desc-poll_mode_normal = poll_mode;
+
+   /* Polling mode in sleep state */
+   if (!of_property_read_u32(np, cm-poll-mode-sleep, poll_mode))
+   desc-poll_mode_sleep = poll_mode;
+   else
+   desc-poll_mode_sleep = -EINVAL;
 
of_property_read_u32(np, cm-poll-interval,
desc-polling_interval_ms);
diff --git a/include/linux/power/charger-manager.h 
b/include/linux/power/charger-manager.h
index 37fb181..a30a0b6 100644
--- a/include/linux/power/charger-manager.h
+++ b/include/linux/power/charger-manager.h
@@ -131,8 +131,10 @@ struct charger_regulator {
 /**
  * struct charger_desc
  * @psy_name: the name of power-supply-class for charger manager
- * @polling_mode:
- * Determine which polling mode will be used
+ * @poll_mode_normal:
+ * Determine which polling mode will be used in normal state.
+ * @poll_mode_sleep:
+ * Determine which polling mode will be used in sleep state.
  * @fullbatt_vchkdrop_uV:
  * Check voltage drop after the battery is fully charged.
  * If it has dropped more than fullbatt_vchkdrop_uV
@@ -170,7 +172,8 @@ struct charger_regulator {
 struct charger_desc {
const char *psy_name;
 
-   enum polling_modes polling_mode;
+   enum polling_modes poll_mode_normal;
+   enum polling_modes poll_mode_sleep;
unsigned int polling_interval_ms;
 
unsigned int fullbatt_vchkdrop_uV;
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 06/10] power: charger-manager: Get external power souce information only from EXTCON.

2014-10-30 Thread Jonghwa Lee
When charger-manager checks whether external power source is available,
it gets information from charger IC driver. However, it's not correct source,
charger IC doesn't have responsibilty to give cable connection status.
The charger-manager already gets cable information from EXTCON susbsystem,
so it can re-use it.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 drivers/power/charger-manager.c |   34 ++
 1 file changed, 14 insertions(+), 20 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index bb44588..172dfe5 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -115,34 +115,28 @@ static bool is_batt_present(struct charger_manager *cm)
  * is_ext_pwr_online - See if an external power source is attached to charge
  * @cm: the Charger Manager representing the battery.
  *
- * Returns true if at least one of the chargers of the battery has an external
- * power source attached to charge the battery regardless of whether it is
- * actually charging or not.
+ * Returns true if there is external power source.
+ * Cable connection information is only obtained by EXTCON class notification.
  */
 static bool is_ext_pwr_online(struct charger_manager *cm)
 {
-   union power_supply_propval val;
-   struct power_supply *psy;
-   bool online = false;
-   int i, ret;
 
-   /* If at least one of them has one, it's yes. */
-   for (i = 0; cm-desc-psy_charger_stat[i]; i++) {
-   psy = power_supply_get_by_name(cm-desc-psy_charger_stat[i]);
-   if (!psy) {
-   dev_err(cm-dev, Cannot find power supply \%s\\n,
-   cm-desc-psy_charger_stat[i]);
-   continue;
-   }
+   struct charger_desc *desc = cm-desc;
+   struct charger_regulator *regulators = desc-charger_regulators;
+   struct charger_cable *cables;
+   int i, j, num_cables;
 
-   ret = psy-get_property(psy, POWER_SUPPLY_PROP_ONLINE, val);
-   if (ret == 0  val.intval) {
-   online = true;
-   break;
+   /* If at least one of them has one, it's yes. */
+   for (i = 0; i  desc-num_charger_regulators; i++) {
+   cables = regulators[i].cables;
+   num_cables = regulators[i].num_cables;
+   for (j = 0; j  num_cables; j++) {
+   if (cables[j].attached)
+   return true;
}
}
 
-   return online;
+   return false;
 }
 
 /**
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 07/10] power: charger-manager: Make chraging decision focusing on battery status.

2014-10-30 Thread Jonghwa Lee
In cm_monitor() where charging management starts, it checks various charging
condition sequentially to decide next charging operation. However, as it
follows sequential process, cascaded IF statements, it does some duplicated
jobs which is already done in previous stage. It results delay in decision
making. And moreover, starting point of charing is spreaded all around, so
it makes maintain codes and debugging difficult.

Both of problems mentioned above becomes clean if it manages battery charging
focusing on battery status not following sequential condition checking.
Now, cm_monitor() moves battery state diagram and does optimal operation for
current state. As a result, it reduces whole monitoring time almost in half.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 drivers/power/charger-manager.c   |  177 +++--
 include/linux/power/charger-manager.h |3 +
 2 files changed, 62 insertions(+), 118 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 172dfe5..065b92a 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -249,6 +249,19 @@ static bool is_full_charged(struct charger_manager *cm)
if (!fuel_gauge)
return false;
 
+   /* Full, if it's over the fullbatt voltage */
+   if (desc-fullbatt_uV  0) {
+   ret = get_batt_uV(cm, uV);
+   if (!ret) {
+   /* Battery is already full, checks voltage drop. */
+   if (cm-battery_status == POWER_SUPPLY_STATUS_FULL
+desc-fullbatt_vchkdrop_uV)
+   uV += desc-fullbatt_vchkdrop_uV;
+   if (uV = desc-fullbatt_uV)
+   return true;
+   }
+   }
+
if (desc-fullbatt_full_capacity  0) {
val.intval = 0;
 
@@ -259,13 +272,6 @@ static bool is_full_charged(struct charger_manager *cm)
return true;
}
 
-   /* Full, if it's over the fullbatt voltage */
-   if (desc-fullbatt_uV  0) {
-   ret = get_batt_uV(cm, uV);
-   if (!ret  uV = desc-fullbatt_uV)
-   return true;
-   }
-
/* Full, if the capacity is more than fullbatt_soc */
if (desc-fullbatt_soc  0) {
val.intval = 0;
@@ -376,67 +382,13 @@ static int try_charger_enable(struct charger_manager *cm, 
bool enable)
}
}
 
-   if (!err) {
+   if (!err)
cm-charger_enabled = enable;
-   power_supply_changed(cm-charger_psy);
-   }
 
return err;
 }
 
 /**
- * try_charger_restart - Restart charging.
- * @cm: the Charger Manager representing the battery.
- *
- * Restart charging by turning off and on the charger.
- */
-static int try_charger_restart(struct charger_manager *cm)
-{
-   int err;
-
-   if (cm-emergency_stop)
-   return -EAGAIN;
-
-   err = try_charger_enable(cm, false);
-   if (err)
-   return err;
-
-   return try_charger_enable(cm, true);
-}
-
-/**
- * fullbatt_vchk - Check voltage drop some times after FULL event.
- *
- * If a user has designated fullbatt_vchkdrop_uV values with
- * charger_desc, Charger Manager checks voltage drop after the battery
- * FULL event. It checks whether the voltage has dropped more than
- * fullbatt_vchkdrop_uV by calling this function after fullbatt_vchkrop_ms.
- */
-static void fullbatt_vchk(struct charger_manager *cm)
-{
-   struct charger_desc *desc = cm-desc;
-   int batt_uV, err, diff;
-
-   if (!desc-fullbatt_vchkdrop_uV)
-   return;
-
-   err = get_batt_uV(cm, batt_uV);
-   if (err) {
-   dev_err(cm-dev, %s: get_batt_uV error(%d)\n, __func__, err);
-   return;
-   }
-
-   diff = desc-fullbatt_uV - batt_uV;
-   if (diff  0)
-   return;
-
-   dev_info(cm-dev, VBATT dropped %duV after full-batt\n, diff);
-
-   if (diff  desc-fullbatt_vchkdrop_uV)
-   try_charger_restart(cm);
-}
-
-/**
  * check_charging_duration - Monitor charging/discharging duration
  * @cm: the Charger Manager representing the battery.
  *
@@ -463,17 +415,14 @@ static int check_charging_duration(struct charger_manager 
*cm)
if (duration  desc-charging_max_duration_ms) {
dev_info(cm-dev, Charging duration exceed %ums\n,
 desc-charging_max_duration_ms);
-   try_charger_enable(cm, false);
ret = true;
}
-   } else if (is_ext_pwr_online(cm)  !cm-charger_enabled) {
+   } else if (cm-battery_status == POWER_SUPPLY_STATUS_NOT_CHARGING) {
duration = curr - cm-charging_end_time;
 
-   if (duration  desc-charging_max_duration_ms

[PATCH V2 0/10] Improve charger manager driver for optimized operation.

2014-10-30 Thread Jonghwa Lee
After charger manager's initially introduced, it has kept its codes without any
big change. However, the charger manager working operation isn't optimized and
it also has unused codes and non-generic interface. This series tries to make
charger manager more generic and maintainable with some fixes.

[Changes in V2]
- Rebase patch series on latest of battery-2.6.git.
- Seperate 'power: charger-manager: Rearrange data and monitor ~' patch into
  several patches depends on its purpose.
- Add 2 patches related with polling mode.

Jonghwa Lee (10):
  power: charger-manager: Use thermal subsystem interface only to get
temperature.
  power: charger-manager: Use power_supply_changed() not private
uevent.
  power: charger-manager: Remove deprecated function,
cm_notify_event().
  power: charger-manager: Fix to use CHARGE_NOW/FULL property
correctly.
  power: charger-manager: Concentrate scattered power_supply_changed()
calls.
  power: charger-manager: Get external power souce information only
from EXTCON.
  power: charger-manager: Make chraging decision focusing on battery
status.
  power: charger-manager: Not to start charging directly in cable
nofitication.
  power: charger-manager: Support different polling mode for sleep
state.
  power: charger-manager: Support to change polling rate in runtime.

 .../bindings/power_supply/charger-manager.txt  |1 -
 drivers/power/Kconfig  |1 +
 drivers/power/charger-manager.c|  758 ++--
 include/linux/power/charger-manager.h  |   34 +-
 4 files changed, 219 insertions(+), 575 deletions(-)

-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 08/10] power: charger-manager: Not to start charging directly in cable nofitication.

2014-10-30 Thread Jonghwa Lee
This patch prevents direct charging control in cable notification.
It sets only input current limit according to cable type and yields charging
control to be done by cm_monitor() where charging management proceeds.
It may loose few ms to enable charging compared to before, even though it's
more important that charging is enabled always in safe context.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 drivers/power/charger-manager.c |   12 ++--
 1 file changed, 2 insertions(+), 10 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 065b92a..1ccb9be 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -849,7 +849,8 @@ static void charger_extcon_work(struct work_struct *work)
cable-min_uA, cable-max_uA);
}
 
-   try_charger_enable(cable-cm, cable-attached);
+   cancel_delayed_work(cm_monitor_work);
+   queue_delayed_work(cm_wq, cm_monitor_work, 0);
 }
 
 /**
@@ -873,15 +874,6 @@ static int charger_extcon_notifier(struct notifier_block 
*self,
cable-attached = event;
 
/*
-* Setup monitoring to check battery state
-* when charger cable is attached.
-*/
-   if (cable-attached  is_polling_required(cable-cm)) {
-   cancel_work_sync(setup_polling);
-   schedule_work(setup_polling);
-   }
-
-   /*
 * Setup work for controlling charger(regulator)
 * according to charger cable.
 */
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 03/10] power: charger-manager: Remove deprecated function, cm_notify_event().

2014-10-30 Thread Jonghwa Lee
cm_notify_event() is introduced to get event associated with battery status
externally, but no one had been used. Moreover it makes charger manager
driver more complicated. This patch tries to drop the function and all data
related to simplify the driver.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 .../bindings/power_supply/charger-manager.txt  |1 -
 drivers/power/charger-manager.c|  196 +---
 include/linux/power/charger-manager.h  |   19 +-
 3 files changed, 8 insertions(+), 208 deletions(-)

diff --git a/Documentation/devicetree/bindings/power_supply/charger-manager.txt 
b/Documentation/devicetree/bindings/power_supply/charger-manager.txt
index 2b33750..767aaa5 100644
--- a/Documentation/devicetree/bindings/power_supply/charger-manager.txt
+++ b/Documentation/devicetree/bindings/power_supply/charger-manager.txt
@@ -39,7 +39,6 @@ Example :
cm-poll-mode = 1;
cm-poll-interval = 3;
 
-   cm-fullbatt-vchkdrop-ms = 3;
cm-fullbatt-vchkdrop-volt = 15;
cm-fullbatt-soc = 100;
 
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 33a1a4d..64fdaaf 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -410,25 +410,18 @@ static int try_charger_restart(struct charger_manager *cm)
 
 /**
  * fullbatt_vchk - Check voltage drop some times after FULL event.
- * @work: the work_struct appointing the function
  *
- * If a user has designated fullbatt_vchkdrop_ms/uV values with
+ * If a user has designated fullbatt_vchkdrop_uV values with
  * charger_desc, Charger Manager checks voltage drop after the battery
  * FULL event. It checks whether the voltage has dropped more than
  * fullbatt_vchkdrop_uV by calling this function after fullbatt_vchkrop_ms.
  */
-static void fullbatt_vchk(struct work_struct *work)
+static void fullbatt_vchk(struct charger_manager *cm)
 {
-   struct delayed_work *dwork = to_delayed_work(work);
-   struct charger_manager *cm = container_of(dwork,
-   struct charger_manager, fullbatt_vchk_work);
struct charger_desc *desc = cm-desc;
int batt_uV, err, diff;
 
-   /* remove the appointment for fullbatt_vchk */
-   cm-fullbatt_vchk_jiffies_at = 0;
-
-   if (!desc-fullbatt_vchkdrop_uV || !desc-fullbatt_vchkdrop_ms)
+   if (!desc-fullbatt_vchkdrop_uV)
return;
 
err = get_batt_uV(cm, batt_uV);
@@ -585,7 +578,7 @@ static bool _cm_monitor(struct charger_manager *cm)
 */
} else if (!cm-emergency_stop  is_ext_pwr_online(cm) 
!cm-charger_enabled) {
-   fullbatt_vchk(cm-fullbatt_vchk_work.work);
+   fullbatt_vchk(cm);
 
/*
 * Check whether fully charged state to protect overcharge
@@ -598,7 +591,7 @@ static bool _cm_monitor(struct charger_manager *cm)
 
try_charger_enable(cm, false);
 
-   fullbatt_vchk(cm-fullbatt_vchk_work.work);
+   fullbatt_vchk(cm);
} else {
cm-emergency_stop = 0;
if (is_ext_pwr_online(cm)) {
@@ -700,66 +693,6 @@ static void cm_monitor_poller(struct work_struct *work)
schedule_work(setup_polling);
 }
 
-/**
- * fullbatt_handler - Event handler for CM_EVENT_BATT_FULL
- * @cm: the Charger Manager representing the battery.
- */
-static void fullbatt_handler(struct charger_manager *cm)
-{
-   struct charger_desc *desc = cm-desc;
-
-   if (!desc-fullbatt_vchkdrop_uV || !desc-fullbatt_vchkdrop_ms)
-   goto out;
-
-   if (cm_suspended)
-   device_set_wakeup_capable(cm-dev, true);
-
-   mod_delayed_work(cm_wq, cm-fullbatt_vchk_work,
-msecs_to_jiffies(desc-fullbatt_vchkdrop_ms));
-   cm-fullbatt_vchk_jiffies_at = jiffies + msecs_to_jiffies(
-  desc-fullbatt_vchkdrop_ms);
-
-   if (cm-fullbatt_vchk_jiffies_at == 0)
-   cm-fullbatt_vchk_jiffies_at = 1;
-
-out:
-   dev_info(cm-dev, EVENT_HANDLE: Battery Fully Charged\n);
-   power_supply_changed(cm-charger_psy);
-}
-
-/**
- * battout_handler - Event handler for CM_EVENT_BATT_OUT
- * @cm: the Charger Manager representing the battery.
- */
-static void battout_handler(struct charger_manager *cm)
-{
-   if (cm_suspended)
-   device_set_wakeup_capable(cm-dev, true);
-
-   if (!is_batt_present(cm)) {
-   dev_emerg(cm-dev, Battery Pulled Out!\n);
-   power_supply_changed(cm-charger_psy);
-   } else {
-   power_supply_changed(cm-charger_psy);
-   }
-}
-
-/**
- * misc_event_handler - Handler for other evnets
- * @cm: the Charger Manager representing the battery.
- * @type: the Charger Manager representing the battery.
- */
-static void misc_event_handler(struct charger_manager *cm

[PATCH 01/10] power: charger-manager: Use thermal subsystem interface only to get temperature.

2014-10-30 Thread Jonghwa Lee
It drops the way of using power_supply interface to reference battery's
temperature. Then it tries to use thermal subsystem's only. This makes driver
more simple and also can remove ifdeferies.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 drivers/power/Kconfig |1 +
 drivers/power/charger-manager.c   |  113 -
 include/linux/power/charger-manager.h |3 +-
 3 files changed, 28 insertions(+), 89 deletions(-)

diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 8ff2511..115d153 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -317,6 +317,7 @@ config CHARGER_MANAGER
bool Battery charger manager for multiple chargers
depends on REGULATOR
select EXTCON
+   select THERMAL
help
   Say Y to enable charger-manager support, which allows multiple
   chargers attached to a battery and multiple batteries attached to a
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 22246b9..b4b101c 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -28,13 +28,6 @@
 #include linux/of.h
 #include linux/thermal.h
 
-/*
- * Default termperature threshold for charging.
- * Every temperature units are in tenth of centigrade.
- */
-#define CM_DEFAULT_RECHARGE_TEMP_DIFF  50
-#define CM_DEFAULT_CHARGE_TEMP_MAX 500
-
 static const char * const default_event_names[] = {
[CM_EVENT_UNKNOWN] = Unknown,
[CM_EVENT_BATT_FULL] = Battery Full,
@@ -572,40 +565,18 @@ static int check_charging_duration(struct charger_manager 
*cm)
return ret;
 }
 
-static int cm_get_battery_temperature_by_psy(struct charger_manager *cm,
-   int *temp)
-{
-   struct power_supply *fuel_gauge;
-
-   fuel_gauge = power_supply_get_by_name(cm-desc-psy_fuel_gauge);
-   if (!fuel_gauge)
-   return -ENODEV;
-
-   return fuel_gauge-get_property(fuel_gauge,
-   POWER_SUPPLY_PROP_TEMP,
-   (union power_supply_propval *)temp);
-}
-
 static int cm_get_battery_temperature(struct charger_manager *cm,
int *temp)
 {
int ret;
 
-   if (!cm-desc-measure_battery_temp)
+   if (!cm-tzd_batt)
return -ENODEV;
 
-#ifdef CONFIG_THERMAL
-   if (cm-tzd_batt) {
-   ret = thermal_zone_get_temp(cm-tzd_batt, (unsigned long 
*)temp);
-   if (!ret)
-   /* Calibrate temperature unit */
-   *temp /= 100;
-   } else
-#endif
-   {
-   /* if-else continued from CONFIG_THERMAL */
-   ret = cm_get_battery_temperature_by_psy(cm, temp);
-   }
+   ret = thermal_zone_get_temp(cm-tzd_batt, (unsigned long *)temp);
+   if (!ret)
+   /* Calibrate temperature unit */
+   *temp /= 100;
 
return ret;
 }
@@ -623,7 +594,7 @@ static int cm_check_thermal_status(struct charger_manager 
*cm)
 * occur hazadous result. We have to handle it
 * depending on battery type.
 */
-   dev_err(cm-dev, Failed to get battery temperature\n);
+   dev_dbg(cm-dev, Failed to get battery temperature\n);
return 0;
}
 
@@ -1007,12 +978,11 @@ static enum power_supply_property 
default_charger_props[] = {
POWER_SUPPLY_PROP_CAPACITY,
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_CHARGE_FULL,
+   POWER_SUPPLY_PROP_TEMP,
/*
 * Optional properties are:
 * POWER_SUPPLY_PROP_CHARGE_NOW,
 * POWER_SUPPLY_PROP_CURRENT_NOW,
-* POWER_SUPPLY_PROP_TEMP, and
-* POWER_SUPPLY_PROP_TEMP_AMBIENT,
 */
 };
 
@@ -1417,49 +1387,6 @@ err:
return ret;
 }
 
-static int cm_init_thermal_data(struct charger_manager *cm,
-   struct power_supply *fuel_gauge)
-{
-   struct charger_desc *desc = cm-desc;
-   union power_supply_propval val;
-   int ret;
-
-   /* Verify whether fuel gauge provides battery temperature */
-   ret = fuel_gauge-get_property(fuel_gauge,
-   POWER_SUPPLY_PROP_TEMP, val);
-
-   if (!ret) {
-   cm-charger_psy.properties[cm-charger_psy.num_properties] =
-   POWER_SUPPLY_PROP_TEMP;
-   cm-charger_psy.num_properties++;
-   cm-desc-measure_battery_temp = true;
-   }
-#ifdef CONFIG_THERMAL
-   if (ret  desc-thermal_zone) {
-   cm-tzd_batt =
-   thermal_zone_get_zone_by_name(desc-thermal_zone);
-   if (IS_ERR(cm-tzd_batt))
-   return PTR_ERR(cm-tzd_batt);
-
-   /* Use external thermometer */
-   cm-charger_psy.properties[cm-charger_psy.num_properties

[PATCH 05/10] power: charger-manager: Concentrate scattered power_supply_changed() calls.

2014-10-30 Thread Jonghwa Lee
Current charger-manager calls power_suuply_changed() whenever charging
status is changed. This patch removes seperated power_supply_changed()
use and let it be called at end of try_charger_enable() function which
is called to set charging/discharging.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 drivers/power/charger-manager.c |   18 ++
 1 file changed, 6 insertions(+), 12 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 687f109..bb44588 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -382,8 +382,10 @@ static int try_charger_enable(struct charger_manager *cm, 
bool enable)
}
}
 
-   if (!err)
+   if (!err) {
cm-charger_enabled = enable;
+   power_supply_changed(cm-charger_psy);
+   }
 
return err;
 }
@@ -436,10 +438,8 @@ static void fullbatt_vchk(struct charger_manager *cm)
 
dev_info(cm-dev, VBATT dropped %duV after full-batt\n, diff);
 
-   if (diff  desc-fullbatt_vchkdrop_uV) {
+   if (diff  desc-fullbatt_vchkdrop_uV)
try_charger_restart(cm);
-   power_supply_changed(cm-charger_psy);
-   }
 }
 
 /**
@@ -469,7 +469,6 @@ static int check_charging_duration(struct charger_manager 
*cm)
if (duration  desc-charging_max_duration_ms) {
dev_info(cm-dev, Charging duration exceed %ums\n,
 desc-charging_max_duration_ms);
-   power_supply_changed(cm-charger_psy);
try_charger_enable(cm, false);
ret = true;
}
@@ -480,7 +479,6 @@ static int check_charging_duration(struct charger_manager 
*cm)
is_ext_pwr_online(cm)) {
dev_info(cm-dev, Discharging duration exceed %ums\n,
 desc-discharging_max_duration_ms);
-   power_supply_changed(cm-charger_psy);
try_charger_enable(cm, true);
ret = true;
}
@@ -561,8 +559,7 @@ static bool _cm_monitor(struct charger_manager *cm)
 */
if (temp_alrt) {
cm-emergency_stop = temp_alrt;
-   if (!try_charger_enable(cm, false))
-   power_supply_changed(cm-charger_psy);
+   try_charger_enable(cm, false);
 
/*
 * Check whole charging duration and discharing duration
@@ -587,16 +584,13 @@ static bool _cm_monitor(struct charger_manager *cm)
} else if (!cm-emergency_stop  is_full_charged(cm) 
cm-charger_enabled) {
dev_info(cm-dev, EVENT_HANDLE: Battery Fully Charged\n);
-   power_supply_changed(cm-charger_psy);
-
try_charger_enable(cm, false);
 
fullbatt_vchk(cm);
} else {
cm-emergency_stop = 0;
if (is_ext_pwr_online(cm)) {
-   if (!try_charger_enable(cm, true))
-   power_supply_changed(cm-charger_psy);
+   try_charger_enable(cm, true);
}
}
 
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 02/10] power: charger-manager: Use power_supply_changed() not private uevent.

2014-10-30 Thread Jonghwa Lee
Whenever battery status is changed, charger manager tries to trigger uevent
through private interface. This patch modifies it to use power_supply_changed()
since it belongs to power supply subsystem.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 drivers/power/charger-manager.c |   91 +--
 1 file changed, 11 insertions(+), 80 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index b4b101c..33a1a4d 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -28,18 +28,6 @@
 #include linux/of.h
 #include linux/thermal.h
 
-static const char * const default_event_names[] = {
-   [CM_EVENT_UNKNOWN] = Unknown,
-   [CM_EVENT_BATT_FULL] = Battery Full,
-   [CM_EVENT_BATT_IN] = Battery Inserted,
-   [CM_EVENT_BATT_OUT] = Battery Pulled Out,
-   [CM_EVENT_BATT_OVERHEAT] = Battery Overheat,
-   [CM_EVENT_BATT_COLD] = Battery Cold,
-   [CM_EVENT_EXT_PWR_IN_OUT] = External Power Attach/Detach,
-   [CM_EVENT_CHG_START_STOP] = Charging Start/Stop,
-   [CM_EVENT_OTHERS] = Other battery events
-};
-
 /*
  * Regard CM_JIFFIES_SMALL jiffies is small enough to ignore for
  * delayed works so that we can run delayed works with CM_JIFFIES_SMALL
@@ -56,8 +44,6 @@ static const char * const default_event_names[] = {
  */
 #define CM_RTC_SMALL   (2)
 
-#define UEVENT_BUF_SIZE32
-
 static LIST_HEAD(cm_list);
 static DEFINE_MUTEX(cm_list_mtx);
 
@@ -423,61 +409,6 @@ static int try_charger_restart(struct charger_manager *cm)
 }
 
 /**
- * uevent_notify - Let users know something has changed.
- * @cm: the Charger Manager representing the battery.
- * @event: the event string.
- *
- * If @event is null, it implies that uevent_notify is called
- * by resume function. When called in the resume function, cm_suspended
- * should be already reset to false in order to let uevent_notify
- * notify the recent event during the suspend to users. While
- * suspended, uevent_notify does not notify users, but tracks
- * events so that uevent_notify can notify users later after resumed.
- */
-static void uevent_notify(struct charger_manager *cm, const char *event)
-{
-   static char env_str[UEVENT_BUF_SIZE + 1] = ;
-   static char env_str_save[UEVENT_BUF_SIZE + 1] = ;
-
-   if (cm_suspended) {
-   /* Nothing in suspended-event buffer */
-   if (env_str_save[0] == 0) {
-   if (!strncmp(env_str, event, UEVENT_BUF_SIZE))
-   return; /* status not changed */
-   strncpy(env_str_save, event, UEVENT_BUF_SIZE);
-   return;
-   }
-
-   if (!strncmp(env_str_save, event, UEVENT_BUF_SIZE))
-   return; /* Duplicated. */
-   strncpy(env_str_save, event, UEVENT_BUF_SIZE);
-   return;
-   }
-
-   if (event == NULL) {
-   /* No messages pending */
-   if (!env_str_save[0])
-   return;
-
-   strncpy(env_str, env_str_save, UEVENT_BUF_SIZE);
-   kobject_uevent(cm-dev-kobj, KOBJ_CHANGE);
-   env_str_save[0] = 0;
-
-   return;
-   }
-
-   /* status not changed */
-   if (!strncmp(env_str, event, UEVENT_BUF_SIZE))
-   return;
-
-   /* save the status and notify the update */
-   strncpy(env_str, event, UEVENT_BUF_SIZE);
-   kobject_uevent(cm-dev-kobj, KOBJ_CHANGE);
-
-   dev_info(cm-dev, %s\n, event);
-}
-
-/**
  * fullbatt_vchk - Check voltage drop some times after FULL event.
  * @work: the work_struct appointing the function
  *
@@ -514,7 +445,7 @@ static void fullbatt_vchk(struct work_struct *work)
 
if (diff  desc-fullbatt_vchkdrop_uV) {
try_charger_restart(cm);
-   uevent_notify(cm, Recharging);
+   power_supply_changed(cm-charger_psy);
}
 }
 
@@ -545,7 +476,7 @@ static int check_charging_duration(struct charger_manager 
*cm)
if (duration  desc-charging_max_duration_ms) {
dev_info(cm-dev, Charging duration exceed %ums\n,
 desc-charging_max_duration_ms);
-   uevent_notify(cm, Discharging);
+   power_supply_changed(cm-charger_psy);
try_charger_enable(cm, false);
ret = true;
}
@@ -556,7 +487,7 @@ static int check_charging_duration(struct charger_manager 
*cm)
is_ext_pwr_online(cm)) {
dev_info(cm-dev, Discharging duration exceed %ums\n,
 desc-discharging_max_duration_ms);
-   uevent_notify(cm, Recharging);
+   power_supply_changed(cm-charger_psy);
try_charger_enable(cm, true

[PATCH 04/10] power: charger-manager: Fix to use CHARGE_NOW/FULL property correctly.

2014-10-30 Thread Jonghwa Lee
The POWER_SUPPLY_CHARGE_NOW/FULL property reflects battery's charges
in uAh unit, but charger-manager has been used it wrongly. This patch
makes it to use those propeties correctly and change to be optional.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 drivers/power/charger-manager.c |   85 +--
 1 file changed, 28 insertions(+), 57 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 64fdaaf..687f109 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -796,35 +796,13 @@ static int charger_get_property(struct power_supply *psy,
val-intval = 0;
break;
case POWER_SUPPLY_PROP_CHARGE_FULL:
-   if (is_full_charged(cm))
-   val-intval = 1;
-   else
-   val-intval = 0;
-   ret = 0;
-   break;
case POWER_SUPPLY_PROP_CHARGE_NOW:
-   if (is_charging(cm)) {
-   fuel_gauge = power_supply_get_by_name(
-   cm-desc-psy_fuel_gauge);
-   if (!fuel_gauge) {
-   ret = -ENODEV;
-   break;
-   }
-
-   ret = fuel_gauge-get_property(fuel_gauge,
-   POWER_SUPPLY_PROP_CHARGE_NOW,
-   val);
-   if (ret) {
-   val-intval = 1;
-   ret = 0;
-   } else {
-   /* If CHARGE_NOW is supplied, use it */
-   val-intval = (val-intval  0) ?
-   val-intval : 1;
-   }
-   } else {
-   val-intval = 0;
+   fuel_gauge = power_supply_get_by_name(cm-desc-psy_fuel_gauge);
+   if (!fuel_gauge) {
+   ret = -ENODEV;
+   break;
}
+   ret = fuel_gauge-get_property(fuel_gauge, psp, val);
break;
default:
return -EINVAL;
@@ -832,8 +810,7 @@ static int charger_get_property(struct power_supply *psy,
return ret;
 }
 
-#define NUM_CHARGER_PSY_OPTIONAL   (4)
-static enum power_supply_property default_charger_props[] = {
+static enum power_supply_property cm_default_props[] = {
/* Guaranteed to provide */
POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_HEALTH,
@@ -841,20 +818,21 @@ static enum power_supply_property default_charger_props[] 
= {
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_CAPACITY,
POWER_SUPPLY_PROP_ONLINE,
-   POWER_SUPPLY_PROP_CHARGE_FULL,
POWER_SUPPLY_PROP_TEMP,
-   /*
-* Optional properties are:
-* POWER_SUPPLY_PROP_CHARGE_NOW,
-* POWER_SUPPLY_PROP_CURRENT_NOW,
-*/
 };
 
+static enum power_supply_property cm_optional_props[] = {
+   POWER_SUPPLY_PROP_CHARGE_FULL,
+   POWER_SUPPLY_PROP_CHARGE_NOW,
+   POWER_SUPPLY_PROP_CURRENT_NOW,
+};
+
+#define CM_NUM_OF_PROPS\
+   (ARRAY_SIZE(cm_default_props) + ARRAY_SIZE(cm_optional_props))
+
 static struct power_supply psy_default = {
.name = battery,
.type = POWER_SUPPLY_TYPE_BATTERY,
-   .properties = default_charger_props,
-   .num_properties = ARRAY_SIZE(default_charger_props),
.get_property = charger_get_property,
.no_thermal = true,
 };
@@ -1484,29 +1462,22 @@ static int charger_manager_probe(struct platform_device 
*pdev)
/* Allocate for psy properties because they may vary */
cm-charger_psy.properties = devm_kzalloc(pdev-dev,
sizeof(enum power_supply_property)
-   * (ARRAY_SIZE(default_charger_props) +
-   NUM_CHARGER_PSY_OPTIONAL), GFP_KERNEL);
+   * CM_NUM_OF_PROPS, GFP_KERNEL);
if (!cm-charger_psy.properties)
return -ENOMEM;
 
-   memcpy(cm-charger_psy.properties, default_charger_props,
-   sizeof(enum power_supply_property) *
-   ARRAY_SIZE(default_charger_props));
-   cm-charger_psy.num_properties = psy_default.num_properties;
-
-   /* Find which optional psy-properties are available */
-   if (!fuel_gauge-get_property(fuel_gauge,
- POWER_SUPPLY_PROP_CHARGE_NOW, val)) {
-   cm-charger_psy.properties[cm-charger_psy.num_properties] =
-   POWER_SUPPLY_PROP_CHARGE_NOW;
-   cm-charger_psy.num_properties++;
-   }
-   if (!fuel_gauge-get_property(fuel_gauge,
- POWER_SUPPLY_PROP_CURRENT_NOW

[PATCH 1/3] power: core: Add generic interface to get battery specification.

2014-10-07 Thread Jonghwa Lee
In power supply system, battery specification's dealt as static
information regardless of battery chainging. And it often assumed
fuelgauge's role to hold battery specification even same driver is
used with different batteries. To make subsystem handles above cases
properly, this patch adds helper functions to manager the battery
specification.

Signed-off-by: Jonghwa Lee 
---
 drivers/power/power_supply_core.c |   91 +
 include/linux/power_supply.h  |7 +++
 2 files changed, 98 insertions(+)

diff --git a/drivers/power/power_supply_core.c 
b/drivers/power/power_supply_core.c
index 078afd6..59207d9 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -653,6 +653,97 @@ static void __exit power_supply_class_exit(void)
 subsys_initcall(power_supply_class_init);
 module_exit(power_supply_class_exit);
 
+/
+ *   Battery information interface  *
+ /
+
+ATOMIC_NOTIFIER_HEAD(psy_battery_info_notifier);
+static LIST_HEAD(psy_battery_info_list);
+
+struct psy_battery_info {
+   struct list_head entry;
+   struct power_supply_info *info;
+};
+
+enum battery_info_notifier_events {
+   PSY_BATT_INFO_REGISTERED,
+   PSY_BATT_INFO_UNREGISTERED,
+};
+
+int psy_battery_info_notifier_register(struct notifier_block *nb)
+{
+   return atomic_notifier_chain_register(_battery_info_notifier, nb);
+}
+EXPORT_SYMBOL_GPL(psy_battery_info_notifier_register);
+
+void psy_battery_info_notifier_unregister(struct notifier_block *nb)
+{
+   atomic_notifier_chain_unregister(_battery_info_notifier, nb);
+}
+EXPORT_SYMBOL_GPL(psy_battery_info_notifier_unregister);
+
+struct power_supply_info *psy_get_battery_info(const char *name)
+{
+   struct psy_battery_info *battery;
+
+   /* Sanity check */
+   if (!name)
+   goto err_out;
+
+   list_for_each_entry(battery, _battery_info_list, entry) {
+   if (!strcmp(battery->info->name, name))
+   return battery->info;
+   }
+
+err_out:
+   return NULL;
+}
+EXPORT_SYMBOL(psy_get_battery_info);
+
+int psy_register_battery_info(struct power_supply_info *info)
+{
+   struct psy_battery_info *battery;
+
+   /* Sanity check */
+   if (!info->name)
+   return -EINVAL;
+
+   /* Check if same data is existed */
+   list_for_each_entry(battery, _battery_info_list, entry)
+   if (!strcmp(battery->info->name, info->name))
+   return -EEXIST;
+
+   battery = kzalloc(sizeof(*battery), GFP_KERNEL);
+   if (!battery)
+   return -ENOMEM;
+
+   battery->info = info;
+   list_add_tail(>entry, _battery_info_list);
+
+   atomic_notifier_call_chain(_battery_info_notifier,
+   PSY_BATT_INFO_REGISTERED, info);
+
+   return 0;
+}
+EXPORT_SYMBOL(psy_register_battery_info);
+
+void psy_unregister_battery_info(struct power_supply_info *info)
+{
+   struct psy_battery_info *battery, *tmp;
+
+   list_for_each_entry_safe(battery, tmp, _battery_info_list, entry) {
+   if (battery->info == info) {
+   list_del(>entry);
+   kfree(battery);
+   return;
+   }
+   }
+
+   atomic_notifier_call_chain(_battery_info_notifier,
+   PSY_BATT_INFO_UNREGISTERED, info);
+}
+EXPORT_SYMBOL(psy_unregister_battery_info);
+
 MODULE_DESCRIPTION("Universal power supply monitor class");
 MODULE_AUTHOR("Ian Molton , "
  "Szabolcs Gyurko, "
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index f3dea41..99306aa 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -276,6 +276,13 @@ extern int power_supply_powers(struct power_supply *psy, 
struct device *dev);
 /* For APM emulation, think legacy userspace. */
 extern struct class *power_supply_class;
 
+/* Battery information helper */
+extern int psy_battery_info_notifier_register(struct notifier_block *);
+extern void psy_battery_info_notifier_unregister(struct notifier_block *);
+extern struct power_supply_info *psy_get_battery_info(const char *);
+extern int psy_register_battery_info(struct power_supply_info *);
+extern void psy_unregister_battery_info(struct power_supply_info *);
+
 static inline bool power_supply_is_amp_property(enum power_supply_property psp)
 {
switch (psp) {
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 3/3] power: of_battery: Initial support for of-based battery specification driver.

2014-10-07 Thread Jonghwa Lee
This driver supports battery specification through the generic interface of
power_supply subsystem. All data are parsed from device tree and it exactly
matches with power_supply_info's content.

Signed-off-by: Jonghwa Lee 
---
 .../bindings/power_supply/of_battery.txt   |   34 +++
 drivers/power/Kconfig  |7 ++
 drivers/power/Makefile |1 +
 drivers/power/of_battery.c |  100 
 4 files changed, 142 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/power_supply/of_battery.txt
 create mode 100644 drivers/power/of_battery.c

diff --git a/Documentation/devicetree/bindings/power_supply/of_battery.txt 
b/Documentation/devicetree/bindings/power_supply/of_battery.txt
new file mode 100644
index 000..5ccd2a1
--- /dev/null
+++ b/Documentation/devicetree/bindings/power_supply/of_battery.txt
@@ -0,0 +1,34 @@
+of_battery bindings
+~~~
+
+This documentation describes how to define data in device tree
+to use of_battery driver. All properties are just matched with
+power_supply_info's.
+
+Required properties :
+ - battery-name : battery's name for identifying.
+
+Optional properties :
+ - voltage_max : Maximum voltage of the battery (uV).
+ - voltage_min : Minimum voltage of the battery (uV).
+ - charge_full : Full capacity of the battery (uAh).
+ - charge_empty : Empty capacity of the battery (uAh).
+ - energy_full : Full capacity of the battery (uWh).
+ - energy_empty : Empty capacity of the battery (uWh).
+ - temperature_max : Maximum temperature for the battery (deci 'C)
+ - temperature_min : Minium temperature for the battery (deci 'C)
+
+Example:
+   battery {
+   main-battery {
+   battery-name = "battery";
+   voltage-max = <435>;
+   charge-full = <250>;
+   temperature_max = <600>;
+   temperature_min = <(-100)>;
+   };
+   backup-battery {
+   battery-name = "coin-battery";
+   voltage-max = <300>;
+   };
+   };
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 73cfcdf..c324ac6 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -36,6 +36,13 @@ config GENERIC_ADC_BATTERY
  Say Y here to enable support for the generic battery driver
  which uses IIO framework to read adc.
 
+config BATTERY_OF
+   tristate "Generic of-based battery specification driver"
+   depends on OF
+   help
+ Say Y here to enable support for the of-based generic battery
+ specification driver which gives static battery data.
+
 config MAX8925_POWER
tristate "MAX8925 battery charger support"
depends on MFD_MAX8925
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index dfa8942..38a83aa 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -6,6 +6,7 @@ power_supply-$(CONFIG_LEDS_TRIGGERS)+= power_supply_leds.o
 
 obj-$(CONFIG_POWER_SUPPLY) += power_supply.o
 obj-$(CONFIG_GENERIC_ADC_BATTERY)  += generic-adc-battery.o
+obj-$(CONFIG_BATTERY_OF)   += of_battery.o
 
 obj-$(CONFIG_PDA_POWER)+= pda_power.o
 obj-$(CONFIG_APM_POWER)+= apm_power.o
diff --git a/drivers/power/of_battery.c b/drivers/power/of_battery.c
new file mode 100644
index 000..3c66765
--- /dev/null
+++ b/drivers/power/of_battery.c
@@ -0,0 +1,100 @@
+/*
+ * OF-based battery specification driver
+ *
+ * This driver supports generic interface to get static battery data.
+ *
+ * Copyright © 2014 Jonghwa Lee 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include 
+#include 
+#include 
+#include 
+
+static struct power_supply_info *of_get_battery_info(struct device_node *np)
+{
+   struct power_supply_info *info;
+
+   info = kzalloc(sizeof(*info), GFP_KERNEL);
+   if (!info)
+   return ERR_PTR(-ENOMEM);
+
+   if (of_property_read_string(np, "battery-name", >name)) {
+   kfree(info);
+   return ERR_PTR(-EINVAL);
+   }
+
+   of_property_read_u32(np, "voltage_max", >voltage_max_design);
+   of_property_read_u32(np, "voltage_min", >voltage_min_design);
+   of_property_read_u32(np, "charge_full", >charge_full_design);
+   of_property_read_u32(np, "charge_empty", >charge_empty_design);
+   of_property_read_u32(np, "energy_full", >energy_full_design);
+   of_property_read_u32(np, "energy_empty", >energy_empty_design);
+ 

[RFC PATCH 0/3] power: Generic interface to get battery specification.

2014-10-07 Thread Jonghwa Lee
This patches contains supporting generic interface to get battery specification
and of-based battery driver which use the interface.

Up to now, power supply subsystem assumes that battery's charartric data is
static and also often left as fuelgauge's role. However, fuelgauge driver or
any power_supply driver can be worked with different battery with different
implementation and battery also can be changed even in runtime.
If so, it needs to notify its change to all related power_supply drivers not
let them notice all with private way. Thus, it tries to introduce generic
interface for management of the battery specification.

In addition to, for the smart battery, this'll help to abstract battery
interface which can be varied with different batteries. (SDQ, MIPI BIF..)

Jonghwa Lee (3):
  power: core: Add generic interface to get battery specification.
  power: core: Add variables related temperature to power_supply_info.
  power: of_battery: Initial support for of-based battery specification
driver.

 .../bindings/power_supply/of_battery.txt   |   34 +++
 drivers/power/Kconfig  |7 ++
 drivers/power/Makefile |1 +
 drivers/power/of_battery.c |  100 
 drivers/power/power_supply_core.c  |   91 ++
 include/linux/power_supply.h   |9 ++
 6 files changed, 242 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/power_supply/of_battery.txt
 create mode 100644 drivers/power/of_battery.c

-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 2/3] power: core: Add variables related temperature to power_supply_info.

2014-10-07 Thread Jonghwa Lee
To represent thermal limitation of power_supply, it adds 'temperature_max,
temperature_min' to power_supply_info structure.

Signed-off-by: Jonghwa Lee 
---
 include/linux/power_supply.h |2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 99306aa..0c8588c 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -241,6 +241,8 @@ struct power_supply_info {
int charge_empty_design;
int energy_full_design;
int energy_empty_design;
+   int temperature_max;
+   int temperature_min;
int use_for_apm;
 };
 
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RFC PATCH 0/3] power: Generic interface to get battery specification.

2014-10-07 Thread Jonghwa Lee
This patches contains supporting generic interface to get battery specification
and of-based battery driver which use the interface.

Up to now, power supply subsystem assumes that battery's charartric data is
static and also often left as fuelgauge's role. However, fuelgauge driver or
any power_supply driver can be worked with different battery with different
implementation and battery also can be changed even in runtime.
If so, it needs to notify its change to all related power_supply drivers not
let them notice all with private way. Thus, it tries to introduce generic
interface for management of the battery specification.

In addition to, for the smart battery, this'll help to abstract battery
interface which can be varied with different batteries. (SDQ, MIPI BIF..)

Jonghwa Lee (3):
  power: core: Add generic interface to get battery specification.
  power: core: Add variables related temperature to power_supply_info.
  power: of_battery: Initial support for of-based battery specification
driver.

 .../bindings/power_supply/of_battery.txt   |   34 +++
 drivers/power/Kconfig  |7 ++
 drivers/power/Makefile |1 +
 drivers/power/of_battery.c |  100 
 drivers/power/power_supply_core.c  |   91 ++
 include/linux/power_supply.h   |9 ++
 6 files changed, 242 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/power_supply/of_battery.txt
 create mode 100644 drivers/power/of_battery.c

-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 2/3] power: core: Add variables related temperature to power_supply_info.

2014-10-07 Thread Jonghwa Lee
To represent thermal limitation of power_supply, it adds 'temperature_max,
temperature_min' to power_supply_info structure.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 include/linux/power_supply.h |2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 99306aa..0c8588c 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -241,6 +241,8 @@ struct power_supply_info {
int charge_empty_design;
int energy_full_design;
int energy_empty_design;
+   int temperature_max;
+   int temperature_min;
int use_for_apm;
 };
 
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 3/3] power: of_battery: Initial support for of-based battery specification driver.

2014-10-07 Thread Jonghwa Lee
This driver supports battery specification through the generic interface of
power_supply subsystem. All data are parsed from device tree and it exactly
matches with power_supply_info's content.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 .../bindings/power_supply/of_battery.txt   |   34 +++
 drivers/power/Kconfig  |7 ++
 drivers/power/Makefile |1 +
 drivers/power/of_battery.c |  100 
 4 files changed, 142 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/power_supply/of_battery.txt
 create mode 100644 drivers/power/of_battery.c

diff --git a/Documentation/devicetree/bindings/power_supply/of_battery.txt 
b/Documentation/devicetree/bindings/power_supply/of_battery.txt
new file mode 100644
index 000..5ccd2a1
--- /dev/null
+++ b/Documentation/devicetree/bindings/power_supply/of_battery.txt
@@ -0,0 +1,34 @@
+of_battery bindings
+~~~
+
+This documentation describes how to define data in device tree
+to use of_battery driver. All properties are just matched with
+power_supply_info's.
+
+Required properties :
+ - battery-name : battery's name for identifying.
+
+Optional properties :
+ - voltage_max : Maximum voltage of the battery (uV).
+ - voltage_min : Minimum voltage of the battery (uV).
+ - charge_full : Full capacity of the battery (uAh).
+ - charge_empty : Empty capacity of the battery (uAh).
+ - energy_full : Full capacity of the battery (uWh).
+ - energy_empty : Empty capacity of the battery (uWh).
+ - temperature_max : Maximum temperature for the battery (deci 'C)
+ - temperature_min : Minium temperature for the battery (deci 'C)
+
+Example:
+   battery {
+   main-battery {
+   battery-name = battery;
+   voltage-max = 435;
+   charge-full = 250;
+   temperature_max = 600;
+   temperature_min = (-100);
+   };
+   backup-battery {
+   battery-name = coin-battery;
+   voltage-max = 300;
+   };
+   };
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 73cfcdf..c324ac6 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -36,6 +36,13 @@ config GENERIC_ADC_BATTERY
  Say Y here to enable support for the generic battery driver
  which uses IIO framework to read adc.
 
+config BATTERY_OF
+   tristate Generic of-based battery specification driver
+   depends on OF
+   help
+ Say Y here to enable support for the of-based generic battery
+ specification driver which gives static battery data.
+
 config MAX8925_POWER
tristate MAX8925 battery charger support
depends on MFD_MAX8925
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index dfa8942..38a83aa 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -6,6 +6,7 @@ power_supply-$(CONFIG_LEDS_TRIGGERS)+= power_supply_leds.o
 
 obj-$(CONFIG_POWER_SUPPLY) += power_supply.o
 obj-$(CONFIG_GENERIC_ADC_BATTERY)  += generic-adc-battery.o
+obj-$(CONFIG_BATTERY_OF)   += of_battery.o
 
 obj-$(CONFIG_PDA_POWER)+= pda_power.o
 obj-$(CONFIG_APM_POWER)+= apm_power.o
diff --git a/drivers/power/of_battery.c b/drivers/power/of_battery.c
new file mode 100644
index 000..3c66765
--- /dev/null
+++ b/drivers/power/of_battery.c
@@ -0,0 +1,100 @@
+/*
+ * OF-based battery specification driver
+ *
+ * This driver supports generic interface to get static battery data.
+ *
+ * Copyright © 2014 Jonghwa Lee jonghwa3@samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME :  fmt
+
+#include linux/power_supply.h
+#include linux/module.h
+#include linux/slab.h
+#include linux/of.h
+
+static struct power_supply_info *of_get_battery_info(struct device_node *np)
+{
+   struct power_supply_info *info;
+
+   info = kzalloc(sizeof(*info), GFP_KERNEL);
+   if (!info)
+   return ERR_PTR(-ENOMEM);
+
+   if (of_property_read_string(np, battery-name, info-name)) {
+   kfree(info);
+   return ERR_PTR(-EINVAL);
+   }
+
+   of_property_read_u32(np, voltage_max, info-voltage_max_design);
+   of_property_read_u32(np, voltage_min, info-voltage_min_design);
+   of_property_read_u32(np, charge_full, info-charge_full_design);
+   of_property_read_u32(np, charge_empty, info-charge_empty_design);
+   of_property_read_u32(np, energy_full, info-energy_full_design);
+   of_property_read_u32(np, energy_empty, info-energy_empty_design);
+   of_property_read_u32(np, temperature_max, info-temperature_max

[PATCH 1/3] power: core: Add generic interface to get battery specification.

2014-10-07 Thread Jonghwa Lee
In power supply system, battery specification's dealt as static
information regardless of battery chainging. And it often assumed
fuelgauge's role to hold battery specification even same driver is
used with different batteries. To make subsystem handles above cases
properly, this patch adds helper functions to manager the battery
specification.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 drivers/power/power_supply_core.c |   91 +
 include/linux/power_supply.h  |7 +++
 2 files changed, 98 insertions(+)

diff --git a/drivers/power/power_supply_core.c 
b/drivers/power/power_supply_core.c
index 078afd6..59207d9 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -653,6 +653,97 @@ static void __exit power_supply_class_exit(void)
 subsys_initcall(power_supply_class_init);
 module_exit(power_supply_class_exit);
 
+/
+ *   Battery information interface  *
+ /
+
+ATOMIC_NOTIFIER_HEAD(psy_battery_info_notifier);
+static LIST_HEAD(psy_battery_info_list);
+
+struct psy_battery_info {
+   struct list_head entry;
+   struct power_supply_info *info;
+};
+
+enum battery_info_notifier_events {
+   PSY_BATT_INFO_REGISTERED,
+   PSY_BATT_INFO_UNREGISTERED,
+};
+
+int psy_battery_info_notifier_register(struct notifier_block *nb)
+{
+   return atomic_notifier_chain_register(psy_battery_info_notifier, nb);
+}
+EXPORT_SYMBOL_GPL(psy_battery_info_notifier_register);
+
+void psy_battery_info_notifier_unregister(struct notifier_block *nb)
+{
+   atomic_notifier_chain_unregister(psy_battery_info_notifier, nb);
+}
+EXPORT_SYMBOL_GPL(psy_battery_info_notifier_unregister);
+
+struct power_supply_info *psy_get_battery_info(const char *name)
+{
+   struct psy_battery_info *battery;
+
+   /* Sanity check */
+   if (!name)
+   goto err_out;
+
+   list_for_each_entry(battery, psy_battery_info_list, entry) {
+   if (!strcmp(battery-info-name, name))
+   return battery-info;
+   }
+
+err_out:
+   return NULL;
+}
+EXPORT_SYMBOL(psy_get_battery_info);
+
+int psy_register_battery_info(struct power_supply_info *info)
+{
+   struct psy_battery_info *battery;
+
+   /* Sanity check */
+   if (!info-name)
+   return -EINVAL;
+
+   /* Check if same data is existed */
+   list_for_each_entry(battery, psy_battery_info_list, entry)
+   if (!strcmp(battery-info-name, info-name))
+   return -EEXIST;
+
+   battery = kzalloc(sizeof(*battery), GFP_KERNEL);
+   if (!battery)
+   return -ENOMEM;
+
+   battery-info = info;
+   list_add_tail(battery-entry, psy_battery_info_list);
+
+   atomic_notifier_call_chain(psy_battery_info_notifier,
+   PSY_BATT_INFO_REGISTERED, info);
+
+   return 0;
+}
+EXPORT_SYMBOL(psy_register_battery_info);
+
+void psy_unregister_battery_info(struct power_supply_info *info)
+{
+   struct psy_battery_info *battery, *tmp;
+
+   list_for_each_entry_safe(battery, tmp, psy_battery_info_list, entry) {
+   if (battery-info == info) {
+   list_del(battery-entry);
+   kfree(battery);
+   return;
+   }
+   }
+
+   atomic_notifier_call_chain(psy_battery_info_notifier,
+   PSY_BATT_INFO_UNREGISTERED, info);
+}
+EXPORT_SYMBOL(psy_unregister_battery_info);
+
 MODULE_DESCRIPTION(Universal power supply monitor class);
 MODULE_AUTHOR(Ian Molton sp...@f2s.com, 
  Szabolcs Gyurko, 
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index f3dea41..99306aa 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -276,6 +276,13 @@ extern int power_supply_powers(struct power_supply *psy, 
struct device *dev);
 /* For APM emulation, think legacy userspace. */
 extern struct class *power_supply_class;
 
+/* Battery information helper */
+extern int psy_battery_info_notifier_register(struct notifier_block *);
+extern void psy_battery_info_notifier_unregister(struct notifier_block *);
+extern struct power_supply_info *psy_get_battery_info(const char *);
+extern int psy_register_battery_info(struct power_supply_info *);
+extern void psy_unregister_battery_info(struct power_supply_info *);
+
 static inline bool power_supply_is_amp_property(enum power_supply_property psp)
 {
switch (psp) {
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 0/2] ARM: EXYNOS3250: Add support EXYNOS3250 suspend/resume.

2014-09-26 Thread Jonghwa Lee
This patches adds and modifies exynos suspend driver to support exynos3250's
suspend/resume. To work suspend/resume, it also needs a work at pmu driver.
It'll be supported after refactoring job on pmu driver is done.

Jonghwa Lee (2):
  ARM: EXYNOS: suspend: Make restoring registers into selectable
option.
  ARM: EXYNOS3250: Add initial support EXYNOS3250 suspend/resume.

 arch/arm/mach-exynos/regs-pmu.h |4 +++
 arch/arm/mach-exynos/suspend.c  |   70 +--
 2 files changed, 56 insertions(+), 18 deletions(-)

-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/2] ARM: EXYNOS: suspend: Make restoring registers into selectable option.

2014-09-26 Thread Jonghwa Lee
Some EXYNOS series may not requried to save ROM registers as it's default
for now. This patch makes restoring registers into machine-specific option.

Signed-off-by: Jonghwa Lee 
---
 arch/arm/mach-exynos/suspend.c |   39 +--
 1 file changed, 21 insertions(+), 18 deletions(-)

diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c
index f5d9773..b41d146 100644
--- a/arch/arm/mach-exynos/suspend.c
+++ b/arch/arm/mach-exynos/suspend.c
@@ -48,23 +48,28 @@ struct exynos_wkup_irq {
u32 mask;
 };
 
-static struct sleep_save exynos5_sys_save[] = {
-   SAVE_ITEM(EXYNOS5_SYS_I2C_CFG),
+static struct sleep_save exynos_save_regs[] = {
+   /* SROM side */
+   SAVE_ITEM(S5P_SROM_BW),
+   SAVE_ITEM(S5P_SROM_BC0),
+   SAVE_ITEM(S5P_SROM_BC1),
+   SAVE_ITEM(S5P_SROM_BC2),
+   SAVE_ITEM(S5P_SROM_BC3),
 };
 
-static struct sleep_save exynos_core_save[] = {
-   /* SROM side */
+static struct sleep_save exynos5_save_regs[] = {
SAVE_ITEM(S5P_SROM_BW),
SAVE_ITEM(S5P_SROM_BC0),
SAVE_ITEM(S5P_SROM_BC1),
SAVE_ITEM(S5P_SROM_BC2),
SAVE_ITEM(S5P_SROM_BC3),
+   SAVE_ITEM(EXYNOS5_SYS_I2C_CFG),
 };
 
 struct exynos_pm_data {
const struct exynos_wkup_irq *wkup_irq;
-   struct sleep_save *extra_save;
-   int num_extra_save;
+   struct sleep_save *save_regs;
+   int num_save_regs;
unsigned int wake_disable_mask;
unsigned int *release_ret_regs;
 
@@ -165,11 +170,9 @@ static void exynos_pm_prepare(void)
/* Set wake-up mask registers */
exynos_pm_set_wakeup_mask();
 
-   s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save));
-
-if (pm_data->extra_save)
-   s3c_pm_do_save(pm_data->extra_save,
-   pm_data->num_extra_save);
+if (pm_data->save_regs)
+   s3c_pm_do_save(pm_data->save_regs,
+   pm_data->num_save_regs);
 
exynos_pm_enter_sleep_mode();
 }
@@ -203,11 +206,9 @@ static void exynos_pm_resume(void)
/* For release retention */
exynos_pm_release_retention();
 
-   if (pm_data->extra_save)
-   s3c_pm_do_restore_core(pm_data->extra_save,
-   pm_data->num_extra_save);
-
-   s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save));
+   if (pm_data->save_regs)
+   s3c_pm_do_restore_core(pm_data->save_regs,
+   pm_data->num_save_regs);
 
if (cpuid == ARM_CPU_PART_CORTEX_A9)
scu_enable(S5P_VA_SCU);
@@ -291,6 +292,8 @@ static const struct exynos_pm_data exynos4_pm_data = {
.wkup_irq   = exynos4_wkup_irq,
.wake_disable_mask = ((0xFF << 8) | (0x1F << 1)),
.release_ret_regs = exynos_release_ret_regs,
+   .save_regs  = exynos_save_regs,
+   .num_save_regs  = ARRAY_SIZE(exynos_save_regs),
.pm_suspend = exynos_pm_suspend,
.pm_resume  = exynos_pm_resume,
.pm_prepare = exynos_pm_prepare,
@@ -301,8 +304,8 @@ static const struct exynos_pm_data exynos5250_pm_data = {
.wkup_irq   = exynos5250_wkup_irq,
.wake_disable_mask = ((0xFF << 8) | (0x1F << 1)),
.release_ret_regs = exynos_release_ret_regs,
-   .extra_save = exynos5_sys_save,
-   .num_extra_save = ARRAY_SIZE(exynos5_sys_save),
+   .save_regs  = exynos5_save_regs,
+   .num_save_regs  = ARRAY_SIZE(exynos5_save_regs),
.pm_suspend = exynos_pm_suspend,
.pm_resume  = exynos_pm_resume,
.pm_prepare = exynos_pm_prepare,
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 2/2] ARM: EXYNOS3250: Add initial support EXYNOS3250 suspend/resume.

2014-09-26 Thread Jonghwa Lee
It adds data and callback needed for exynos3250's suspend/resume.

Signed-off-by: Jonghwa Lee 
---
 arch/arm/mach-exynos/regs-pmu.h |4 
 arch/arm/mach-exynos/suspend.c  |   31 +++
 2 files changed, 35 insertions(+)

diff --git a/arch/arm/mach-exynos/regs-pmu.h b/arch/arm/mach-exynos/regs-pmu.h
index 322f132..b5125dc1 100644
--- a/arch/arm/mach-exynos/regs-pmu.h
+++ b/arch/arm/mach-exynos/regs-pmu.h
@@ -131,6 +131,10 @@
 #define S5P_CORE_LOCAL_PWR_EN  0x3
 #define S5P_CORE_WAKEUP_FROM_LOCAL_CFG (0x3 << 8)
 
+/* Only for EXYNOS3250 */
+#defineS5P_PAD_RET_MMCC_OPTION 0x30C8
+#defineS5P_PAD_RET_SPI_OPTION  0x31C8
+
 /* Only for EXYNOS4210 */
 #define S5P_CMU_CLKSTOP_LCD1_LOWPWR0x1154
 #define S5P_CMU_RESET_LCD1_LOWPWR  0x1174
diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c
index b41d146..de7d6d5 100644
--- a/arch/arm/mach-exynos/suspend.c
+++ b/arch/arm/mach-exynos/suspend.c
@@ -87,6 +87,12 @@ struct exynos_pm_data *pm_data;
 
 static u32 exynos_irqwake_intmask = 0x;
 
+static const struct exynos_wkup_irq exynos3250_wkup_irq[] = {
+   { 105, BIT(1) }, /* RTC alarm */
+   { 106, BIT(2) }, /* RTC tick */
+   { /* sentinel */ },
+};
+
 static const struct exynos_wkup_irq exynos4_wkup_irq[] = {
{ 76, BIT(1) }, /* RTC alarm */
{ 77, BIT(2) }, /* RTC tick */
@@ -99,6 +105,19 @@ static const struct exynos_wkup_irq exynos5250_wkup_irq[] = 
{
{ /* sentinel */ },
 };
 
+unsigned int exynos3250_release_ret_regs[] = {
+   S5P_PAD_RET_MAUDIO_OPTION,
+   S5P_PAD_RET_GPIO_OPTION,
+   S5P_PAD_RET_UART_OPTION,
+   S5P_PAD_RET_MMCA_OPTION,
+   S5P_PAD_RET_MMCB_OPTION,
+   S5P_PAD_RET_MMCC_OPTION,
+   S5P_PAD_RET_EBIA_OPTION,
+   S5P_PAD_RET_EBIB_OPTION,
+   S5P_PAD_RET_SPI_OPTION,
+   REG_TABLE_END,
+};
+
 unsigned int exynos_release_ret_regs[] = {
S5P_PAD_RET_MAUDIO_OPTION,
S5P_PAD_RET_GPIO_OPTION,
@@ -288,6 +307,15 @@ static const struct platform_suspend_ops 
exynos_suspend_ops = {
.valid  = suspend_valid_only_mem,
 };
 
+static const struct exynos_pm_data exynos3250_pm_data = {
+   .wkup_irq   = exynos3250_wkup_irq,
+   .release_ret_regs = exynos3250_release_ret_regs,
+   .pm_suspend = exynos_pm_suspend,
+   .pm_resume  = exynos_pm_resume,
+   .pm_prepare = exynos_pm_prepare,
+   .cpu_suspend= exynos_cpu_suspend,
+};
+
 static const struct exynos_pm_data exynos4_pm_data = {
.wkup_irq   = exynos4_wkup_irq,
.wake_disable_mask = ((0xFF << 8) | (0x1F << 1)),
@@ -314,6 +342,9 @@ static const struct exynos_pm_data exynos5250_pm_data = {
 
 static struct of_device_id exynos_pmu_of_device_ids[] = {
{
+   .compatible = "samsung,exynos3250-pmu",
+   .data = _pm_data,
+   }, {
.compatible = "samsung,exynos4210-pmu",
.data = _pm_data,
}, {
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 0/2] ARM: EXYNOS3250: Add support EXYNOS3250 suspend/resume.

2014-09-26 Thread Jonghwa Lee
This patches adds and modifies exynos suspend driver to support exynos3250's
suspend/resume. To work suspend/resume, it also needs a work at pmu driver.
It'll be supported after refactoring job on pmu driver is done.

Jonghwa Lee (2):
  ARM: EXYNOS: suspend: Make restoring registers into selectable
option.
  ARM: EXYNOS3250: Add initial support EXYNOS3250 suspend/resume.

 arch/arm/mach-exynos/regs-pmu.h |4 +++
 arch/arm/mach-exynos/suspend.c  |   70 +--
 2 files changed, 56 insertions(+), 18 deletions(-)

-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/2] ARM: EXYNOS: suspend: Make restoring registers into selectable option.

2014-09-26 Thread Jonghwa Lee
Some EXYNOS series may not requried to save ROM registers as it's default
for now. This patch makes restoring registers into machine-specific option.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 arch/arm/mach-exynos/suspend.c |   39 +--
 1 file changed, 21 insertions(+), 18 deletions(-)

diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c
index f5d9773..b41d146 100644
--- a/arch/arm/mach-exynos/suspend.c
+++ b/arch/arm/mach-exynos/suspend.c
@@ -48,23 +48,28 @@ struct exynos_wkup_irq {
u32 mask;
 };
 
-static struct sleep_save exynos5_sys_save[] = {
-   SAVE_ITEM(EXYNOS5_SYS_I2C_CFG),
+static struct sleep_save exynos_save_regs[] = {
+   /* SROM side */
+   SAVE_ITEM(S5P_SROM_BW),
+   SAVE_ITEM(S5P_SROM_BC0),
+   SAVE_ITEM(S5P_SROM_BC1),
+   SAVE_ITEM(S5P_SROM_BC2),
+   SAVE_ITEM(S5P_SROM_BC3),
 };
 
-static struct sleep_save exynos_core_save[] = {
-   /* SROM side */
+static struct sleep_save exynos5_save_regs[] = {
SAVE_ITEM(S5P_SROM_BW),
SAVE_ITEM(S5P_SROM_BC0),
SAVE_ITEM(S5P_SROM_BC1),
SAVE_ITEM(S5P_SROM_BC2),
SAVE_ITEM(S5P_SROM_BC3),
+   SAVE_ITEM(EXYNOS5_SYS_I2C_CFG),
 };
 
 struct exynos_pm_data {
const struct exynos_wkup_irq *wkup_irq;
-   struct sleep_save *extra_save;
-   int num_extra_save;
+   struct sleep_save *save_regs;
+   int num_save_regs;
unsigned int wake_disable_mask;
unsigned int *release_ret_regs;
 
@@ -165,11 +170,9 @@ static void exynos_pm_prepare(void)
/* Set wake-up mask registers */
exynos_pm_set_wakeup_mask();
 
-   s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save));
-
-if (pm_data-extra_save)
-   s3c_pm_do_save(pm_data-extra_save,
-   pm_data-num_extra_save);
+if (pm_data-save_regs)
+   s3c_pm_do_save(pm_data-save_regs,
+   pm_data-num_save_regs);
 
exynos_pm_enter_sleep_mode();
 }
@@ -203,11 +206,9 @@ static void exynos_pm_resume(void)
/* For release retention */
exynos_pm_release_retention();
 
-   if (pm_data-extra_save)
-   s3c_pm_do_restore_core(pm_data-extra_save,
-   pm_data-num_extra_save);
-
-   s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save));
+   if (pm_data-save_regs)
+   s3c_pm_do_restore_core(pm_data-save_regs,
+   pm_data-num_save_regs);
 
if (cpuid == ARM_CPU_PART_CORTEX_A9)
scu_enable(S5P_VA_SCU);
@@ -291,6 +292,8 @@ static const struct exynos_pm_data exynos4_pm_data = {
.wkup_irq   = exynos4_wkup_irq,
.wake_disable_mask = ((0xFF  8) | (0x1F  1)),
.release_ret_regs = exynos_release_ret_regs,
+   .save_regs  = exynos_save_regs,
+   .num_save_regs  = ARRAY_SIZE(exynos_save_regs),
.pm_suspend = exynos_pm_suspend,
.pm_resume  = exynos_pm_resume,
.pm_prepare = exynos_pm_prepare,
@@ -301,8 +304,8 @@ static const struct exynos_pm_data exynos5250_pm_data = {
.wkup_irq   = exynos5250_wkup_irq,
.wake_disable_mask = ((0xFF  8) | (0x1F  1)),
.release_ret_regs = exynos_release_ret_regs,
-   .extra_save = exynos5_sys_save,
-   .num_extra_save = ARRAY_SIZE(exynos5_sys_save),
+   .save_regs  = exynos5_save_regs,
+   .num_save_regs  = ARRAY_SIZE(exynos5_save_regs),
.pm_suspend = exynos_pm_suspend,
.pm_resume  = exynos_pm_resume,
.pm_prepare = exynos_pm_prepare,
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 2/2] ARM: EXYNOS3250: Add initial support EXYNOS3250 suspend/resume.

2014-09-26 Thread Jonghwa Lee
It adds data and callback needed for exynos3250's suspend/resume.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
 arch/arm/mach-exynos/regs-pmu.h |4 
 arch/arm/mach-exynos/suspend.c  |   31 +++
 2 files changed, 35 insertions(+)

diff --git a/arch/arm/mach-exynos/regs-pmu.h b/arch/arm/mach-exynos/regs-pmu.h
index 322f132..b5125dc1 100644
--- a/arch/arm/mach-exynos/regs-pmu.h
+++ b/arch/arm/mach-exynos/regs-pmu.h
@@ -131,6 +131,10 @@
 #define S5P_CORE_LOCAL_PWR_EN  0x3
 #define S5P_CORE_WAKEUP_FROM_LOCAL_CFG (0x3  8)
 
+/* Only for EXYNOS3250 */
+#defineS5P_PAD_RET_MMCC_OPTION 0x30C8
+#defineS5P_PAD_RET_SPI_OPTION  0x31C8
+
 /* Only for EXYNOS4210 */
 #define S5P_CMU_CLKSTOP_LCD1_LOWPWR0x1154
 #define S5P_CMU_RESET_LCD1_LOWPWR  0x1174
diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c
index b41d146..de7d6d5 100644
--- a/arch/arm/mach-exynos/suspend.c
+++ b/arch/arm/mach-exynos/suspend.c
@@ -87,6 +87,12 @@ struct exynos_pm_data *pm_data;
 
 static u32 exynos_irqwake_intmask = 0x;
 
+static const struct exynos_wkup_irq exynos3250_wkup_irq[] = {
+   { 105, BIT(1) }, /* RTC alarm */
+   { 106, BIT(2) }, /* RTC tick */
+   { /* sentinel */ },
+};
+
 static const struct exynos_wkup_irq exynos4_wkup_irq[] = {
{ 76, BIT(1) }, /* RTC alarm */
{ 77, BIT(2) }, /* RTC tick */
@@ -99,6 +105,19 @@ static const struct exynos_wkup_irq exynos5250_wkup_irq[] = 
{
{ /* sentinel */ },
 };
 
+unsigned int exynos3250_release_ret_regs[] = {
+   S5P_PAD_RET_MAUDIO_OPTION,
+   S5P_PAD_RET_GPIO_OPTION,
+   S5P_PAD_RET_UART_OPTION,
+   S5P_PAD_RET_MMCA_OPTION,
+   S5P_PAD_RET_MMCB_OPTION,
+   S5P_PAD_RET_MMCC_OPTION,
+   S5P_PAD_RET_EBIA_OPTION,
+   S5P_PAD_RET_EBIB_OPTION,
+   S5P_PAD_RET_SPI_OPTION,
+   REG_TABLE_END,
+};
+
 unsigned int exynos_release_ret_regs[] = {
S5P_PAD_RET_MAUDIO_OPTION,
S5P_PAD_RET_GPIO_OPTION,
@@ -288,6 +307,15 @@ static const struct platform_suspend_ops 
exynos_suspend_ops = {
.valid  = suspend_valid_only_mem,
 };
 
+static const struct exynos_pm_data exynos3250_pm_data = {
+   .wkup_irq   = exynos3250_wkup_irq,
+   .release_ret_regs = exynos3250_release_ret_regs,
+   .pm_suspend = exynos_pm_suspend,
+   .pm_resume  = exynos_pm_resume,
+   .pm_prepare = exynos_pm_prepare,
+   .cpu_suspend= exynos_cpu_suspend,
+};
+
 static const struct exynos_pm_data exynos4_pm_data = {
.wkup_irq   = exynos4_wkup_irq,
.wake_disable_mask = ((0xFF  8) | (0x1F  1)),
@@ -314,6 +342,9 @@ static const struct exynos_pm_data exynos5250_pm_data = {
 
 static struct of_device_id exynos_pmu_of_device_ids[] = {
{
+   .compatible = samsung,exynos3250-pmu,
+   .data = exynos3250_pm_data,
+   }, {
.compatible = samsung,exynos4210-pmu,
.data = exynos4_pm_data,
}, {
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v3] hwmon: ntc_thermistor: Add ntc thermistor to thermal subsystem as a sensor.

2014-09-16 Thread Jonghwa Lee
To get more comprehensive and integrated thermal management, it adds ntc
thermistor to thermal framework as a thermal sensor. It's governed thermal
susbsystem only if it is described in DT node. Otherwise, it just notifies
temperature to userspace via sysfs as it used to be.

Signed-off-by: Jonghwa Lee 
---
Changes:
v3:
 - Add dependencies of thermal subsystem for proper building.
v2:
 - Remove NULL pointer checking already done by 
thermal_zone_of_sensor_unregister().

 .../devicetree/bindings/hwmon/ntc_thermistor.txt   |3 +++
 drivers/hwmon/Kconfig  |1 +
 drivers/hwmon/ntc_thermistor.c |   25 
 3 files changed, 29 insertions(+)

diff --git a/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt 
b/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
index 2391e5c..fcca8e7 100644
--- a/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
+++ b/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
@@ -25,6 +25,9 @@ Requires node properties:
 - "io-channels"Channel node of ADC to be used for
conversion.
 
+Optional node properties:
+- "#thermal-sensor-cells" Used to expose itself to thermal fw.
+
 Read more about iio bindings at
Documentation/devicetree/bindings/iio/iio-bindings.txt
 
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 4289a4f..f790b41 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1077,6 +1077,7 @@ config SENSORS_PC87427
 config SENSORS_NTC_THERMISTOR
tristate "NTC thermistor support from Murata"
depends on !OF || IIO=n || IIO
+   depends on THERMAL || !THERMAL_OF
help
  This driver supports NTC thermistors sensor reading and its
  interpretation. The driver can also monitor the temperature and
diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c
index bd41072..4ff89b2 100644
--- a/drivers/hwmon/ntc_thermistor.c
+++ b/drivers/hwmon/ntc_thermistor.c
@@ -38,6 +38,7 @@
 
 #include 
 #include 
+#include 
 
 struct ntc_compensation {
int temp_c;
@@ -182,6 +183,7 @@ struct ntc_data {
struct device *dev;
int n_comp;
char name[PLATFORM_NAME_SIZE];
+   struct thermal_zone_device *tz;
 };
 
 #if defined(CONFIG_OF) && IS_ENABLED(CONFIG_IIO)
@@ -428,6 +430,20 @@ static int ntc_thermistor_get_ohm(struct ntc_data *data)
return -EINVAL;
 }
 
+static int ntc_read_temp(void *dev, long *temp)
+{
+   struct ntc_data *data = dev_get_drvdata(dev);
+   int ohm;
+
+   ohm = ntc_thermistor_get_ohm(data);
+   if (ohm < 0)
+   return ohm;
+
+   *temp = get_temp_mc(data, ohm);
+
+   return 0;
+}
+
 static ssize_t ntc_show_name(struct device *dev,
struct device_attribute *attr, char *buf)
 {
@@ -562,6 +578,13 @@ static int ntc_thermistor_probe(struct platform_device 
*pdev)
dev_info(>dev, "Thermistor type: %s successfully probed.\n",
pdev_id->name);
 
+   data->tz = thermal_zone_of_sensor_register(data->dev, 0, data->dev,
+   ntc_read_temp, NULL);
+   if (IS_ERR(data->tz)) {
+   dev_dbg(>dev, "Failed to register to thermal fw.\n");
+   data->tz = NULL;
+   }
+
return 0;
 err_after_sysfs:
sysfs_remove_group(>dev->kobj, _attr_group);
@@ -578,6 +601,8 @@ static int ntc_thermistor_remove(struct platform_device 
*pdev)
sysfs_remove_group(>dev->kobj, _attr_group);
ntc_iio_channel_release(pdata);
 
+   thermal_zone_of_sensor_unregister(data->dev, data->tz);
+
return 0;
 }
 
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v3] extcon: max77693: Fix a bug occured at changing ADC debounce time.

2014-09-16 Thread Jonghwa Lee
When it writes some value other than 0 to BTLDset and JIGset, muic device
will be reset automatically. And it happens during updating ADC debounce time,
because it shares same register. To update ADC debounce time without reset,
set value only to ADCDbset and 0 to BTLDset and JIGset.

Signed-off-by: Jonghwa Lee 
---
Changes:
v3: - Fix typo (regmap_write_bits -> regmap_write)
v2: - Fix comments.

 drivers/extcon/extcon-max77693.c |   13 +
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c
index 77460f2..132540e 100644
--- a/drivers/extcon/extcon-max77693.c
+++ b/drivers/extcon/extcon-max77693.c
@@ -255,10 +255,15 @@ static int max77693_muic_set_debounce_time(struct 
max77693_muic_info *info,
case ADC_DEBOUNCE_TIME_10MS:
case ADC_DEBOUNCE_TIME_25MS:
case ADC_DEBOUNCE_TIME_38_62MS:
-   ret = regmap_update_bits(info->max77693->regmap_muic,
- MAX77693_MUIC_REG_CTRL3,
- CONTROL3_ADCDBSET_MASK,
- time << CONTROL3_ADCDBSET_SHIFT);
+   /*
+* Don't touch BTLDset, JIGset when you want to change adc
+* debounce time. If it writes other than 0 to BTLDset, JIGset
+* muic device will be reset and loose current state.
+*/
+   ret = regmap_write(info->max77693->regmap_muic,
+ MAX77693_MUIC_REG_CTRL3,
+ (CONTROL3_ADCDBSET_MASK &
+ time << CONTROL3_ADCDBSET_SHIFT));
if (ret) {
dev_err(info->dev, "failed to set ADC debounce time\n");
return ret;
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RESEND PATCH] arm: exynos: Allow rtc alarm and tick wakeup irq for exynos3250.

2014-09-16 Thread Jonghwa Lee
Add rtc alarm and tick irq to wakeup sources in exynos3250.

Signed-off-by: Jonghwa Lee 
Acked-by : Chanwoo choi 
---
 arch/arm/mach-exynos/pm.c |9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c
index fa7218a..d78dcf9 100644
--- a/arch/arm/mach-exynos/pm.c
+++ b/arch/arm/mach-exynos/pm.c
@@ -66,6 +66,12 @@ static struct sleep_save exynos_core_save[] = {
 
 static u32 exynos_irqwake_intmask = 0x;
 
+static const struct exynos_wkup_irq exynos3250_wkup_irq[] = {
+   { 105, BIT(1) }, /* RTC alarm */
+   { 106, BIT(2) }, /* RTC tick */
+   { /* sentinel */ },
+};
+
 static const struct exynos_wkup_irq exynos4_wkup_irq[] = {
{ 76, BIT(1) }, /* RTC alarm */
{ 77, BIT(2) }, /* RTC tick */
@@ -81,9 +87,10 @@ static const struct exynos_wkup_irq exynos5250_wkup_irq[] = {
 static int exynos_irq_set_wake(struct irq_data *data, unsigned int state)
 {
const struct exynos_wkup_irq *wkup_irq;
-
if (soc_is_exynos5250())
wkup_irq = exynos5250_wkup_irq;
+   else if (soc_is_exynos3250())
+   wkup_irq = exynos3250_wkup_irq;
else
wkup_irq = exynos4_wkup_irq;
 
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 2/2] power: smb347-charger: Support Summit SMB358 charger IC.

2014-09-16 Thread Jonghwa Lee
Summit microelectronics' SMB358 charger chip has almost same register map
and functionality with SMB347. The voltage and current table are only differed.
Thus, SMB347 driver can support SMB358 chip fully with few modifications.

Signed-off-by: Jonghwa Lee 
Acked-by : Chanwoo Choi 
Acked-by : Myungjoo Ham 
---
 .../bindings/power_supply/smb347_charger.txt   |1 +
 drivers/power/smb347-charger.c |   98 +---
 2 files changed, 47 insertions(+), 52 deletions(-)

diff --git a/Documentation/devicetree/bindings/power_supply/smb347_charger.txt 
b/Documentation/devicetree/bindings/power_supply/smb347_charger.txt
index 91570a5..776ae29 100644
--- a/Documentation/devicetree/bindings/power_supply/smb347_charger.txt
+++ b/Documentation/devicetree/bindings/power_supply/smb347_charger.txt
@@ -3,6 +3,7 @@ smb347_charger bindings
 
 [Required porperties]
 - compatible : "summit,smb347"
+  "summit,smb358"
 - reg : Slave address for i2c interface
 # At least one of followings should be set
   - enable-usb-charging
diff --git a/drivers/power/smb347-charger.c b/drivers/power/smb347-charger.c
index 8073879..1bfb115 100644
--- a/drivers/power/smb347-charger.c
+++ b/drivers/power/smb347-charger.c
@@ -136,6 +136,7 @@
  * @pdata: pointer to platform data
  */
 struct smb347_charger {
+   int id;
struct mutexlock;
struct device   *dev;
struct regmap   *regmap;
@@ -148,58 +149,46 @@ struct smb347_charger {
const struct smb347_charger_platform_data *pdata;
 };
 
+enum smb_charger_chipid {
+   SMB347,
+   SMB358,
+   NUM_CHIP_TYPES,
+};
+
 /* Fast charge current in uA */
-static const unsigned int fcc_tbl[] = {
-   70,
-   90,
-   120,
-   150,
-   180,
-   200,
-   220,
-   250,
+static const unsigned int fcc_tbl[NUM_CHIP_TYPES][8] = {
+   [SMB347] = { 70, 90, 120, 150,
+   180, 200, 220, 250 },
+   [SMB358] = { 20, 45, 60, 90,
+   130, 150, 180, 200 },
 };
 
 /* Pre-charge current in uA */
-static const unsigned int pcc_tbl[] = {
-   10,
-   15,
-   20,
-   25,
+static const unsigned int pcc_tbl[NUM_CHIP_TYPES][4] = {
+   [SMB347] = { 10, 15, 20, 25 },
+   [SMB358] = { 15, 25, 35, 45 },
 };
 
 /* Termination current in uA */
-static const unsigned int tc_tbl[] = {
-   37500,
-   5,
-   10,
-   15,
-   20,
-   25,
-   50,
-   60,
+static const unsigned int tc_tbl[NUM_CHIP_TYPES][8] = {
+   [SMB347] = { 37500, 5, 10, 15,
+   20, 25, 50, 60 },
+   [SMB358] = { 3, 4, 6, 8,
+   10, 125000, 15, 20 },
 };
 
 /* Input current limit in uA */
-static const unsigned int icl_tbl[] = {
-   30,
-   50,
-   70,
-   90,
-   120,
-   150,
-   180,
-   200,
-   220,
-   250,
+static const unsigned int icl_tbl[NUM_CHIP_TYPES][10] = {
+   [SMB347] = { 30, 50, 70, 90, 120,
+   150, 180, 200, 220, 250 },
+   [SMB358] = { 30, 50, 70, 100, 150,
+   180, 200, 200, 200, 200 },
 };
 
 /* Charge current compensation in uA */
-static const unsigned int ccc_tbl[] = {
-   25,
-   70,
-   90,
-   120,
+static const unsigned int ccc_tbl[NUM_CHIP_TYPES][4] = {
+   [SMB347] = { 25, 70, 90, 120 },
+   [SMB358] = { 20, 45, 60, 90 },
 };
 
 /* Convert register value to current using lookup table */
@@ -354,10 +343,10 @@ static int smb347_start_stop_charging(struct 
smb347_charger *smb)
 
 static int smb347_set_charge_current(struct smb347_charger *smb)
 {
-   int ret;
+   int ret, id = smb->id;
 
if (smb->pdata->max_charge_current) {
-   ret = current_to_hw(fcc_tbl, ARRAY_SIZE(fcc_tbl),
+   ret = current_to_hw(fcc_tbl[id], ARRAY_SIZE(fcc_tbl[id]),
smb->pdata->max_charge_current);
if (ret < 0)
return ret;
@@ -370,7 +359,7 @@ static int smb347_set_charge_current(struct smb347_charger 
*smb)
}
 
if (smb->pdata->pre_charge_current) {
-   ret = current_to_hw(pcc_tbl, ARRAY_SIZE(pcc_tbl),
+   ret = current_to_hw(pcc_tbl[id], ARRAY_SIZE(pcc_tbl[id]),
smb->pdata->pre_charge_current);
if (ret < 0)
return ret;
@@ -383,7 +372,7 @@ static int smb347_set_charge_current(str

[PATCH 1/2] power: smb347-charger: Support devicetree binding for smb347 driver.

2014-09-16 Thread Jonghwa Lee
This patch makes smb347 charger driver to support dt binding. All legacy
platform data now can be parsed from dt.
Because of that smb347 is i2c client driver, IRQ number can be passed
automatically through client's irq variable if it is defined in dt.
No more to use requesting gpio to irq manually in dt-way.

Signed-off-by: Jonghwa Lee 
Acked-by : Chanwoo Choi 
Acked-by : Myungjoo Ham 
---
 .../bindings/power_supply/smb347_charger.txt   |   57 
 .../devicetree/bindings/vendor-prefixes.txt|1 +
 drivers/power/smb347-charger.c |  144 +++-
 3 files changed, 167 insertions(+), 35 deletions(-)
 create mode 100644 
Documentation/devicetree/bindings/power_supply/smb347_charger.txt

diff --git a/Documentation/devicetree/bindings/power_supply/smb347_charger.txt 
b/Documentation/devicetree/bindings/power_supply/smb347_charger.txt
new file mode 100644
index 000..91570a5
--- /dev/null
+++ b/Documentation/devicetree/bindings/power_supply/smb347_charger.txt
@@ -0,0 +1,57 @@
+smb347_charger bindings
+
+
+[Required porperties]
+- compatible : "summit,smb347"
+- reg : Slave address for i2c interface
+# At least one of followings should be set
+  - enable-usb-charging
+  - enable-otg-charging
+  - enable-mains-charging
+
+[Optional properties]
+- interrupt-parent : The phandle for the interrupt controller
+- interrupts : Interrupt line index for mapping
+- enable-chg-ctrl : Enable charging control
+   <0> : SW (i2c interface)
+   <1> : Pin control (Active Low)
+   <2> : Pin control (Active High)
+# Charging constraints
+- max-chg-curr : Maximum current for charging (in uA)
+- max-chg-volt : Maximum voltage for charging (in uV)
+- pre-chg-curr : Pre-charging current (in uA)
+- term-curr : Charging cycle termination current (in uA)
+- fast-volt-thershold : Voltage threshold to transit to fast charge mode (in 
uV)
+- mains-curr-limit : Maximum input current from AC/DC input (in uA)
+- usb-curr-limit : Maximum input current from USB input (in uA)
+
+# Related thermometer monitoring (in degree C)
+- chip-temp-threshold : Chip temperature for thermal regulaton.   <100, 130>
+- soft-cold-temp-limit : Cold battery temperature for soft alarm. <0, 15>*
+- soft-hot-temp-limit : Hot battery temperature for soft alarm.   <40, 55>
+- hard-cold-temp-limit : Cold battery temperature for hard alarm. <0, 15>*
+- hard-hot-temp-limit : Hot battery temperature for hard alarm.   <55, 65>
+(* The written temperature has +5'C offset. 0'C -> -5'C, 15'C -> 10'C)
+- soft-comp-method : Soft temperature limit compensation method
+   (Not defined) : Use default setting
+   <0> : Compensation none
+   <1> : Charge current compensation
+   <2> : Voltage compensation
+
+Example:
+   smb347@7f {
+   compatible = "summit,smb347";
+   reg = <0x7f>;
+   status = "okay";
+
+   max-chg-curr = <180>;
+   mains-curr-limit = <200>;
+   usb-curr-limit = <45>;
+
+   chip-temp-thershold = <110>;
+
+   enable-usb-charging;
+   enable-mains-charging;
+
+   enable-chg-ctrl = <2>;  /* Pin control (Active High) */
+   };
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt 
b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 13fda72..616e2a1 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -121,6 +121,7 @@ spansionSpansion Inc.
 st STMicroelectronics
 steST-Ericsson
 stericsson ST-Ericsson
+summit Summit microelectronics
 synology   Synology, Inc.
 ti Texas Instruments
 tlmTrusted Logic Mobility
diff --git a/drivers/power/smb347-charger.c b/drivers/power/smb347-charger.c
index acf84e8..8073879 100644
--- a/drivers/power/smb347-charger.c
+++ b/drivers/power/smb347-charger.c
@@ -835,20 +835,28 @@ static int smb347_irq_init(struct smb347_charger *smb,
   struct i2c_client *client)
 {
const struct smb347_charger_platform_data *pdata = smb->pdata;
-   int ret, irq = gpio_to_irq(pdata->irq_gpio);
+   int ret;
 
-   ret = gpio_request_one(pdata->irq_gpio, GPIOF_IN, client->name);
-   if (ret < 0)
-   goto fail;
+   /* Requesting GPIO for IRQ is only needed in non-DT way */
+   if (!client->irq) {
+   int irq = gpio_to_irq(pdata->irq_gpio);
+   ret = devm_gpio_request_one(smb->dev, pdata->irq_gpio,
+   GPIOF_IN, client->name);
+   if (ret < 0)
+   goto out;
 
-   ret = request_threaded_irq(irq, NULL, smb347_interru

[PATCH RESEND 0/2] Update smb347 charger driver.

2014-09-16 Thread Jonghwa Lee
This patch set updates smb347 driver to support dt-binding and smb358 chip.

Jonghwa Lee (2):
  power: smb347-charger: Support devicetree binding for smb347 driver.
  power: smb347-charger: Support Summit SMB358 charger IC.

 .../bindings/power_supply/smb347_charger.txt   |   58 +
 .../devicetree/bindings/vendor-prefixes.txt|1 +
 drivers/power/smb347-charger.c |  242 +---
 3 files changed, 214 insertions(+), 87 deletions(-)
 create mode 100644 
Documentation/devicetree/bindings/power_supply/smb347_charger.txt

-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH RESEND v2] hwmon: ntc_thermistor: Add ntc thermistor to thermal subsystem as a sensor.

2014-09-16 Thread Jonghwa Lee
To get more comprehensive and integrated thermal management, it adds ntc
thermistor to thermal framework as a thermal sensor. It's governed thermal
susbsystem only if it is described in DT node. Otherwise, it just notifies
temperature to userspace via sysfs as it used to be.

Signed-off-by: Jonghwa Lee 
---
Updates in v2
 - Remove NULL pointer checking already done by 
thermal_zone_of_sensor_unregister().

 .../devicetree/bindings/hwmon/ntc_thermistor.txt   |3 +++
 drivers/hwmon/ntc_thermistor.c |   25 
 2 files changed, 28 insertions(+)

diff --git a/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt 
b/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
index 2391e5c..fcca8e7 100644
--- a/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
+++ b/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
@@ -25,6 +25,9 @@ Requires node properties:
 - "io-channels"Channel node of ADC to be used for
conversion.
 
+Optional node properties:
+- "#thermal-sensor-cells" Used to expose itself to thermal fw.
+
 Read more about iio bindings at
Documentation/devicetree/bindings/iio/iio-bindings.txt
 
diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c
index bd41072..4ff89b2 100644
--- a/drivers/hwmon/ntc_thermistor.c
+++ b/drivers/hwmon/ntc_thermistor.c
@@ -38,6 +38,7 @@
 
 #include 
 #include 
+#include 
 
 struct ntc_compensation {
int temp_c;
@@ -182,6 +183,7 @@ struct ntc_data {
struct device *dev;
int n_comp;
char name[PLATFORM_NAME_SIZE];
+   struct thermal_zone_device *tz;
 };
 
 #if defined(CONFIG_OF) && IS_ENABLED(CONFIG_IIO)
@@ -428,6 +430,20 @@ static int ntc_thermistor_get_ohm(struct ntc_data *data)
return -EINVAL;
 }
 
+static int ntc_read_temp(void *dev, long *temp)
+{
+   struct ntc_data *data = dev_get_drvdata(dev);
+   int ohm;
+
+   ohm = ntc_thermistor_get_ohm(data);
+   if (ohm < 0)
+   return ohm;
+
+   *temp = get_temp_mc(data, ohm);
+
+   return 0;
+}
+
 static ssize_t ntc_show_name(struct device *dev,
struct device_attribute *attr, char *buf)
 {
@@ -562,6 +578,13 @@ static int ntc_thermistor_probe(struct platform_device 
*pdev)
dev_info(>dev, "Thermistor type: %s successfully probed.\n",
pdev_id->name);
 
+   data->tz = thermal_zone_of_sensor_register(data->dev, 0, data->dev,
+   ntc_read_temp, NULL);
+   if (IS_ERR(data->tz)) {
+   dev_dbg(>dev, "Failed to register to thermal fw.\n");
+   data->tz = NULL;
+   }
+
return 0;
 err_after_sysfs:
sysfs_remove_group(>dev->kobj, _attr_group);
@@ -578,6 +601,8 @@ static int ntc_thermistor_remove(struct platform_device 
*pdev)
sysfs_remove_group(>dev->kobj, _attr_group);
ntc_iio_channel_release(pdata);
 
+   thermal_zone_of_sensor_unregister(data->dev, data->tz);
+
return 0;
 }
 
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH RESEND v2] hwmon: ntc_thermistor: Add ntc thermistor to thermal subsystem as a sensor.

2014-09-16 Thread Jonghwa Lee
To get more comprehensive and integrated thermal management, it adds ntc
thermistor to thermal framework as a thermal sensor. It's governed thermal
susbsystem only if it is described in DT node. Otherwise, it just notifies
temperature to userspace via sysfs as it used to be.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
---
Updates in v2
 - Remove NULL pointer checking already done by 
thermal_zone_of_sensor_unregister().

 .../devicetree/bindings/hwmon/ntc_thermistor.txt   |3 +++
 drivers/hwmon/ntc_thermistor.c |   25 
 2 files changed, 28 insertions(+)

diff --git a/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt 
b/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
index 2391e5c..fcca8e7 100644
--- a/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
+++ b/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
@@ -25,6 +25,9 @@ Requires node properties:
 - io-channelsChannel node of ADC to be used for
conversion.
 
+Optional node properties:
+- #thermal-sensor-cells Used to expose itself to thermal fw.
+
 Read more about iio bindings at
Documentation/devicetree/bindings/iio/iio-bindings.txt
 
diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c
index bd41072..4ff89b2 100644
--- a/drivers/hwmon/ntc_thermistor.c
+++ b/drivers/hwmon/ntc_thermistor.c
@@ -38,6 +38,7 @@
 
 #include linux/hwmon.h
 #include linux/hwmon-sysfs.h
+#include linux/thermal.h
 
 struct ntc_compensation {
int temp_c;
@@ -182,6 +183,7 @@ struct ntc_data {
struct device *dev;
int n_comp;
char name[PLATFORM_NAME_SIZE];
+   struct thermal_zone_device *tz;
 };
 
 #if defined(CONFIG_OF)  IS_ENABLED(CONFIG_IIO)
@@ -428,6 +430,20 @@ static int ntc_thermistor_get_ohm(struct ntc_data *data)
return -EINVAL;
 }
 
+static int ntc_read_temp(void *dev, long *temp)
+{
+   struct ntc_data *data = dev_get_drvdata(dev);
+   int ohm;
+
+   ohm = ntc_thermistor_get_ohm(data);
+   if (ohm  0)
+   return ohm;
+
+   *temp = get_temp_mc(data, ohm);
+
+   return 0;
+}
+
 static ssize_t ntc_show_name(struct device *dev,
struct device_attribute *attr, char *buf)
 {
@@ -562,6 +578,13 @@ static int ntc_thermistor_probe(struct platform_device 
*pdev)
dev_info(pdev-dev, Thermistor type: %s successfully probed.\n,
pdev_id-name);
 
+   data-tz = thermal_zone_of_sensor_register(data-dev, 0, data-dev,
+   ntc_read_temp, NULL);
+   if (IS_ERR(data-tz)) {
+   dev_dbg(pdev-dev, Failed to register to thermal fw.\n);
+   data-tz = NULL;
+   }
+
return 0;
 err_after_sysfs:
sysfs_remove_group(data-dev-kobj, ntc_attr_group);
@@ -578,6 +601,8 @@ static int ntc_thermistor_remove(struct platform_device 
*pdev)
sysfs_remove_group(data-dev-kobj, ntc_attr_group);
ntc_iio_channel_release(pdata);
 
+   thermal_zone_of_sensor_unregister(data-dev, data-tz);
+
return 0;
 }
 
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH RESEND 0/2] Update smb347 charger driver.

2014-09-16 Thread Jonghwa Lee
This patch set updates smb347 driver to support dt-binding and smb358 chip.

Jonghwa Lee (2):
  power: smb347-charger: Support devicetree binding for smb347 driver.
  power: smb347-charger: Support Summit SMB358 charger IC.

 .../bindings/power_supply/smb347_charger.txt   |   58 +
 .../devicetree/bindings/vendor-prefixes.txt|1 +
 drivers/power/smb347-charger.c |  242 +---
 3 files changed, 214 insertions(+), 87 deletions(-)
 create mode 100644 
Documentation/devicetree/bindings/power_supply/smb347_charger.txt

-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/2] power: smb347-charger: Support devicetree binding for smb347 driver.

2014-09-16 Thread Jonghwa Lee
This patch makes smb347 charger driver to support dt binding. All legacy
platform data now can be parsed from dt.
Because of that smb347 is i2c client driver, IRQ number can be passed
automatically through client's irq variable if it is defined in dt.
No more to use requesting gpio to irq manually in dt-way.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
Acked-by : Chanwoo Choi cw00.c...@samsung.com
Acked-by : Myungjoo Ham myungjoo@samsung.com
---
 .../bindings/power_supply/smb347_charger.txt   |   57 
 .../devicetree/bindings/vendor-prefixes.txt|1 +
 drivers/power/smb347-charger.c |  144 +++-
 3 files changed, 167 insertions(+), 35 deletions(-)
 create mode 100644 
Documentation/devicetree/bindings/power_supply/smb347_charger.txt

diff --git a/Documentation/devicetree/bindings/power_supply/smb347_charger.txt 
b/Documentation/devicetree/bindings/power_supply/smb347_charger.txt
new file mode 100644
index 000..91570a5
--- /dev/null
+++ b/Documentation/devicetree/bindings/power_supply/smb347_charger.txt
@@ -0,0 +1,57 @@
+smb347_charger bindings
+
+
+[Required porperties]
+- compatible : summit,smb347
+- reg : Slave address for i2c interface
+# At least one of followings should be set
+  - enable-usb-charging
+  - enable-otg-charging
+  - enable-mains-charging
+
+[Optional properties]
+- interrupt-parent : The phandle for the interrupt controller
+- interrupts : Interrupt line index for mapping
+- enable-chg-ctrl : Enable charging control
+   0 : SW (i2c interface)
+   1 : Pin control (Active Low)
+   2 : Pin control (Active High)
+# Charging constraints
+- max-chg-curr : Maximum current for charging (in uA)
+- max-chg-volt : Maximum voltage for charging (in uV)
+- pre-chg-curr : Pre-charging current (in uA)
+- term-curr : Charging cycle termination current (in uA)
+- fast-volt-thershold : Voltage threshold to transit to fast charge mode (in 
uV)
+- mains-curr-limit : Maximum input current from AC/DC input (in uA)
+- usb-curr-limit : Maximum input current from USB input (in uA)
+
+# Related thermometer monitoring (in degree C)
+- chip-temp-threshold : Chip temperature for thermal regulaton.   100, 130
+- soft-cold-temp-limit : Cold battery temperature for soft alarm. 0, 15*
+- soft-hot-temp-limit : Hot battery temperature for soft alarm.   40, 55
+- hard-cold-temp-limit : Cold battery temperature for hard alarm. 0, 15*
+- hard-hot-temp-limit : Hot battery temperature for hard alarm.   55, 65
+(* The written temperature has +5'C offset. 0'C - -5'C, 15'C - 10'C)
+- soft-comp-method : Soft temperature limit compensation method
+   (Not defined) : Use default setting
+   0 : Compensation none
+   1 : Charge current compensation
+   2 : Voltage compensation
+
+Example:
+   smb347@7f {
+   compatible = summit,smb347;
+   reg = 0x7f;
+   status = okay;
+
+   max-chg-curr = 180;
+   mains-curr-limit = 200;
+   usb-curr-limit = 45;
+
+   chip-temp-thershold = 110;
+
+   enable-usb-charging;
+   enable-mains-charging;
+
+   enable-chg-ctrl = 2;  /* Pin control (Active High) */
+   };
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt 
b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 13fda72..616e2a1 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -121,6 +121,7 @@ spansionSpansion Inc.
 st STMicroelectronics
 steST-Ericsson
 stericsson ST-Ericsson
+summit Summit microelectronics
 synology   Synology, Inc.
 ti Texas Instruments
 tlmTrusted Logic Mobility
diff --git a/drivers/power/smb347-charger.c b/drivers/power/smb347-charger.c
index acf84e8..8073879 100644
--- a/drivers/power/smb347-charger.c
+++ b/drivers/power/smb347-charger.c
@@ -835,20 +835,28 @@ static int smb347_irq_init(struct smb347_charger *smb,
   struct i2c_client *client)
 {
const struct smb347_charger_platform_data *pdata = smb-pdata;
-   int ret, irq = gpio_to_irq(pdata-irq_gpio);
+   int ret;
 
-   ret = gpio_request_one(pdata-irq_gpio, GPIOF_IN, client-name);
-   if (ret  0)
-   goto fail;
+   /* Requesting GPIO for IRQ is only needed in non-DT way */
+   if (!client-irq) {
+   int irq = gpio_to_irq(pdata-irq_gpio);
+   ret = devm_gpio_request_one(smb-dev, pdata-irq_gpio,
+   GPIOF_IN, client-name);
+   if (ret  0)
+   goto out;
 
-   ret = request_threaded_irq(irq, NULL, smb347_interrupt,
-  IRQF_TRIGGER_FALLING, client-name, smb);
+   client-irq = irq;
+   }
+
+   ret

[PATCH 2/2] power: smb347-charger: Support Summit SMB358 charger IC.

2014-09-16 Thread Jonghwa Lee
Summit microelectronics' SMB358 charger chip has almost same register map
and functionality with SMB347. The voltage and current table are only differed.
Thus, SMB347 driver can support SMB358 chip fully with few modifications.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
Acked-by : Chanwoo Choi cw00.c...@samsung.com
Acked-by : Myungjoo Ham myungjoo@samsung.com
---
 .../bindings/power_supply/smb347_charger.txt   |1 +
 drivers/power/smb347-charger.c |   98 +---
 2 files changed, 47 insertions(+), 52 deletions(-)

diff --git a/Documentation/devicetree/bindings/power_supply/smb347_charger.txt 
b/Documentation/devicetree/bindings/power_supply/smb347_charger.txt
index 91570a5..776ae29 100644
--- a/Documentation/devicetree/bindings/power_supply/smb347_charger.txt
+++ b/Documentation/devicetree/bindings/power_supply/smb347_charger.txt
@@ -3,6 +3,7 @@ smb347_charger bindings
 
 [Required porperties]
 - compatible : summit,smb347
+  summit,smb358
 - reg : Slave address for i2c interface
 # At least one of followings should be set
   - enable-usb-charging
diff --git a/drivers/power/smb347-charger.c b/drivers/power/smb347-charger.c
index 8073879..1bfb115 100644
--- a/drivers/power/smb347-charger.c
+++ b/drivers/power/smb347-charger.c
@@ -136,6 +136,7 @@
  * @pdata: pointer to platform data
  */
 struct smb347_charger {
+   int id;
struct mutexlock;
struct device   *dev;
struct regmap   *regmap;
@@ -148,58 +149,46 @@ struct smb347_charger {
const struct smb347_charger_platform_data *pdata;
 };
 
+enum smb_charger_chipid {
+   SMB347,
+   SMB358,
+   NUM_CHIP_TYPES,
+};
+
 /* Fast charge current in uA */
-static const unsigned int fcc_tbl[] = {
-   70,
-   90,
-   120,
-   150,
-   180,
-   200,
-   220,
-   250,
+static const unsigned int fcc_tbl[NUM_CHIP_TYPES][8] = {
+   [SMB347] = { 70, 90, 120, 150,
+   180, 200, 220, 250 },
+   [SMB358] = { 20, 45, 60, 90,
+   130, 150, 180, 200 },
 };
 
 /* Pre-charge current in uA */
-static const unsigned int pcc_tbl[] = {
-   10,
-   15,
-   20,
-   25,
+static const unsigned int pcc_tbl[NUM_CHIP_TYPES][4] = {
+   [SMB347] = { 10, 15, 20, 25 },
+   [SMB358] = { 15, 25, 35, 45 },
 };
 
 /* Termination current in uA */
-static const unsigned int tc_tbl[] = {
-   37500,
-   5,
-   10,
-   15,
-   20,
-   25,
-   50,
-   60,
+static const unsigned int tc_tbl[NUM_CHIP_TYPES][8] = {
+   [SMB347] = { 37500, 5, 10, 15,
+   20, 25, 50, 60 },
+   [SMB358] = { 3, 4, 6, 8,
+   10, 125000, 15, 20 },
 };
 
 /* Input current limit in uA */
-static const unsigned int icl_tbl[] = {
-   30,
-   50,
-   70,
-   90,
-   120,
-   150,
-   180,
-   200,
-   220,
-   250,
+static const unsigned int icl_tbl[NUM_CHIP_TYPES][10] = {
+   [SMB347] = { 30, 50, 70, 90, 120,
+   150, 180, 200, 220, 250 },
+   [SMB358] = { 30, 50, 70, 100, 150,
+   180, 200, 200, 200, 200 },
 };
 
 /* Charge current compensation in uA */
-static const unsigned int ccc_tbl[] = {
-   25,
-   70,
-   90,
-   120,
+static const unsigned int ccc_tbl[NUM_CHIP_TYPES][4] = {
+   [SMB347] = { 25, 70, 90, 120 },
+   [SMB358] = { 20, 45, 60, 90 },
 };
 
 /* Convert register value to current using lookup table */
@@ -354,10 +343,10 @@ static int smb347_start_stop_charging(struct 
smb347_charger *smb)
 
 static int smb347_set_charge_current(struct smb347_charger *smb)
 {
-   int ret;
+   int ret, id = smb-id;
 
if (smb-pdata-max_charge_current) {
-   ret = current_to_hw(fcc_tbl, ARRAY_SIZE(fcc_tbl),
+   ret = current_to_hw(fcc_tbl[id], ARRAY_SIZE(fcc_tbl[id]),
smb-pdata-max_charge_current);
if (ret  0)
return ret;
@@ -370,7 +359,7 @@ static int smb347_set_charge_current(struct smb347_charger 
*smb)
}
 
if (smb-pdata-pre_charge_current) {
-   ret = current_to_hw(pcc_tbl, ARRAY_SIZE(pcc_tbl),
+   ret = current_to_hw(pcc_tbl[id], ARRAY_SIZE(pcc_tbl[id]),
smb-pdata-pre_charge_current);
if (ret  0)
return ret;
@@ -383,7 +372,7 @@ static int smb347_set_charge_current(struct

[RESEND PATCH] arm: exynos: Allow rtc alarm and tick wakeup irq for exynos3250.

2014-09-16 Thread Jonghwa Lee
Add rtc alarm and tick irq to wakeup sources in exynos3250.

Signed-off-by: Jonghwa Lee jonghwa3@samsung.com
Acked-by : Chanwoo choi cw00.c...@samsung.com
---
 arch/arm/mach-exynos/pm.c |9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c
index fa7218a..d78dcf9 100644
--- a/arch/arm/mach-exynos/pm.c
+++ b/arch/arm/mach-exynos/pm.c
@@ -66,6 +66,12 @@ static struct sleep_save exynos_core_save[] = {
 
 static u32 exynos_irqwake_intmask = 0x;
 
+static const struct exynos_wkup_irq exynos3250_wkup_irq[] = {
+   { 105, BIT(1) }, /* RTC alarm */
+   { 106, BIT(2) }, /* RTC tick */
+   { /* sentinel */ },
+};
+
 static const struct exynos_wkup_irq exynos4_wkup_irq[] = {
{ 76, BIT(1) }, /* RTC alarm */
{ 77, BIT(2) }, /* RTC tick */
@@ -81,9 +87,10 @@ static const struct exynos_wkup_irq exynos5250_wkup_irq[] = {
 static int exynos_irq_set_wake(struct irq_data *data, unsigned int state)
 {
const struct exynos_wkup_irq *wkup_irq;
-
if (soc_is_exynos5250())
wkup_irq = exynos5250_wkup_irq;
+   else if (soc_is_exynos3250())
+   wkup_irq = exynos3250_wkup_irq;
else
wkup_irq = exynos4_wkup_irq;
 
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


  1   2   3   >