[RESEND PATCH v3] drivers/tty: Folding Android's keyreset driver in sysRQ

2012-09-24 Thread mathieu . poirier
From: Mathieu J. Poirier mathieu.poir...@linaro.org

The last version of this patch was sent a week ago but did not
generate comments or an acknowledgement.  It is being resent
after a rebase on 3.6-rc7.

This patch adds keyreset functionality to the sysrq driver. It
allows certain button/key combinations to be used in order to
trigger device resets.

The first time the key-combo is detected a work function that syncs
the filesystems is scheduled and the kernel rebooted. If all the keys
are released and then pressed again, it calls panic. Reboot on panic
should be set for this to work.

A platform device that specify a reset key-combo should be added to
the board file to trigger the feature.  Alternatively keys can be
passed to the driver via the /sys/module/sysrq interface.

This functionality comes from the keyreset driver submitted by
Arve Hjønnevåg in the Android kernel.

Cc: a...@android.com
Cc: kernel-t...@android.com
Cc: dmitry.torok...@gmail.com
Cc: john.stu...@linaro.org
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
---
 drivers/tty/sysrq.c   |  308 +
 include/linux/sysrq.h |8 ++
 2 files changed, 316 insertions(+), 0 deletions(-)

diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index 05728894..c44056f 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -41,14 +41,30 @@
 #include linux/slab.h
 #include linux/input.h
 #include linux/uaccess.h
+#include linux/platform_device.h
+#include linux/syscalls.h
+#include linux/atomic.h
+#include linux/moduleparam.h
+#include linux/mutex.h
 
 #include asm/ptrace.h
 #include asm/irq_regs.h
 
+#define KEY_DOWN_MAX   20 /* how  many is enough ? */
+int keyreset_param[KEY_DOWN_MAX];
+struct mutex sysrq_mutex;
+static struct sysrq_state *sysrq_handle;
+
 /* Whether we react on sysrq keys or just ignore them */
 static int __read_mostly sysrq_enabled = SYSRQ_DEFAULT_ENABLE;
 static bool __read_mostly sysrq_always_enabled;
 
+static struct input_handler sysrq_handler;
+
+/* Keep track of what has been called */
+static atomic_t restart_requested;
+
+
 static bool sysrq_on(void)
 {
return sysrq_enabled || sysrq_always_enabled;
@@ -570,6 +586,15 @@ struct sysrq_state {
struct input_handle handle;
struct work_struct reinject_work;
unsigned long key_down[BITS_TO_LONGS(KEY_CNT)];
+   unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];
+   unsigned long upbit[BITS_TO_LONGS(KEY_CNT)];
+   unsigned long key[BITS_TO_LONGS(KEY_CNT)];
+   int (*reset_fn)(void);
+   int key_down_target;
+   int key_down_ctn;
+   int key_up_ctn;
+   int keyreset_data;
+   int restart_disabled;
unsigned int alt;
unsigned int alt_use;
bool active;
@@ -603,6 +628,101 @@ static void sysrq_reinject_alt_sysrq(struct work_struct 
*work)
}
 }
 
+
+static int sysrq_probe(struct platform_device *pdev)
+{
+   struct keyreset_platform_data *pdata = pdev-dev.platform_data;
+
+   /*
+* No sequence of keys to trigger on,
+* assuming default sysRQ behavior.
+*/
+   if (pdata) {
+   atomic_set(restart_requested, 0);
+   sysrq_handler.private = pdata;
+   } else
+   sysrq_handler.private = NULL;
+
+   /* FETCH DT INFO HERE */
+
+   return 0;
+
+}
+
+static void deferred_restart(struct work_struct *dummy)
+{
+   atomic_inc(restart_requested);
+   sys_sync();
+   atomic_inc(restart_requested);
+   kernel_restart(NULL);
+}
+static DECLARE_WORK(restart_work, deferred_restart);
+
+static int do_keyreset_event(struct sysrq_state *state,
+unsigned int code, int value)
+{
+   int ret;
+   int processed = 0;
+
+   mutex_lock(sysrq_mutex);
+
+   /* Is the code of interest to us */
+   if (!test_bit(code, state-keybit)) {
+   mutex_unlock(sysrq_mutex);
+   return processed;
+   }
+
+   /* No need to take care of key up events */
+   if (!test_bit(code, state-key) == !value) {
+   mutex_unlock(sysrq_mutex);
+   return processed;
+   }
+
+   /* Record new entry */
+   __change_bit(code, state-key);
+
+   processed = 1;
+
+   if (test_bit(code, state-upbit)) {
+   if (value) {
+   state-restart_disabled = 1;
+   state-key_up_ctn++;
+   } else
+   state-key_up_ctn--;
+   } else {
+   if (value)
+   state-key_down_ctn++;
+   else
+   state-key_down_ctn--;
+   }
+
+   if (state-key_down_ctn == 0  state-key_up_ctn == 0)
+   state-restart_disabled = 0;
+
+   if (value  !state-restart_disabled 
+   state-key_down_ctn == state-key_down_target) {
+   state-restart_disabled = 1;
+   if (atomic_read

[PATCH 01/57] power: ab8500_bm: Charger current step-up/down

2012-09-25 Thread mathieu . poirier
From: Johan Bjornstedt johan.bjornst...@stericsson.com

There is no state machine in the AB to step up/down
the charger current to avoid dips and spikes on VBUS
and VBAT when charging is started.
Instead this is implemented in SW

Signed-off-by: Johan Bjornstedt johan.bjornst...@stericsson.com
Signed-off-by: Mattias Wallin mattias.wal...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Karl KOMIEROWSKI karl.komierow...@stericsson.com
---
 drivers/power/ab8500_charger.c |  172 +++-
 1 files changed, 133 insertions(+), 39 deletions(-)

diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index d4f0c98..3ceb788 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -77,6 +77,9 @@
 /* Lowest charger voltage is 3.39V - 0x4E */
 #define LOW_VOLT_REG   0x4E
 
+/* Step up/down delay in us */
+#define STEP_UDELAY1000
+
 /* UsbLineStatus register - usb types */
 enum ab8500_charger_link_status {
USB_STAT_NOT_CONFIGURED,
@@ -934,6 +937,88 @@ static int ab8500_charger_get_usb_cur(struct 
ab8500_charger *di)
 }
 
 /**
+ * ab8500_charger_set_current() - set charger current
+ * @di:pointer to the ab8500_charger structure
+ * @ich:   charger current, in mA
+ * @reg:   select what charger register to set
+ *
+ * Set charger current.
+ * There is no state machine in the AB to step up/down the charger
+ * current to avoid dips and spikes on MAIN, VBUS and VBAT when
+ * charging is started. Instead we need to implement
+ * this charger current step-up/down here.
+ * Returns error code in case of failure else 0(on success)
+ */
+static int ab8500_charger_set_current(struct ab8500_charger *di,
+   int ich, int reg)
+{
+   int ret, i;
+   int curr_index, prev_curr_index, shift_value;
+   u8 reg_value;
+
+   switch (reg) {
+   case AB8500_MCH_IPT_CURLVL_REG:
+   shift_value = MAIN_CH_INPUT_CURR_SHIFT;
+   curr_index = ab8500_current_to_regval(ich);
+   break;
+   case AB8500_USBCH_IPT_CRNTLVL_REG:
+   shift_value = VBUS_IN_CURR_LIM_SHIFT;
+   curr_index = ab8500_vbus_in_curr_to_regval(ich);
+   break;
+   case AB8500_CH_OPT_CRNTLVL_REG:
+   shift_value = 0;
+   curr_index = ab8500_current_to_regval(ich);
+   break;
+   default:
+   dev_err(di-dev, %s current register not valid\n, __func__);
+   return -ENXIO;
+   }
+
+   if (curr_index  0) {
+   dev_err(di-dev, requested current limit out-of-range\n);
+   return -ENXIO;
+   }
+
+   ret = abx500_get_register_interruptible(di-dev, AB8500_CHARGER,
+   reg, reg_value);
+   if (ret  0) {
+   dev_err(di-dev, %s read failed\n, __func__);
+   return ret;
+   }
+   prev_curr_index = (reg_value  shift_value);
+
+   /* only update current if it's been changed */
+   if (prev_curr_index == curr_index)
+   return 0;
+
+   dev_dbg(di-dev, %s set charger current: %d mA for reg: 0x%02x\n,
+   __func__, ich, reg);
+
+   if (prev_curr_index  curr_index) {
+   for (i = prev_curr_index - 1; i = curr_index; i--) {
+   ret = abx500_set_register_interruptible(di-dev,
+   AB8500_CHARGER, reg, (u8) i  shift_value);
+   if (ret) {
+   dev_err(di-dev, %s write failed\n, __func__);
+   return ret;
+   }
+   usleep_range(STEP_UDELAY, STEP_UDELAY * 2);
+   }
+   } else {
+   for (i = prev_curr_index + 1; i = curr_index; i++) {
+   ret = abx500_set_register_interruptible(di-dev,
+   AB8500_CHARGER, reg, (u8) i  shift_value);
+   if (ret) {
+   dev_err(di-dev, %s write failed\n, __func__);
+   return ret;
+   }
+   usleep_range(STEP_UDELAY, STEP_UDELAY * 2);
+   }
+   }
+   return ret;
+}
+
+/**
  * ab8500_charger_set_vbus_in_curr() - set VBUS input current limit
  * @di:pointer to the ab8500_charger structure
  * @ich_in:charger input current limit
@@ -944,8 +1029,6 @@ static int ab8500_charger_get_usb_cur(struct 
ab8500_charger *di)
 static int ab8500_charger_set_vbus_in_curr(struct ab8500_charger *di,
int ich_in)
 {
-   int ret;
-   int input_curr_index;
int min_value;
 
/* We should always use to lowest current limit */
@@ -964,19 +1047,38 @@ static int ab8500_charger_set_vbus_in_curr(struct 
ab8500_charger *di,
break;
}
 
-   input_curr_index

[PATCH 04/57] power: ab8500: bm: movimg back to ab8500 platform data managment

2012-09-25 Thread mathieu . poirier
From: Philippe Langlais philippe.langl...@linaro.org

Signed-off-by: Philippe Langlais philippe.langl...@linaro.org
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
---
 drivers/power/ab8500_btemp.c  |8 ++--
 drivers/power/ab8500_charger.c|9 +++--
 drivers/power/ab8500_fg.c |8 ++--
 drivers/power/abx500_chargalg.c   |7 ---
 include/linux/mfd/abx500/ab8500.h |7 ++-
 5 files changed, 17 insertions(+), 22 deletions(-)

diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c
index 94a3ee8..41a8ce4 100644
--- a/drivers/power/ab8500_btemp.c
+++ b/drivers/power/ab8500_btemp.c
@@ -973,14 +973,9 @@ static int __devinit ab8500_btemp_probe(struct 
platform_device *pdev)
 {
int irq, i, ret = 0;
u8 val;
-   struct abx500_bm_plat_data *plat_data = pdev-dev.platform_data;
+   struct ab8500_platform_data *plat_data;
struct ab8500_btemp *di;
 
-   if (!plat_data) {
-   dev_err(pdev-dev, No platform data\n);
-   return -EINVAL;
-   }
-
di = kzalloc(sizeof(*di), GFP_KERNEL);
if (!di)
return -ENOMEM;
@@ -993,6 +988,7 @@ static int __devinit ab8500_btemp_probe(struct 
platform_device *pdev)
di-initialized = false;
 
/* get btemp specific platform data */
+   plat_data = dev_get_platdata(di-parent-dev);
di-pdata = plat_data-btemp;
if (!di-pdata) {
dev_err(di-dev, no btemp platform data supplied\n);
diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index 3ceb788..22076f5 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -2628,14 +2628,9 @@ static int __devexit ab8500_charger_remove(struct 
platform_device *pdev)
 static int __devinit ab8500_charger_probe(struct platform_device *pdev)
 {
int irq, i, charger_status, ret = 0;
-   struct abx500_bm_plat_data *plat_data = pdev-dev.platform_data;
+   struct ab8500_platform_data *plat_data;
struct ab8500_charger *di;
 
-   if (!plat_data) {
-   dev_err(pdev-dev, No platform data\n);
-   return -EINVAL;
-   }
-
di = kzalloc(sizeof(*di), GFP_KERNEL);
if (!di)
return -ENOMEM;
@@ -2649,6 +2644,8 @@ static int __devinit ab8500_charger_probe(struct 
platform_device *pdev)
spin_lock_init(di-usb_state.usb_lock);
 
/* get charger specific platform data */
+   plat_data = dev_get_platdata(di-parent-dev);
+
di-pdata = plat_data-charger;
if (!di-pdata) {
dev_err(di-dev, no charger platform data supplied\n);
diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
index af792a8..c098ddd 100644
--- a/drivers/power/ab8500_fg.c
+++ b/drivers/power/ab8500_fg.c
@@ -2446,14 +2446,9 @@ static int __devinit ab8500_fg_probe(struct 
platform_device *pdev)
 {
int i, irq;
int ret = 0;
-   struct abx500_bm_plat_data *plat_data = pdev-dev.platform_data;
+   struct ab8500_platform_data *plat_data;
struct ab8500_fg *di;
 
-   if (!plat_data) {
-   dev_err(pdev-dev, No platform data\n);
-   return -EINVAL;
-   }
-
di = kzalloc(sizeof(*di), GFP_KERNEL);
if (!di)
return -ENOMEM;
@@ -2466,6 +2461,7 @@ static int __devinit ab8500_fg_probe(struct 
platform_device *pdev)
di-gpadc = ab8500_gpadc_get(ab8500-gpadc.0);
 
/* get fg specific platform data */
+   plat_data = dev_get_platdata(di-parent-dev);
di-pdata = plat_data-fg;
if (!di-pdata) {
dev_err(di-dev, no fg platform data supplied\n);
diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c
index 804b88c..032b27d 100644
--- a/drivers/power/abx500_chargalg.c
+++ b/drivers/power/abx500_chargalg.c
@@ -220,6 +220,7 @@ enum maxim_ret {
  */
 struct abx500_chargalg {
struct device *dev;
+   struct ab8500 *parent;
int charge_status;
int eoc_cnt;
int rch_cnt;
@@ -1802,7 +1803,7 @@ static int __devexit abx500_chargalg_remove(struct 
platform_device *pdev)
 
 static int __devinit abx500_chargalg_probe(struct platform_device *pdev)
 {
-   struct abx500_bm_plat_data *plat_data;
+   struct ab8500_platform_data *plat_data;
int ret = 0;
 
struct abx500_chargalg *di =
@@ -1812,8 +1813,8 @@ static int __devinit abx500_chargalg_probe(struct 
platform_device *pdev)
 
/* get device struct */
di-dev = pdev-dev;
-
-   plat_data = pdev-dev.platform_data;
+   di-parent = dev_get_drvdata(pdev-dev.parent);
+   plat_data = dev_get_platdata(di-parent-dev);
di-pdata = plat_data-chargalg;
di-bat = plat_data-battery;
 
diff --git a/include/linux/mfd/abx500/ab8500.h 
b/include/linux/mfd/abx500/ab8500.h
index 3764cb6..db8a1e3 100644
--- a/include/linux/mfd/abx500/ab8500.h
+++ b/include/linux/mfd

[PATCH 09/57] power: ab8500_fg: usleep_range instead of short msleep

2012-09-25 Thread mathieu . poirier
From: Jonas Aaberg jonas.ab...@stericsson.com

Signed-off-by: Jonas ABERG jonas.ab...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Johan BJORNSTEDT johan.bjornst...@stericsson.com
---
 drivers/power/ab8500_fg.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
index 1e02b00..0db17c7 100644
--- a/drivers/power/ab8500_fg.c
+++ b/drivers/power/ab8500_fg.c
@@ -957,7 +957,7 @@ static int ab8500_fg_load_comp_volt_to_capacity(struct 
ab8500_fg *di)
do {
vbat += ab8500_fg_bat_voltage(di);
i++;
-   msleep(5);
+   usleep_range(5000, 5001);
} while (!ab8500_fg_inst_curr_done(di));
 
ab8500_fg_inst_curr_finalize(di, di-inst_curr);
-- 
1.7.5.4

--
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 18/57] power: Add sysfs interfaces for capacity

2012-09-25 Thread mathieu . poirier
From: Daniel WILLERUD daniel.wille...@stericsson.com

Switchable depending on whether capacity scaling is enabled

Signed-off-by: Marcus Cooper marcus.xm.coo...@stericsson.com
Signed-off-by: Daniel WILLERUD daniel.wille...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Jonas ABERG jonas.ab...@stericsson.com
---
 drivers/power/ab8500_fg.c |   57 -
 1 files changed, 56 insertions(+), 1 deletions(-)

diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
index 8507254..46010ec 100644
--- a/drivers/power/ab8500_fg.c
+++ b/drivers/power/ab8500_fg.c
@@ -266,7 +266,6 @@ static enum power_supply_property ab8500_fg_props[] = {
POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
POWER_SUPPLY_PROP_CHARGE_FULL,
POWER_SUPPLY_PROP_CHARGE_NOW,
-   POWER_SUPPLY_PROP_CAPACITY,
POWER_SUPPLY_PROP_CAPACITY_LEVEL,
 };
 
@@ -2543,6 +2542,54 @@ static int ab8500_fg_sysfs_init(struct ab8500_fg *di)
 
return ret;
 }
+
+static ssize_t ab8500_show_capacity(struct device *dev,
+struct device_attribute *attr,
+char *buf)
+{
+   struct power_supply *psy = dev_get_drvdata(dev);
+   struct ab8500_fg *di;
+   int capacity;
+
+   di = to_ab8500_fg_device_info(psy);
+
+   if (di-bat-capacity_scaling)
+   capacity = di-bat_cap.cap_scale.scaled_cap;
+   else
+   capacity = DIV_ROUND_CLOSEST(di-bat_cap.permille, 10);
+
+   return scnprintf(buf, PAGE_SIZE, %d\n, capacity);
+}
+
+static struct device_attribute ab8500_fg_sysfs_psy_attrs[] = {
+   __ATTR(capacity, S_IRUGO, ab8500_show_capacity, NULL),
+};
+
+static int ab8500_fg_sysfs_psy_create_attrs(struct device *dev)
+{
+   unsigned int i;
+
+   for (i = 0; i  ARRAY_SIZE(ab8500_fg_sysfs_psy_attrs); i++)
+   if (device_create_file(dev, ab8500_fg_sysfs_psy_attrs[i]))
+   goto sysfs_psy_create_attrs_failed;
+
+   return 0;
+
+sysfs_psy_create_attrs_failed:
+   dev_err(dev, Failed creating sysfs psy attrs.\n);
+   while (i--)
+   device_remove_file(dev, ab8500_fg_sysfs_psy_attrs[i]);
+
+   return -EIO;
+}
+
+static void ab8500_fg_sysfs_psy_remove_attrs(struct device *dev)
+{
+   unsigned int i;
+
+   for (i = 0; i  ARRAY_SIZE(ab8500_fg_sysfs_psy_attrs); i++)
+   (void)device_remove_file(dev, ab8500_fg_sysfs_psy_attrs[i]);
+}
 /* Exposure to the sysfs interface END */
 
 #if defined(CONFIG_PM)
@@ -2599,6 +2646,7 @@ static int __devexit ab8500_fg_remove(struct 
platform_device *pdev)
ab8500_fg_sysfs_exit(di);
 
flush_scheduled_work();
+   ab8500_fg_sysfs_psy_remove_attrs(di-fg_psy.dev);
power_supply_unregister(di-fg_psy);
platform_set_drvdata(pdev, NULL);
kfree(di);
@@ -2754,6 +2802,13 @@ static int __devinit ab8500_fg_probe(struct 
platform_device *pdev)
goto free_irq;
}
 
+   ret = ab8500_fg_sysfs_psy_create_attrs(di-fg_psy.dev);
+   if (ret) {
+   dev_err(di-dev, failed to create FG psy\n);
+   ab8500_fg_sysfs_exit(di);
+   goto free_irq;
+   }
+
/* Calibrate the fg first time */
di-flags.calibrate = true;
di-calib_state = AB8500_FG_CALIB_INIT;
-- 
1.7.5.4

--
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 24/57] power: ab8500_fg: Adjust for RF bursts voltage drops.

2012-09-25 Thread mathieu . poirier
From: Hakan Berg hakan.b...@stericsson.com

Changed conditions for restarting low battery measurements counter
and adjusted the interval between measurements to avoid RF burst
induced voltage drops, and to shorten time to decide to shut down.

Signed-off-by: Hakan Berg hakan.b...@stericsson.com
Signed-off-by: Martin Bergstrom martin.bergst...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Jonas ABERG jonas.ab...@stericsson.com
Reviewed-by: Marcus COOPER marcus.xm.coo...@stericsson.com
---
 drivers/power/ab8500_fg.c |   44 ++--
 1 files changed, 30 insertions(+), 14 deletions(-)

diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
index 7c42150..861927d 100644
--- a/drivers/power/ab8500_fg.c
+++ b/drivers/power/ab8500_fg.c
@@ -42,7 +42,7 @@
 
 #define NBR_AVG_SAMPLES20
 
-#define LOW_BAT_CHECK_INTERVAL (2 * HZ)
+#define LOW_BAT_CHECK_INTERVAL (HZ / 16) /* 62.5 ms */
 
 #define VALID_CAPACITY_SEC (45 * 60) /* 45 minutes */
 #define BATT_OK_MIN2360 /* mV */
@@ -168,6 +168,7 @@ struct inst_curr_result_list {
  * @recovery_cnt:  Counter for recovery mode
  * @high_curr_cnt: Counter for high current mode
  * @init_cnt:  Counter for init mode
+ * @low_bat_cntCounter for number of consecutive low battery 
measures
  * @nbr_cceoc_irq_cnt  Counter for number of CCEOC irqs received since enabled
  * @recovery_needed:   Indicate if recovery is needed
  * @high_curr_mode:Indicate if we're in high current mode
@@ -210,6 +211,7 @@ struct ab8500_fg {
int recovery_cnt;
int high_curr_cnt;
int init_cnt;
+   int low_bat_cnt;
int nbr_cceoc_irq_cnt;
bool recovery_needed;
bool high_curr_mode;
@@ -1882,25 +1884,29 @@ static void ab8500_fg_low_bat_work(struct work_struct 
*work)
 
/* Check if LOW_BAT still fulfilled */
if (vbat  di-bat-fg_params-lowbat_threshold) {
-   di-flags.low_bat = true;
-   dev_warn(di-dev, Battery voltage still LOW\n);
-
-   /*
-* We need to re-schedule this check to be able to detect
-* if the voltage increases again during charging
-*/
-   queue_delayed_work(di-fg_wq, di-fg_low_bat_work,
-   round_jiffies(LOW_BAT_CHECK_INTERVAL));
+   /* Is it time to shut down? */
+   if (di-low_bat_cnt  1) {
+   di-flags.low_bat = true;
+   dev_warn(di-dev, Shut down pending...\n);
+   } else {
+   /*
+   * Else we need to re-schedule this check to be able
+   * to detect if the voltage increases again during
+   * charging or due to decreasing load.
+   */
+   di-low_bat_cnt--;
+   dev_warn(di-dev, Battery voltage still LOW\n);
+   queue_delayed_work(di-fg_wq, di-fg_low_bat_work,
+   round_jiffies(LOW_BAT_CHECK_INTERVAL));
+   }
} else {
-   di-flags.low_bat = false;
+   di-flags.low_bat_delay = false;
+   di-low_bat_cnt = 10;
dev_warn(di-dev, Battery voltage OK again\n);
}
 
/* This is needed to dispatch LOW_BAT */
ab8500_fg_check_capacity_limits(di, false);
-
-   /* Set this flag to check if LOW_BAT IRQ still occurs */
-   di-flags.low_bat_delay = false;
 }
 
 /**
@@ -2059,6 +2065,10 @@ static irqreturn_t ab8500_fg_lowbatf_handler(int irq, 
void *_di)
 {
struct ab8500_fg *di = _di;
 
+   /*
+* Initiate handling in ab8500_fg_low_bat_work() if not already
+* initiated.
+*/
if (!di-flags.low_bat_delay) {
dev_warn(di-dev, Battery voltage is below LOW threshold\n);
di-flags.low_bat_delay = true;
@@ -2748,6 +2758,12 @@ static int __devinit ab8500_fg_probe(struct 
platform_device *pdev)
INIT_DELAYED_WORK_DEFERRABLE(di-fg_check_hw_failure_work,
ab8500_fg_check_hw_failure_work);
 
+   /* Reset battery low voltage flag */
+   di-flags.low_bat = false;
+
+   /* Initialize low battery counter */
+   di-low_bat_cnt = 10;
+
/* Initialize OVV, and other registers */
ret = ab8500_fg_init_hw_registers(di);
if (ret) {
-- 
1.7.5.4

--
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 31/57] power: ab8500_fg: fix to use correct battery charge full design

2012-09-25 Thread mathieu . poirier
From: Rajkumar Kasirajan rajkumar.kasira...@stericsson.com

If battery is not identified while fg probe, mah_max_design gets
initialized with unknown battery's charge full design. Reinitialize
mah_max_design if battery is identified after fg probe.

Signed-off-by: Rajkumar Kasirajan rajkumar.kasira...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Jonas ABERG jonas.ab...@stericsson.com
Reviewed-by: Vijaya Kumar K-1 vijay.kil...@stericsson.com
Reviewed-by: Marcus COOPER marcus.xm.coo...@stericsson.com
Reviewed-by: Olivier CLERGEAUD olivier.clerge...@stericsson.com
Reviewed-by: Arun MURTHY arun.mur...@stericsson.com
Reviewed-by: Rupesh KUMAR rupesh.ku...@stericsson.com
Reviewed-by: Rabin VINCENT rabin.vinc...@stericsson.com
---
 drivers/power/ab8500_fg.c |4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
index 0e71e7e..5e4a46b 100644
--- a/drivers/power/ab8500_fg.c
+++ b/drivers/power/ab8500_fg.c
@@ -2258,9 +2258,9 @@ static int ab8500_fg_get_ext_psy_data(struct device *dev, 
void *data)
case POWER_SUPPLY_PROP_TECHNOLOGY:
switch (ext-type) {
case POWER_SUPPLY_TYPE_BATTERY:
-   if (!di-flags.batt_id_received) {
+   if (!di-flags.batt_id_received 
+   di-bat-batt_id != BATTERY_UNKNOWN) {
const struct abx500_battery_type *b;
-
b = 
(di-bat-bat_type[di-bat-batt_id]);
 
di-flags.batt_id_received = true;
-- 
1.7.5.4

--
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 34/57] power: ab8500_fg: add power cut feature for ab8505

2012-09-25 Thread mathieu . poirier
From: Rikard Olsson rikard.p.ols...@stericsson.com

Add support for a power cut feature which allows user to
configure when ab8505 should shut down system due to low
battery.

Signed-off-by: Rikard Olsson rikard.p.ols...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Martin SJOBLOM martin.w.sjob...@stericsson.com
Reviewed-by: Jonas ABERG jonas.ab...@stericsson.com
---
 drivers/power/ab8500_fg.c|  488 +-
 include/linux/mfd/abx500.h   |   10 +
 include/linux/mfd/abx500/ab8500-bm.h |8 +
 3 files changed, 502 insertions(+), 4 deletions(-)

diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
index 5e4a46b..fde189a 100644
--- a/drivers/power/ab8500_fg.c
+++ b/drivers/power/ab8500_fg.c
@@ -2351,6 +2351,64 @@ static int ab8500_fg_init_hw_registers(struct ab8500_fg 
*di)
dev_err(di-dev, BattOk init write failed.\n);
goto out;
}
+
+   if ((is_ab8505(di-parent) || is_ab9540(di-parent)) 
+   abx500_get_chip_id(di-dev) = AB8500_CUT2P0) {
+   ret = abx500_set_register_interruptible(di-dev, AB8500_RTC,
+   AB8505_RTC_PCUT_MAX_TIME_REG,
+di-bat-fg_params-pcut_max_time);
+
+   if (ret) {
+   dev_err(di-dev,
+   %s write failed 
AB8505_RTC_PCUT_MAX_TIME_REG\n,
+__func__);
+   goto out;
+   };
+
+   ret = abx500_set_register_interruptible(di-dev, AB8500_RTC,
+   AB8505_RTC_PCUT_FLAG_TIME_REG,
+di-bat-fg_params-pcut_flag_time);
+
+   if (ret) {
+   dev_err(di-dev,
+   %s write failed AB8505_RTC_PCUT_FLAG_TIME_REG\n,
+__func__);
+   goto out;
+   };
+
+   ret = abx500_set_register_interruptible(di-dev, AB8500_RTC,
+   AB8505_RTC_PCUT_RESTART_REG,
+   di-bat-fg_params-pcut_max_restart);
+
+   if (ret) {
+   dev_err(di-dev,
+   %s write failed AB8505_RTC_PCUT_RESTART_REG\n,
+__func__);
+   goto out;
+   };
+
+   ret = abx500_set_register_interruptible(di-dev, AB8500_RTC,
+   AB8505_RTC_PCUT_DEBOUNCE_REG,
+di-bat-fg_params-pcut_debunce_time);
+
+   if (ret) {
+   dev_err(di-dev,
+   %s write failed AB8505_RTC_PCUT_DEBOUNCE_REG\n,
+__func__);
+   goto out;
+   };
+
+   ret = abx500_set_register_interruptible(di-dev, AB8500_RTC,
+   AB8505_RTC_PCUT_CTL_STATUS_REG,
+di-bat-fg_params-pcut_enable);
+
+   if (ret) {
+   dev_err(di-dev,
+   %s write failed AB8505_RTC_PCUT_CTL_STATUS_REG\n,
+__func__);
+   goto out;
+   };
+   }
 out:
return ret;
 }
@@ -2572,22 +2630,433 @@ static ssize_t ab8500_show_capacity(struct device *dev,
return scnprintf(buf, PAGE_SIZE, %d\n, capacity);
 }
 
+static ssize_t ab8505_powercut_flagtime_read(struct device *dev,
+struct device_attribute *attr,
+char *buf)
+{
+   int ret;
+   u8 reg_value;
+   struct power_supply *psy = dev_get_drvdata(dev);
+   struct ab8500_fg *di;
+
+   di = to_ab8500_fg_device_info(psy);
+
+   ret = abx500_get_register_interruptible(di-dev, AB8500_RTC,
+   AB8505_RTC_PCUT_FLAG_TIME_REG, reg_value);
+
+   if (ret  0) {
+   dev_err(dev, Failed to read AB8505_RTC_PCUT_FLAG_TIME_REG\n);
+   goto fail;
+   }
+
+   return scnprintf(buf, PAGE_SIZE, %d\n, (reg_value  0x7F));
+
+fail:
+   return ret;
+}
+
+static ssize_t ab8505_powercut_flagtime_write(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+   int ret;
+   long unsigned reg_value;
+   struct power_supply *psy = dev_get_drvdata(dev);
+   struct ab8500_fg *di;
+
+   di = to_ab8500_fg_device_info(psy);
+
+   if (kstrtoul(buf, 10, reg_value) != 0)
+   goto fail;
+
+   if (reg_value  0x7F) {
+   dev_err(dev, Incorrect parameter, echo 0 (1.98s) - 127 
(15.625ms) for flagtime\n);
+   goto fail;
+   }
+
+   ret = abx500_set_register_interruptible(di-dev, AB8500_RTC,
+   AB8505_RTC_PCUT_FLAG_TIME_REG, (u8)reg_value);
+
+   if (ret  0

[PATCH 51/57] power: ab8500: Re-alignment with internal developement.

2012-09-25 Thread mathieu . poirier
From: Mathieu J. Poirier mathieu.poir...@linaro.org

A lot of developement happened internally since the first
mainlining of the battery managmenent driver.  Most of the
new code can be historically accounted for but some of it
can't.

This patch is a gathering of the code for which history was
lost but still relevant to the well being of the driver.

Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
---
 drivers/power/ab8500_charger.c  |2 +-
 drivers/power/abx500_chargalg.c |   66 +++
 2 files changed, 47 insertions(+), 21 deletions(-)

diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index 1290470..3a97012 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -720,7 +720,7 @@ static int ab8500_charger_max_usb_curr(struct 
ab8500_charger *di,
di-is_aca_rid = 0;
break;
case USB_STAT_ACA_RID_C_HS_CHIRP:
-   case USB_STAT_ACA_RID_C_NM:
+   case USB_STAT_ACA_RID_C_NM:
di-max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_1P5;
di-is_aca_rid = 1;
break;
diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c
index 1df238f..636d970 100644
--- a/drivers/power/abx500_chargalg.c
+++ b/drivers/power/abx500_chargalg.c
@@ -27,7 +27,7 @@
 #include linux/notifier.h
 
 /* Watchdog kick interval */
-#define CHG_WD_INTERVAL(6 * HZ)
+#define CHG_WD_INTERVAL(60 * HZ)
 
 /* End-of-charge criteria counter */
 #define EOC_COND_CNT   10
@@ -513,7 +513,7 @@ static int abx500_chargalg_kick_watchdog(struct 
abx500_chargalg *di)
 static int abx500_chargalg_ac_en(struct abx500_chargalg *di, int enable,
int vset, int iset)
 {
-   static int ab8500_chargalg_ex_ac_enable_toggle;
+   static int abx500_chargalg_ex_ac_enable_toggle;
 
if (!di-ac_chg || !di-ac_chg-ops.enable)
return -ENXIO;
@@ -529,10 +529,10 @@ static int abx500_chargalg_ac_en(struct abx500_chargalg 
*di, int enable,
 
/*enable external charger*/
if (enable  di-ac_chg-external 
-   !ab8500_chargalg_ex_ac_enable_toggle) {
+   !abx500_chargalg_ex_ac_enable_toggle) {
blocking_notifier_call_chain(charger_notifier_list,
0, di-dev);
-   ab8500_chargalg_ex_ac_enable_toggle++;
+   abx500_chargalg_ex_ac_enable_toggle++;
}
 
return di-ac_chg-ops.enable(di-ac_chg, enable, vset, iset);
@@ -899,6 +899,27 @@ static void handle_maxim_chg_curr(struct abx500_chargalg 
*di)
}
 }
 
+static void abx500_chargalg_check_safety_timer(struct abx500_chargalg *di)
+{
+   /*
+* The safety timer will not be started until the capacity reported
+* from the FG algorithm is 100%. Then we know that the amount of
+* charge that's gone into the battery is enough for the battery
+* to be full. If it has not reached end-of-charge before the safety
+* timer has expired then we know that the battery is overcharged
+* and charging will be stopped to protect the battery.
+*/
+   if (di-batt_data.percent == 100 
+   !timer_pending(di-safety_timer)) {
+   abx500_chargalg_start_safety_timer(di);
+   dev_dbg(di-dev, start safety timer\n);
+   } else if (di-batt_data.percent != 100 
+   timer_pending(di-safety_timer)) {
+   abx500_chargalg_stop_safety_timer(di);
+   dev_dbg(di-dev, stop safety timer\n);
+   }
+}
+
 static int abx500_chargalg_get_ext_psy_data(struct device *dev, void *data)
 {
struct power_supply *psy;
@@ -1125,6 +1146,10 @@ static int abx500_chargalg_get_ext_psy_data(struct 
device *dev, void *data)
switch (ext-type) {
case POWER_SUPPLY_TYPE_BATTERY:
di-batt_data.volt = ret.intval / 1000;
+   if (di-batt_data.volt = BATT_OVV_VALUE)
+   di-events.batt_ovv = true;
+   else
+   di-events.batt_ovv = false;
break;
case POWER_SUPPLY_TYPE_MAINS:
di-chg_info.ac_volt = ret.intval / 1000;
@@ -1214,7 +1239,6 @@ static int abx500_chargalg_get_ext_psy_data(struct device 
*dev, void *data)
}
break;
case POWER_SUPPLY_PROP_CAPACITY:
-   di-batt_data.percent = ret.intval;
if (!capacity_updated)
di-batt_data.percent = ret.intval;
break;
@@ -1465,12 +1489,12 @@ static void abx500_chargalg_algorithm(struct 
abx500_chargalg *di

[PATCH 54/57] power: ab8500_charger: Use USBLink1Status Register

2012-09-25 Thread mathieu . poirier
From: Marcus Cooper marcus.xm.coo...@stericsson.com

The newer AB's such as the AB8505, AB9540 etc include a
USBLink1 Status register which detects a larger range of
external devices. This should be used instead of the
USBLine Status register.

Signed-off-by: Marcus Cooper marcus.xm.coo...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Hakan BERG hakan.b...@stericsson.com
Reviewed-by: Yang QU yang...@stericsson.com
Reviewed-by: Jonas ABERG jonas.ab...@stericsson.com
---
 drivers/power/ab8500_charger.c |   22 --
 1 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index 3a97012..7f8f362 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -2258,8 +2258,13 @@ static void ab8500_charger_usb_link_status_work(struct 
work_struct *work)
 * to start the charging process. but by jumping
 * thru a few hoops it can be forced to start.
 */
-   ret = abx500_get_register_interruptible(di-dev, AB8500_USB,
-   AB8500_USB_LINE_STAT_REG, val);
+   if (is_ab8500(di-parent))
+   ret = abx500_get_register_interruptible(di-dev, AB8500_USB,
+   AB8500_USB_LINE_STAT_REG, val);
+   else
+   ret = abx500_get_register_interruptible(di-dev, AB8500_USB,
+   AB8500_USB_LINK1_STAT_REG, val);
+
if (ret = 0)
dev_dbg(di-dev, UsbLineStatus register = 0x%02x\n, val);
else
@@ -2299,10 +2304,15 @@ static void ab8500_charger_usb_link_status_work(struct 
work_struct *work)
AB8500_MCH_IPT_CURLVL_REG,
0x01, 0x00);
/*Check link status*/
-   ret = abx500_get_register_interruptible(di-dev,
-   AB8500_USB,
-   AB8500_USB_LINE_STAT_REG,
-   val);
+   if (is_ab8500(di-parent))
+   ret = abx500_get_register_interruptible(di-dev,
+   AB8500_USB, AB8500_USB_LINE_STAT_REG,
+   val);
+   else
+   ret = abx500_get_register_interruptible(di-dev,
+   AB8500_USB, AB8500_USB_LINK1_STAT_REG,
+   val);
+
dev_dbg(di-dev, USB link status= 0x%02x\n,
(val  link_status)  USB_LINK_STATUS_SHIFT);
di-invalid_charger_detect_state = 2;
-- 
1.7.5.4

--
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 57/57] power: ab8500_charger: Limit USB charger current

2012-09-25 Thread mathieu . poirier
From: Martin Bergstrom martin.bergst...@stericsson.com

The USB charger current is limited according to information comming
from the USB driver

Signed-off-by: Martin Bergstrom martin.bergst...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Jonas ABERG jonas.ab...@stericsson.com
---
 drivers/power/ab8500_charger.c |4 
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index afb4fda..3c6f11c 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -1248,6 +1248,9 @@ static int ab8500_charger_set_vbus_in_curr(struct 
ab8500_charger *di,
if (di-max_usb_in_curr.set_max  0)
min_value = min(di-max_usb_in_curr.set_max, min_value);
 
+   if (di-usb_state.usb_current = 0)
+   min_value = min(di-usb_state.usb_current, min_value);
+
switch (min_value) {
case 100:
if (di-vbat  VBAT_TRESH_IP_CUR_RED)
@@ -3413,6 +3416,7 @@ static int __devinit ab8500_charger_probe(struct 
platform_device *pdev)
di-usb_chg.wdt_refresh = CHG_WD_INTERVAL;
di-usb_chg.enabled = di-pdata-usb_enabled;
di-usb_chg.external = false;
+   di-usb_state.usb_current = -1;
 
/* Create a work queue for the charger */
di-charger_wq =
-- 
1.7.5.4

--
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 56/57] power: abx500_chargalg: Fix quick re-attach charger issue.

2012-09-25 Thread mathieu . poirier
From: Marcus Cooper marcus.xm.coo...@stericsson.com

The patch for 426250 added a change to check for the quick
re-attachment of the charger connection as an error in the
AB8500 HW meant that a quick detach/attach wouldn't be
detected.
This patch isolates the original change so that newer AB's
are not affected.

Signed-off-by: Marcus Cooper marcus.xm.coo...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Martin SJOBLOM martin.w.sjob...@stericsson.com
Reviewed-by: Hakan BERG hakan.b...@stericsson.com
Reviewed-by: Jonas ABERG jonas.ab...@stericsson.com
---
 drivers/power/abx500_chargalg.c |   11 ++-
 1 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c
index c8849af..7a81e4e 100644
--- a/drivers/power/abx500_chargalg.c
+++ b/drivers/power/abx500_chargalg.c
@@ -1299,11 +1299,12 @@ static void abx500_chargalg_algorithm(struct 
abx500_chargalg *di)
abx500_chargalg_check_charger_voltage(di);
charger_status = abx500_chargalg_check_charger_connection(di);
 
-   ret = abx500_chargalg_check_charger_enable(di);
-   if (ret  0)
-   dev_err(di-dev, Checking charger if enabled error: %d line: 
%d\n,
-   ret, __LINE__);
-
+   if (is_ab8500(di-parent)) {
+   ret = abx500_chargalg_check_charger_enable(di);
+   if (ret  0)
+   dev_err(di-dev, Checking charger is enabled error);
+   dev_err(di-dev, : Returned Value %d\n, ret);
+   }
/*
 * First check if we have a charger connected.
 * Also we don't allow charging of unknown batteries if configured
-- 
1.7.5.4

--
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 44/57] power: ab8500: remove unecesary define flag

2012-09-25 Thread mathieu . poirier
From: Marcus Cooper marcus.xm.coo...@stericsson.com

Remove flag that serve no purpose from source code, Kconfig
and Makefile.

Signed-off-by: Marcus Cooper marcus.xm.coo...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Hakan BERG hakan.b...@stericsson.com
Reviewed-by: Mian Yousaf KAUKAB mian.yousaf.kau...@stericsson.com
---
 drivers/power/Kconfig  |7 ---
 drivers/power/ab8500_charger.c |2 +-
 2 files changed, 1 insertions(+), 8 deletions(-)

diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index c1892f3..f7c13ae 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -303,13 +303,6 @@ config AB8500_BM
depends on AB8500_CORE  AB8500_GPADC
help
  Say Y to include support for AB8500 battery management.
-
-config AB8500_BATTERY_THERM_ON_BATCTRL
-   bool Thermistor connected on BATCTRL ADC
-   depends on AB8500_BM
-   help
- Say Y to enable battery temperature measurements using
- thermistor connected on BATCTRL ADC.
 endif # POWER_SUPPLY
 
 source drivers/power/avs/Kconfig
diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index 9449a33..d90fe9f 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -3369,7 +3369,7 @@ static int __devexit ab8500_charger_remove(struct 
platform_device *pdev)
flush_scheduled_work();
if (di-usb_chg.enabled)
power_supply_unregister(di-usb_chg.psy);
-   if (di-ac_chg.enabled)
+   if (di-ac_chg.enabled  !di-ac_chg.external)
power_supply_unregister(di-ac_chg.psy);
 
platform_set_drvdata(pdev, NULL);
-- 
1.7.5.4

--
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 46/57] power: chargealg: Realign with upstream version

2012-09-25 Thread mathieu . poirier
From: Loic Pallardy loic.palla...@stericsson.com

Upstream version of AB charge algo has been reverted
during kernel 3.4 port.
This patch restore state by:
- renaming ab8500_chargal.c in abx500_chargal.c
- renaming function from ab8500 to abx500
- moving generic structure in include/mfd/abx500.h

Goal is to ease next code reversion and realignment
with mainline

Signed-off-by: Loic Pallardy loic.palla...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Philippe LANGLAIS philippe.langl...@stericsson.com
---
 drivers/power/ab8500_charger.c   |  166 +++---
 include/linux/mfd/abx500.h   |   10 ++-
 include/linux/mfd/abx500/ab8500-bm.h |5 +-
 3 files changed, 65 insertions(+), 116 deletions(-)

diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index d90fe9f..68a4128 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -79,6 +79,7 @@
 #define AB8500_USB_LINK_STATUS 0x78
 #define AB8505_USB_LINK_STATUS 0xF8
 #define AB8500_STD_HOST_SUSP   0x18
+#define USB_LINK_STATUS_SHIFT  3
 
 /* Watchdog timeout constant */
 #define WD_TIMER   0x30 /* 4min */
@@ -743,8 +744,7 @@ static int ab8500_charger_max_usb_curr(struct 
ab8500_charger *di,
dev_err(di-dev, VBUS has collapsed\n);
ret = -ENXIO;
break;
-   }
-   if (is_ab9540(di-parent) || is_ab8505(di-parent)) {
+   } else {
dev_dbg(di-dev, USB Type - Charging not allowed\n);
di-max_usb_in_curr.usb_type_max =
USB_CH_IP_CUR_LVL_0P05;
@@ -799,30 +799,22 @@ static int ab8500_charger_read_usb_type(struct 
ab8500_charger *di)
dev_err(di-dev, %s ab8500 read failed\n, __func__);
return ret;
}
-   if (is_ab8500(di-parent)) {
+   if (is_ab8500(di-parent))
ret = abx500_get_register_interruptible(di-dev, AB8500_USB,
-   AB8500_USB_LINE_STAT_REG, val);
-   } else if (is_ab9540(di-parent) || is_ab8505(di-parent)) {
-   ret = abx500_get_register_interruptible(di-dev,
-   AB8500_USB, AB8500_USB_LINK1_STAT_REG, val);
-   } else {
-   dev_err(di-dev, %s unsupported analog baseband\n, __func__);
-   return -ENXIO;
-   }
+   AB8500_USB_LINE_STAT_REG, val);
+   else
+   ret = abx500_get_register_interruptible(di-dev,
+   AB8500_USB, AB8500_USB_LINK1_STAT_REG, val);
if (ret  0) {
dev_err(di-dev, %s ab8500 read failed\n, __func__);
return ret;
}
 
/* get the USB type */
-   if (is_ab8500(di-parent)) {
-   val = (val  AB8500_USB_LINK_STATUS)  3;
-   } else if (is_ab9540(di-parent) || is_ab8505(di-parent)) {
-   val = (val  AB8505_USB_LINK_STATUS)  3;
-   } else {
-   dev_err(di-dev, %s unsupported analog baseband\n, __func__);
-   return -ENXIO;
-   }
+   if (is_ab8500(di-parent))
+   val = (val  AB8500_USB_LINK_STATUS)  USB_LINK_STATUS_SHIFT;
+   else
+   val = (val  AB8505_USB_LINK_STATUS)  USB_LINK_STATUS_SHIFT;
ret = ab8500_charger_max_usb_curr(di,
(enum ab8500_charger_link_status) val);
 
@@ -858,17 +850,12 @@ static int ab8500_charger_detect_usb_type(struct 
ab8500_charger *di)
return ret;
}
 
-   if (is_ab8500(di-parent)) {
+   if (is_ab8500(di-parent))
ret = abx500_get_register_interruptible(di-dev,
AB8500_USB, AB8500_USB_LINE_STAT_REG, val);
-   } else if (is_ab9540(di-parent) || is_ab8505(di-parent)) {
+   else
ret = abx500_get_register_interruptible(di-dev,
AB8500_USB, AB8500_USB_LINK1_STAT_REG, val);
-   } else {
-   dev_err(di-dev,
-%s unsupported analog baseband\n, __func__);
-   return -ENXIO;
-   }
if (ret  0) {
dev_err(di-dev, %s ab8500 read failed\n, __func__);
return ret;
@@ -882,15 +869,12 @@ static int ab8500_charger_detect_usb_type(struct 
ab8500_charger *di)
 */
 
/* get the USB type */
-   if (is_ab8500(di-parent)) {
-   val = (val  AB8500_USB_LINK_STATUS)  3;
-   } else if (is_ab9540(di-parent) || is_ab8505(di-parent)) {
-   val = (val  AB8505_USB_LINK_STATUS)  3;
-   } else {
-   dev_err(di-dev

[PATCH 52/57] power: abx500_chargalg: Use hrtimer

2012-09-25 Thread mathieu . poirier
From: Hakan Berg hakan.b...@stericsson.com

Timers used for charging safety and maintenance must work even when
CPU is power collapsed. By using hrtimers with realtime clock, system
is able to trigger an alarm that wakes the CPU up and make it possible
to handle the event.

Allow a little slack of 5 minutes to the hrtimers to allow CPU to be
waked up in a more optimal power saving way. A 5 minute delay to
time out timers on hours does not impact on safety.

Signed-off-by: Hakan Berg hakan.b...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Mian Yousaf KAUKAB mian.yousaf.kau...@stericsson.com
---
 drivers/power/abx500_chargalg.c |   94 ++-
 1 files changed, 53 insertions(+), 41 deletions(-)

diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c
index 636d970..c8849af 100644
--- a/drivers/power/abx500_chargalg.c
+++ b/drivers/power/abx500_chargalg.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) ST-Ericsson SA 2012
+ * Copyright (c) 2012 Sony Mobile Communications AB
  *
  * Charging algorithm driver for abx500 variants
  *
@@ -8,11 +9,13 @@
  * Johan Palsson johan.pals...@stericsson.com
  * Karl Komierowski karl.komierow...@stericsson.com
  * Arun R Murthy arun.mur...@stericsson.com
+ * Imre Sunyi imre.su...@sonymobile.com
  */
 
 #include linux/init.h
 #include linux/module.h
 #include linux/device.h
+#include linux/hrtimer.h
 #include linux/interrupt.h
 #include linux/delay.h
 #include linux/slab.h
@@ -32,6 +35,12 @@
 /* End-of-charge criteria counter */
 #define EOC_COND_CNT   10
 
+/* One hour expressed in seconds */
+#define ONE_HOUR_IN_SECONDS3600
+
+/* Five minutes expressed in seconds */
+#define FIVE_MINUTES_IN_SECONDS300
+
 #define to_abx500_chargalg_device_info(x) container_of((x), \
struct abx500_chargalg, chargalg_psy);
 
@@ -245,8 +254,8 @@ struct abx500_chargalg {
struct delayed_work chargalg_periodic_work;
struct delayed_work chargalg_wd_work;
struct work_struct chargalg_work;
-   struct timer_list safety_timer;
-   struct timer_list maintenance_timer;
+   struct hrtimer safety_timer;
+   struct hrtimer maintenance_timer;
struct kobject chargalg_kobject;
 };
 
@@ -261,38 +270,47 @@ BLOCKING_NOTIFIER_HEAD(charger_notifier_list);
 
 /**
  * abx500_chargalg_safety_timer_expired() - Expiration of the safety timer
- * @data:  pointer to the abx500_chargalg structure
+ * @timer: pointer to the hrtimer structure
  *
  * This function gets called when the safety timer for the charger
  * expires
  */
-static void abx500_chargalg_safety_timer_expired(unsigned long data)
+static enum hrtimer_restart
+abx500_chargalg_safety_timer_expired(struct hrtimer *timer)
 {
-   struct abx500_chargalg *di = (struct abx500_chargalg *) data;
+   struct abx500_chargalg *di = container_of(timer, struct abx500_chargalg,
+   safety_timer);
dev_err(di-dev, Safety timer expired\n);
di-events.safety_timer_expired = true;
 
/* Trigger execution of the algorithm instantly */
queue_work(di-chargalg_wq, di-chargalg_work);
+
+   return HRTIMER_NORESTART;
 }
 
 /**
  * abx500_chargalg_maintenance_timer_expired() - Expiration of
  * the maintenance timer
- * @i: pointer to the abx500_chargalg structure
+ * @timer: pointer to the timer structure
  *
  * This function gets called when the maintenence timer
  * expires
  */
-static void abx500_chargalg_maintenance_timer_expired(unsigned long data)
+static enum hrtimer_restart
+abx500_chargalg_maintenance_timer_expired(struct hrtimer *timer)
+
 {
 
-   struct abx500_chargalg *di = (struct abx500_chargalg *) data;
+   struct abx500_chargalg *di = container_of(timer, struct abx500_chargalg,
+   maintenance_timer);
dev_dbg(di-dev, Maintenance timer expired\n);
di-events.maintenance_timer_expired = true;
 
/* Trigger execution of the algorithm instantly */
queue_work(di-chargalg_wq, di-chargalg_work);
+
+   return HRTIMER_NORESTART;
 }
 
 /**
@@ -392,19 +410,16 @@ static int 
abx500_chargalg_check_charger_connection(struct abx500_chargalg *di)
  */
 static void abx500_chargalg_start_safety_timer(struct abx500_chargalg *di)
 {
-   unsigned long timer_expiration = 0;
+   /* Charger-dependent expiration time in hours*/
+   int timer_expiration = 0;
 
switch (di-chg_info.charger_type) {
case AC_CHG:
-   timer_expiration =
-   round_jiffies(jiffies +
-   (di-bat-main_safety_tmr_h * 3600 * HZ));
+   timer_expiration = di-bat-main_safety_tmr_h;
break;
 
case USB_CHG:
-   timer_expiration =
-   round_jiffies(jiffies +
-   (di-bat

[PATCH 55/57] power: ab8500_charger: Add UsbLineCtrl2 reference

2012-09-25 Thread mathieu . poirier
From: Marcus Cooper marcus.xm.coo...@stericsson.com

When the state of USB Charge detection is changed then the calls
use a define for another register in other bank. This change
creates a new define for the correct register and removes the
magic numbers that are present.

Signed-off-by: Marcus Cooper marcus.xm.coo...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Hakan BERG hakan.b...@stericsson.com
Reviewed-by: Jonas ABERG jonas.ab...@stericsson.com

Conflicts:

drivers/power/ab8500_charger.c
---
 drivers/power/ab8500_charger.c   |   11 +--
 include/linux/mfd/abx500/ab8500-bm.h |1 +
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index 7f8f362..afb4fda 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -51,6 +51,7 @@
 #define VBUS_DET_DBNC1 0x01
 #define OTP_ENABLE_WD  0x01
 #define DROP_COUNT_RESET   0x01
+#define USB_CH_DET 0x01
 
 #define MAIN_CH_INPUT_CURR_SHIFT   4
 #define VBUS_IN_CURR_LIM_SHIFT 4
@@ -2287,9 +2288,8 @@ static void ab8500_charger_usb_link_status_work(struct 
work_struct *work)
USB_CH_ENA, USB_CH_ENA);
/*Enable charger detection*/
abx500_mask_and_set_register_interruptible(di-dev,
-   AB8500_USB,
-   AB8500_MCH_IPT_CURLVL_REG,
-   0x01, 0x01);
+   AB8500_USB, AB8500_USB_LINE_CTRL2_REG,
+   USB_CH_DET, USB_CH_DET);
di-invalid_charger_detect_state = 1;
/*exit and wait for new link status interrupt.*/
return;
@@ -2300,9 +2300,8 @@ static void ab8500_charger_usb_link_status_work(struct 
work_struct *work)
Invalid charger detected, state= 1\n);
/*Stop charger detection*/
abx500_mask_and_set_register_interruptible(di-dev,
-   AB8500_USB,
-   AB8500_MCH_IPT_CURLVL_REG,
-   0x01, 0x00);
+   AB8500_USB, AB8500_USB_LINE_CTRL2_REG,
+   USB_CH_DET, 0x00);
/*Check link status*/
if (is_ab8500(di-parent))
ret = abx500_get_register_interruptible(di-dev,
diff --git a/include/linux/mfd/abx500/ab8500-bm.h 
b/include/linux/mfd/abx500/ab8500-bm.h
index 721bd6d..6b69ad5 100644
--- a/include/linux/mfd/abx500/ab8500-bm.h
+++ b/include/linux/mfd/abx500/ab8500-bm.h
@@ -23,6 +23,7 @@
  * Bank : 0x5
  */
 #define AB8500_USB_LINE_STAT_REG   0x80
+#define AB8500_USB_LINE_CTRL2_REG  0x82
 #define AB8500_USB_LINK1_STAT_REG  0x94
 
 /*
-- 
1.7.5.4

--
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 53/57] power: ab8500_fg: Moving structure definitions to header file

2012-09-25 Thread mathieu . poirier
From: Mathieu J. Poirier mathieu.poir...@linaro.org

Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
---
 drivers/power/ab8500_fg.c |  196 +--
 drivers/power/ab8500_fg.h |  201 +
 2 files changed, 206 insertions(+), 191 deletions(-)
 create mode 100644 drivers/power/ab8500_fg.h

diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
index 5b5c7ea..145c1f1 100644
--- a/drivers/power/ab8500_fg.c
+++ b/drivers/power/ab8500_fg.c
@@ -32,51 +32,7 @@
 #include linux/time.h
 #include linux/completion.h
 #include linux/kernel.h
-
-#define MILLI_TO_MICRO 1000
-#define FG_LSB_IN_MA   1627
-#define QLSB_NANO_AMP_HOURS_X101129
-#define INS_CURR_TIMEOUT   (3 * HZ)
-
-#define SEC_TO_SAMPLE(S)   (S * 4)
-
-#define NBR_AVG_SAMPLES20
-
-#define LOW_BAT_CHECK_INTERVAL (HZ / 16) /* 62.5 ms */
-
-#define VALID_CAPACITY_SEC (45 * 60) /* 45 minutes */
-#define BATT_OK_MIN2360 /* mV */
-#define BATT_OK_INCREMENT  50 /* mV */
-#define BATT_OK_MAX_NR_INCREMENTS  0xE
-
-/* FG constants */
-#define BATT_OVV   0x01
-
-#define interpolate(x, x1, y1, x2, y2) \
-   ((y1) + y2) - (y1)) * ((x) - (x1))) / ((x2) - (x1;
-
-#define to_ab8500_fg_device_info(x) container_of((x), \
-   struct ab8500_fg, fg_psy);
-
-/**
- * struct ab8500_fg_interrupts - ab8500 fg interupts
- * @name:  name of the interrupt
- * @isrfunction pointer to the isr
- */
-struct ab8500_fg_interrupts {
-   char *name;
-   irqreturn_t (*isr)(int irq, void *data);
-};
-
-enum ab8500_fg_discharge_state {
-   AB8500_FG_DISCHARGE_INIT,
-   AB8500_FG_DISCHARGE_INITMEASURING,
-   AB8500_FG_DISCHARGE_INIT_RECOVERY,
-   AB8500_FG_DISCHARGE_RECOVERY,
-   AB8500_FG_DISCHARGE_READOUT_INIT,
-   AB8500_FG_DISCHARGE_READOUT,
-   AB8500_FG_DISCHARGE_WAKEUP,
-};
+#include ab8500_fg.h
 
 static char *discharge_state[] = {
DISCHARGE_INIT,
@@ -87,159 +43,17 @@ static char *discharge_state[] = {
DISCHARGE_READOUT,
DISCHARGE_WAKEUP,
 };
-
-enum ab8500_fg_charge_state {
-   AB8500_FG_CHARGE_INIT,
-   AB8500_FG_CHARGE_READOUT,
-};
-
 static char *charge_state[] = {
CHARGE_INIT,
CHARGE_READOUT,
 };
 
-enum ab8500_fg_calibration_state {
-   AB8500_FG_CALIB_INIT,
-   AB8500_FG_CALIB_WAIT,
-   AB8500_FG_CALIB_END,
-};
-
-struct ab8500_fg_avg_cap {
-   int avg;
-   int samples[NBR_AVG_SAMPLES];
-   __kernel_time_t time_stamps[NBR_AVG_SAMPLES];
-   int pos;
-   int nbr_samples;
-   int sum;
-};
-
-struct ab8500_fg_cap_scaling {
-   bool enable;
-   int cap_to_scale[2];
-   int disable_cap_level;
-   int scaled_cap;
-};
-
-struct ab8500_fg_battery_capacity {
-   int max_mah_design;
-   int max_mah;
-   int mah;
-   int permille;
-   int level;
-   int prev_mah;
-   int prev_percent;
-   int prev_level;
-   int user_mah;
-   struct ab8500_fg_cap_scaling cap_scale;
-};
-
-struct ab8500_fg_flags {
-   bool fg_enabled;
-   bool conv_done;
-   bool charging;
-   bool fully_charged;
-   bool force_full;
-   bool low_bat_delay;
-   bool low_bat;
-   bool bat_ovv;
-   bool batt_unknown;
-   bool calibrate;
-   bool user_cap;
-   bool batt_id_received;
-};
+#define interpolate(x, x1, y1, x2, y2) \
+   ((y1) + y2) - (y1)) * ((x) - (x1))) / ((x2) - (x1;
 
-struct inst_curr_result_list {
-   struct list_head list;
-   int *result;
-};
+#define to_ab8500_fg_device_info(x) container_of((x), \
+   struct ab8500_fg, fg_psy);
 
-/**
- * struct ab8500_fg - ab8500 FG device information
- * @dev:   Pointer to the structure device
- * @node:  a list of AB8500 FGs, hence prepared for reentrance
- * @irqholds the CCEOC interrupt number
- * @vbat:  Battery voltage in mV
- * @vbat_nom:  Nominal battery voltage in mV
- * @inst_curr: Instantenous battery current in mA
- * @avg_curr:  Average battery current in mA
- * @bat_temp   battery temperature
- * @fg_samples:Number of samples used in the FG accumulation
- * @accu_charge:   Accumulated charge from the last conversion
- * @recovery_cnt:  Counter for recovery mode
- * @high_curr_cnt: Counter for high current mode
- * @init_cnt:  Counter for init mode
- * @low_bat_cntCounter for number of consecutive low battery 
measures
- * @nbr_cceoc_irq_cnt  Counter for number of CCEOC irqs received since enabled
- * @recovery_needed:   Indicate if recovery is needed
- * @high_curr_mode:Indicate if we're in high current mode
- * @init_capacity: Indicate if initial capacity measuring should

[PATCH 50/57] power: ab8500-chargalg: update battery health on safety timer exp

2012-09-25 Thread mathieu . poirier
From: Hakan Berg hakan.b...@stericsson.com

When the charging safety timer is elapsed the battery health is shown as Good.
This is misleading and also hard to distingiush problems reported on phone
discharges although charger is attached.

When safety timer elapses that is an indication of a fault in the battery of
some kind. Hence report as POWER_SUPPLY_HEALTH_UNSPEC_FAILURE.

Signed-off-by: Hakan Berg hakan.b...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Arun MURTHY arun.mur...@stericsson.com
Reviewed-by: Karl KOMIEROWSKI karl.komierow...@stericsson.com
---
 drivers/power/abx500_chargalg.c |4 
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c
index 4db0ef0..1df238f 100644
--- a/drivers/power/abx500_chargalg.c
+++ b/drivers/power/abx500_chargalg.c
@@ -1711,6 +1711,10 @@ static int abx500_chargalg_get_property(struct 
power_supply *psy,
val-intval = POWER_SUPPLY_HEALTH_COLD;
else
val-intval = POWER_SUPPLY_HEALTH_OVERHEAT;
+   } else if (di-charge_state == STATE_SAFETY_TIMER_EXPIRED ||
+   di-charge_state ==
+   STATE_SAFETY_TIMER_EXPIRED_INIT) {
+   val-intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
} else {
val-intval = POWER_SUPPLY_HEALTH_GOOD;
}
-- 
1.7.5.4

--
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 49/57] power: Cancelling status charging notification.

2012-09-25 Thread mathieu . poirier
From: Mathieu J. Poirier mathieu.poir...@linaro.org

Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
---
 drivers/power/abx500_chargalg.c |2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c
index ce58f20..4db0ef0 100644
--- a/drivers/power/abx500_chargalg.c
+++ b/drivers/power/abx500_chargalg.c
@@ -641,10 +641,8 @@ static void abx500_chargalg_hold_charging(struct 
abx500_chargalg *di)
abx500_chargalg_usb_en(di, false, 0, 0);
abx500_chargalg_stop_safety_timer(di);
abx500_chargalg_stop_maintenance_timer(di);
-   di-charge_status = POWER_SUPPLY_STATUS_CHARGING;
di-maintenance_chg = false;
cancel_delayed_work(di-chargalg_wd_work);
-   power_supply_changed(di-chargalg_psy);
 }
 
 /**
-- 
1.7.5.4

--
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 48/57] power: ab8500 : quick re-attach for ext charger

2012-09-25 Thread mathieu . poirier
From: Rupesh Kumar rupesh.ku...@stericsson.com

Quick re-attach charging behaviour is not required
for external ac charger. Internal AC/USB Charger removal
detection problem is due to a bug in AB8500 ASICs.

Signed-off-by: Rupesh Kumar rupesh.ku...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Hakan BERG hakan.b...@stericsson.com
Reviewed-by: Philippe LANGLAIS philippe.langl...@stericsson.com
---
 drivers/power/abx500_chargalg.c |5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c
index 180deab..ce58f20 100644
--- a/drivers/power/abx500_chargalg.c
+++ b/drivers/power/abx500_chargalg.c
@@ -330,12 +330,13 @@ static int abx500_chargalg_check_charger_enable(struct 
abx500_chargalg *di)
return di-usb_chg-ops.check_enable(di-usb_chg,
di-bat-bat_type[di-bat-batt_id].normal_vol_lvl,
di-bat-bat_type[di-bat-batt_id].normal_cur_lvl);
-   } else if (di-chg_info.charger_type  AC_CHG) {
+   } else if ((di-chg_info.charger_type  AC_CHG) 
+   !(di-ac_chg-external)) {
return di-ac_chg-ops.check_enable(di-ac_chg,
di-bat-bat_type[di-bat-batt_id].normal_vol_lvl,
di-bat-bat_type[di-bat-batt_id].normal_cur_lvl);
}
-   return -ENXIO;
+   return 0;
 }
 
 /**
-- 
1.7.5.4

--
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 47/57] power: Harmonising platform data declaration/handling

2012-09-25 Thread mathieu . poirier
From: Mathieu J. Poirier mathieu.poir...@linaro.org

Making platform data declaration and handling similar accross all
ab8500_xyc.c battery management files.  Also adding gards against
NULL platform data.

Signed-off-by: Philippe Langlais philippe.langl...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
---
 drivers/power/ab8500_btemp.c|   17 +
 drivers/power/ab8500_charger.c  |   18 +-
 drivers/power/ab8500_fg.c   |   17 +
 drivers/power/abx500_chargalg.c |   25 -
 4 files changed, 47 insertions(+), 30 deletions(-)

diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c
index 1f33122..cf4b653 100644
--- a/drivers/power/ab8500_btemp.c
+++ b/drivers/power/ab8500_btemp.c
@@ -1028,10 +1028,10 @@ static int __devinit ab8500_btemp_probe(struct 
platform_device *pdev)
 {
int irq, i, ret = 0;
u8 val;
-   struct ab8500_platform_data *plat_data;
-   struct ab8500_btemp *di;
+   struct ab8500_platform_data *plat;
 
-   di = kzalloc(sizeof(*di), GFP_KERNEL);
+   struct ab8500_btemp *di =
+   kzalloc(sizeof(struct ab8500_btemp), GFP_KERNEL);
if (!di)
return -ENOMEM;
 
@@ -1042,22 +1042,23 @@ static int __devinit ab8500_btemp_probe(struct 
platform_device *pdev)
 
di-initialized = false;
 
+   plat = dev_get_platdata(di-parent-dev);
+
/* get btemp specific platform data */
-   plat_data = dev_get_platdata(di-parent-dev);
-   di-pdata = plat_data-btemp;
-   if (!di-pdata) {
+   if (!plat || !plat-btemp) {
dev_err(di-dev, no btemp platform data supplied\n);
ret = -EINVAL;
goto free_device_info;
}
+   di-pdata = plat-btemp;
 
/* get battery specific platform data */
-   di-bat = plat_data-battery;
-   if (!di-bat) {
+   if (!plat-battery) {
dev_err(di-dev, no battery platform data supplied\n);
ret = -EINVAL;
goto free_device_info;
}
+   di-bat = plat-battery;
 
/* BTEMP supply */
di-btemp_psy.name = ab8500_btemp;
diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index 68a4128..1290470 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -3319,10 +3319,10 @@ static int __devexit ab8500_charger_remove(struct 
platform_device *pdev)
 static int __devinit ab8500_charger_probe(struct platform_device *pdev)
 {
int irq, i, charger_status, ret = 0, ch_stat;
-   struct ab8500_platform_data *plat_data;
-   struct ab8500_charger *di;
+   struct ab8500_platform_data *plat;
 
-   di = kzalloc(sizeof(*di), GFP_KERNEL);
+   struct ab8500_charger *di =
+   kzalloc(sizeof(struct ab8500_charger), GFP_KERNEL);
if (!di)
return -ENOMEM;
 
@@ -3335,24 +3335,24 @@ static int __devinit ab8500_charger_probe(struct 
platform_device *pdev)
spin_lock_init(di-usb_state.usb_lock);
mutex_init(di-usb_ipt_crnt_lock);
 
-   /* get charger specific platform data */
-   plat_data = dev_get_platdata(di-parent-dev);
+   plat = dev_get_platdata(di-parent-dev);
 
-   di-pdata = plat_data-charger;
-   if (!di-pdata) {
+   /* get charger specific platform data */
+   if (!plat || !plat-charger) {
dev_err(di-dev, no charger platform data supplied\n);
ret = -EINVAL;
goto free_device_info;
}
+   di-pdata = plat-charger;
 
/* get battery specific platform data */
-   di-bat = plat_data-battery;
-   if (!di-bat) {
+   if (!plat-battery) {
dev_err(di-dev, no battery platform data supplied\n);
ret = -EINVAL;
goto free_device_info;
}
 
+   di-bat = plat-battery;
di-autopower = false;
di-invalid_charger_detect_state = 0;
 
diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
index cf6d2b5..5b5c7ea 100644
--- a/drivers/power/ab8500_fg.c
+++ b/drivers/power/ab8500_fg.c
@@ -3158,10 +3158,10 @@ static int __devinit ab8500_fg_probe(struct 
platform_device *pdev)
 {
int i, irq;
int ret = 0;
-   struct ab8500_platform_data *plat_data;
-   struct ab8500_fg *di;
+   struct ab8500_platform_data *plat;
 
-   di = kzalloc(sizeof(*di), GFP_KERNEL);
+   struct ab8500_fg *di =
+   kzalloc(sizeof(struct ab8500_fg), GFP_KERNEL);
if (!di)
return -ENOMEM;
 
@@ -3172,22 +3172,23 @@ static int __devinit ab8500_fg_probe(struct 
platform_device *pdev)
di-parent = dev_get_drvdata(pdev-dev.parent);
di-gpadc = ab8500_gpadc_get(ab8500-gpadc.0);
 
+   plat = dev_get_platdata(di-parent-dev);
+
/* get fg specific platform data */
-   plat_data = dev_get_platdata(di-parent-dev);
-   di

[PATCH 36/57] power: add backup battery charge voltages.

2012-09-25 Thread mathieu . poirier
From: Yang QU yang...@stericsson.com

Add 2.7v, 2.9v, 3.0v, 3.2v and 3.3v charging voltage
for backup battery. Before that only 2.5v, 2.6v, 2.8v,
3.1v are available.

Signed-off-by: Yang QU yang...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Maxime COQUELIN maxime.coque...@stericsson.com
Reviewed-by: Marcus COOPER marcus.xm.coo...@stericsson.com
Reviewed-by: Xiao Mei ZHANG xiaomei.zh...@stericsson.com
---
 drivers/power/ab8500_charger.c   |9 +++--
 include/linux/mfd/abx500/ab8500-bm.h |   24 
 2 files changed, 27 insertions(+), 6 deletions(-)

diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index b3b8f77..8137ea5 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -2834,6 +2834,7 @@ static int ab8500_charger_usb_get_property(struct 
power_supply *psy,
 static int ab8500_charger_init_hw_registers(struct ab8500_charger *di)
 {
int ret = 0;
+   u8 bup_vch_range = 0, vbup33_vrtcn = 0;
 
/* Setup maximum charger current and voltage for ABB cut2.0 */
if (!is_ab8500_1p1_or_earlier(di-parent)) {
@@ -2935,11 +2936,15 @@ static int ab8500_charger_init_hw_registers(struct 
ab8500_charger *di)
}
 
/* Backup battery voltage and current */
+   if (di-bat-bkup_bat_v  BUP_VCH_SEL_3P1V)
+   bup_vch_range = BUP_VCH_RANGE;
+   if (di-bat-bkup_bat_v == BUP_VCH_SEL_3P3V)
+   vbup33_vrtcn = VBUP33_VRTCN;
+
ret = abx500_set_register_interruptible(di-dev,
AB8500_RTC,
AB8500_RTC_BACKUP_CHG_REG,
-   di-bat-bkup_bat_v |
-   di-bat-bkup_bat_i);
+   (di-bat-bkup_bat_v  0x3) | di-bat-bkup_bat_i);
if (ret) {
dev_err(di-dev, failed to setup backup battery charging\n);
goto out;
diff --git a/include/linux/mfd/abx500/ab8500-bm.h 
b/include/linux/mfd/abx500/ab8500-bm.h
index cd15ea3..5ae8a6f 100644
--- a/include/linux/mfd/abx500/ab8500-bm.h
+++ b/include/linux/mfd/abx500/ab8500-bm.h
@@ -105,6 +105,7 @@
 #define AB8500_RTC_BACKUP_CHG_REG  0x0C
 #define AB8500_RTC_CC_CONF_REG 0x01
 #define AB8500_RTC_CTRL_REG0x0B
+#define AB8500_RTC_CTRL1_REG   0x11
 
 /*
  * OTP register offsets
@@ -179,10 +180,25 @@
 #define BUP_ICH_SEL_300UA  0x08
 #define BUP_ICH_SEL_700UA  0x0C
 
-#define BUP_VCH_SEL_2P5V   0x00
-#define BUP_VCH_SEL_2P6V   0x01
-#define BUP_VCH_SEL_2P8V   0x02
-#define BUP_VCH_SEL_3P1V   0x03
+enum bup_vch_sel {
+   BUP_VCH_SEL_2P5V,
+   BUP_VCH_SEL_2P6V,
+   BUP_VCH_SEL_2P8V,
+   BUP_VCH_SEL_3P1V,
+   /*
+* Note that the following 5 values 2.7v, 2.9v, 3.0v, 3.2v, 3.3v
+* are only available on ab8540. You can't choose these 5
+* voltage on ab8500/ab8505/ab9540.
+*/
+   BUP_VCH_SEL_2P7V,
+   BUP_VCH_SEL_2P9V,
+   BUP_VCH_SEL_3P0V,
+   BUP_VCH_SEL_3P2V,
+   BUP_VCH_SEL_3P3V,
+};
+
+#define BUP_VCH_RANGE  0x02
+#define VBUP33_VRTCN   0x01
 
 /* Battery OVV constants */
 #define BATT_OVV_ENA   0x02
-- 
1.7.5.4

--
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 45/57] power: ab8500: defer btemp filtering while init

2012-09-25 Thread mathieu . poirier
From: Rupesh Kumar rupesh.ku...@stericsson.com

Due to btemp filtering enabled during init, temp values
reported to charge algorithm driver started from 0.
As a result,charge algorithm was going into wrong
state and charging was stopped.
This patch defers btemp filtering till init is done.

Signed-off-by: Rupesh Kumar rupesh.ku...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Marcus COOPER marcus.xm.coo...@stericsson.com
Reviewed-by: Martin SJOBLOM martin.w.sjob...@stericsson.com
Reviewed-by: Philippe LANGLAIS philippe.langl...@stericsson.com
---
 drivers/power/ab8500_btemp.c |6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c
index b24835f..1f33122 100644
--- a/drivers/power/ab8500_btemp.c
+++ b/drivers/power/ab8500_btemp.c
@@ -613,7 +613,6 @@ static void ab8500_btemp_periodic_work(struct work_struct 
*work)
struct ab8500_btemp, btemp_periodic_work.work);
 
if (!di-initialized) {
-   di-initialized = true;
/* Identify the battery */
if (ab8500_btemp_id(di)  0)
dev_warn(di-dev, failed to identify the battery\n);
@@ -626,8 +625,9 @@ static void ab8500_btemp_periodic_work(struct work_struct 
*work)
 * same temperature. Else only allow 1 degree change from previous
 * reported value in the direction of the new measurement.
 */
-   if (bat_temp == di-prev_bat_temp || !di-initialized) {
-   if (di-bat_temp != di-prev_bat_temp || !di-initialized) {
+   if ((bat_temp == di-prev_bat_temp) || !di-initialized) {
+   if ((di-bat_temp != di-prev_bat_temp) || !di-initialized) {
+   di-initialized = true;
di-bat_temp = bat_temp;
power_supply_changed(di-btemp_psy);
}
-- 
1.7.5.4

--
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 27/57] power: sysfs interface update

2012-09-25 Thread mathieu . poirier
From: Michel JAOUEN michel.jao...@stericsson.com

Add new sysfs interface to get current charge status

Signed-off-by: Michel JAOUEN michel.jao...@stericsson.com
Signed-off-by: Loic Pallardy loic.palla...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Marcus COOPER marcus.xm.coo...@stericsson.com
Reviewed-by: Olivier CLERGEAUD olivier.clerge...@stericsson.com
Reviewed-by: Jonas ABERG jonas.ab...@stericsson.com
---
 drivers/power/ab8500_charger.c  |3 +++
 drivers/power/abx500_chargalg.c |   24 +++-
 2 files changed, 26 insertions(+), 1 deletions(-)

diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index 4129599..0a781a0 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -2759,6 +2759,9 @@ static int ab8500_charger_usb_notifier_call(struct 
notifier_block *nb,
enum ab8500_usb_state bm_usb_state;
unsigned mA = *((unsigned *)power);
 
+   if (di == NULL)
+   return NOTIFY_DONE;
+
if (event != USB_EVENT_VBUS) {
dev_dbg(di-dev, not a standard host, returning\n);
return NOTIFY_DONE;
diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c
index d3efc2a..4e3d20f 100644
--- a/drivers/power/abx500_chargalg.c
+++ b/drivers/power/abx500_chargalg.c
@@ -1679,6 +1679,27 @@ static int abx500_chargalg_get_property(struct 
power_supply *psy,
return 0;
 }
 
+/**
+ * abx500_chargalg_sysfs_show() - sysfs show operations
+ * @kobj:  pointer to the struct kobject
+ * @attr:  pointer to the struct attribute
+ * @buf:   buffer that holds the parameter to send to userspace
+ *
+ * Returns a buffer to be displayed in user space
+ */
+static ssize_t abx500_chargalg_sysfs_show(struct kobject *kobj,
+   struct attribute *attr, char *buf)
+{
+   struct abx500_chargalg *di = container_of(kobj,
+   struct abx500_chargalg, chargalg_kobject);
+
+   if ((di-susp_status.ac_suspended == true) 
+   (di-susp_status.usb_suspended == true))
+   return sprintf(buf, 0\n);
+   else
+   return sprintf(buf, 1\n);
+}
+
 /* Exposure to the sysfs interface */
 
 /**
@@ -1749,7 +1770,7 @@ static ssize_t abx500_chargalg_sysfs_charger(struct 
kobject *kobj,
 static struct attribute abx500_chargalg_en_charger = \
 {
.name = chargalg,
-   .mode = S_IWUGO,
+   .mode = S_IRUGO | S_IWUSR,
 };
 
 static struct attribute *abx500_chargalg_chg[] = {
@@ -1758,6 +1779,7 @@ static struct attribute *abx500_chargalg_chg[] = {
 };
 
 static const struct sysfs_ops abx500_chargalg_sysfs_ops = {
+   .show = abx500_chargalg_sysfs_show,
.store = abx500_chargalg_sysfs_charger,
 };
 
-- 
1.7.5.4

--
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 29/57] power: ab8500_fg: Goto INIT_RECOVERY when charger removed

2012-09-25 Thread mathieu . poirier
From: Martin Bergström martin.bergst...@stericsson.com

When the charger is removed we need to go to INIT_RECOVERY
state instead of directly to RECOVERY state.

Signed-off-by: Martin Bergstrom martin.bergst...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Marcus COOPER marcus.xm.coo...@stericsson.com
Reviewed-by: Jonas ABERG jonas.ab...@stericsson.com
---
 drivers/power/ab8500_fg.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
index 861927d..e7a0e1f 100644
--- a/drivers/power/ab8500_fg.c
+++ b/drivers/power/ab8500_fg.c
@@ -1644,7 +1644,7 @@ static void ab8500_fg_algorithm_discharging(struct 
ab8500_fg *di)
 
if (di-recovery_needed) {
ab8500_fg_discharge_state_to(di,
-   AB8500_FG_DISCHARGE_RECOVERY);
+   AB8500_FG_DISCHARGE_INIT_RECOVERY);
 
queue_delayed_work(di-fg_wq,
di-fg_periodic_work, 0);
-- 
1.7.5.4

--
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 37/57] power: ab8500_bm: Quick re-attach charging behaviour

2012-09-25 Thread mathieu . poirier
From: Kalle Komierowski karl.komierow...@stericsson.com

Due to a bug in some AB8500 ASICs charger removal cannot always
be detected if the removal and reinsertion is done to close in time.
This patch detects above described case and handles the situation
so that charging will be kept turned on.

Signed-off-by: Kalle Komierowski karl.komierow...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Marcus COOPER marcus.xm.coo...@stericsson.com
Reviewed-by: Jonas ABERG jonas.ab...@stericsson.com
Reviewed-by: Philippe LANGLAIS philippe.langl...@stericsson.com
---
 drivers/power/ab8500_charger.c|  105 -
 drivers/power/abx500_chargalg.c   |   31 -
 include/linux/mfd/abx500/ux500_chargalg.h |1 +
 3 files changed, 134 insertions(+), 3 deletions(-)

diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index 8137ea5..70e7c5e 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -49,6 +49,7 @@
 #define VBUS_DET_DBNC100   0x02
 #define VBUS_DET_DBNC1 0x01
 #define OTP_ENABLE_WD  0x01
+#define DROP_COUNT_RESET   0x01
 
 #define MAIN_CH_INPUT_CURR_SHIFT   4
 #define VBUS_IN_CURR_LIM_SHIFT 4
@@ -1672,6 +1673,105 @@ static int ab8500_charger_usb_en(struct ux500_charger 
*charger,
 }
 
 /**
+ * ab8500_charger_usb_check_enable() - enable usb charging
+ * @charger:   pointer to the ux500_charger structure
+ * @vset:  charging voltage
+ * @iset:  charger output current
+ *
+ * Check if the VBUS charger has been disconnected and reconnected without
+ * AB8500 rising an interrupt. Returns 0 on success.
+ */
+static int ab8500_charger_usb_check_enable(struct ux500_charger *charger,
+   int vset, int iset)
+{
+   u8 usbch_ctrl1 = 0;
+   int ret = 0;
+
+   struct ab8500_charger *di = to_ab8500_charger_usb_device_info(charger);
+
+   if (!di-usb.charger_connected)
+   return ret;
+
+   ret = abx500_get_register_interruptible(di-dev, AB8500_CHARGER,
+   AB8500_USBCH_CTRL1_REG, usbch_ctrl1);
+   if (ret  0) {
+   dev_err(di-dev, ab8500 read failed %d\n, __LINE__);
+   return ret;
+   }
+   dev_dbg(di-dev, USB charger ctrl: 0x%02x\n, usbch_ctrl1);
+
+   if (!(usbch_ctrl1  USB_CH_ENA)) {
+   dev_info(di-dev, Charging has been disabled abnormally and 
will be re-enabled\n);
+
+   ret = abx500_mask_and_set_register_interruptible(di-dev,
+   AB8500_CHARGER, AB8500_CHARGER_CTRL,
+   DROP_COUNT_RESET, DROP_COUNT_RESET);
+   if (ret  0) {
+   dev_err(di-dev, ab8500 write failed %d\n, __LINE__);
+   return ret;
+   }
+
+   ret = ab8500_charger_usb_en(di-usb_chg, true, vset, iset);
+   if (ret  0) {
+   dev_err(di-dev, Failed to enable VBUS charger %d\n,
+   __LINE__);
+   return ret;
+   }
+   }
+   return ret;
+}
+
+/**
+ * ab8500_charger_ac_check_enable() - enable usb charging
+ * @charger:   pointer to the ux500_charger structure
+ * @vset:  charging voltage
+ * @iset:  charger output current
+ *
+ * Check if the AC charger has been disconnected and reconnected without
+ * AB8500 rising an interrupt. Returns 0 on success.
+ */
+static int ab8500_charger_ac_check_enable(struct ux500_charger *charger,
+   int vset, int iset)
+{
+   u8 mainch_ctrl1 = 0;
+   int ret = 0;
+
+   struct ab8500_charger *di = to_ab8500_charger_ac_device_info(charger);
+
+   if (!di-ac.charger_connected)
+   return ret;
+
+   ret = abx500_get_register_interruptible(di-dev, AB8500_CHARGER,
+   AB8500_MCH_CTRL1, mainch_ctrl1);
+   if (ret  0) {
+   dev_err(di-dev, ab8500 read failed %d\n, __LINE__);
+   return ret;
+   }
+   dev_dbg(di-dev, AC charger ctrl: 0x%02x\n, mainch_ctrl1);
+
+   if (!(mainch_ctrl1  MAIN_CH_ENA)) {
+   dev_info(di-dev, Charging has been disabled abnormally and 
will be re-enabled\n);
+
+   ret = abx500_mask_and_set_register_interruptible(di-dev,
+   AB8500_CHARGER, AB8500_CHARGER_CTRL,
+   DROP_COUNT_RESET, DROP_COUNT_RESET);
+
+   if (ret  0) {
+   dev_err(di-dev, ab8500 write failed %d\n, __LINE__);
+   return ret;
+   }
+
+   ret = ab8500_charger_ac_en(di-usb_chg, true, vset, iset);
+   if (ret  0) {
+   dev_err(di-dev, failed to enable AC charger %d\n,
+   __LINE__);
+   return ret

[PATCH 43/57] power: charging: Add AB8505_USB_LINK_STATUS

2012-09-25 Thread mathieu . poirier
From: Hakan Berg hakan.b...@stericsson.com

The ab8505 does not have the same address for USB link-status
as has ab8500. Add AB8505_USB_LINK_STATUS and code to switch
to correct constant.

Signed-off-by: Hakan Berg hakan.b...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Mian Yousaf KAUKAB mian.yousaf.kau...@stericsson.com
Reviewed-by: Marcus COOPER marcus.xm.coo...@stericsson.com
Reviewed-by: Rabin VINCENT rabin.vinc...@stericsson.com
---
 drivers/power/ab8500_charger.c |   46 ---
 1 files changed, 37 insertions(+), 9 deletions(-)

diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index 18931e4..9449a33 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -77,6 +77,7 @@
 
 /* UsbLineStatus register bit masks */
 #define AB8500_USB_LINK_STATUS 0x78
+#define AB8505_USB_LINK_STATUS 0xF8
 #define AB8500_STD_HOST_SUSP   0x18
 
 /* Watchdog timeout constant */
@@ -801,10 +802,12 @@ static int ab8500_charger_read_usb_type(struct 
ab8500_charger *di)
if (is_ab8500(di-parent)) {
ret = abx500_get_register_interruptible(di-dev, AB8500_USB,
AB8500_USB_LINE_STAT_REG, val);
-   } else {
-   if (is_ab9540(di-parent) || is_ab8505(di-parent))
+   } else if (is_ab9540(di-parent) || is_ab8505(di-parent)) {
ret = abx500_get_register_interruptible(di-dev,
AB8500_USB, AB8500_USB_LINK1_STAT_REG, val);
+   } else {
+   dev_err(di-dev, %s unsupported analog baseband\n, __func__);
+   return -ENXIO;
}
if (ret  0) {
dev_err(di-dev, %s ab8500 read failed\n, __func__);
@@ -812,7 +815,14 @@ static int ab8500_charger_read_usb_type(struct 
ab8500_charger *di)
}
 
/* get the USB type */
-   val = (val  AB8500_USB_LINK_STATUS)  3;
+   if (is_ab8500(di-parent)) {
+   val = (val  AB8500_USB_LINK_STATUS)  3;
+   } else if (is_ab9540(di-parent) || is_ab8505(di-parent)) {
+   val = (val  AB8505_USB_LINK_STATUS)  3;
+   } else {
+   dev_err(di-dev, %s unsupported analog baseband\n, __func__);
+   return -ENXIO;
+   }
ret = ab8500_charger_max_usb_curr(di,
(enum ab8500_charger_link_status) val);
 
@@ -848,12 +858,17 @@ static int ab8500_charger_detect_usb_type(struct 
ab8500_charger *di)
return ret;
}
 
-   if (is_ab8500(di-parent))
+   if (is_ab8500(di-parent)) {
ret = abx500_get_register_interruptible(di-dev,
AB8500_USB, AB8500_USB_LINE_STAT_REG, val);
-   else
+   } else if (is_ab9540(di-parent) || is_ab8505(di-parent)) {
ret = abx500_get_register_interruptible(di-dev,
AB8500_USB, AB8500_USB_LINK1_STAT_REG, val);
+   } else {
+   dev_err(di-dev,
+%s unsupported analog baseband\n, __func__);
+   return -ENXIO;
+   }
if (ret  0) {
dev_err(di-dev, %s ab8500 read failed\n, __func__);
return ret;
@@ -867,7 +882,15 @@ static int ab8500_charger_detect_usb_type(struct 
ab8500_charger *di)
 */
 
/* get the USB type */
-   val = (val  AB8500_USB_LINK_STATUS)  3;
+   if (is_ab8500(di-parent)) {
+   val = (val  AB8500_USB_LINK_STATUS)  3;
+   } else if (is_ab9540(di-parent) || is_ab8505(di-parent)) {
+   val = (val  AB8505_USB_LINK_STATUS)  3;
+   } else {
+   dev_err(di-dev,
+%s unsupported analog baseband\n, __func__);
+   return -ENXIO;
+   }
if (val)
break;
}
@@ -2277,6 +2300,7 @@ static void ab8500_charger_usb_link_status_work(struct 
work_struct *work)
int detected_chargers;
int ret;
u8 val;
+   u8 link_status;
 
struct ab8500_charger *di = container_of(work,
struct ab8500_charger, usb_link_status_work);
@@ -2303,9 +2327,13 @@ static void ab8500_charger_usb_link_status_work(struct 
work_struct *work)
else
dev_dbg(di-dev, Error reading USB link status\n);
 
+   if (is_ab9540(di-parent) || is_ab8505(di-parent))
+   link_status = AB8505_USB_LINK_STATUS;
+   else
+   link_status = AB8500_USB_LINK_STATUS;
+
if (detected_chargers  USB_PW_CONN) {
-   if (((val  AB8500_USB_LINK_STATUS)  3) ==
-   USB_STAT_NOT_VALID_LINK

[PATCH 42/57] power: charging: Allow capacity to raise from 1%

2012-09-25 Thread mathieu . poirier
From: Hakan Berg hakan.b...@stericsson.com

When battery capacity was going below 1% fg in not supposed
to report 0% unless we've got the LOW_BAT IRQ, no matter
what the FG-algorithm says. This made fg get stuck at 1% if
charger is connected when capacity is 1%.
That problem is addressed with this patch.

Signed-off-by: Hakan BERG hakan.b...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Marcus COOPER marcus.xm.coo...@stericsson.com
Reviewed-by: Srinidhi KASAGAR srinidhi.kasa...@stericsson.com
---
 drivers/power/ab8500_fg.c |6 ++
 1 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
index c5732e7..cf6d2b5 100644
--- a/drivers/power/ab8500_fg.c
+++ b/drivers/power/ab8500_fg.c
@@ -1357,9 +1357,6 @@ static void ab8500_fg_check_capacity_limits(struct 
ab8500_fg *di, bool init)
 * algorithm says.
 */
di-bat_cap.prev_percent = 1;
-   di-bat_cap.permille = 1;
-   di-bat_cap.prev_mah = 1;
-   di-bat_cap.mah = 1;
percent = 1;
 
changed = true;
@@ -1771,9 +1768,10 @@ static void ab8500_fg_algorithm(struct ab8500_fg *di)
ab8500_fg_algorithm_discharging(di);
}
 
-   dev_dbg(di-dev, [FG_DATA] %d %d %d %d %d %d %d %d %d 
+   dev_dbg(di-dev, [FG_DATA] %d %d %d %d %d %d %d %d %d %d 
%d %d %d %d %d %d %d\n,
di-bat_cap.max_mah_design,
+   di-bat_cap.max_mah,
di-bat_cap.mah,
di-bat_cap.permille,
di-bat_cap.level,
-- 
1.7.5.4

--
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 41/57] power: ab8500_btemp: Filter btemp readings

2012-09-25 Thread mathieu . poirier
From: Hakan Berg hakan.b...@stericsson.com

Battery tempreature readings sometimes fails and results in
a value far from recent values. This patch adds a software
filter that disposes such readings, by allowing direct
updates on temperature only if two samples result in the
same temperature. Else only allow 1 degree change from previous
reported value in the direction of the new measurement.

Signed-off-by: Hakan Berg hakan.b...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Marcus COOPER marcus.xm.coo...@stericsson.com
Reviewed-by: Martin SJOBLOM martin.w.sjob...@stericsson.com
Reviewed-by: Rabin VINCENT rabin.vinc...@stericsson.com
---
 drivers/power/ab8500_btemp.c |   27 +--
 1 files changed, 21 insertions(+), 6 deletions(-)

diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c
index 56a3bb9..b24835f 100644
--- a/drivers/power/ab8500_btemp.c
+++ b/drivers/power/ab8500_btemp.c
@@ -74,8 +74,8 @@ struct ab8500_btemp_ranges {
  * @dev:   Pointer to the structure device
  * @node:  List of AB8500 BTEMPs, hence prepared for reentrance
  * @curr_source:   What current source we use, in uA
- * @bat_temp:  Battery temperature in degree Celcius
- * @prev_bat_temp  Last dispatched battery temperature
+ * @bat_temp:  Dispatched battery temperature in degree Celcius
+ * @prev_bat_temp  Last measured battery temperature in degree Celcius
  * @parent:Pointer to the struct ab8500
  * @gpadc: Pointer to the struct gpadc
  * @fg:Pointer to the struct fg
@@ -608,6 +608,7 @@ static int ab8500_btemp_id(struct ab8500_btemp *di)
 static void ab8500_btemp_periodic_work(struct work_struct *work)
 {
int interval;
+   int bat_temp;
struct ab8500_btemp *di = container_of(work,
struct ab8500_btemp, btemp_periodic_work.work);
 
@@ -618,12 +619,26 @@ static void ab8500_btemp_periodic_work(struct work_struct 
*work)
dev_warn(di-dev, failed to identify the battery\n);
}
 
-   di-bat_temp = ab8500_btemp_measure_temp(di);
-
-   if (di-bat_temp != di-prev_bat_temp) {
-   di-prev_bat_temp = di-bat_temp;
+   bat_temp = ab8500_btemp_measure_temp(di);
+   /*
+* Filter battery temperature.
+* Allow direct updates on temperature only if two samples result in
+* same temperature. Else only allow 1 degree change from previous
+* reported value in the direction of the new measurement.
+*/
+   if (bat_temp == di-prev_bat_temp || !di-initialized) {
+   if (di-bat_temp != di-prev_bat_temp || !di-initialized) {
+   di-bat_temp = bat_temp;
+   power_supply_changed(di-btemp_psy);
+   }
+   } else if (bat_temp  di-prev_bat_temp) {
+   di-bat_temp--;
+   power_supply_changed(di-btemp_psy);
+   } else if (bat_temp  di-prev_bat_temp) {
+   di-bat_temp++;
power_supply_changed(di-btemp_psy);
}
+   di-prev_bat_temp = bat_temp;
 
if (di-events.ac_conn || di-events.usb_conn)
interval = di-bat-temp_interval_chg;
-- 
1.7.5.4

--
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 40/57] power: ab8500: ADC for battery thermistor

2012-09-25 Thread mathieu . poirier
From: Marcus Cooper marcus.xm.coo...@stericsson.com

When using ABx500_ADC_THERM_BATCTRL the battery ID resistor
is combined with a NTC resistor to both identify the battery and
to measure its temperature.

Signed-off-by: Marcus Cooper marcus.xm.coo...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Mian Yousaf KAUKAB mian.yousaf.kau...@stericsson.com
Reviewed-by: Michel JAOUEN michel.jao...@stericsson.com
Reviewed-by: Hakan BERG hakan.b...@stericsson.com
Reviewed-by: Rabin VINCENT rabin.vinc...@stericsson.com
---
 drivers/power/ab8500_btemp.c |4 +++-
 include/linux/mfd/abx500.h   |2 ++
 2 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c
index 506f124..56a3bb9 100644
--- a/drivers/power/ab8500_btemp.c
+++ b/drivers/power/ab8500_btemp.c
@@ -557,7 +557,9 @@ static int ab8500_btemp_id(struct ab8500_btemp *di)
/* BATTERY_UNKNOWN is defined on position 0, skip it! */
for (i = BATTERY_UNKNOWN + 1; i  di-bat-n_btypes; i++) {
if ((res = di-bat-bat_type[i].resis_high) 
-   (res = di-bat-bat_type[i].resis_low)) {
+   (res = di-bat-bat_type[i].resis_low) 
+   (di-bat-bat_type[i].adc_therm ==
+   di-bat-adc_therm)) {
dev_dbg(di-dev, Battery detected on %s
 low %d  res %d  high: %d
 index: %d\n,
diff --git a/include/linux/mfd/abx500.h b/include/linux/mfd/abx500.h
index 97e918f..cb2b82a 100644
--- a/include/linux/mfd/abx500.h
+++ b/include/linux/mfd/abx500.h
@@ -270,6 +270,7 @@ struct abx500_maxim_parameters {
  * @low_high_cur_lvl:  charger current in temp low/high state in mA
  * @low_high_vol_lvl:  charger voltage in temp low/high state in mV'
  * @battery_resistance:battery inner resistance in mOhm.
+ * @adc_therm: battery uses controller or resistor for temp.
  * @n_r_t_tbl_elements:number of elements in r_to_t_tbl
  * @r_to_t_tbl:table containing resistance to temp 
points
  * @n_v_cap_tbl_elements:  number of elements in v_to_cap_tbl
@@ -297,6 +298,7 @@ struct abx500_battery_type {
int low_high_cur_lvl;
int low_high_vol_lvl;
int battery_resistance;
+   enum abx500_adc_therm adc_therm;
int n_temp_tbl_elements;
struct abx500_res_to_temp *r_to_t_tbl;
int n_v_cap_tbl_elements;
-- 
1.7.5.4

--
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 39/57] power: ab8500_charger: Prevent auto drop of VBUS

2012-09-25 Thread mathieu . poirier
From: Martin Sjoblom martin.w.sjob...@stericsson.com

Do not set higher current in stepping functionality if VBUS is dropping.
After VBUS has dropped try to set current once again. If dropping again
then we have found the maximum capability of the charger.

Signed-off-by: Martin Sjoblom martin.w.sjob...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Per FORLIN per.for...@stericsson.com
---
 drivers/power/ab8500_charger.c |  166 
 1 files changed, 117 insertions(+), 49 deletions(-)

diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index ebeb068..18931e4 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -55,6 +55,7 @@
 #define MAIN_CH_INPUT_CURR_SHIFT   4
 #define VBUS_IN_CURR_LIM_SHIFT 4
 #define AUTO_VBUS_IN_CURR_LIM_SHIFT4
+#define VBUS_IN_CURR_LIM_RETRY_SET_TIME30 /* seconds */
 
 #define LED_INDICATOR_PWM_ENA  0x01
 #define LED_INDICATOR_PWM_DIS  0x00
@@ -199,10 +200,15 @@ struct ab8500_charger_usb_state {
spinlock_t usb_lock;
 };
 
+struct ab8500_charger_max_usb_in_curr {
+   int usb_type_max;
+   int set_max;
+   int calculated_max;
+};
+
 /**
  * struct ab8500_charger - ab8500 Charger device information
  * @dev:   Pointer to the structure device
- * @max_usb_in_curr:   Max USB charger input current
  * @vbus_detected: VBUS detected
  * @vbus_detected_start:
  * VBUS detected during startup
@@ -227,6 +233,7 @@ struct ab8500_charger_usb_state {
  * @bat:   Pointer to the abx500_bm platform data
  * @flags: Structure for information about events triggered
  * @usb_state: Structure for usb stack information
+ * @max_usb_in_curr:   Max USB charger input current
  * @ac_chg:AC charger power supply
  * @usb_chg:   USB charger power supply
  * @ac:Structure that holds the AC charger properties
@@ -255,7 +262,6 @@ struct ab8500_charger_usb_state {
  */
 struct ab8500_charger {
struct device *dev;
-   int max_usb_in_curr;
bool vbus_detected;
bool vbus_detected_start;
bool ac_conn;
@@ -266,7 +272,6 @@ struct ab8500_charger {
bool usb_device_is_unrecognised;
bool autopower;
int invalid_charger_detect_state;
-   bool is_usb_host;
int is_aca_rid;
atomic_t current_stepping_sessions;
struct ab8500 *parent;
@@ -275,6 +280,7 @@ struct ab8500_charger {
struct abx500_bm_data *bat;
struct ab8500_charger_event_flags flags;
struct ab8500_charger_usb_state usb_state;
+   struct ab8500_charger_max_usb_in_curr max_usb_in_curr;
struct ux500_charger ac_chg;
struct ux500_charger usb_chg;
struct ab8500_charger_info ac;
@@ -416,6 +422,10 @@ static void ab8500_charger_set_usb_connected(struct 
ab8500_charger *di,
if (connected != di-usb.charger_connected) {
dev_dbg(di-dev, USB connected:%i\n, connected);
di-usb.charger_connected = connected;
+
+   if (!connected)
+   di-flags.vbus_drop_end = false;
+
sysfs_notify(di-usb_chg.psy.dev-kobj, NULL, present);
 
if (connected) {
@@ -665,23 +675,19 @@ static int ab8500_charger_max_usb_curr(struct 
ab8500_charger *di,
case USB_STAT_STD_HOST_C_S:
dev_dbg(di-dev, USB Type - Standard host is );
dev_dbg(di-dev, detected through USB driver\n);
-   di-max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5;
-   di-is_usb_host = true;
+   di-max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5;
di-is_aca_rid = 0;
break;
case USB_STAT_HOST_CHG_HS_CHIRP:
-   di-max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5;
-   di-is_usb_host = true;
+   di-max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5;
di-is_aca_rid = 0;
break;
case USB_STAT_HOST_CHG_HS:
-   di-max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5;
-   di-is_usb_host = true;
+   di-max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5;
di-is_aca_rid = 0;
break;
case USB_STAT_ACA_RID_C_HS:
-   di-max_usb_in_curr = USB_CH_IP_CUR_LVL_0P9;
-   di-is_usb_host = false;
+   di-max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P9;
di-is_aca_rid = 0;
break;
case USB_STAT_ACA_RID_A:
@@ -690,8 +696,7 @@ static int ab8500_charger_max_usb_curr(struct 
ab8500_charger *di,
 * can consume (900mA). Closest level is 500mA
 */
dev_dbg(di-dev, USB_STAT_ACA_RID_A detected\n);
-   di-max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5;
-   di-is_usb_host

[PATCH 38/57] power: l9540: Charge only mode fixes

2012-09-25 Thread mathieu . poirier
From: Rupesh Kumar rupesh.ku...@stericsson.com

Fix for: charging not getting enabled in
charge only mode by external charger.

Signed-off-by: Rupesh Kumar rupesh.ku...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Marcus COOPER marcus.xm.coo...@stericsson.com
Reviewed-by: Michel JAOUEN michel.jao...@stericsson.com
Reviewed-by: Philippe LANGLAIS philippe.langl...@stericsson.com
Reviewed-by: Philippe LANGLAIS philippe.langl...@stericsson.com
---
 drivers/power/ab8500_charger.c|   42 +
 drivers/power/abx500_chargalg.c   |   14 +
 include/linux/mfd/abx500/ux500_chargalg.h |2 +
 3 files changed, 58 insertions(+), 0 deletions(-)

diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index 70e7c5e..ebeb068 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -15,6 +15,7 @@
 #include linux/device.h
 #include linux/interrupt.h
 #include linux/delay.h
+#include linux/notifier.h
 #include linux/slab.h
 #include linux/platform_device.h
 #include linux/power_supply.h
@@ -94,6 +95,10 @@
 #define AB8500_SW_CONTROL_FALLBACK 0x03
 /* Wait for enumeration before charging in us */
 #define WAIT_ACA_RID_ENUMERATION   (5 * 1000)
+/*External charger control*/
+#define AB8500_SYS_CHARGER_CONTROL_REG 0x52
+#define EXTERNAL_CHARGER_DISABLE_REG_VAL   0x03
+#define EXTERNAL_CHARGER_ENABLE_REG_VAL0x07
 
 /* UsbLineStatus register - usb types */
 enum ab8500_charger_link_status {
@@ -1672,6 +1677,29 @@ static int ab8500_charger_usb_en(struct ux500_charger 
*charger,
return ret;
 }
 
+static int ab8500_external_charger_prepare(struct notifier_block *charger_nb,
+   unsigned long event, void *data)
+{
+   int ret;
+   struct device *dev = data;
+   /*Toggle External charger control pin*/
+   ret = abx500_set_register_interruptible(dev, AB8500_SYS_CTRL1_BLOCK,
+ AB8500_SYS_CHARGER_CONTROL_REG,
+ EXTERNAL_CHARGER_DISABLE_REG_VAL);
+   if (ret  0) {
+   dev_err(dev, write reg failed %d\n, ret);
+   goto out;
+   }
+   ret = abx500_set_register_interruptible(dev, AB8500_SYS_CTRL1_BLOCK,
+ AB8500_SYS_CHARGER_CONTROL_REG,
+ EXTERNAL_CHARGER_ENABLE_REG_VAL);
+   if (ret  0)
+   dev_err(dev, Write reg failed %d\n, ret);
+
+out:
+   return ret;
+}
+
 /**
  * ab8500_charger_usb_check_enable() - enable usb charging
  * @charger:   pointer to the ux500_charger structure
@@ -3201,6 +3229,10 @@ static int ab8500_charger_suspend(struct platform_device 
*pdev,
 #define ab8500_charger_resume  NULL
 #endif
 
+static struct notifier_block charger_nb = {
+   .notifier_call = ab8500_external_charger_prepare,
+};
+
 static int __devexit ab8500_charger_remove(struct platform_device *pdev)
 {
struct ab8500_charger *di = platform_get_drvdata(pdev);
@@ -3233,6 +3265,11 @@ static int __devexit ab8500_charger_remove(struct 
platform_device *pdev)
/* Delete the work queue */
destroy_workqueue(di-charger_wq);
 
+   /*Unregister external charger enable notifier*/
+   if (!di-ac_chg.enabled)
+   blocking_notifier_chain_unregister(
+   charger_notifier_list, charger_nb);
+
flush_scheduled_work();
if (di-usb_chg.enabled)
power_supply_unregister(di-usb_chg.psy);
@@ -3307,6 +3344,11 @@ static int __devinit ab8500_charger_probe(struct 
platform_device *pdev)
di-ac_chg.enabled = di-pdata-ac_enabled;
di-ac_chg.external = false;
 
+   /*notifier for external charger enabling*/
+   if (!di-ac_chg.enabled)
+   blocking_notifier_chain_register(
+   charger_notifier_list, charger_nb);
+
/* USB supply */
/* power_supply base class */
di-usb_chg.psy.name = ab8500_usb;
diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c
index 9568f63..3ca00dd 100644
--- a/drivers/power/abx500_chargalg.c
+++ b/drivers/power/abx500_chargalg.c
@@ -24,6 +24,7 @@
 #include linux/mfd/abx500.h
 #include linux/mfd/abx500/ux500_chargalg.h
 #include linux/mfd/abx500/ab8500-bm.h
+#include linux/notifier.h
 
 /* Watchdog kick interval */
 #define CHG_WD_INTERVAL(6 * HZ)
@@ -255,6 +256,9 @@ static enum power_supply_property abx500_chargalg_props[] = 
{
POWER_SUPPLY_PROP_HEALTH,
 };
 
+/*External charger prepare notifier*/
+BLOCKING_NOTIFIER_HEAD(charger_notifier_list);
+
 /**
  * abx500_chargalg_safety_timer_expired() - Expiration of the safety timer
  * @data:  pointer to the abx500_chargalg structure
@@ -508,6 +512,8 @@ static int abx500_chargalg_kick_watchdog(struct 
abx500_chargalg *di)
 static int abx500_chargalg_ac_en(struct abx500_chargalg *di

[PATCH 35/57] power: ab8500_fg: Report unscaled capacity

2012-09-25 Thread mathieu . poirier
From: Martin Bergstrom martin.bergst...@stericsson.com

Unscaled capacity should be reported for POWER_SUPPLY_PROP_CAPACITY.

Signed-off-by: Martin Bergstrom martin.bergst...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Marcus COOPER marcus.xm.coo...@stericsson.com
Reviewed-by: Jonas ABERG jonas.ab...@stericsson.com
---
 drivers/power/ab8500_fg.c |6 ++
 1 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
index fde189a..c5732e7 100644
--- a/drivers/power/ab8500_fg.c
+++ b/drivers/power/ab8500_fg.c
@@ -2159,9 +2159,7 @@ static int ab8500_fg_get_property(struct power_supply 
*psy,
val-intval = di-bat_cap.prev_mah;
break;
case POWER_SUPPLY_PROP_CAPACITY:
-   if (di-bat-capacity_scaling)
-   val-intval = di-bat_cap.cap_scale.scaled_cap;
-   else if (di-flags.batt_unknown  !di-bat-chg_unknown_bat 
+   if (di-flags.batt_unknown  !di-bat-chg_unknown_bat 
di-flags.batt_id_received)
val-intval = 100;
else
@@ -2625,7 +2623,7 @@ static ssize_t ab8500_show_capacity(struct device *dev,
if (di-bat-capacity_scaling)
capacity = di-bat_cap.cap_scale.scaled_cap;
else
-   capacity = DIV_ROUND_CLOSEST(di-bat_cap.permille, 10);
+   capacity = di-bat_cap.prev_percent;
 
return scnprintf(buf, PAGE_SIZE, %d\n, capacity);
 }
-- 
1.7.5.4

--
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 33/57] power: u8500_charger: Delay for USB enumeration

2012-09-25 Thread mathieu . poirier
From: Paer-Olof Haakansson par-olof.hakans...@stericsson.com

If charging is started before USB enumeration of an
Accessory Charger Adapter has finished, the AB8500 will
generate a VBUS_ERROR. This in turn results in timeouts
and delays the enumeration with around 15 seconds.
This patch delays the charging and then ramps currents
slowly to avoid VBUS errors. The delay allows the enumeration
to have finished before charging is turned on.

Signed-off-by: Martin Sjoblom martin.w.sjob...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Jonas ABERG jonas.ab...@stericsson.com
---
 drivers/mfd/ab8500-core.c  |6 +
 drivers/power/ab8500_charger.c |  435 +--
 2 files changed, 329 insertions(+), 112 deletions(-)

diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
index 47adf80..ef13fe1 100644
--- a/drivers/mfd/ab8500-core.c
+++ b/drivers/mfd/ab8500-core.c
@@ -786,6 +786,12 @@ static struct resource __devinitdata 
ab8500_charger_resources[] = {
.end = AB8500_INT_CH_WD_EXP,
.flags = IORESOURCE_IRQ,
},
+   {
+   .name = VBUS_CH_DROP_END,
+   .start = AB8500_INT_VBUS_CH_DROP_END,
+   .end = AB8500_INT_VBUS_CH_DROP_END,
+   .flags = IORESOURCE_IRQ,
+   },
 };
 
 static struct resource __devinitdata ab8500_btemp_resources[] = {
diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index 2a323cf..b3b8f77 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -52,6 +52,7 @@
 
 #define MAIN_CH_INPUT_CURR_SHIFT   4
 #define VBUS_IN_CURR_LIM_SHIFT 4
+#define AUTO_VBUS_IN_CURR_LIM_SHIFT4
 
 #define LED_INDICATOR_PWM_ENA  0x01
 #define LED_INDICATOR_PWM_DIS  0x00
@@ -85,14 +86,13 @@
 /* Step up/down delay in us */
 #define STEP_UDELAY1000
 
-/* Wait for enumeration before charging in ms */
-#define WAIT_FOR_USB_ENUMERATION   (5 * 1000)
-
 #define CHARGER_STATUS_POLL 10 /* in ms */
 
 #define CHG_WD_INTERVAL(60 * HZ)
 
 #define AB8500_SW_CONTROL_FALLBACK 0x03
+/* Wait for enumeration before charging in us */
+#define WAIT_ACA_RID_ENUMERATION   (5 * 1000)
 
 /* UsbLineStatus register - usb types */
 enum ab8500_charger_link_status {
@@ -182,12 +182,14 @@ struct ab8500_charger_event_flags {
bool usbchargernotok;
bool chgwdexp;
bool vbus_collapse;
+   bool vbus_drop_end;
 };
 
 struct ab8500_charger_usb_state {
-   bool usb_changed;
int usb_current;
+   int usb_current_tmp;
enum ab8500_usb_state state;
+   enum ab8500_usb_state state_tmp;
spinlock_t usb_lock;
 };
 
@@ -207,6 +209,11 @@ struct ab8500_charger_usb_state {
  * @old_vbat   Previously measured battery voltage
  * @usb_device_is_unrecognised USB device is unrecognised by the hardware
  * @autopower  Indicate if we should have automatic pwron after pwrloss
+ * @invalid_charger_detect_state:
+   State when forcing AB to use invalid charger
+ * @is_aca_rid:Incicate if accessory is ACA type
+ * @current_stepping_sessions:
+ * Counter for current stepping sessions
  * @invalid_charger_detect_state   State when forcing AB to use invalid 
charger
  * @parent:Pointer to the struct ab8500
  * @gpadc: Pointer to the struct gpadc
@@ -225,7 +232,6 @@ struct ab8500_charger_usb_state {
  * @check_usbchgnotok_work:Work for checking USB charger not ok status
  * @kick_wd_work:  Work for kicking the charger watchdog in case
  * of ABB rev 1.* due to the watchog logic bug
- * @attach_work:   Work for checking the usb enumeration
  * @ac_charger_attached_work:  Work for checking if AC charger is still
  * connected
  * @usb_charger_attached_work: Work for checking if USB charger is still
@@ -234,6 +240,8 @@ struct ab8500_charger_usb_state {
  * @detect_usb_type_work:  Work for detecting the USB type connected
  * @usb_link_status_work:  Work for checking the new USB link status
  * @usb_state_changed_work:Work for checking USB state
+ * @attach_work:   Work for detecting USB type
+ * @vbus_drop_end_work:Work for detecting VBUS drop end
  * @check_main_thermal_prot_work:
  * Work for checking Main thermal status
  * @check_usb_thermal_prot_work:
@@ -252,6 +260,9 @@ struct ab8500_charger {
bool usb_device_is_unrecognised;
bool autopower;
int invalid_charger_detect_state;
+   bool is_usb_host;
+   int is_aca_rid;
+   atomic_t current_stepping_sessions;
struct ab8500 *parent;
struct ab8500_gpadc *gpadc;
struct abx500_charger_platform_data *pdata;
@@ -264,17 +275,19 @@ struct ab8500_charger

[PATCH 32/57] power: ab8500_charger: Do not touch VBUSOVV bits

2012-09-25 Thread mathieu . poirier
From: Jonas Aaberg jonas.ab...@stericsson.com

Do not touch the VBUSOVV in USBCHTRL2 when running on AB8505.

Signed-off-by: Jonas Aaberg jonas.ab...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Marcus COOPER marcus.xm.coo...@stericsson.com
---
 drivers/power/ab8500_charger.c|   22 --
 include/linux/mfd/abx500/ab8500.h |   10 ++
 2 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index 071c7c2..2a323cf 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -2667,13 +2667,23 @@ static int ab8500_charger_init_hw_registers(struct 
ab8500_charger *di)
}
}
 
-   /* VBUS OVV set to 6.3V and enable automatic current limitiation */
-   ret = abx500_set_register_interruptible(di-dev,
-   AB8500_CHARGER,
-   AB8500_USBCH_CTRL2_REG,
-   VBUS_OVV_SELECT_6P3V | VBUS_AUTO_IN_CURR_LIM_ENA);
+   if (is_ab9540_2p0(di-parent) || is_ab8505_2p0(di-parent))
+   ret = abx500_mask_and_set_register_interruptible(di-dev,
+   AB8500_CHARGER,
+   AB8500_USBCH_CTRL2_REG,
+   VBUS_AUTO_IN_CURR_LIM_ENA,
+   VBUS_AUTO_IN_CURR_LIM_ENA);
+   else
+   /*
+* VBUS OVV set to 6.3V and enable automatic current limitation
+*/
+   ret = abx500_set_register_interruptible(di-dev,
+   AB8500_CHARGER,
+   AB8500_USBCH_CTRL2_REG,
+   VBUS_OVV_SELECT_6P3V | VBUS_AUTO_IN_CURR_LIM_ENA);
if (ret) {
-   dev_err(di-dev, failed to set VBUS OVV\n);
+   dev_err(di-dev,
+   failed to set automatic current limitation\n);
goto out;
}
 
diff --git a/include/linux/mfd/abx500/ab8500.h 
b/include/linux/mfd/abx500/ab8500.h
index 087b445..5a4b186 100644
--- a/include/linux/mfd/abx500/ab8500.h
+++ b/include/linux/mfd/abx500/ab8500.h
@@ -351,6 +351,16 @@ static inline int is_ab8500_2p0(struct ab8500 *ab)
return (is_ab8500(ab)  (ab-chip_id == AB8500_CUT2P0));
 }
 
+static inline int is_ab8505_2p0(struct ab8500 *ab)
+{
+   return (is_ab8505(ab)  (ab-chip_id == AB8500_CUT2P0));
+}
+
+static inline int is_ab9540_2p0(struct ab8500 *ab)
+{
+   return (is_ab9540(ab)  (ab-chip_id == AB8500_CUT2P0));
+}
+
 int ab8500_irq_get_virq(struct ab8500 *ab8500, int irq);
 
 #endif /* MFD_AB8500_H */
-- 
1.7.5.4

--
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 30/57] power: ab8500: Flush sync all works

2012-09-25 Thread mathieu . poirier
From: Jonas Aaberg jonas.ab...@stericsson.com

Flush and sync all workqueues at suspend to avoid
that we suspend in the middle of a work.

Signed-off-by: Jonas Aaberg jonas.ab...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Marcus COOPER marcus.xm.coo...@stericsson.com
---
 drivers/power/ab8500_charger.c |   11 +++
 drivers/power/ab8500_fg.c  |5 +
 2 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index ee5ad7b..071c7c2 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -2862,6 +2862,17 @@ static int ab8500_charger_suspend(struct platform_device 
*pdev,
if (delayed_work_pending(di-check_hw_failure_work))
cancel_delayed_work(di-check_hw_failure_work);
 
+   flush_delayed_work_sync(di-attach_work);
+   flush_delayed_work_sync(di-usb_charger_attached_work);
+   flush_delayed_work_sync(di-ac_charger_attached_work);
+   flush_delayed_work_sync(di-check_usbchgnotok_work);
+   flush_delayed_work_sync(di-check_vbat_work);
+   flush_delayed_work_sync(di-kick_wd_work);
+
+   flush_work_sync(di-usb_link_status_work);
+   flush_work_sync(di-ac_work);
+   flush_work_sync(di-detect_usb_type_work);
+
return 0;
 }
 #else
diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
index e7a0e1f..0e71e7e 100644
--- a/drivers/power/ab8500_fg.c
+++ b/drivers/power/ab8500_fg.c
@@ -2626,6 +2626,11 @@ static int ab8500_fg_suspend(struct platform_device 
*pdev,
struct ab8500_fg *di = platform_get_drvdata(pdev);
 
flush_delayed_work_sync(di-fg_periodic_work);
+   flush_work_sync(di-fg_work);
+   flush_work_sync(di-fg_acc_cur_work);
+   flush_delayed_work_sync(di-fg_reinit_work);
+   flush_delayed_work_sync(di-fg_low_bat_work);
+   flush_delayed_work_sync(di-fg_check_hw_failure_work);
 
/*
 * If the FG is enabled we will disable it before going to suspend
-- 
1.7.5.4

--
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 28/57] power: ab8500 - Accessing Autopower register fails

2012-09-25 Thread mathieu . poirier
From: Nicolas Guion nicolas.gu...@stericsson.com

The fallback software control register has moved in the ab8505
and ab9540.

Signed-off-by: Marcus Cooper marcus.xm.coo...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Mattias WALLIN mattias.wal...@stericsson.com
Reviewed-by: Nicolas GUION nicolas.gu...@stericsson.com
Reviewed-by: Jonas ABERG jonas.ab...@stericsson.com
---
 drivers/power/ab8500_charger.c |   53 +++-
 1 files changed, 36 insertions(+), 17 deletions(-)

diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index 0a781a0..ee5ad7b 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -92,6 +92,8 @@
 
 #define CHG_WD_INTERVAL(60 * HZ)
 
+#define AB8500_SW_CONTROL_FALLBACK 0x03
+
 /* UsbLineStatus register - usb types */
 enum ab8500_charger_link_status {
USB_STAT_NOT_CONFIGURED,
@@ -307,42 +309,59 @@ static enum power_supply_property 
ab8500_charger_usb_props[] = {
 static void ab8500_enable_disable_sw_fallback(struct ab8500_charger *di,
bool fallback)
 {
+   u8 val;
u8 reg;
+   u8 bank;
+   u8 bit;
int ret;
 
dev_dbg(di-dev, SW Fallback: %d\n, fallback);
 
+   if (is_ab8500(di-parent)) {
+   bank = 0x15;
+   reg = 0x0;
+   bit = 3;
+   } else {
+   bank = AB8500_SYS_CTRL1_BLOCK;
+   reg = AB8500_SW_CONTROL_FALLBACK;
+   bit = 0;
+   }
+
/* read the register containing fallback bit */
-   ret = abx500_get_register_interruptible(di-dev, 0x15, 0x00, reg);
-   if (ret) {
-   dev_err(di-dev, %d write failed\n, __LINE__);
+   ret = abx500_get_register_interruptible(di-dev, bank, reg, val);
+   if (ret  0) {
+   dev_err(di-dev, %d read failed\n, __LINE__);
return;
}
 
-   /* enable the OPT emulation registers */
-   ret = abx500_set_register_interruptible(di-dev, 0x11, 0x00, 0x2);
-   if (ret) {
-   dev_err(di-dev, %d write failed\n, __LINE__);
-   return;
+   if (is_ab8500(di-parent)) {
+   /* enable the OPT emulation registers */
+   ret = abx500_set_register_interruptible(di-dev,
+0x11, 0x00, 0x2);
+   if (ret) {
+   dev_err(di-dev, %d write failed\n, __LINE__);
+   goto disable_otp;
+   }
}
 
if (fallback)
-   reg |= 0x8;
+   val |= (1  bit);
else
-   reg = ~0x8;
+   val = ~(1  bit);
 
/* write back the changed fallback bit value to register */
-   ret = abx500_set_register_interruptible(di-dev, 0x15, 0x00, reg);
+   ret = abx500_set_register_interruptible(di-dev, bank, reg, val);
if (ret) {
dev_err(di-dev, %d write failed\n, __LINE__);
-   return;
}
 
-   /* disable the set OTP registers again */
-   ret = abx500_set_register_interruptible(di-dev, 0x11, 0x00, 0x0);
-   if (ret) {
-   dev_err(di-dev, %d write failed\n, __LINE__);
-   return;
+disable_otp:
+   if (is_ab8500(di-parent)) {
+   /* disable the set OTP registers again */
+   ret = abx500_set_register_interruptible(di-dev,
+0x11, 0x00, 0x0);
+   if (ret)
+   dev_err(di-dev, %d write failed\n, __LINE__);
}
 }
 
-- 
1.7.5.4

--
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 26/57] power: charge: update watchdog for pm2xxx support

2012-09-25 Thread mathieu . poirier
From: Loic Pallardy loic.palla...@stericsson.com

AB and PMxxx doesn't have same watchdog refresh period
Add watchdog to refresh period parameters in x500 charger structure,
this should kick watchdog every 30sec.
The AC charging should also kick both pm2xxx
and the AB charger watchdog.

Signed-off-by: Rajkumar Kasirajan rajkumar.kasira...@stericsson.com
Signed-off-by: Loic Pallardy loic.palla...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Michel JAOUEN michel.jao...@stericsson.com
Reviewed-by: Marcus COOPER marcus.xm.coo...@stericsson.com
Reviewed-by: Jonas ABERG jonas.ab...@stericsson.com
---
 drivers/power/ab8500_charger.c|6 ++
 drivers/power/abx500_chargalg.c   |   23 +--
 include/linux/mfd/abx500/ux500_chargalg.h |3 +++
 3 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index 3100f11..4129599 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -90,6 +90,8 @@
 
 #define CHARGER_STATUS_POLL 10 /* in ms */
 
+#define CHG_WD_INTERVAL(60 * HZ)
+
 /* UsbLineStatus register - usb types */
 enum ab8500_charger_link_status {
USB_STAT_NOT_CONFIGURED,
@@ -2945,7 +2947,9 @@ static int __devinit ab8500_charger_probe(struct 
platform_device *pdev)
ARRAY_SIZE(ab8500_charger_voltage_map) - 1];
di-ac_chg.max_out_curr = ab8500_charger_current_map[
ARRAY_SIZE(ab8500_charger_current_map) - 1];
+   di-ac_chg.wdt_refresh = CHG_WD_INTERVAL;
di-ac_chg.enabled = di-pdata-ac_enabled;
+   di-ac_chg.external = false;
 
/* USB supply */
/* power_supply base class */
@@ -2964,7 +2968,9 @@ static int __devinit ab8500_charger_probe(struct 
platform_device *pdev)
ARRAY_SIZE(ab8500_charger_voltage_map) - 1];
di-usb_chg.max_out_curr = ab8500_charger_current_map[
ARRAY_SIZE(ab8500_charger_current_map) - 1];
+   di-usb_chg.wdt_refresh = CHG_WD_INTERVAL;
di-usb_chg.enabled = di-pdata-usb_enabled;
+   di-usb_chg.external = false;
 
/* Create a work queue for the charger */
di-charger_wq =
diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c
index ca87cb2..d3efc2a 100644
--- a/drivers/power/abx500_chargalg.c
+++ b/drivers/power/abx500_chargalg.c
@@ -453,8 +453,18 @@ static int abx500_chargalg_kick_watchdog(struct 
abx500_chargalg *di)
 {
/* Check if charger exists and kick watchdog if charging */
if (di-ac_chg  di-ac_chg-ops.kick_wd 
-   di-chg_info.online_chg  AC_CHG)
+   di-chg_info.online_chg  AC_CHG) {
+   /*
+* If AB charger watchdog expired, pm2xxx charging
+* gets disabled. To be safe, kick both AB charger watchdog
+* and pm2xxx watchdog.
+*/
+   if (di-ac_chg-external 
+   di-usb_chg  di-usb_chg-ops.kick_wd)
+   di-usb_chg-ops.kick_wd(di-usb_chg);
+
return di-ac_chg-ops.kick_wd(di-ac_chg);
+   }
else if (di-usb_chg  di-usb_chg-ops.kick_wd 
di-chg_info.online_chg  USB_CHG)
return di-usb_chg-ops.kick_wd(di-usb_chg);
@@ -1591,6 +1601,8 @@ static void abx500_chargalg_periodic_work(struct 
work_struct *work)
 static void abx500_chargalg_wd_work(struct work_struct *work)
 {
int ret;
+   int refresh_time;
+
struct abx500_chargalg *di = container_of(work,
struct abx500_chargalg, chargalg_wd_work.work);
 
@@ -1600,8 +1612,15 @@ static void abx500_chargalg_wd_work(struct work_struct 
*work)
if (ret  0)
dev_err(di-dev, failed to kick watchdog\n);
 
+   if (di-chg_info.online_chg  AC_CHG)
+   refresh_time = di-ac_chg-wdt_refresh;
+   else if (di-chg_info.online_chg  USB_CHG)
+   refresh_time = di-usb_chg-wdt_refresh;
+   else
+   refresh_time = CHG_WD_INTERVAL;
+
queue_delayed_work(di-chargalg_wq,
-   di-chargalg_wd_work, CHG_WD_INTERVAL);
+   di-chargalg_wd_work, refresh_time);
 }
 
 /**
diff --git a/include/linux/mfd/abx500/ux500_chargalg.h 
b/include/linux/mfd/abx500/ux500_chargalg.h
index 5b77a61..d43ac0f 100644
--- a/include/linux/mfd/abx500/ux500_chargalg.h
+++ b/include/linux/mfd/abx500/ux500_chargalg.h
@@ -28,13 +28,16 @@ struct ux500_charger_ops {
  * @max_out_volt   maximum output charger voltage in mV
  * @max_out_curr   maximum output charger current in mA
  * @enabledindicates if this charger is used or not
+ * @external   external charger unit (pm2xxx)
  */
 struct ux500_charger {
struct power_supply psy;
struct ux500_charger_ops ops;
int max_out_volt;
int max_out_curr;
+   int

[PATCH 08/57] power: ab8500_fg: flush sync on suspend

2012-09-25 Thread mathieu . poirier
From: Jonas Aaberg jonas.ab...@stericsson.com

Do flush sync on the fg workqueue at suspend instead of
just flushing it.

Signed-off-by: Jonas Aaberg jonas.ab...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Johan BJORNSTEDT johan.bjornst...@stericsson.com
---
 drivers/power/ab8500_fg.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
index 342d118..1e02b00 100644
--- a/drivers/power/ab8500_fg.c
+++ b/drivers/power/ab8500_fg.c
@@ -2437,7 +2437,7 @@ static int ab8500_fg_suspend(struct platform_device *pdev,
 {
struct ab8500_fg *di = platform_get_drvdata(pdev);
 
-   flush_delayed_work(di-fg_periodic_work);
+   flush_delayed_work_sync(di-fg_periodic_work);
 
/*
 * If the FG is enabled we will disable it before going to suspend
-- 
1.7.5.4

--
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/57] power: ab8500_bm: Detect removed charger

2012-09-25 Thread mathieu . poirier
From: Jonas Aaberg jonas.ab...@stericsson.com

Signed-off-by: Jonas Aaberg jonas.ab...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
---
 drivers/power/ab8500_charger.c |  122 +++-
 1 files changed, 121 insertions(+), 1 deletions(-)

diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index a7d0c3a..f7bba07 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -66,6 +66,11 @@
 #define MAIN_CH_NOK0x01
 #define VBUS_DET   0x80
 
+#define MAIN_CH_STATUS2_MAINCHGDROP0x80
+#define MAIN_CH_STATUS2_MAINCHARGERDETDBNC 0x40
+#define USB_CH_VBUSDROP0x40
+#define USB_CH_VBUSDETDBNC 0x01
+
 /* UsbLineStatus register bit masks */
 #define AB8500_USB_LINK_STATUS 0x78
 #define AB8500_STD_HOST_SUSP   0x18
@@ -80,6 +85,8 @@
 /* Step up/down delay in us */
 #define STEP_UDELAY1000
 
+#define CHARGER_STATUS_POLL 10 /* in ms */
+
 /* UsbLineStatus register - usb types */
 enum ab8500_charger_link_status {
USB_STAT_NOT_CONFIGURED,
@@ -201,6 +208,10 @@ struct ab8500_charger_usb_state {
  * @check_usbchgnotok_work:Work for checking USB charger not ok status
  * @kick_wd_work:  Work for kicking the charger watchdog in case
  * of ABB rev 1.* due to the watchog logic bug
+ * @ac_charger_attached_work:  Work for checking if AC charger is still
+ * connected
+ * @usb_charger_attached_work: Work for checking if USB charger is still
+ * connected
  * @ac_work:   Work for checking AC charger connection
  * @detect_usb_type_work:  Work for detecting the USB type connected
  * @usb_link_status_work:  Work for checking the new USB link status
@@ -237,6 +248,8 @@ struct ab8500_charger {
struct delayed_work check_hw_failure_work;
struct delayed_work check_usbchgnotok_work;
struct delayed_work kick_wd_work;
+   struct delayed_work ac_charger_attached_work;
+   struct delayed_work usb_charger_attached_work;
struct work_struct ac_work;
struct work_struct detect_usb_type_work;
struct work_struct usb_link_status_work;
@@ -347,6 +360,15 @@ static void ab8500_charger_set_usb_connected(struct 
ab8500_charger *di,
dev_dbg(di-dev, USB connected:%i\n, connected);
di-usb.charger_connected = connected;
sysfs_notify(di-usb_chg.psy.dev-kobj, NULL, present);
+
+   if (connected) {
+   queue_delayed_work(di-charger_wq,
+  di-usb_charger_attached_work,
+  HZ);
+   } else {
+   cancel_delayed_work_sync
+   (di-usb_charger_attached_work);
+   }
}
 }
 
@@ -1703,6 +1725,81 @@ static void ab8500_charger_ac_work(struct work_struct 
*work)
sysfs_notify(di-ac_chg.psy.dev-kobj, NULL, present);
 }
 
+static void ab8500_charger_usb_attached_work(struct work_struct *work)
+{
+   int i;
+   int ret;
+   u8 statval;
+   struct ab8500_charger *di = container_of(work,
+struct ab8500_charger,
+usb_charger_attached_work.work);
+
+   for (i = 0 ; i  10; i++) {
+   ret = abx500_get_register_interruptible(di-dev,
+   AB8500_CHARGER,
+   AB8500_CH_USBCH_STAT1_REG,
+   statval);
+   if (ret  0) {
+   dev_err(di-dev, ab8500 read failed %d\n,
+   __LINE__);
+   goto reschedule;
+   }
+   if ((statval  (USB_CH_VBUSDROP |
+   USB_CH_VBUSDETDBNC)) !=
+   (USB_CH_VBUSDROP | USB_CH_VBUSDETDBNC))
+   goto reschedule;
+
+   msleep(CHARGER_STATUS_POLL);
+   }
+
+   (void) ab8500_charger_usb_en(di-usb_chg, 0, 0, 0);
+
+   return;
+reschedule:
+   queue_delayed_work(di-charger_wq,
+  di-usb_charger_attached_work,
+  HZ);
+}
+
+static void ab8500_charger_ac_attached_work(struct work_struct *work)
+{
+
+   int i;
+   int ret;
+   u8 statval;
+   struct ab8500_charger *di = container_of(work,
+struct ab8500_charger,
+ac_charger_attached_work.work);
+
+   for (i = 0 ; i  10; i++) {
+   ret = abx500_get_register_interruptible(di-dev,
+   AB8500_CHARGER

[PATCH 14/57] power: Adds support for Car/Travel Adapters

2012-09-25 Thread mathieu . poirier
From: Hakan Berg hakan.b...@stericsson.com

The Travel and Carkit adapter should be handled directly by
the charger driver.

Signed-off-by: Marcus Cooper marcus.xm.coo...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Jonas ABERG jonas.ab...@stericsson.com
---
 drivers/power/ab8500_charger.c   |   94 +-
 include/linux/mfd/abx500/ab8500-bm.h |1 +
 2 files changed, 70 insertions(+), 25 deletions(-)

diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index 06a7c8b..09edd9c 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -105,6 +105,18 @@ enum ab8500_charger_link_status {
USB_STAT_HM_IDGND,
USB_STAT_RESERVED,
USB_STAT_NOT_VALID_LINK,
+   USB_STAT_PHY_EN,
+   USB_STAT_SUP_NO_IDGND_VBUS,
+   USB_STAT_SUP_IDGND_VBUS,
+   USB_STAT_CHARGER_LINE_1,
+   USB_STAT_CARKIT_1,
+   USB_STAT_CARKIT_2,
+   USB_STAT_ACA_DOCK_CHARGER,
+   USB_STAT_SAMSUNG_USB_PHY_DIS,
+   USB_STAT_SAMSUNG_USB_PHY_ENA,
+   USB_STAT_SAMSUNG_UART_PHY_DIS,
+   USB_STAT_SAMSUNG_UART_PHY_ENA,
+   USB_STAT_MOTOROLA_USB_PHY_ENA,
 };
 
 enum ab8500_usb_state {
@@ -577,7 +589,7 @@ static int ab8500_charger_detect_chargers(struct 
ab8500_charger *di)
  * Returns error code in case of failure else 0 on success
  */
 static int ab8500_charger_max_usb_curr(struct ab8500_charger *di,
-   enum ab8500_charger_link_status link_status)
+   enum ab8500_charger_link_status link_status)
 {
int ret = 0;
 
@@ -585,16 +597,20 @@ static int ab8500_charger_max_usb_curr(struct 
ab8500_charger *di,
case USB_STAT_STD_HOST_NC:
case USB_STAT_STD_HOST_C_NS:
case USB_STAT_STD_HOST_C_S:
-   dev_dbg(di-dev, USB Type - Standard host is 
-   detected through USB driver\n);
+   dev_dbg(di-dev, USB Type - Standard host is );
+   dev_dbg(di-dev, detected through USB driver\n);
di-max_usb_in_curr = USB_CH_IP_CUR_LVL_0P09;
break;
case USB_STAT_HOST_CHG_HS_CHIRP:
di-max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5;
+   dev_dbg(di-dev, USB Type - 0x%02x MaxCurr: %d, link_status,
+   di-max_usb_in_curr);
break;
case USB_STAT_HOST_CHG_HS:
case USB_STAT_ACA_RID_C_HS:
di-max_usb_in_curr = USB_CH_IP_CUR_LVL_0P9;
+   dev_dbg(di-dev, USB Type - 0x%02x MaxCurr: %d, link_status,
+   di-max_usb_in_curr);
break;
case USB_STAT_ACA_RID_A:
/*
@@ -602,6 +618,8 @@ static int ab8500_charger_max_usb_curr(struct 
ab8500_charger *di,
 * can consume (300mA). Closest level is 1100mA
 */
di-max_usb_in_curr = USB_CH_IP_CUR_LVL_1P1;
+   dev_dbg(di-dev, USB Type - 0x%02x MaxCurr: %d, link_status,
+   di-max_usb_in_curr);
break;
case USB_STAT_ACA_RID_B:
/*
@@ -609,34 +627,50 @@ static int ab8500_charger_max_usb_curr(struct 
ab8500_charger *di,
 * 100mA for potential accessory). Closest level is 1300mA
 */
di-max_usb_in_curr = USB_CH_IP_CUR_LVL_1P3;
+   dev_dbg(di-dev, USB Type - 0x%02x MaxCurr: %d, link_status,
+   di-max_usb_in_curr);
break;
-   case USB_STAT_DEDICATED_CHG:
case USB_STAT_HOST_CHG_NM:
-   case USB_STAT_ACA_RID_C_HS_CHIRP:
+   case USB_STAT_DEDICATED_CHG:
case USB_STAT_ACA_RID_C_NM:
+   case USB_STAT_ACA_RID_C_HS_CHIRP:
di-max_usb_in_curr = USB_CH_IP_CUR_LVL_1P5;
-   break;
-   case USB_STAT_RESERVED:
-   /*
-* This state is used to indicate that VBUS has dropped below
-* the detection level 4 times in a row. This is due to the
-* charger output current is set to high making the charger
-* voltage collapse. This have to be propagated through to
-* chargalg. This is done using the property
-* POWER_SUPPLY_PROP_CURRENT_AVG = 1
-*/
-   di-flags.vbus_collapse = true;
-   dev_dbg(di-dev, USB Type - USB_STAT_RESERVED 
-   VBUS has collapsed\n);
-   ret = -1;
+   dev_dbg(di-dev, USB Type - 0x%02x MaxCurr: %d, link_status,
+   di-max_usb_in_curr);
break;
case USB_STAT_HM_IDGND:
-   case USB_STAT_NOT_CONFIGURED:
case USB_STAT_NOT_VALID_LINK:
+   case USB_STAT_NOT_CONFIGURED:
dev_err(di-dev, USB Type - Charging not allowed\n);
di-max_usb_in_curr = USB_CH_IP_CUR_LVL_0P05;
ret = -ENXIO

[PATCH 16/57] power: bm remove superfluous BTEMP thermal comp.

2012-09-25 Thread mathieu . poirier
From: Hakan Berg hakan.b...@stericsson.com

BTEMP thermal compensation factor times 10 is applied in two
places, probe and get_property. Removed from probe.

Signed-off-by: Hakan Berg hakan.b...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Karl KOMIEROWSKI karl.komierow...@stericsson.com
---
 drivers/power/ab8500_btemp.c |4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c
index 04f9dec..74cddba 100644
--- a/drivers/power/ab8500_btemp.c
+++ b/drivers/power/ab8500_btemp.c
@@ -1026,8 +1026,8 @@ static int __devinit ab8500_btemp_probe(struct 
platform_device *pdev)
ab8500_btemp_periodic_work);
 
/* Set BTEMP thermal limits. Low and Med are fixed */
-   di-btemp_ranges.btemp_low_limit = BTEMP_THERMAL_LOW_LIMIT * 10;
-   di-btemp_ranges.btemp_med_limit = BTEMP_THERMAL_MED_LIMIT * 10;
+   di-btemp_ranges.btemp_low_limit = BTEMP_THERMAL_LOW_LIMIT;
+   di-btemp_ranges.btemp_med_limit = BTEMP_THERMAL_MED_LIMIT;
 
ret = abx500_get_register_interruptible(di-dev, AB8500_CHARGER,
AB8500_BTEMP_HIGH_TH, val);
-- 
1.7.5.4

--
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 21/57] power: Overflow in current calculation

2012-09-25 Thread mathieu . poirier
From: Paer-Olof Haakansson par-olof.hakans...@stericsson.com

When calculating the average current the nominator will
overflow when the charging current is high.

Signed-off-by: Henrik Sölver henrik.sol...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Par-Olof HAKANSSON par-olof.hakans...@stericsson.com
Reviewed-by: Jonas ABERG jonas.ab...@stericsson.com
---
 drivers/power/ab8500_fg.c |   15 ---
 1 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
index 46010ec..7c42150 100644
--- a/drivers/power/ab8500_fg.c
+++ b/drivers/power/ab8500_fg.c
@@ -805,15 +805,13 @@ static void ab8500_fg_acc_cur_work(struct work_struct 
*work)
 
/*
 * Convert to unit value in mA
-* Full scale input voltage is
-* 66.660mV = LSB = 66.660mV/(4096*res) = 1.627mA
-* Given a 250ms conversion cycle time the LSB corresponds
-* to 112.9 nAh. Convert to current by dividing by the conversion
+* by dividing by the conversion
 * time in hours (= samples / (3600 * 4)h)
-* 112.9nAh assumes 10mOhm, but fg_res is in 0.1mOhm
+* and multiply with 1000
 */
-   di-avg_curr = (val * QLSB_NANO_AMP_HOURS_X10 * 36) /
-   (1000 * di-bat-fg_res * (di-fg_samples / 4));
+
+   di-avg_curr = (di-accu_charge * 36) /
+   ((di-fg_samples / 4) * 10);
 
di-flags.conv_done = true;
 
@@ -821,6 +819,9 @@ static void ab8500_fg_acc_cur_work(struct work_struct *work)
 
queue_work(di-fg_wq, di-fg_work);
 
+   dev_dbg(di-dev,
+   fg_res: %d, fg_samples: %d, gasg: %d, accu_charge: %d\n,
+   di-bat-fg_res, di-fg_samples, val, di-accu_charge);
return;
 exit:
dev_err(di-dev,
-- 
1.7.5.4

--
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 25/57] power: ab8500: adaptation to ab version

2012-09-25 Thread mathieu . poirier
From: Michel JAOUEN michel.jao...@stericsson.com

Add AB9540 and AB8505 support to ab8500_temp
driver.

Signed-off-by: Rajkumar Kasirajan rajkumar.kasira...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Michel JAOUEN michel.jao...@stericsson.com
Reviewed-by: Marcus COOPER marcus.xm.coo...@stericsson.com
Reviewed-by: Jonas ABERG jonas.ab...@stericsson.com
---
 drivers/power/ab8500_btemp.c |   71 ++---
 include/linux/mfd/abx500/ab8500-bm.h |2 +
 2 files changed, 58 insertions(+), 15 deletions(-)

diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c
index 74cddba..506f124 100644
--- a/drivers/power/ab8500_btemp.c
+++ b/drivers/power/ab8500_btemp.c
@@ -37,6 +37,9 @@
 #define BTEMP_BATCTRL_CURR_SRC_7UA 7
 #define BTEMP_BATCTRL_CURR_SRC_20UA20
 
+#define BTEMP_BATCTRL_CURR_SRC_16UA16
+#define BTEMP_BATCTRL_CURR_SRC_18UA18
+
 #define to_ab8500_btemp_device_info(x) container_of((x), \
struct ab8500_btemp, btemp_psy);
 
@@ -212,10 +215,18 @@ static int ab8500_btemp_curr_source_enable(struct 
ab8500_btemp *di,
 
/* Only do this for batteries with internal NTC */
if (di-bat-adc_therm == ABx500_ADC_THERM_BATCTRL  enable) {
-   if (di-curr_source == BTEMP_BATCTRL_CURR_SRC_7UA)
-   curr = BAT_CTRL_7U_ENA;
-   else
-   curr = BAT_CTRL_20U_ENA;
+
+   if (is_ab9540(di-parent) || is_ab8505(di-parent)) {
+   if (di-curr_source == BTEMP_BATCTRL_CURR_SRC_16UA)
+   curr = BAT_CTRL_16U_ENA;
+   else
+   curr = BAT_CTRL_18U_ENA;
+   } else {
+   if (di-curr_source == BTEMP_BATCTRL_CURR_SRC_7UA)
+   curr = BAT_CTRL_7U_ENA;
+   else
+   curr = BAT_CTRL_20U_ENA;
+   }
 
dev_dbg(di-dev, Set BATCTRL %duA\n, di-curr_source);
 
@@ -246,11 +257,22 @@ static int ab8500_btemp_curr_source_enable(struct 
ab8500_btemp *di,
} else if (di-bat-adc_therm == ABx500_ADC_THERM_BATCTRL  !enable) {
dev_dbg(di-dev, Disable BATCTRL curr source\n);
 
-   /* Write 0 to the curr bits */
-   ret = abx500_mask_and_set_register_interruptible(di-dev,
-   AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
-   BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA,
-   ~(BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA));
+   if (is_ab9540(di-parent) || is_ab8505(di-parent)) {
+   /* Write 0 to the curr bits */
+   ret = abx500_mask_and_set_register_interruptible(
+   di-dev,
+   AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
+   BAT_CTRL_16U_ENA | BAT_CTRL_18U_ENA,
+   ~(BAT_CTRL_16U_ENA | BAT_CTRL_18U_ENA));
+   } else {
+   /* Write 0 to the curr bits */
+   ret = abx500_mask_and_set_register_interruptible(
+   di-dev,
+   AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
+   BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA,
+   ~(BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA));
+   }
+
if (ret) {
dev_err(di-dev, %s failed disabling current source\n,
__func__);
@@ -292,11 +314,20 @@ static int ab8500_btemp_curr_source_enable(struct 
ab8500_btemp *di,
 * if we got an error above
 */
 disable_curr_source:
-   /* Write 0 to the curr bits */
-   ret = abx500_mask_and_set_register_interruptible(di-dev,
+   if (is_ab9540(di-parent) || is_ab8505(di-parent)) {
+   /* Write 0 to the curr bits */
+   ret = abx500_mask_and_set_register_interruptible(di-dev,
+   AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
+   BAT_CTRL_16U_ENA | BAT_CTRL_18U_ENA,
+   ~(BAT_CTRL_16U_ENA | BAT_CTRL_18U_ENA));
+   } else {
+   /* Write 0 to the curr bits */
+   ret = abx500_mask_and_set_register_interruptible(di-dev,
AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA,
~(BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA));
+   }
+
if (ret) {
dev_err(di-dev, %s failed disabling current source\n,
__func__);
@@ -510,8 +541,11 @@ static int ab8500_btemp_id(struct ab8500_btemp *di)
 {
int res;
u8 i;
+   if (is_ab9540(di-parent) || is_ab8505(di-parent))
+   di-curr_source

[PATCH 23/57] power: Add plaform data charger configurables

2012-09-25 Thread mathieu . poirier
From: Loic Pallardy loic.palla...@stericsson.com

Allow to indicate wheter AC and USB charge capabilities are
supported from platform data.

Signed-off-by: Loic Pallardy loic.palla...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/58093
Reviewed-by: Marcus COOPER marcus.xm.coo...@stericsson.com
Reviewed-by: Olivier CLERGEAUD olivier.clerge...@stericsson.com
---
 drivers/power/ab8500_charger.c|   36 ++--
 include/linux/mfd/abx500.h|2 +
 include/linux/mfd/abx500/ux500_chargalg.h |2 +
 3 files changed, 27 insertions(+), 13 deletions(-)

diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index cbc9fd7..3100f11 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -2878,8 +2878,11 @@ static int __devexit ab8500_charger_remove(struct 
platform_device *pdev)
destroy_workqueue(di-charger_wq);
 
flush_scheduled_work();
-   power_supply_unregister(di-usb_chg.psy);
-   power_supply_unregister(di-ac_chg.psy);
+   if (di-usb_chg.enabled)
+   power_supply_unregister(di-usb_chg.psy);
+   if (di-ac_chg.enabled)
+   power_supply_unregister(di-ac_chg.psy);
+
platform_set_drvdata(pdev, NULL);
kfree(di);
 
@@ -2942,6 +2945,7 @@ static int __devinit ab8500_charger_probe(struct 
platform_device *pdev)
ARRAY_SIZE(ab8500_charger_voltage_map) - 1];
di-ac_chg.max_out_curr = ab8500_charger_current_map[
ARRAY_SIZE(ab8500_charger_current_map) - 1];
+   di-ac_chg.enabled = di-pdata-ac_enabled;
 
/* USB supply */
/* power_supply base class */
@@ -2960,7 +2964,7 @@ static int __devinit ab8500_charger_probe(struct 
platform_device *pdev)
ARRAY_SIZE(ab8500_charger_voltage_map) - 1];
di-usb_chg.max_out_curr = ab8500_charger_current_map[
ARRAY_SIZE(ab8500_charger_current_map) - 1];
-
+   di-usb_chg.enabled = di-pdata-usb_enabled;
 
/* Create a work queue for the charger */
di-charger_wq =
@@ -3036,17 +3040,21 @@ static int __devinit ab8500_charger_probe(struct 
platform_device *pdev)
}
 
/* Register AC charger class */
-   ret = power_supply_register(di-dev, di-ac_chg.psy);
-   if (ret) {
-   dev_err(di-dev, failed to register AC charger\n);
-   goto free_regulator;
+   if (di-ac_chg.enabled) {
+   ret = power_supply_register(di-dev, di-ac_chg.psy);
+   if (ret) {
+   dev_err(di-dev, failed to register AC charger\n);
+   goto free_regulator;
+   }
}
 
/* Register USB charger class */
-   ret = power_supply_register(di-dev, di-usb_chg.psy);
-   if (ret) {
-   dev_err(di-dev, failed to register USB charger\n);
-   goto free_ac;
+   if (di-usb_chg.enabled) {
+   ret = power_supply_register(di-dev, di-usb_chg.psy);
+   if (ret) {
+   dev_err(di-dev, failed to register USB charger\n);
+   goto free_ac;
+   }
}
 
di-usb_phy = usb_get_phy(USB_PHY_TYPE_USB2);
@@ -3122,9 +3130,11 @@ free_irq:
 put_usb_phy:
usb_put_phy(di-usb_phy);
 free_usb:
-   power_supply_unregister(di-usb_chg.psy);
+   if (di-usb_chg.enabled)
+   power_supply_unregister(di-usb_chg.psy);
 free_ac:
-   power_supply_unregister(di-ac_chg.psy);
+   if (di-ac_chg.enabled)
+   power_supply_unregister(di-ac_chg.psy);
 free_regulator:
regulator_put(di-regu);
 free_charger_wq:
diff --git a/include/linux/mfd/abx500.h b/include/linux/mfd/abx500.h
index 4d44a10..eef1ddc 100644
--- a/include/linux/mfd/abx500.h
+++ b/include/linux/mfd/abx500.h
@@ -398,6 +398,8 @@ struct abx500_charger_platform_data {
char **supplied_to;
size_t num_supplicants;
bool autopower_cfg;
+   bool ac_enabled;
+   bool usb_enabled;
 };
 
 struct abx500_btemp_platform_data {
diff --git a/include/linux/mfd/abx500/ux500_chargalg.h 
b/include/linux/mfd/abx500/ux500_chargalg.h
index 9b07725..5b77a61 100644
--- a/include/linux/mfd/abx500/ux500_chargalg.h
+++ b/include/linux/mfd/abx500/ux500_chargalg.h
@@ -27,12 +27,14 @@ struct ux500_charger_ops {
  * @opsux500 charger operations
  * @max_out_volt   maximum output charger voltage in mV
  * @max_out_curr   maximum output charger current in mA
+ * @enabledindicates if this charger is used or not
  */
 struct ux500_charger {
struct power_supply psy;
struct ux500_charger_ops ops;
int max_out_volt;
int max_out_curr;
+   bool enabled;
 };
 
 #endif
-- 
1.7.5.4

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord

[PATCH 22/57] power: AB workaround for invalid charger

2012-09-25 Thread mathieu . poirier
From: Henrik Sölver henrik.sol...@stericsson.com

AB8500 refuses to start charging when some types of non standard
chargers are connected. This change force the AB to start charging.

Signed-off-by: Henrik Sölver henrik.sol...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Yvan FILLION yvan.fill...@stericsson.com
Reviewed-by: Jonas ABERG jonas.ab...@stericsson.com
---
 drivers/power/ab8500_charger.c |   70 +--
 1 files changed, 66 insertions(+), 4 deletions(-)

diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index 7cd4165..cbc9fd7 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -203,6 +203,7 @@ struct ab8500_charger_usb_state {
  * @old_vbat   Previously measured battery voltage
  * @usb_device_is_unrecognised USB device is unrecognised by the hardware
  * @autopower  Indicate if we should have automatic pwron after pwrloss
+ * @invalid_charger_detect_state   State when forcing AB to use invalid 
charger
  * @parent:Pointer to the struct ab8500
  * @gpadc: Pointer to the struct gpadc
  * @pdata: Pointer to the abx500_charger platform data
@@ -246,6 +247,7 @@ struct ab8500_charger {
int old_vbat;
bool usb_device_is_unrecognised;
bool autopower;
+   int invalid_charger_detect_state;
struct ab8500 *parent;
struct ab8500_gpadc *gpadc;
struct abx500_charger_platform_data *pdata;
@@ -650,7 +652,6 @@ static int ab8500_charger_max_usb_curr(struct 
ab8500_charger *di,
break;
}
case USB_STAT_HM_IDGND:
-   case USB_STAT_NOT_VALID_LINK:
dev_err(di-dev, USB Type - Charging not allowed\n);
di-max_usb_in_curr = USB_CH_IP_CUR_LVL_0P05;
ret = -ENXIO;
@@ -679,6 +680,9 @@ static int ab8500_charger_max_usb_curr(struct 
ab8500_charger *di,
di-max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5;
dev_dbg(di-dev, USB Type - 0x%02x MaxCurr: %d, link_status,
di-max_usb_in_curr);
+   case USB_STAT_NOT_VALID_LINK:
+   dev_err(di-dev, USB Type invalid - try charging anyway\n);
+   di-max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5;
break;
 
default:
@@ -1945,7 +1949,9 @@ static void ab8500_charger_usb_link_attach_work(struct 
work_struct *work)
  */
 static void ab8500_charger_usb_link_status_work(struct work_struct *work)
 {
+   int detected_chargers;
int ret;
+   u8 val;
 
struct ab8500_charger *di = container_of(work,
struct ab8500_charger, usb_link_status_work);
@@ -1955,11 +1961,66 @@ static void ab8500_charger_usb_link_status_work(struct 
work_struct *work)
 * synchronously, we have the check if  is
 * connected by reading the status register
 */
-   ret = ab8500_charger_detect_chargers(di);
-   if (ret  0)
+   detected_chargers = ab8500_charger_detect_chargers(di);
+   if (detected_chargers  0)
return;
 
-   if (!(ret  USB_PW_CONN)) {
+   /*
+* Some chargers that breaks the USB spec is
+* identified as invalid by AB8500 and it refuse
+* to start the charging process. but by jumping
+* thru a few hoops it can be forced to start.
+*/
+   ret = abx500_get_register_interruptible(di-dev, AB8500_USB,
+   AB8500_USB_LINE_STAT_REG, val);
+   if (ret = 0)
+   dev_dbg(di-dev, UsbLineStatus register = 0x%02x\n, val);
+   else
+   dev_dbg(di-dev, Error reading USB link status\n);
+
+   if (detected_chargers  USB_PW_CONN) {
+   if (((val  AB8500_USB_LINK_STATUS)  3) ==
+   USB_STAT_NOT_VALID_LINK 
+   di-invalid_charger_detect_state == 0) {
+   dev_dbg(di-dev,
+Invalid charger detected, state= 0\n);
+   /*Enable charger*/
+   abx500_mask_and_set_register_interruptible(di-dev,
+   AB8500_CHARGER,
+   AB8500_USBCH_CTRL1_REG,
+   0x01, 0x01)
+   /*Enable charger detection*/
+   abx500_mask_and_set_register_interruptible(di-dev,
+   AB8500_USB,
+   AB8500_MCH_IPT_CURLVL_REG,
+   0x01, 0x01);
+   di-invalid_charger_detect_state = 1;
+   /*exit and wait for new link status interrupt.*/
+   return;
+
+   }
+   if (di-invalid_charger_detect_state == 1

[PATCH 20/57] power: Adds support for legacy USB chargers

2012-09-25 Thread mathieu . poirier
From: Marcus Cooper marcus.xm.coo...@stericsson.com

A Legacy USB charger should be handled directly by the charger
driver.

Signed-off-by: Marcus Cooper marcus.xm.coo...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Karl KOMIEROWSKI karl.komierow...@stericsson.com
Reviewed-by: Jonas ABERG jonas.ab...@stericsson.com
---
 drivers/power/ab8500_charger.c |   66 ++-
 1 files changed, 57 insertions(+), 9 deletions(-)

diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index 4155feb..7cd4165 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -85,6 +85,9 @@
 /* Step up/down delay in us */
 #define STEP_UDELAY1000
 
+/* Wait for enumeration before charging in ms */
+#define WAIT_FOR_USB_ENUMERATION   (5 * 1000)
+
 #define CHARGER_STATUS_POLL 10 /* in ms */
 
 /* UsbLineStatus register - usb types */
@@ -198,6 +201,7 @@ struct ab8500_charger_usb_state {
  * charger is enabled
  * @vbat   Battery voltage
  * @old_vbat   Previously measured battery voltage
+ * @usb_device_is_unrecognised USB device is unrecognised by the hardware
  * @autopower  Indicate if we should have automatic pwron after pwrloss
  * @parent:Pointer to the struct ab8500
  * @gpadc: Pointer to the struct gpadc
@@ -216,6 +220,7 @@ struct ab8500_charger_usb_state {
  * @check_usbchgnotok_work:Work for checking USB charger not ok status
  * @kick_wd_work:  Work for kicking the charger watchdog in case
  * of ABB rev 1.* due to the watchog logic bug
+ * @attach_work:   Work for checking the usb enumeration
  * @ac_charger_attached_work:  Work for checking if AC charger is still
  * connected
  * @usb_charger_attached_work: Work for checking if USB charger is still
@@ -239,6 +244,7 @@ struct ab8500_charger {
bool vddadc_en_usb;
int vbat;
int old_vbat;
+   bool usb_device_is_unrecognised;
bool autopower;
struct ab8500 *parent;
struct ab8500_gpadc *gpadc;
@@ -256,6 +262,7 @@ struct ab8500_charger {
struct delayed_work check_hw_failure_work;
struct delayed_work check_usbchgnotok_work;
struct delayed_work kick_wd_work;
+   struct delayed_work attach_work;
struct delayed_work ac_charger_attached_work;
struct delayed_work usb_charger_attached_work;
struct work_struct ac_work;
@@ -588,6 +595,8 @@ static int ab8500_charger_max_usb_curr(struct 
ab8500_charger *di,
 {
int ret = 0;
 
+   di-usb_device_is_unrecognised = false;
+
switch (link_status) {
case USB_STAT_STD_HOST_NC:
case USB_STAT_STD_HOST_C_NS:
@@ -633,9 +642,15 @@ static int ab8500_charger_max_usb_curr(struct 
ab8500_charger *di,
dev_dbg(di-dev, USB Type - 0x%02x MaxCurr: %d, link_status,
di-max_usb_in_curr);
break;
+   case USB_STAT_NOT_CONFIGURED:
+   if (di-vbus_detected) {
+   di-usb_device_is_unrecognised = true;
+   dev_dbg(di-dev, USB Type - Legacy charger.\n);
+   di-max_usb_in_curr = USB_CH_IP_CUR_LVL_1P5;
+   break;
+   }
case USB_STAT_HM_IDGND:
case USB_STAT_NOT_VALID_LINK:
-   case USB_STAT_NOT_CONFIGURED:
dev_err(di-dev, USB Type - Charging not allowed\n);
di-max_usb_in_curr = USB_CH_IP_CUR_LVL_0P05;
ret = -ENXIO;
@@ -1899,6 +1914,30 @@ static void ab8500_charger_detect_usb_type_work(struct 
work_struct *work)
 }
 
 /**
+ * ab8500_charger_usb_link_attach_work() - delayd work to detect USB type
+ * @work:  pointer to the work_struct structure
+ *
+ * Detect the type of USB plugged
+ */
+static void ab8500_charger_usb_link_attach_work(struct work_struct *work)
+{
+   int ret;
+
+   struct ab8500_charger *di = container_of(work,
+   struct ab8500_charger, attach_work.work);
+
+   /* Update maximum input current if USB enumeration is not detected */
+   if (!di-usb.charger_online) {
+   ret = ab8500_charger_set_vbus_in_curr(di, di-max_usb_in_curr);
+   if (ret)
+   return;
+   }
+
+   ab8500_charger_set_usb_connected(di, true);
+   ab8500_power_supply_changed(di, di-usb_chg.psy);
+}
+
+/**
  * ab8500_charger_usb_link_status_work() - work to detect USB type
  * @work:  pointer to the work_struct structure
  *
@@ -1928,14 +1967,20 @@ static void ab8500_charger_usb_link_status_work(struct 
work_struct *work)
di-vbus_detected = 1;
ret = ab8500_charger_read_usb_type(di);
if (!ret) {
-   /* Update maximum input current */
-   ret

[PATCH 19/57] power: remove unused defines.

2012-09-25 Thread mathieu . poirier
From: Marcus Cooper marcus.xm.coo...@stericsson.com

Cleanup of the ab8500_charger driver.

Signed-off-by: Marcus Cooper marcus.xm.coo...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Karl KOMIEROWSKI karl.komierow...@stericsson.com
---
 drivers/power/ab8500_charger.c |5 -
 1 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index 09edd9c..4155feb 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -112,11 +112,6 @@ enum ab8500_charger_link_status {
USB_STAT_CARKIT_1,
USB_STAT_CARKIT_2,
USB_STAT_ACA_DOCK_CHARGER,
-   USB_STAT_SAMSUNG_USB_PHY_DIS,
-   USB_STAT_SAMSUNG_USB_PHY_ENA,
-   USB_STAT_SAMSUNG_UART_PHY_DIS,
-   USB_STAT_SAMSUNG_UART_PHY_ENA,
-   USB_STAT_MOTOROLA_USB_PHY_ENA,
 };
 
 enum ab8500_usb_state {
-- 
1.7.5.4

--
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 17/57] power: ab8500_bm: Added support for BATT_OVV

2012-09-25 Thread mathieu . poirier
From: Hakan Berg hakan.b...@stericsson.com

Add support for the battery over-voltage situation

Signed-off-by: Hakan Berg hakan.b...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Karl KOMIEROWSKI karl.komierow...@stericsson.com
---
 drivers/power/ab8500_fg.c |   32 
 1 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
index c4d9307..8507254 100644
--- a/drivers/power/ab8500_fg.c
+++ b/drivers/power/ab8500_fg.c
@@ -1842,24 +1842,26 @@ static void ab8500_fg_check_hw_failure_work(struct 
work_struct *work)
 * If we have had a battery over-voltage situation,
 * check ovv-bit to see if it should be reset.
 */
-   if (di-flags.bat_ovv) {
-   ret = abx500_get_register_interruptible(di-dev,
-   AB8500_CHARGER, AB8500_CH_STAT_REG,
-   reg_value);
-   if (ret  0) {
-   dev_err(di-dev, %s ab8500 read failed\n, __func__);
-   return;
-   }
-   if ((reg_value  BATT_OVV) != BATT_OVV) {
-   dev_dbg(di-dev, Battery recovered from OVV\n);
-   di-flags.bat_ovv = false;
+   ret = abx500_get_register_interruptible(di-dev,
+   AB8500_CHARGER, AB8500_CH_STAT_REG,
+   reg_value);
+   if (ret  0) {
+   dev_err(di-dev, %s ab8500 read failed\n, __func__);
+   return;
+   }
+   if ((reg_value  BATT_OVV) == BATT_OVV) {
+   if (!di-flags.bat_ovv) {
+   dev_dbg(di-dev, Battery OVV\n);
+   di-flags.bat_ovv = true;
power_supply_changed(di-fg_psy);
-   return;
}
-
/* Not yet recovered from ovv, reschedule this test */
queue_delayed_work(di-fg_wq, di-fg_check_hw_failure_work,
-  round_jiffies(HZ));
+   HZ);
+   } else {
+   dev_dbg(di-dev, Battery recovered from OVV\n);
+   di-flags.bat_ovv = false;
+   power_supply_changed(di-fg_psy);
}
 }
 
@@ -2039,8 +2041,6 @@ static irqreturn_t ab8500_fg_batt_ovv_handler(int irq, 
void *_di)
struct ab8500_fg *di = _di;
 
dev_dbg(di-dev, Battery OVV\n);
-   di-flags.bat_ovv = true;
-   power_supply_changed(di-fg_psy);
 
/* Schedule a new HW failure check */
queue_delayed_work(di-fg_wq, di-fg_check_hw_failure_work, 0);
-- 
1.7.5.4

--
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 15/57] power: ab8500_fg: Round capacity output

2012-09-25 Thread mathieu . poirier
From: pender01 peter.enderb...@stericsson.com

Round the capacity values for better enduser experience.

Signed-off-by: pender01 peter.enderb...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Jonas ABERG jonas.ab...@stericsson.com
---
 drivers/power/ab8500_fg.c |   28 +++-
 1 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
index 492f6bf..c4d9307 100644
--- a/drivers/power/ab8500_fg.c
+++ b/drivers/power/ab8500_fg.c
@@ -31,6 +31,7 @@
 #include linux/mfd/abx500.h
 #include linux/time.h
 #include linux/completion.h
+#include linux/kernel.h
 
 #define MILLI_TO_MICRO 1000
 #define FG_LSB_IN_MA   1627
@@ -1160,7 +1161,7 @@ static int ab8500_fg_capacity_level(struct ab8500_fg *di)
 {
int ret, percent;
 
-   percent = di-bat_cap.permille / 10;
+   percent = DIV_ROUND_CLOSEST(di-bat_cap.permille, 10);
 
if (percent = di-bat-cap_levels-critical ||
di-flags.low_bat)
@@ -1281,6 +1282,7 @@ static void ab8500_fg_update_cap_scalers(struct ab8500_fg 
*di)
 static void ab8500_fg_check_capacity_limits(struct ab8500_fg *di, bool init)
 {
bool changed = false;
+   int percent = DIV_ROUND_CLOSEST(di-bat_cap.permille, 10);
 
di-bat_cap.level = ab8500_fg_capacity_level(di);
 
@@ -1312,6 +1314,7 @@ static void ab8500_fg_check_capacity_limits(struct 
ab8500_fg *di, bool init)
dev_dbg(di-dev, Battery low, set capacity to 0\n);
di-bat_cap.prev_percent = 0;
di-bat_cap.permille = 0;
+   percent = 0;
di-bat_cap.prev_mah = 0;
di-bat_cap.mah = 0;
changed = true;
@@ -1321,7 +1324,7 @@ static void ab8500_fg_check_capacity_limits(struct 
ab8500_fg *di, bool init)
 * and show 100% during maintenance charging (scaling).
 */
if (di-flags.force_full) {
-   di-bat_cap.prev_percent = di-bat_cap.permille / 10;
+   di-bat_cap.prev_percent = percent;
di-bat_cap.prev_mah = di-bat_cap.mah;
 
changed = true;
@@ -1334,19 +1337,18 @@ static void ab8500_fg_check_capacity_limits(struct 
ab8500_fg *di, bool init)
di-bat_cap.prev_percent;
di-bat_cap.cap_scale.disable_cap_level = 100;
}
-   } else if (di-bat_cap.prev_percent !=
-   (di-bat_cap.permille) / 10) {
+   } else if (di-bat_cap.prev_percent != percent) {
dev_dbg(di-dev,
battery reported full 
but capacity dropping: %d\n,
-   di-bat_cap.permille / 10);
-   di-bat_cap.prev_percent = di-bat_cap.permille / 10;
+   percent);
+   di-bat_cap.prev_percent = percent;
di-bat_cap.prev_mah = di-bat_cap.mah;
 
changed = true;
}
-   } else if (di-bat_cap.prev_percent != di-bat_cap.permille / 10) {
-   if (di-bat_cap.permille / 10 == 0) {
+   } else if (di-bat_cap.prev_percent != percent) {
+   if (percent == 0) {
/*
 * We will not report 0% unless we've got
 * the LOW_BAT IRQ, no matter what the FG
@@ -1356,11 +1358,11 @@ static void ab8500_fg_check_capacity_limits(struct 
ab8500_fg *di, bool init)
di-bat_cap.permille = 1;
di-bat_cap.prev_mah = 1;
di-bat_cap.mah = 1;
+   percent = 1;
 
changed = true;
} else if (!(!di-flags.charging 
-   (di-bat_cap.permille / 10) 
-   di-bat_cap.prev_percent) || init) {
+   percent  di-bat_cap.prev_percent) || init) {
/*
 * We do not allow reported capacity to go up
 * unless we're charging or if we're in init
@@ -1368,9 +1370,9 @@ static void ab8500_fg_check_capacity_limits(struct 
ab8500_fg *di, bool init)
dev_dbg(di-dev,
capacity changed from %d to %d (%d)\n,
di-bat_cap.prev_percent,
-   di-bat_cap.permille / 10,
+   percent,
di-bat_cap.permille);
-   di-bat_cap.prev_percent = di-bat_cap.permille / 10;
+   di-bat_cap.prev_percent = percent;
di-bat_cap.prev_mah = di-bat_cap.mah;
 
changed = true;
@@ -1378,7

[PATCH 13/57] power: ab8500_bm: Ignore false btemp low interrupt

2012-09-25 Thread mathieu . poirier
From: Hakan Berg hakan.b...@stericsson.com

Ignore the low btemp interrupts for ab8500 3.0 and 3.3

Signed-off-by: Hakan Berg hakan.b...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Jonas ABERG jonas.ab...@stericsson.com
---
 drivers/power/ab8500_btemp.c  |   22 +++---
 include/linux/mfd/abx500/ab8500.h |5 +
 2 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c
index 45b10ad..04f9dec 100644
--- a/drivers/power/ab8500_btemp.c
+++ b/drivers/power/ab8500_btemp.c
@@ -622,9 +622,9 @@ static irqreturn_t ab8500_btemp_templow_handler(int irq, 
void *_di)
 {
struct ab8500_btemp *di = _di;
 
-   if (is_ab8500_2p0_or_earlier(di-parent)) {
-   dev_dbg(di-dev, Ignore false btemp low irq
-for ABB cut 1.0, 1.1 and 2.0\n);
+   if (is_ab8500_3p3_or_earlier(di-parent)) {
+   dev_dbg(di-dev, Ignore false btemp low irq);
+   dev_dbg(di-dev,  for ABB cut 1.0, 1.1, 2.0 and 3.3\n);
} else {
dev_crit(di-dev, Battery temperature lower than -10deg c\n);
 
@@ -738,30 +738,30 @@ static int ab8500_btemp_get_temp(struct ab8500_btemp *di)
int temp = 0;
 
/*
-* The BTEMP events are not reliabe on AB8500 cut2.0
+* The BTEMP events are not reliabe on AB8500 cut3.3
 * and prior versions
 */
-   if (is_ab8500_2p0_or_earlier(di-parent)) {
+   if (is_ab8500_3p3_or_earlier(di-parent)) {
temp = di-bat_temp * 10;
} else {
if (di-events.btemp_low) {
if (temp  di-btemp_ranges.btemp_low_limit)
-   temp = di-btemp_ranges.btemp_low_limit;
+   temp = di-btemp_ranges.btemp_low_limit * 10;
else
temp = di-bat_temp * 10;
} else if (di-events.btemp_high) {
if (temp  di-btemp_ranges.btemp_high_limit)
-   temp = di-btemp_ranges.btemp_high_limit;
+   temp = di-btemp_ranges.btemp_high_limit * 10;
else
temp = di-bat_temp * 10;
} else if (di-events.btemp_lowmed) {
if (temp  di-btemp_ranges.btemp_med_limit)
-   temp = di-btemp_ranges.btemp_med_limit;
+   temp = di-btemp_ranges.btemp_med_limit * 10;
else
temp = di-bat_temp * 10;
} else if (di-events.btemp_medhigh) {
if (temp  di-btemp_ranges.btemp_med_limit)
-   temp = di-btemp_ranges.btemp_med_limit;
+   temp = di-btemp_ranges.btemp_med_limit * 10;
else
temp = di-bat_temp * 10;
} else
@@ -1026,8 +1026,8 @@ static int __devinit ab8500_btemp_probe(struct 
platform_device *pdev)
ab8500_btemp_periodic_work);
 
/* Set BTEMP thermal limits. Low and Med are fixed */
-   di-btemp_ranges.btemp_low_limit = BTEMP_THERMAL_LOW_LIMIT;
-   di-btemp_ranges.btemp_med_limit = BTEMP_THERMAL_MED_LIMIT;
+   di-btemp_ranges.btemp_low_limit = BTEMP_THERMAL_LOW_LIMIT * 10;
+   di-btemp_ranges.btemp_med_limit = BTEMP_THERMAL_MED_LIMIT * 10;
 
ret = abx500_get_register_interruptible(di-dev, AB8500_CHARGER,
AB8500_BTEMP_HIGH_TH, val);
diff --git a/include/linux/mfd/abx500/ab8500.h 
b/include/linux/mfd/abx500/ab8500.h
index db8a1e3..087b445 100644
--- a/include/linux/mfd/abx500/ab8500.h
+++ b/include/linux/mfd/abx500/ab8500.h
@@ -340,6 +340,11 @@ static inline int is_ab8500_2p0_or_earlier(struct ab8500 
*ab)
return (is_ab8500(ab)  (ab-chip_id = AB8500_CUT2P0));
 }
 
+static inline int is_ab8500_3p3_or_earlier(struct ab8500 *ab)
+{
+   return (is_ab8500(ab)  (ab-chip_id = AB8500_CUT3P3));
+}
+
 /* exclude also ab8505, ab9540... */
 static inline int is_ab8500_2p0(struct ab8500 *ab)
 {
-- 
1.7.5.4

--
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 12/57] power: ab8500_fg: balance IRQ enable

2012-09-25 Thread mathieu . poirier
From: Rickard Andersson rickard.anders...@stericsson.com

In case of time out error IRQ needs to be disabled
otherwise we will get unbalanced enable/disable pairs.

Signed-off-by: Rickard Andersson rickard.anders...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Jonas ABERG jonas.ab...@stericsson.com
---
 drivers/power/ab8500_fg.c |1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
index 7af616c..492f6bf 100644
--- a/drivers/power/ab8500_fg.c
+++ b/drivers/power/ab8500_fg.c
@@ -746,6 +746,7 @@ int ab8500_fg_inst_curr_blocking(struct ab8500_fg *di)
dev_dbg(di-dev, %s instant current: %d, __func__, res);
return res;
 fail:
+   disable_irq(di-irq);
mutex_unlock(di-cc_lock);
return ret;
 }
-- 
1.7.5.4

--
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 11/57] power: Recharge condition not optimal for battery

2012-09-25 Thread mathieu . poirier
From: Marcus Cooper marcus.xm.coo...@stericsson.com

Today the battery recharge is determined with a voltage threshold. This
voltage threshold is only valid when the battery is relaxed. In charging
algorithm the voltage read is the loaded battery voltage and no
compensation is done to get the relaxed voltage. When maintenance
charging is not selected, this makes the recharging condition to almost
immediately activate when there is a discharge present on the battery.

Depending on which vendor the battery comes from this behavior can wear
out the battery much faster than normal.

The fuelgauge driver is responsible to monitor the actual battery
capacity and is able to estimate the remaining capacity. It is better to
use the remaining capacity as a limit to determine when battery should
be recharged.

Signed-off-by: Marcus Cooper marcus.xm.coo...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Hakan BERG hakan.b...@stericsson.com
Reviewed-by: Jonas ABERG jonas.ab...@stericsson.com
---
 drivers/power/ab8500_fg.c   |  157 +++
 drivers/power/abx500_chargalg.c |   59 +++
 include/linux/mfd/abx500.h  |6 +-
 3 files changed, 191 insertions(+), 31 deletions(-)

diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
index 0db17c7..7af616c 100644
--- a/drivers/power/ab8500_fg.c
+++ b/drivers/power/ab8500_fg.c
@@ -112,6 +112,13 @@ struct ab8500_fg_avg_cap {
int sum;
 };
 
+struct ab8500_fg_cap_scaling {
+   bool enable;
+   int cap_to_scale[2];
+   int disable_cap_level;
+   int scaled_cap;
+};
+
 struct ab8500_fg_battery_capacity {
int max_mah_design;
int max_mah;
@@ -122,6 +129,7 @@ struct ab8500_fg_battery_capacity {
int prev_percent;
int prev_level;
int user_mah;
+   struct ab8500_fg_cap_scaling cap_scale;
 };
 
 struct ab8500_fg_flags {
@@ -928,10 +936,11 @@ static int ab8500_fg_battery_resistance(struct ab8500_fg 
*di)
resist = tbl[tbl_size - 1].resist;
}
 
-   dev_dbg(di-dev, %s Temp: %d battery internal resistance: %d
-fg resistance %d, total: %d (mOhm)\n,
-   __func__, di-bat_temp, resist, di-bat-fg_res / 10,
-   (di-bat-fg_res / 10) + resist);
+   dev_dbg(di-dev, %s Temp: %d battery internal resistance: %d,
+   __func__, di-bat_temp, resist);
+   dev_dbg(di-dev,  fg resistance %d, total: %d (mOhm)\n,
+   di-bat-fg_res / 10,
+   (di-bat-fg_res / 10) + resist);
 
/* fg_res variable is in 0.1mOhm */
resist += di-bat-fg_res / 10;
@@ -1168,6 +1177,99 @@ static int ab8500_fg_capacity_level(struct ab8500_fg *di)
 }
 
 /**
+ * ab8500_fg_calculate_scaled_capacity() - Capacity scaling
+ * @di:pointer to the ab8500_fg structure
+ *
+ * Calculates the capacity to be shown to upper layers. Scales the capacity
+ * to have 100% as a reference from the actual capacity upon removal of charger
+ * when charging is in maintenance mode.
+ */
+static int ab8500_fg_calculate_scaled_capacity(struct ab8500_fg *di)
+{
+   struct ab8500_fg_cap_scaling *cs = di-bat_cap.cap_scale;
+   int capacity = di-bat_cap.prev_percent;
+
+   if (!cs-enable)
+   return capacity;
+
+   /*
+* As long as we are in fully charge mode scale the capacity
+* to show 100%.
+*/
+   if (di-flags.fully_charged) {
+   cs-cap_to_scale[0] = 100;
+   cs-cap_to_scale[1] =
+   max(capacity, di-bat-fg_params-maint_thres);
+   dev_dbg(di-dev, Scale cap with %d/%d\n,
+cs-cap_to_scale[0], cs-cap_to_scale[1]);
+   }
+
+   /* Calculates the scaled capacity. */
+   if ((cs-cap_to_scale[0] != cs-cap_to_scale[1])
+(cs-cap_to_scale[1]  0))
+   capacity = min(100,
+DIV_ROUND_CLOSEST(di-bat_cap.prev_percent *
+cs-cap_to_scale[0],
+cs-cap_to_scale[1]));
+
+   if (di-flags.charging) {
+   if (capacity  cs-disable_cap_level) {
+   cs-disable_cap_level = capacity;
+   dev_dbg(di-dev, Cap to stop scale lowered %d%%\n,
+   cs-disable_cap_level);
+   } else if (!di-flags.fully_charged) {
+   if (di-bat_cap.prev_percent =
+   cs-disable_cap_level) {
+   dev_dbg(di-dev, Disabling scaled capacity\n);
+   cs-enable = false;
+   capacity = di-bat_cap.prev_percent;
+   } else {
+   dev_dbg(di-dev

[PATCH 10/57] power: ab8500_charger: Handle gpadc errors

2012-09-25 Thread mathieu . poirier
From: Jonas Aaberg jonas.ab...@stericsson.com

Gracefully handle gpadc conversion errors.

Signed-off-by: Jonas Aaberg jonas.ab...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Johan BJORNSTEDT johan.bjornst...@stericsson.com
---
 drivers/power/ab8500_charger.c |   22 ++
 1 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index f7bba07..06a7c8b 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -157,6 +157,7 @@ struct ab8500_charger_info {
int charger_voltage;
int cv_active;
bool wd_expired;
+   int charger_current;
 };
 
 struct ab8500_charger_event_flags {
@@ -2341,6 +2342,7 @@ static int ab8500_charger_ac_get_property(struct 
power_supply *psy,
union power_supply_propval *val)
 {
struct ab8500_charger *di;
+   int ret;
 
di = to_ab8500_charger_ac_device_info(psy_to_ux500_charger(psy));
 
@@ -2362,7 +2364,10 @@ static int ab8500_charger_ac_get_property(struct 
power_supply *psy,
val-intval = di-ac.charger_connected;
break;
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
-   di-ac.charger_voltage = ab8500_charger_get_ac_voltage(di);
+   ret = ab8500_charger_get_ac_voltage(di);
+   if (ret = 0)
+   di-ac.charger_voltage = ret;
+   /* On error, use previous value */
val-intval = di-ac.charger_voltage * 1000;
break;
case POWER_SUPPLY_PROP_VOLTAGE_AVG:
@@ -2374,7 +2379,10 @@ static int ab8500_charger_ac_get_property(struct 
power_supply *psy,
val-intval = di-ac.cv_active;
break;
case POWER_SUPPLY_PROP_CURRENT_NOW:
-   val-intval = ab8500_charger_get_ac_current(di) * 1000;
+   ret = ab8500_charger_get_ac_current(di);
+   if (ret = 0)
+   di-ac.charger_current = ret;
+   val-intval = di-ac.charger_current * 1000;
break;
default:
return -EINVAL;
@@ -2401,6 +2409,7 @@ static int ab8500_charger_usb_get_property(struct 
power_supply *psy,
union power_supply_propval *val)
 {
struct ab8500_charger *di;
+   int ret;
 
di = to_ab8500_charger_usb_device_info(psy_to_ux500_charger(psy));
 
@@ -2424,7 +2433,9 @@ static int ab8500_charger_usb_get_property(struct 
power_supply *psy,
val-intval = di-usb.charger_connected;
break;
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
-   di-usb.charger_voltage = ab8500_charger_get_vbus_voltage(di);
+   ret = ab8500_charger_get_vbus_voltage(di);
+   if (ret = 0)
+   di-usb.charger_voltage = ret;
val-intval = di-usb.charger_voltage * 1000;
break;
case POWER_SUPPLY_PROP_VOLTAGE_AVG:
@@ -2436,7 +2447,10 @@ static int ab8500_charger_usb_get_property(struct 
power_supply *psy,
val-intval = di-usb.cv_active;
break;
case POWER_SUPPLY_PROP_CURRENT_NOW:
-   val-intval = ab8500_charger_get_usb_current(di) * 1000;
+   ret = ab8500_charger_get_usb_current(di);
+   if (ret = 0)
+   di-usb.charger_current = ret;
+   val-intval = di-usb.charger_current * 1000;
break;
case POWER_SUPPLY_PROP_CURRENT_AVG:
/*
-- 
1.7.5.4

--
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/57] power: ab8500_bm: Skip first CCEOC irq for instant current

2012-09-25 Thread mathieu . poirier
From: Johan Bjornstedt johan.bjornst...@stericsson.com

When enabling the CCEOC irq we might get false interrupt
from ab8500-driver due to the latched value will be saved
and interpreted as an IRQ when enabled

Signed-off-by: Johan Bjornstedt johan.bjornst...@stericsson.com
Signed-off-by: Henrik Solver henrik.sol...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Karl KOMIEROWSKI karl.komierow...@stericsson.com
---
 drivers/power/ab8500_btemp.c |   11 ++
 drivers/power/ab8500_fg.c|   63 +
 include/linux/mfd/abx500/ab8500-bm.h |6 +++
 3 files changed, 65 insertions(+), 15 deletions(-)

diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c
index 41a8ce4..45b10ad 100644
--- a/drivers/power/ab8500_btemp.c
+++ b/drivers/power/ab8500_btemp.c
@@ -374,13 +374,10 @@ static int ab8500_btemp_get_batctrl_res(struct 
ab8500_btemp *di)
return ret;
}
 
-   /*
-* Since there is no interrupt when current measurement is done,
-* loop for over 250ms (250ms is one sample conversion time
-* with 32.768 Khz RTC clock). Note that a stop time must be set
-* since the ab8500_btemp_read_batctrl_voltage call can block and
-* take an unknown amount of time to complete.
-*/
+   do {
+   msleep(20);
+   } while (!ab8500_fg_inst_curr_started(di-fg));
+
i = 0;
 
do {
diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
index c098ddd..342d118 100644
--- a/drivers/power/ab8500_fg.c
+++ b/drivers/power/ab8500_fg.c
@@ -159,6 +159,7 @@ struct inst_curr_result_list {
  * @recovery_cnt:  Counter for recovery mode
  * @high_curr_cnt: Counter for high current mode
  * @init_cnt:  Counter for init mode
+ * @nbr_cceoc_irq_cnt  Counter for number of CCEOC irqs received since enabled
  * @recovery_needed:   Indicate if recovery is needed
  * @high_curr_mode:Indicate if we're in high current mode
  * @init_capacity: Indicate if initial capacity measuring should be done
@@ -166,6 +167,7 @@ struct inst_curr_result_list {
  * @calib_stateState during offset calibration
  * @discharge_state:   Current discharge state
  * @charge_state:  Current charge state
+ * @ab8500_fg_started  Completion struct used for the instant current start
  * @ab8500_fg_complete Completion struct used for the instant current reading
  * @flags: Structure for information about events triggered
  * @bat_cap:   Structure for battery capacity specific parameters
@@ -199,6 +201,7 @@ struct ab8500_fg {
int recovery_cnt;
int high_curr_cnt;
int init_cnt;
+   int nbr_cceoc_irq_cnt;
bool recovery_needed;
bool high_curr_mode;
bool init_capacity;
@@ -206,6 +209,7 @@ struct ab8500_fg {
enum ab8500_fg_calibration_state calib_state;
enum ab8500_fg_discharge_state discharge_state;
enum ab8500_fg_charge_state charge_state;
+   struct completion ab8500_fg_started;
struct completion ab8500_fg_complete;
struct ab8500_fg_flags flags;
struct ab8500_fg_battery_capacity bat_cap;
@@ -525,13 +529,14 @@ cc_err:
  * Note: This is part one and has to be called before
  * ab8500_fg_inst_curr_finalize()
  */
- int ab8500_fg_inst_curr_start(struct ab8500_fg *di)
+int ab8500_fg_inst_curr_start(struct ab8500_fg *di)
 {
u8 reg_val;
int ret;
 
mutex_lock(di-cc_lock);
 
+   di-nbr_cceoc_irq_cnt = 0;
ret = abx500_get_register_interruptible(di-dev, AB8500_RTC,
AB8500_RTC_CC_CONF_REG, reg_val);
if (ret  0)
@@ -559,6 +564,7 @@ cc_err:
}
 
/* Return and WFI */
+   INIT_COMPLETION(di-ab8500_fg_started);
INIT_COMPLETION(di-ab8500_fg_complete);
enable_irq(di-irq);
 
@@ -570,6 +576,17 @@ fail:
 }
 
 /**
+ * ab8500_fg_inst_curr_started() - check if fg conversion has started
+ * @di: pointer to the ab8500_fg structure
+ *
+ * Returns 1 if conversion started, 0 if still waiting
+ */
+int ab8500_fg_inst_curr_started(struct ab8500_fg *di)
+{
+   return completion_done(di-ab8500_fg_started);
+}
+
+/**
  * ab8500_fg_inst_curr_done() - check if fg conversion is done
  * @di: pointer to the ab8500_fg structure
  *
@@ -597,13 +614,15 @@ int ab8500_fg_inst_curr_finalize(struct ab8500_fg *di, 
int *res)
int timeout;
 
if (!completion_done(di-ab8500_fg_complete)) {
-   timeout = wait_for_completion_timeout(di-ab8500_fg_complete,
+   timeout = wait_for_completion_timeout(
+   di-ab8500_fg_complete,
INS_CURR_TIMEOUT);
dev_dbg(di-dev, Finalize time: %d ms\n,
((INS_CURR_TIMEOUT - timeout) * 1000) / HZ);
if (!timeout) {
ret = -ETIME

[PATCH 00/57] power: Upgrade to ux500 battery management driver

2012-09-25 Thread mathieu . poirier
From: Mathieu J. Poirier mathieu.poir...@linaro.org

This patch set upgrades the current ux500 battery management driver
to the latest HW and functionality.

Pull request for convenience:

The following changes since commit 56d27adcb536b7430d5f8a6240df8ad261eb00bd:

  Merge git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile 
(2012-09-24 16:17:17 -0700)

are available in the git repository at:

  git://git.linaro.org/people/mpoirier/linux.git ux500-battery-management

Daniel WILLERUD (1):
  power: Add sysfs interfaces for capacity

Hakan Berg (10):
  power: ab8500_bm: Ignore false btemp low interrupt
  power: Adds support for Car/Travel Adapters
  power: bm remove superfluous BTEMP thermal comp.
  power: ab8500_bm: Added support for BATT_OVV
  power: ab8500_fg: Adjust for RF bursts voltage drops.
  power: ab8500_btemp: Filter btemp readings
  power: charging: Allow capacity to raise from 1%
  power: charging: Add AB8505_USB_LINK_STATUS
  power: ab8500-chargalg: update battery health on safety timer exp
  power: abx500_chargalg: Use hrtimer

Henrik Sölver (1):
  power: AB workaround for invalid charger

Johan Bjornstedt (2):
  power: ab8500_bm: Charger current step-up/down
  power: ab8500_bm: Skip first CCEOC irq for instant current

Jonas Aaberg (7):
  power: ab8500_btemp: Detect battery type in workqueue
  power: ab8500_bm: Detect removed charger
  power: ab8500_fg: flush sync on suspend
  power: ab8500_fg: usleep_range instead of short msleep
  power: ab8500_charger: Handle gpadc errors
  power: ab8500: Flush  sync all works
  power: ab8500_charger: Do not touch VBUSOVV bits

Kalle Komierowski (2):
  power: ab8500_bm: Don't clear the CCMuxOffset bit
  power: ab8500_bm: Quick re-attach charging behaviour

Loic Pallardy (3):
  power: Add plaform data charger configurables
  power: charge: update watchdog for pm2xxx support
  power: chargealg: Realign with upstream version

Marcus Cooper (8):
  power: Recharge condition not optimal for battery
  power: remove unused defines.
  power: Adds support for legacy USB chargers
  power: ab8500: ADC for battery thermistor
  power: ab8500: remove unecesary define flag
  power: ab8500_charger: Use USBLink1Status Register
  power: ab8500_charger: Add UsbLineCtrl2 reference
  power: abx500_chargalg: Fix quick re-attach charger issue.

Martin Bergstrom (2):
  power: ab8500_fg: Report unscaled capacity
  power: ab8500_charger: Limit USB charger current

Martin Bergström (1):
  power: ab8500_fg: Goto INIT_RECOVERY when charger removed

Martin Sjoblom (1):
  power: ab8500_charger: Prevent auto drop of VBUS

Mathieu J. Poirier (4):
  power: Harmonising platform data declaration/handling
  power: Cancelling status charging notification.
  power: ab8500: Re-alignment with internal developement.
  power: ab8500_fg: Moving structure definitions to header file

Michel JAOUEN (2):
  power: ab8500: adaptation to ab version
  power: sysfs interface update

Nicolas Guion (1):
  power: ab8500 - Accessing Autopower register fails

Paer-Olof Haakansson (3):
  power: ab8500_bm: Rename the power_loss function
  power: Overflow in current calculation
  power: u8500_charger: Delay for USB enumeration

Philippe Langlais (1):
  power: ab8500: bm: movimg back to ab8500 platform data managment

Rajkumar Kasirajan (1):
  power: ab8500_fg: fix to use correct battery charge full design

Rickard Andersson (1):
  power: ab8500_fg: balance IRQ enable

Rikard Olsson (1):
  power: ab8500_fg: add power cut feature for ab8505

Rupesh Kumar (3):
  power: l9540: Charge only mode fixes
  power: ab8500: defer btemp filtering while init
  power: ab8500 : quick re-attach for ext charger

Yang QU (1):
  power: add backup battery charge voltages.

pender01 (1):
  power: ab8500_fg: Round capacity output

 drivers/mfd/ab8500-core.c |6 +
 drivers/power/Kconfig |7 -
 drivers/power/ab8500_btemp.c  |  165 +++--
 drivers/power/ab8500_charger.c| 1410 +++--
 drivers/power/ab8500_fg.c | 1085 +--
 drivers/power/ab8500_fg.h |  201 
 drivers/power/abx500_chargalg.c   |  333 ++--
 include/linux/mfd/abx500.h|   30 +-
 include/linux/mfd/abx500/ab8500-bm.h  |   47 +-
 include/linux/mfd/abx500/ab8500.h |   22 +-
 include/linux/mfd/abx500/ux500_chargalg.h |8 +
 11 files changed, 2607 insertions(+), 707 deletions(-)
 create mode 100644 drivers/power/ab8500_fg.h
-- 
1.7.5.4

--
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 05/57] power: ab8500_bm: Rename the power_loss function

2012-09-25 Thread mathieu . poirier
From: Paer-Olof Haakansson par-olof.hakans...@stericsson.com

Rename the ab8500_power_loss_handling function
to a more describing name ab8500_enable_disable_sw_fallback

Signed-off-by: Robert Marklund robert.markl...@stericsson.com
Signed-off-by: Paer-Olof Haakansson par-olof.hakans...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Par-Olof HAKANSSON par-olof.hakans...@stericsson.com
Reviewed-by: Karl KOMIEROWSKI karl.komierow...@stericsson.com
---
 drivers/power/ab8500_charger.c |   23 +++
 1 files changed, 11 insertions(+), 12 deletions(-)

diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index 22076f5..a7d0c3a 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -268,20 +268,19 @@ static enum power_supply_property 
ab8500_charger_usb_props[] = {
POWER_SUPPLY_PROP_CURRENT_NOW,
 };
 
-/**
- * ab8500_power_loss_handling - set how we handle powerloss.
- * @di:pointer to the ab8500_charger structure
- *
- * Magic nummbers are from STE HW department.
+/*
+ * Function for enabling and disabling sw fallback mode
+ * should always be disabled when no charger is connected.
  */
-static void ab8500_power_loss_handling(struct ab8500_charger *di)
+static void ab8500_enable_disable_sw_fallback(struct ab8500_charger *di,
+   bool fallback)
 {
u8 reg;
int ret;
 
-   dev_dbg(di-dev, Autopower : %d\n, di-autopower);
+   dev_dbg(di-dev, SW Fallback: %d\n, fallback);
 
-   /* read the autopower register */
+   /* read the register containing fallback bit */
ret = abx500_get_register_interruptible(di-dev, 0x15, 0x00, reg);
if (ret) {
dev_err(di-dev, %d write failed\n, __LINE__);
@@ -295,12 +294,12 @@ static void ab8500_power_loss_handling(struct 
ab8500_charger *di)
return;
}
 
-   if (di-autopower)
+   if (fallback)
reg |= 0x8;
else
reg = ~0x8;
 
-   /* write back the changed value to autopower reg */
+   /* write back the changed fallback bit value to register */
ret = abx500_set_register_interruptible(di-dev, 0x15, 0x00, reg);
if (ret) {
dev_err(di-dev, %d write failed\n, __LINE__);
@@ -330,12 +329,12 @@ static void ab8500_power_supply_changed(struct 
ab8500_charger *di,
!di-ac.charger_connected 
di-autopower) {
di-autopower = false;
-   ab8500_power_loss_handling(di);
+   ab8500_enable_disable_sw_fallback(di, false);
} else if (!di-autopower 
   (di-ac.charger_connected ||
di-usb.charger_connected)) {
di-autopower = true;
-   ab8500_power_loss_handling(di);
+   ab8500_enable_disable_sw_fallback(di, true);
}
}
power_supply_changed(psy);
-- 
1.7.5.4

--
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/57] power: ab8500_btemp: Detect battery type in workqueue

2012-09-25 Thread mathieu . poirier
From: Jonas Aaberg jonas.ab...@stericsson.com

Detect battery type in work queue instead of probe.
This reduces the system boot time with 1.5s

Signed-off-by: Jonas Aaberg jonas.ab...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Karl KOMIEROWSKI karl.komierow...@stericsson.com
---
 drivers/power/ab8500_btemp.c |   15 +++
 1 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c
index bba3cca..94a3ee8 100644
--- a/drivers/power/ab8500_btemp.c
+++ b/drivers/power/ab8500_btemp.c
@@ -83,6 +83,7 @@ struct ab8500_btemp_ranges {
  * @btemp_ranges:  Battery temperature range structure
  * @btemp_wq:  Work queue for measuring the temperature periodically
  * @btemp_periodic_work:   Work for measuring the temperature periodically
+ * @initialized:   True if battery id read.
  */
 struct ab8500_btemp {
struct device *dev;
@@ -100,6 +101,7 @@ struct ab8500_btemp {
struct ab8500_btemp_ranges btemp_ranges;
struct workqueue_struct *btemp_wq;
struct delayed_work btemp_periodic_work;
+   bool initialized;
 };
 
 /* BTEMP power supply properties */
@@ -569,6 +571,13 @@ static void ab8500_btemp_periodic_work(struct work_struct 
*work)
struct ab8500_btemp *di = container_of(work,
struct ab8500_btemp, btemp_periodic_work.work);
 
+   if (!di-initialized) {
+   di-initialized = true;
+   /* Identify the battery */
+   if (ab8500_btemp_id(di)  0)
+   dev_warn(di-dev, failed to identify the battery\n);
+   }
+
di-bat_temp = ab8500_btemp_measure_temp(di);
 
if (di-bat_temp != di-prev_bat_temp) {
@@ -981,6 +990,8 @@ static int __devinit ab8500_btemp_probe(struct 
platform_device *pdev)
di-parent = dev_get_drvdata(pdev-dev.parent);
di-gpadc = ab8500_gpadc_get(ab8500-gpadc.0);
 
+   di-initialized = false;
+
/* get btemp specific platform data */
di-pdata = plat_data-btemp;
if (!di-pdata) {
@@ -1021,10 +1032,6 @@ static int __devinit ab8500_btemp_probe(struct 
platform_device *pdev)
INIT_DELAYED_WORK_DEFERRABLE(di-btemp_periodic_work,
ab8500_btemp_periodic_work);
 
-   /* Identify the battery */
-   if (ab8500_btemp_id(di)  0)
-   dev_warn(di-dev, failed to identify the battery\n);
-
/* Set BTEMP thermal limits. Low and Med are fixed */
di-btemp_ranges.btemp_low_limit = BTEMP_THERMAL_LOW_LIMIT;
di-btemp_ranges.btemp_med_limit = BTEMP_THERMAL_MED_LIMIT;
-- 
1.7.5.4

--
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/57] power: ab8500_bm: Don't clear the CCMuxOffset bit

2012-09-25 Thread mathieu . poirier
From: Kalle Komierowski karl.komierow...@stericsson.com

The CCMuxOffset bit is not kept set, this will force the columb counter
of the AB8500 to use the measure offset calibration.
This should increase the accuracy of the fuel gauge.

Signed-off-by: Kalle Komierowski karl.komierow...@stericsson.com
Signed-off-by: Marcus Cooper marcus.xm.coo...@stericsson.com
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
Reviewed-by: Jonas ABERG jonas.ab...@stericsson.com
---
 drivers/power/ab8500_fg.c |8 
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
index bf02225..af792a8 100644
--- a/drivers/power/ab8500_fg.c
+++ b/drivers/power/ab8500_fg.c
@@ -485,8 +485,9 @@ static int ab8500_fg_coulomb_counter(struct ab8500_fg *di, 
bool enable)
di-flags.fg_enabled = true;
} else {
/* Clear any pending read requests */
-   ret = abx500_set_register_interruptible(di-dev,
-   AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG, 0);
+   ret = abx500_mask_and_set_register_interruptible(di-dev,
+   AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG,
+   (RESET_ACCU | READ_REQ), 0);
if (ret)
goto cc_err;
 
@@ -1404,8 +1405,7 @@ static void ab8500_fg_algorithm_discharging(struct 
ab8500_fg *di)
sleep_time = di-bat-fg_params-init_timer;
 
/* Discard the first [x] seconds */
-   if (di-init_cnt 
-   di-bat-fg_params-init_discard_time) {
+   if (di-init_cnt  di-bat-fg_params-init_discard_time) {
ab8500_fg_calc_cap_discharge_voltage(di, true);
 
ab8500_fg_check_capacity_limits(di, true);
-- 
1.7.5.4

--
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/


Re: [PATCH 00/57] power: Upgrade to ux500 battery management driver

2012-09-27 Thread Mathieu Poirier
On 12-09-26 09:38 PM, Anton Vorontsov wrote:
 On Tue, Sep 25, 2012 at 10:11:57AM -0600, mathieu.poir...@linaro.org wrote:
 From: Mathieu J. Poirier mathieu.poir...@linaro.org

 This patch set upgrades the current ux500 battery management driver
 to the latest HW and functionality.

 Pull request for convenience:

 The following changes since commit 56d27adcb536b7430d5f8a6240df8ad261eb00bd:

   Merge git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile 
 (2012-09-24 16:17:17 -0700)

 are available in the git repository at:

   git://git.linaro.org/people/mpoirier/linux.git ux500-battery-management
 
 I reviewed this series before, and all looked quite good overall. But I
 took another look, especially at the patches w/ empty commit messages, and
 there are some issues.
 
 I tried to write some descriptions myself, but I failed: some changes are
 not obvious to me, so I couldn't write rationale for them. :-/
 
 Thanks,
 Anton.
 

Thank you very much for the review.

I am half way through your comments - some I can handle myself, for
others I needed to go back to the original author for clarification.
Another set will follow shortly.

Your time is much appreciated,
Mathieu.
--
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] drivers/tty: Folding Android's keyreset driver in sysRQ

2012-10-05 Thread mathieu . poirier
From: Mathieu J. Poirier mathieu.poir...@linaro.org

Andrew,

After requesting a number of changes that, to my understanding
have been implemented, I have not been able to get the attention
of the subsystem maintainer on this patch.

If there are still issues, I'm open to making changes but I want
to make sure it doesn't get forgotten.  If there no objections,
would you consider queuint it ?

This patch adds keyreset functionality to the sysrq driver. It
allows certain button/key combinations to be used in order to
trigger device resets.

The first time the key-combo is detected a work function that syncs
the filesystems is scheduled and the kernel rebooted. If all the keys
are released and then pressed again, it calls panic. Reboot on panic
should be set for this to work.

A platform device that specify a reset key-combo should be added to
the board file to trigger the feature.  Alternatively keys can be
passed to the driver via the /sys/module/sysrq interface.

This functionality comes from the keyreset driver submitted by
Arve Hjønnevåg in the Android kernel.

Cc: a...@android.com
Cc: kernel-t...@android.com
Cc: dmitry.torok...@gmail.com
Cc: john.stu...@linaro.org
Cc: a...@lxorguk.ukuu.org.uk
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
---
 drivers/tty/sysrq.c   |  308 +
 include/linux/sysrq.h |8 ++
 2 files changed, 316 insertions(+), 0 deletions(-)

diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index 05728894..c44056f 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -41,14 +41,30 @@
 #include linux/slab.h
 #include linux/input.h
 #include linux/uaccess.h
+#include linux/platform_device.h
+#include linux/syscalls.h
+#include linux/atomic.h
+#include linux/moduleparam.h
+#include linux/mutex.h
 
 #include asm/ptrace.h
 #include asm/irq_regs.h
 
+#define KEY_DOWN_MAX   20 /* how  many is enough ? */
+int keyreset_param[KEY_DOWN_MAX];
+struct mutex sysrq_mutex;
+static struct sysrq_state *sysrq_handle;
+
 /* Whether we react on sysrq keys or just ignore them */
 static int __read_mostly sysrq_enabled = SYSRQ_DEFAULT_ENABLE;
 static bool __read_mostly sysrq_always_enabled;
 
+static struct input_handler sysrq_handler;
+
+/* Keep track of what has been called */
+static atomic_t restart_requested;
+
+
 static bool sysrq_on(void)
 {
return sysrq_enabled || sysrq_always_enabled;
@@ -570,6 +586,15 @@ struct sysrq_state {
struct input_handle handle;
struct work_struct reinject_work;
unsigned long key_down[BITS_TO_LONGS(KEY_CNT)];
+   unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];
+   unsigned long upbit[BITS_TO_LONGS(KEY_CNT)];
+   unsigned long key[BITS_TO_LONGS(KEY_CNT)];
+   int (*reset_fn)(void);
+   int key_down_target;
+   int key_down_ctn;
+   int key_up_ctn;
+   int keyreset_data;
+   int restart_disabled;
unsigned int alt;
unsigned int alt_use;
bool active;
@@ -603,6 +628,101 @@ static void sysrq_reinject_alt_sysrq(struct work_struct 
*work)
}
 }
 
+
+static int sysrq_probe(struct platform_device *pdev)
+{
+   struct keyreset_platform_data *pdata = pdev-dev.platform_data;
+
+   /*
+* No sequence of keys to trigger on,
+* assuming default sysRQ behavior.
+*/
+   if (pdata) {
+   atomic_set(restart_requested, 0);
+   sysrq_handler.private = pdata;
+   } else
+   sysrq_handler.private = NULL;
+
+   /* FETCH DT INFO HERE */
+
+   return 0;
+
+}
+
+static void deferred_restart(struct work_struct *dummy)
+{
+   atomic_inc(restart_requested);
+   sys_sync();
+   atomic_inc(restart_requested);
+   kernel_restart(NULL);
+}
+static DECLARE_WORK(restart_work, deferred_restart);
+
+static int do_keyreset_event(struct sysrq_state *state,
+unsigned int code, int value)
+{
+   int ret;
+   int processed = 0;
+
+   mutex_lock(sysrq_mutex);
+
+   /* Is the code of interest to us */
+   if (!test_bit(code, state-keybit)) {
+   mutex_unlock(sysrq_mutex);
+   return processed;
+   }
+
+   /* No need to take care of key up events */
+   if (!test_bit(code, state-key) == !value) {
+   mutex_unlock(sysrq_mutex);
+   return processed;
+   }
+
+   /* Record new entry */
+   __change_bit(code, state-key);
+
+   processed = 1;
+
+   if (test_bit(code, state-upbit)) {
+   if (value) {
+   state-restart_disabled = 1;
+   state-key_up_ctn++;
+   } else
+   state-key_up_ctn--;
+   } else {
+   if (value)
+   state-key_down_ctn++;
+   else
+   state-key_down_ctn--;
+   }
+
+   if (state-key_down_ctn == 0  state-key_up_ctn == 0)
+   state

Re: [PATCH] drivers/tty: Folding Android's keyreset driver in sysRQ

2012-10-05 Thread Mathieu Poirier
On 12-10-05 12:16 PM, Dmitry Torokhov wrote:
 On Fri, Oct 05, 2012 at 11:59:29AM -0600, mathieu.poir...@linaro.org wrote:
 From: Mathieu J. Poirier mathieu.poir...@linaro.org

 Andrew,

 After requesting a number of changes that, to my understanding
 have been implemented, I have not been able to get the attention
 of the subsystem maintainer on this patch.

 If there are still issues, I'm open to making changes but I want
 to make sure it doesn't get forgotten.  If there no objections,
 would you consider queuint it ?
 
 Mathieu,
 
 I have the same objection as before: using platform device solely for
 the purpose of passing some data from board code to the driver. Surely
 there are other ways of passing this bit of data... What about, for
 example, making it an empty weak symbol so that board code could
 override it with strong one?

Thanks for the comments - I will implement a weak function in the
keyreset driver.

Mathieu.

 
 Thanks.
 

--
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/


Re: [PATCH] drivers/tty: Folding Android's keyreset driver in sysRQ

2012-10-20 Thread Mathieu Poirier
On 12-10-16 09:35 PM, Arve Hjønnevåg wrote:
 On Fri, Oct 5, 2012 at 12:48 PM, Mathieu Poirier
 mathieu.poir...@linaro.org wrote:
 On 12-10-05 12:16 PM, Dmitry Torokhov wrote:
 On Fri, Oct 05, 2012 at 11:59:29AM -0600, mathieu.poir...@linaro.org wrote:
 From: Mathieu J. Poirier mathieu.poir...@linaro.org

 Andrew,

 After requesting a number of changes that, to my understanding
 have been implemented, I have not been able to get the attention
 of the subsystem maintainer on this patch.

 If there are still issues, I'm open to making changes but I want
 to make sure it doesn't get forgotten.  If there no objections,
 would you consider queuint it ?

 Mathieu,

 I have the same objection as before: using platform device solely for
 the purpose of passing some data from board code to the driver. Surely
 there are other ways of passing this bit of data... What about, for
 example, making it an empty weak symbol so that board code could
 override it with strong one?

 Thanks for the comments - I will implement a weak function in the
 keyreset driver.

 
 A weak symbol does not work. A single kernel can support multiple
 devices that have unique reset key combinations.
 

I'm afraid Arve has a point here...  His comment about supporting
multiple combinations got me thinking and forced me to dive back in the
code.

The original keyreset driver can indeed be instantiated multiple times
while the sysrq driver is a one instance model.  In its current
implementation the keyreset extension can only support one reset sequence.

But does a system realistically need to support more than one reset
sequence ?

If so then I can enhance the keyreset extension of the sysrq driver but
that will also mean, as stated by Arve, that we will need to keep the
platform data.  On the flip side it is deemed sufficient to support a
single reset sequence then I'll implement the weak symbol method.

The subject is up for debate, please chime in with your opinion.

Mathieu.
--
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 v4] drivers/tty: Folding Android's keyreset driver in sysRQ

2012-11-11 Thread mathieu . poirier
From: Mathieu J. Poirier mathieu.poir...@linaro.org

This patch adds keyreset functionality to the sysrq driver. It
allows certain button/key combinations to be used in order to
trigger device resets.

The first time the key-combo is detected a work function that syncs
the filesystems is scheduled and the kernel rebooted. If all the keys
are released and then pressed again, it calls panic. Reboot on panic
should be set for this to work.

Redefining the '__weak sysrq_keyreset_get_params' function is required
to trigger the feature.  Alternatively keys can be passed to the
driver via the /sys/module/sysrq interface.

This functionality comes from the keyreset driver submitted by
Arve Hjønnevåg in the Android kernel.

Cc: a...@android.com
Cc: kernel-t...@android.com
Cc: dmitry.torok...@gmail.com
Cc: john.stu...@linaro.org
Cc: a...@lxorguk.ukuu.org.uk
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
---
 drivers/tty/sysrq.c   |  303 +
 include/linux/sysrq.h |2 +
 2 files changed, 305 insertions(+), 0 deletions(-)

diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index 05728894..da4f538 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -41,14 +41,29 @@
 #include linux/slab.h
 #include linux/input.h
 #include linux/uaccess.h
+#include linux/syscalls.h
+#include linux/atomic.h
+#include linux/moduleparam.h
+#include linux/mutex.h
 
 #include asm/ptrace.h
 #include asm/irq_regs.h
 
+#define KEY_RESET_MAX  20 /* how  many is enough ? */
+int keyreset_param[KEY_RESET_MAX];
+struct mutex sysrq_mutex;
+static struct sysrq_state *sysrq_handle;
+
 /* Whether we react on sysrq keys or just ignore them */
 static int __read_mostly sysrq_enabled = SYSRQ_DEFAULT_ENABLE;
 static bool __read_mostly sysrq_always_enabled;
 
+static struct input_handler sysrq_handler;
+
+/* Keep track of what has been called */
+static atomic_t restart_requested;
+
+
 static bool sysrq_on(void)
 {
return sysrq_enabled || sysrq_always_enabled;
@@ -570,6 +585,15 @@ struct sysrq_state {
struct input_handle handle;
struct work_struct reinject_work;
unsigned long key_down[BITS_TO_LONGS(KEY_CNT)];
+   unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];
+   unsigned long upbit[BITS_TO_LONGS(KEY_CNT)];
+   unsigned long key[BITS_TO_LONGS(KEY_CNT)];
+   int (*reset_fn)(void);
+   int key_down_target;
+   int key_down_ctn;
+   int key_up_ctn;
+   int keyreset_data;
+   int restart_disabled;
unsigned int alt;
unsigned int alt_use;
bool active;
@@ -603,6 +627,80 @@ static void sysrq_reinject_alt_sysrq(struct work_struct 
*work)
}
 }
 
+static void deferred_restart(struct work_struct *dummy)
+{
+   atomic_inc(restart_requested);
+   sys_sync();
+   atomic_inc(restart_requested);
+   kernel_restart(NULL);
+}
+static DECLARE_WORK(restart_work, deferred_restart);
+
+static int do_keyreset_event(struct sysrq_state *state,
+unsigned int code, int value)
+{
+   int ret;
+   int processed = 0;
+
+   mutex_lock(sysrq_mutex);
+
+   /* Is the code of interest to us */
+   if (!test_bit(code, state-keybit)) {
+   mutex_unlock(sysrq_mutex);
+   return processed;
+   }
+
+   /* No need to take care of key up events */
+   if (!test_bit(code, state-key) == !value) {
+   mutex_unlock(sysrq_mutex);
+   return processed;
+   }
+
+   /* Record new entry */
+   __change_bit(code, state-key);
+
+   processed = 1;
+
+   if (test_bit(code, state-upbit)) {
+   if (value) {
+   state-restart_disabled = 1;
+   state-key_up_ctn++;
+   } else
+   state-key_up_ctn--;
+   } else {
+   if (value)
+   state-key_down_ctn++;
+   else
+   state-key_down_ctn--;
+   }
+
+   if (state-key_down_ctn == 0  state-key_up_ctn == 0)
+   state-restart_disabled = 0;
+
+   if (value  !state-restart_disabled 
+   state-key_down_ctn == state-key_down_target) {
+   state-restart_disabled = 1;
+   if (atomic_read(restart_requested))
+   panic(keyboard reset failed, %d - panic\n,
+atomic_read(restart_requested));
+   if (state-reset_fn) {
+   ret = state-reset_fn();
+   atomic_set(restart_requested, ret);
+   } else {
+   pr_info(keyboard reset\n);
+   schedule_work(restart_work);
+   atomic_inc(restart_requested);
+   }
+   }
+
+   mutex_unlock(sysrq_mutex);
+
+   /* no need to suppress keyreset characters */
+   state-active = false;
+
+   return processed

Re: Out-of-bound access in sysrq

2013-03-28 Thread Mathieu Poirier
On 13-03-28 04:34 AM, Jiri Slaby wrote:
 Guys,
 
 how is this supposed to work?
 
 #define SYSRQ_KEY_RESET_MAX 20 /* Should be plenty */
 static unsigned short sysrq_reset_seq[SYSRQ_KEY_RESET_MAX];
 ...
 unsigned short platform_sysrq_reset_seq[] __weak = { KEY_RESERVED };
 ...
 static inline void sysrq_register_handler(void)
 {
 ...
 for (i = 0; i  ARRAY_SIZE(sysrq_reset_seq); i++) {
 key = platform_sysrq_reset_seq[i];
 if (key == KEY_RESERVED || key  KEY_MAX)
 ...
 
 
 
 
 i runs from 0 to 19 incl., but platform_sysrq_reset_seq, if not
 overriden, is of size 1, so?
 
 thanks,
 

Unless I'm missing something, 'i' won't go higher than '0' since the
first element of platform_sysrq_reset_seq is set to KEY_RESERVED and in
such case the 'break' is executed.


--
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/


Re: [PATCH v4] drivers/tty: Folding Android's keyreset driver in sysRQ

2013-02-27 Thread Mathieu Poirier
On 13-02-27 09:57 AM, Linus Torvalds wrote:
 On Tue, Feb 26, 2013 at 11:33 PM, Dave Airlie airl...@gmail.com wrote:

 It looks to me like the weak bit isn't working so well

 if (platform_sysrq_reset_seq) {
 for (i = 0; i  ARRAY_SIZE(sysrq_reset_seq); i++) {
 key = platform_sysrq_reset_seq[i];
   6d:   66 8b 8c 00 00 00 00mov0x0(%eax,%eax,1),%cx
   74:   00

 is around where it craps out.
 gcc version 4.7.2 20121109 (Red Hat 4.7.2-8) (GCC)
 Fedora 18 machine.
 
 Hmm. I would love to blame gcc, but no, I think the code is crap.
 
 The whole 'platform_sysrq_reset_seq[]' thing is broken in current git,
 and it apparently only happens to work by mistake for most of us.
 
 Doing a grep for it shows all three uses:
 
git grep platform_sysrq_reset_seq
 
   extern unsigned short platform_sysrq_reset_seq[] __weak;
   if (platform_sysrq_reset_seq) {
 key = platform_sysrq_reset_seq[i];
 
 and the thing is, if it is declared as an array (not a pointer), then
 I think it is perfectly understandable that when then testing the
 *address* of that array, gcc just says you're stupid, you're testing
 something that cannot possibly be NULL, so I'll throw your idiotic
 test away.
 
 And gcc would be completely correct. That test is moronic. You just
 said that platform_sysrq_reset_seq[] was an external array, there is
 no way in hell that is NULL.
 
 Now, if it was a _pointer_, that would be a different thing entirely.
 A pointer can have a NULL value. A named array, not so much.
 
 So I *think* the fix might be something like the attached. Totally
 untested. It may compile, or it may not.
 
 Linus
 

Your fix is compiling, running and yielding the correct results -
apologies about that.

Acked-by: Mathieu Poirier mathieu.poir...@linaro.org
--
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] drivers/tty: Folding Android's keyreset driver in sysRQ

2012-09-16 Thread mathieu . poirier
From: Mathieu J. Poirier mathieu.poir...@linaro.org

This patch adds keyreset functionality to the sysrq driver. It
allows certain button/key combinations to be used in order to
trigger device resets.

The first time the key-combo is detected a work function that syncs
the filesystems is scheduled and the kernel rebooted. If all the keys
are released and then pressed again, it calls panic. Reboot on panic
should be set for this to work.

A platform device that specify a reset key-combo should be added to
the board file to trigger the feature.  Alternatively keys can be
passed to the driver via the /sys/module/sysrq interface.

This functionality comes from the keyreset driver submitted by
Arve Hjønnevåg in the Android kernel.

Cc: a...@android.com
Cc: kernel-t...@android.com
Cc: dmitry.torok...@gmail.com
Cc: john.stu...@linaro.org
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
---
 drivers/tty/sysrq.c   |  302 +
 include/linux/sysrq.h |8 ++
 2 files changed, 310 insertions(+), 0 deletions(-)

diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index 05728894..41122a7 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -41,14 +41,30 @@
 #include linux/slab.h
 #include linux/input.h
 #include linux/uaccess.h
+#include linux/platform_device.h
+#include linux/syscalls.h
+#include linux/atomic.h
+#include linux/moduleparam.h
 
 #include asm/ptrace.h
 #include asm/irq_regs.h
+#include asm/mutex.h
+
+#define KEY_DOWN_MAX   20 /* how  many is enough ? */
+int keyreset_param[KEY_DOWN_MAX];
+struct mutex sysrq_mutex;
+static struct sysrq_state *sysrq_handle;
 
 /* Whether we react on sysrq keys or just ignore them */
 static int __read_mostly sysrq_enabled = SYSRQ_DEFAULT_ENABLE;
 static bool __read_mostly sysrq_always_enabled;
 
+static struct input_handler sysrq_handler;
+
+/* Keep track of what has been called */
+static atomic_t restart_requested;
+
+
 static bool sysrq_on(void)
 {
return sysrq_enabled || sysrq_always_enabled;
@@ -570,6 +586,15 @@ struct sysrq_state {
struct input_handle handle;
struct work_struct reinject_work;
unsigned long key_down[BITS_TO_LONGS(KEY_CNT)];
+   unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];
+   unsigned long upbit[BITS_TO_LONGS(KEY_CNT)];
+   unsigned long key[BITS_TO_LONGS(KEY_CNT)];
+   int (*reset_fn)(void);
+   int key_down_target;
+   int key_down_ctn;
+   int key_up_ctn;
+   int keyreset_data;
+   int restart_disabled;
unsigned int alt;
unsigned int alt_use;
bool active;
@@ -603,6 +628,101 @@ static void sysrq_reinject_alt_sysrq(struct work_struct 
*work)
}
 }
 
+
+static int sysrq_probe(struct platform_device *pdev)
+{
+   struct keyreset_platform_data *pdata = pdev-dev.platform_data;
+
+   /*
+* No sequence of keys to trigger on,
+* assuming default sysRQ behavior.
+*/
+   if (pdata) {
+   atomic_set(restart_requested, 0);
+   sysrq_handler.private = pdata;
+   } else
+   sysrq_handler.private = NULL;
+
+   /* FETCH DT INFO HERE */
+
+   return 0;
+
+}
+
+static void deferred_restart(struct work_struct *dummy)
+{
+   atomic_inc(restart_requested);
+   sys_sync();
+   atomic_inc(restart_requested);
+   kernel_restart(NULL);
+}
+static DECLARE_WORK(restart_work, deferred_restart);
+
+static int do_keyreset_event(struct sysrq_state *state,
+unsigned int code, int value)
+{
+   int ret;
+   int processed = 0;
+
+   mutex_lock(sysrq_mutex);
+
+   /* Is the code of interest to us */
+   if (!test_bit(code, state-keybit)) {
+   mutex_unlock(sysrq_mutex);
+   return processed;
+   }
+
+   /* No need to take care of key up events */
+   if (!test_bit(code, state-key) == !value) {
+   mutex_unlock(sysrq_mutex);
+   return processed;
+   }
+
+   /* Record new entry */
+   __change_bit(code, state-key);
+
+   processed = 1;
+
+   if (test_bit(code, state-upbit)) {
+   if (value) {
+   state-restart_disabled = 1;
+   state-key_up_ctn++;
+   } else
+   state-key_up_ctn--;
+   } else {
+   if (value)
+   state-key_down_ctn++;
+   else
+   state-key_down_ctn--;
+   }
+
+   if (state-key_down_ctn == 0  state-key_up_ctn == 0)
+   state-restart_disabled = 0;
+
+   if (value  !state-restart_disabled 
+   state-key_down_ctn == state-key_down_target) {
+   state-restart_disabled = 1;
+   if (atomic_read(restart_requested))
+   panic(keyboard reset failed, %d - panic\n,
+atomic_read(restart_requested

[PATCH v2] drivers/tty: Folding Android's keyreset driver in sysRQ

2012-08-30 Thread mathieu . poirier
From: Mathieu J. Poirier mathieu.poir...@linaro.org

This patch adds keyreset functionality to the sysrq driver. It
allows certain button/key combinations to be used in order to
trigger device resets.

The first time the key-combo is detected a work function that syncs
the filesystems is scheduled and the kernel rebooted. If all the keys
are released and then pressed again, it calls panic. Reboot on panic
should be set for this to work.  A platform device that specify a
reset key-combo should be added to the board file to trigger the
feature.

This functionality comes from the keyreset driver submitted by
Arve Hjønnevåg in the Android kernel.

Cc: a...@android.com
Cc: kernel-t...@android.com
Cc: dmitry.torok...@gmail.com
Cc: john.stu...@linaro.org
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
---
 drivers/tty/sysrq.c   |  161 +
 include/linux/sysrq.h |8 +++
 2 files changed, 169 insertions(+), 0 deletions(-)

diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index 05728894..f210853 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -41,6 +41,9 @@
 #include linux/slab.h
 #include linux/input.h
 #include linux/uaccess.h
+#include linux/platform_device.h
+#include linux/syscalls.h
+#include linux/atomic.h
 
 #include asm/ptrace.h
 #include asm/irq_regs.h
@@ -49,6 +52,11 @@
 static int __read_mostly sysrq_enabled = SYSRQ_DEFAULT_ENABLE;
 static bool __read_mostly sysrq_always_enabled;
 
+static struct input_handler sysrq_handler;
+
+/* Keep track of what has been called */
+static atomic_t restart_requested;
+
 static bool sysrq_on(void)
 {
return sysrq_enabled || sysrq_always_enabled;
@@ -570,6 +578,15 @@ struct sysrq_state {
struct input_handle handle;
struct work_struct reinject_work;
unsigned long key_down[BITS_TO_LONGS(KEY_CNT)];
+   unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];
+   unsigned long upbit[BITS_TO_LONGS(KEY_CNT)];
+   unsigned long key[BITS_TO_LONGS(KEY_CNT)];
+   int (*reset_fn)(void);
+   int key_down_target;
+   int key_down_ctn;
+   int key_up_ctn;
+   int keyreset_data;
+   int restart_disabled;
unsigned int alt;
unsigned int alt_use;
bool active;
@@ -603,6 +620,93 @@ static void sysrq_reinject_alt_sysrq(struct work_struct 
*work)
}
 }
 
+
+static int sysrq_probe(struct platform_device *pdev)
+{
+   struct keyreset_platform_data *pdata = pdev-dev.platform_data;
+
+   /*
+* No sequence of keys to trigger on,
+* assuming default sysRQ behavior.
+*/
+   if (pdata) {
+   atomic_set(restart_requested, 0);
+   sysrq_handler.private = pdata;
+   } else
+   sysrq_handler.private = NULL;
+
+   /* FETCH DT INFO HERE */
+
+   return 0;
+
+}
+
+static void deferred_restart(struct work_struct *dummy)
+{
+   atomic_inc(restart_requested);
+   sys_sync();
+   atomic_inc(restart_requested);
+   kernel_restart(NULL);
+}
+static DECLARE_WORK(restart_work, deferred_restart);
+
+static int do_keyreset_event(struct sysrq_state *state,
+unsigned int code, int value)
+{
+   int ret;
+   int processed = 0;
+
+   /* Is the code is of interest to us */
+   if (!test_bit(code, state-keybit))
+   return processed;
+
+   /* No need to take care of key up events */
+   if (!test_bit(code, state-key) == !value)
+   return processed;
+
+   /* Record new entry */
+   __change_bit(code, state-key);
+
+   processed = 1;
+
+   if (test_bit(code, state-upbit)) {
+   if (value) {
+   state-restart_disabled = 1;
+   state-key_up_ctn++;
+   } else
+   state-key_up_ctn--;
+   } else {
+   if (value)
+   state-key_down_ctn++;
+   else
+   state-key_down_ctn--;
+   }
+
+   if (state-key_down_ctn == 0  state-key_up_ctn == 0)
+   state-restart_disabled = 0;
+
+   if (value  !state-restart_disabled 
+   state-key_down_ctn == state-key_down_target) {
+   state-restart_disabled = 1;
+   if (atomic_read(restart_requested))
+   panic(keyboard reset failed, %d - panic\n,
+atomic_read(restart_requested));
+   if (state-reset_fn) {
+   ret = state-reset_fn();
+   atomic_set(restart_requested, ret);
+   } else {
+   pr_info(keyboard reset\n);
+   schedule_work(restart_work);
+   atomic_inc(restart_requested);
+   }
+   }
+
+   /* no need to suppress keyreset characters */
+   state-active = false;
+
+   return processed;
+}
+
 static bool

Re: [PATCH v2] drivers/tty: Folding Android's keyreset driver in sysRQ

2012-08-31 Thread Mathieu Poirier
On 12-08-30 05:01 PM, Dmitry Torokhov wrote:
 Hi Matthieu,
 
 On Thu, Aug 30, 2012 at 04:30:54PM -0600, mathieu.poir...@linaro.org wrote:
 From: Mathieu J. Poirier mathieu.poir...@linaro.org

 This patch adds keyreset functionality to the sysrq driver. It
 allows certain button/key combinations to be used in order to
 trigger device resets.

 The first time the key-combo is detected a work function that syncs
 the filesystems is scheduled and the kernel rebooted. If all the keys
 are released and then pressed again, it calls panic. Reboot on panic
 should be set for this to work.  A platform device that specify a
 reset key-combo should be added to the board file to trigger the
 feature.

 Why do we need to involve a platform device and not use, for example, a module
 parameter, that could be set up from userspace?

The platform device comes from the original design and was included to
minimise the amount of changes in code that make use of the current
keyreset driver.

I am definitely willing to explore the possibility of adding module
parameter to complement the platform data but again, to avoid impacting
board code I'm in favour of keeping the platform data/device - get back
to me if you disagree.

Thinking back on this it may be better to call 'platform_driver_probe'
rather than 'platform_driver_register'.  That way one wouldn't have to
instantiate a platform_device.

 
 Also, why do we need reset_fn() and not simply invoke SysRq-B handler
 that should call ctrl_alt_del() for us?

The reset_fn() gives an implementer the chance of calling some custom
function before the reset sequence is started and in my opinion should
stay.  On the flip side I'm not sure that I understand what you mean by
SysRq-B handler - are you talking about the sysrq_reboot_op ?
Please expand on that ?

Thanks for the review and comments,
Mathieu.

 
 Thanks.
 

--
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/


Re: [PATCH v2] drivers/tty: Folding Android's keyreset driver in sysRQ

2012-08-31 Thread Mathieu Poirier
On 12-08-31 04:02 PM, Alan Cox wrote:
 Why do we need to involve a platform device and not use, for example, a 
 module
 parameter, that could be set up from userspace?

 The platform device comes from the original design and was included to
 minimise the amount of changes in code that make use of the current
 keyreset driver.
 
 The platform device is IMHO the right answer. In this class of devices
 the stuff is compiled in, the userspace is Android, there are no modules
 and there is no reason for it to be configurable.
 
 I am definitely willing to explore the possibility of adding module
 parameter to complement the platform data but again, to avoid impacting
 board code I'm in favour of keeping the platform data/device - get back
 to me if you disagree.

 Thinking back on this it may be better to call 'platform_driver_probe'
 rather than 'platform_driver_register'.  That way one wouldn't have to
 instantiate a platform_device.


 Also, why do we need reset_fn() and not simply invoke SysRq-B handler
 that should call ctrl_alt_del() for us?

 The reset_fn() gives an implementer the chance of calling some custom
 function before the reset sequence is started and in my opinion should

I did not express myself clearly - with reset_fn() a system can do
whatever it wants when a specific series of keys is pressed.

Granted that the next steps are most likely converging toward rebooting
the system - but it may not be right away and depending on the
circumstances a reboot could be avoided altogether.

 
 So why wouldn't that already be using the reset notifiers ?

I am not familiar with the reset notifiers that have been referred to
but a little bit of research indicate that a registering subsystem gets
notified when the event of interest (in this case a reboot) happens.

I understand your proposition here but aren't we loosing flexibility in
what we can achieve when the event has been triggered ?

What do you think of adding a keyreset event that would be fired (and
caught by a registering subsystem) instead of calling reset_fn() ?

Thanks,
Mathieu.

 
 Alan
 

--
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/


Re: [PATCH v2] drivers/tty: Folding Android's keyreset driver in sysRQ

2012-08-31 Thread Mathieu Poirier
On 12-08-31 04:41 PM, Dmitry Torokhov wrote:
 On Fri, Aug 31, 2012 at 11:02:27PM +0100, Alan Cox wrote:
 Why do we need to involve a platform device and not use, for example, a 
 module
 parameter, that could be set up from userspace?

 The platform device comes from the original design and was included to
 minimise the amount of changes in code that make use of the current
 keyreset driver.

 The platform device is IMHO the right answer. In this class of devices
 the stuff is compiled in, the userspace is Android, there are no modules
 and there is no reason for it to be configurable.
 
 It does not matter if it is built in or not, /sys/module/XXX/parameters
 is still there, and while havig it in kernel is easy you could as
 easily stuff needed data into a sysfs attribute during booting.
 
 And we should be able to get this from DT even without the platform
 device (this was the next step, wasn't it?).

Correct - my hope was to get the main functionality accepted before
adding DT support.  Do you think the lack of DT support is a blocker for
acceptance ?  Please confirm.

Mathieu.

 
 Thanks.
 

--
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/


Re: [PATCH v2] drivers/tty: Folding Android's keyreset driver in sysRQ

2012-09-04 Thread Mathieu Poirier
On 12-08-31 05:22 PM, Dmitry Torokhov wrote:
 On Fri, Aug 31, 2012 at 04:57:04PM -0600, Mathieu Poirier wrote:
 On 12-08-31 04:41 PM, Dmitry Torokhov wrote:
 On Fri, Aug 31, 2012 at 11:02:27PM +0100, Alan Cox wrote:
 Why do we need to involve a platform device and not use, for example, a 
 module
 parameter, that could be set up from userspace?

 The platform device comes from the original design and was included to
 minimise the amount of changes in code that make use of the current
 keyreset driver.

 The platform device is IMHO the right answer. In this class of devices
 the stuff is compiled in, the userspace is Android, there are no modules
 and there is no reason for it to be configurable.

 It does not matter if it is built in or not, /sys/module/XXX/parameters
 is still there, and while havig it in kernel is easy you could as
 easily stuff needed data into a sysfs attribute during booting.

 And we should be able to get this from DT even without the platform
 device (this was the next step, wasn't it?).

 Correct - my hope was to get the main functionality accepted before
 adding DT support.  Do you think the lack of DT support is a blocker for
 acceptance ?  Please confirm.

 
 No, lack of DT is not a blocker, but I am unconvinced that we need
 platform device.
 
 Thanks,
 

A platform device is really easy to spin-off in a board file and once it
is there you don't have to worry about other loose ends to tie in before
the solution is functional.

I don't mind supplementing the current proposition with a module
parameter interface to get the key_down and key_up sequences.

Which brings us to the reset_fn() function - in my opinion it offers
significant advantages and should be kept in the design.  What I'm not
so clear about is on the implementation.  Should it be kept as part of a
platform data or be implemented as a notifier as suggested by Alan.  I
am looking for guidance here and suggestions are encouraged.

Regards,
Mathieu.
--
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] [RFC]: drivers/tty: Folding Android's keyreset driver in sysRQ

2012-08-16 Thread mathieu . poirier
From: Mathieu J. Poirier mathieu.poir...@linaro.org

This patch adds keyreset functionality to the sysrq driver. It
allows certain button/key combinations to be used in order to
trigger device resets.

The first time the key-combo is detected a work function that syncs
the filesystems is scheduled and the kernel rebooted. If all the keys
are released and then pressed again, it calls panic. Reboot on panic
should be set for this to work.  A platform device that specify a
reset key-combo should be added to the board file to trigger the
feature.

This functionality comes from the keyreset driver submitted by
Arve Hjønnevåg in the Android kernel.  It is sent out as an initial
draft and comments are welcomed.

In the design most of the original author's code has been added
alongside the sysrq functionality, taking great care not to
remove or constrain functionality people might currently be using.

The keyreset platform data and driver name were kept intact to
minimize disruption on products that already instantiate the
keyreset driver.

Cc: a...@android.com
Cc: kernel-t...@android.com
Cc: dmitry.torok...@gmail.com
Cc: john.stu...@linaro.org
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
---
 drivers/tty/sysrq.c   |  159 +
 include/linux/sysrq.h |8 +++
 2 files changed, 167 insertions(+), 0 deletions(-)

diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index 05728894..c2b869d 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -41,6 +41,9 @@
 #include linux/slab.h
 #include linux/input.h
 #include linux/uaccess.h
+#include linux/platform_device.h
+#include linux/syscalls.h
+#include linux/atomic.h
 
 #include asm/ptrace.h
 #include asm/irq_regs.h
@@ -49,6 +52,11 @@
 static int __read_mostly sysrq_enabled = SYSRQ_DEFAULT_ENABLE;
 static bool __read_mostly sysrq_always_enabled;
 
+static struct input_handler sysrq_handler;
+
+/* Keep track of what has been called */
+static atomic_t restart_requested;
+
 static bool sysrq_on(void)
 {
return sysrq_enabled || sysrq_always_enabled;
@@ -570,6 +578,15 @@ struct sysrq_state {
struct input_handle handle;
struct work_struct reinject_work;
unsigned long key_down[BITS_TO_LONGS(KEY_CNT)];
+   unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];
+   unsigned long upbit[BITS_TO_LONGS(KEY_CNT)];
+   unsigned long key[BITS_TO_LONGS(KEY_CNT)];
+   int (*reset_fn)(void);
+   int key_down_target;
+   int key_down_ctn;
+   int key_up_ctn;
+   int keyreset_data;
+   int restart_disabled;
unsigned int alt;
unsigned int alt_use;
bool active;
@@ -603,6 +620,92 @@ static void sysrq_reinject_alt_sysrq(struct work_struct 
*work)
}
 }
 
+
+static int sysrq_probe(struct platform_device *pdev)
+{
+   struct keyreset_platform_data *pdata = pdev-dev.platform_data;
+
+   /* No sequence of keys to trigger on,
+* assuming default sysRQ behavior.
+*/
+   if (pdata) {
+   atomic_set(restart_requested, 0);
+   sysrq_handler.private = pdata;
+   } else
+   sysrq_handler.private = NULL;
+
+   /* FETCH DT INFO HERE */
+
+   return 0;
+
+}
+
+static void deferred_restart(struct work_struct *dummy)
+{
+   atomic_inc(restart_requested);
+   sys_sync();
+   atomic_inc(restart_requested);
+   kernel_restart(NULL);
+}
+static DECLARE_WORK(restart_work, deferred_restart);
+
+static int do_keyreset_event(struct sysrq_state *state,
+unsigned int code, int value)
+{
+   int ret;
+   int processed = 0;
+
+   /* Is the code is of interestest to us */
+   if (!test_bit(code, state-keybit))
+   return processed;
+
+   /* No need to take care of key up events */
+   if (!test_bit(code, state-key) == !value)
+   return processed;
+
+   /* Record new entry */
+   __change_bit(code, state-key);
+
+   processed = 1;
+
+   if (test_bit(code, state-upbit)) {
+   if (value) {
+   state-restart_disabled = 1;
+   state-key_up_ctn++;
+   } else
+   state-key_up_ctn--;
+   } else {
+   if (value)
+   state-key_down_ctn++;
+   else
+   state-key_down_ctn--;
+   }
+
+   if (state-key_down_ctn == 0  state-key_up_ctn == 0)
+   state-restart_disabled = 0;
+
+   if (value  !state-restart_disabled 
+   state-key_down_ctn == state-key_down_target) {
+   state-restart_disabled = 1;
+   if (atomic_read(restart_requested))
+   panic(KERN_ERR keyboard reset failed, %d - panic\n,
+atomic_read(restart_requested));
+   if (state-reset_fn) {
+   ret = state-reset_fn

[PATCH] drivers/tty: Folding Android's keyreset driver in sysRQ

2012-08-27 Thread mathieu . poirier
From: Mathieu J. Poirier mathieu.poir...@linaro.org

This patch adds keyreset functionality to the sysrq driver. It
allows certain button/key combinations to be used in order to
trigger device resets.

The first time the key-combo is detected a work function that syncs
the filesystems is scheduled and the kernel rebooted. If all the keys
are released and then pressed again, it calls panic. Reboot on panic
should be set for this to work.  A platform device that specify a
reset key-combo should be added to the board file to trigger the
feature.

This functionality comes from the keyreset driver submitted by
Arve Hjønnevåg in the Android kernel.

Cc: a...@android.com
Cc: kernel-t...@android.com
Cc: dmitry.torok...@gmail.com
Cc: john.stu...@linaro.org
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
---
 drivers/tty/sysrq.c   |  159 +
 include/linux/sysrq.h |8 +++
 2 files changed, 167 insertions(+), 0 deletions(-)

diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index 05728894..6cf5531 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -41,6 +41,9 @@
 #include linux/slab.h
 #include linux/input.h
 #include linux/uaccess.h
+#include linux/platform_device.h
+#include linux/syscalls.h
+#include linux/atomic.h
 
 #include asm/ptrace.h
 #include asm/irq_regs.h
@@ -49,6 +52,11 @@
 static int __read_mostly sysrq_enabled = SYSRQ_DEFAULT_ENABLE;
 static bool __read_mostly sysrq_always_enabled;
 
+static struct input_handler sysrq_handler;
+
+/* Keep track of what has been called */
+static atomic_t restart_requested;
+
 static bool sysrq_on(void)
 {
return sysrq_enabled || sysrq_always_enabled;
@@ -570,6 +578,15 @@ struct sysrq_state {
struct input_handle handle;
struct work_struct reinject_work;
unsigned long key_down[BITS_TO_LONGS(KEY_CNT)];
+   unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];
+   unsigned long upbit[BITS_TO_LONGS(KEY_CNT)];
+   unsigned long key[BITS_TO_LONGS(KEY_CNT)];
+   int (*reset_fn)(void);
+   int key_down_target;
+   int key_down_ctn;
+   int key_up_ctn;
+   int keyreset_data;
+   int restart_disabled;
unsigned int alt;
unsigned int alt_use;
bool active;
@@ -603,6 +620,92 @@ static void sysrq_reinject_alt_sysrq(struct work_struct 
*work)
}
 }
 
+
+static int sysrq_probe(struct platform_device *pdev)
+{
+   struct keyreset_platform_data *pdata = pdev-dev.platform_data;
+
+   /* No sequence of keys to trigger on,
+* assuming default sysRQ behavior.
+*/
+   if (pdata) {
+   atomic_set(restart_requested, 0);
+   sysrq_handler.private = pdata;
+   } else
+   sysrq_handler.private = NULL;
+
+   /* FETCH DT INFO HERE */
+
+   return 0;
+
+}
+
+static void deferred_restart(struct work_struct *dummy)
+{
+   atomic_inc(restart_requested);
+   sys_sync();
+   atomic_inc(restart_requested);
+   kernel_restart(NULL);
+}
+static DECLARE_WORK(restart_work, deferred_restart);
+
+static int do_keyreset_event(struct sysrq_state *state,
+unsigned int code, int value)
+{
+   int ret;
+   int processed = 0;
+
+   /* Is the code is of interestest to us */
+   if (!test_bit(code, state-keybit))
+   return processed;
+
+   /* No need to take care of key up events */
+   if (!test_bit(code, state-key) == !value)
+   return processed;
+
+   /* Record new entry */
+   __change_bit(code, state-key);
+
+   processed = 1;
+
+   if (test_bit(code, state-upbit)) {
+   if (value) {
+   state-restart_disabled = 1;
+   state-key_up_ctn++;
+   } else
+   state-key_up_ctn--;
+   } else {
+   if (value)
+   state-key_down_ctn++;
+   else
+   state-key_down_ctn--;
+   }
+
+   if (state-key_down_ctn == 0  state-key_up_ctn == 0)
+   state-restart_disabled = 0;
+
+   if (value  !state-restart_disabled 
+   state-key_down_ctn == state-key_down_target) {
+   state-restart_disabled = 1;
+   if (atomic_read(restart_requested))
+   panic(keyboard reset failed, %d - panic\n,
+atomic_read(restart_requested));
+   if (state-reset_fn) {
+   ret = state-reset_fn();
+   atomic_set(restart_requested, ret);
+   } else {
+   pr_info(keyboard reset\n);
+   schedule_work(restart_work);
+   atomic_inc(restart_requested);
+   }
+   }
+
+   /* no need to suppress keyreset characters */
+   state-active = false;
+
+   return processed;
+}
+
 static bool

Re: [PATCH 33/57] power: u8500_charger: Delay for USB enumeration

2012-09-28 Thread Mathieu Poirier
On 12-09-27 01:42 AM, Anton Vorontsov wrote:
 On Tue, Sep 25, 2012 at 10:12:30AM -0600, mathieu.poir...@linaro.org wrote:
 From: Paer-Olof Haakansson par-olof.hakans...@stericsson.com

 If charging is started before USB enumeration of an
 Accessory Charger Adapter has finished, the AB8500 will
 generate a VBUS_ERROR. This in turn results in timeouts
 and delays the enumeration with around 15 seconds.
 This patch delays the charging and then ramps currents
 slowly to avoid VBUS errors. The delay allows the enumeration
 to have finished before charging is turned on.

 Signed-off-by: Martin Sjoblom martin.w.sjob...@stericsson.com
 Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
 Reviewed-by: Jonas ABERG jonas.ab...@stericsson.com
 ---
 [...]
 @@ -264,17 +275,19 @@ struct ab8500_charger {
  struct ab8500_charger_info usb;
  struct regulator *regu;
  struct workqueue_struct *charger_wq;
 +struct mutex usb_ipt_crnt_lock;
  struct delayed_work check_vbat_work;
  struct delayed_work check_hw_failure_work;
  struct delayed_work check_usbchgnotok_work;
  struct delayed_work kick_wd_work;
 +struct delayed_work usb_state_changed_work;
  struct delayed_work attach_work;
  struct delayed_work ac_charger_attached_work;
  struct delayed_work usb_charger_attached_work;
 +struct delayed_work vbus_drop_end_work;
  struct work_struct ac_work;
  struct work_struct detect_usb_type_work;
  struct work_struct usb_link_status_work;
 -struct work_struct usb_state_changed_work;
 
 This just moves line around. Doesn't belong to this patch.

This is moving 'usb_state_changed_work' from type 'struct work_struct'
to 'struct delayed_work'.  Is it that you want to see the change on the
same line rather than two different lines ?

 
  struct work_struct check_main_thermal_prot_work;
  struct work_struct check_usb_thermal_prot_work;
  struct usb_phy *usb_phy;
 @@ -560,6 +573,7 @@ static int ab8500_charger_usb_cv(struct ab8500_charger 
 *di)
  /**
   * ab8500_charger_detect_chargers() - Detect the connected chargers
   * @di: pointer to the ab8500_charger structure
 + * @probe: if probe, don't delay and wait for HW
   *
   * Returns the type of charger connected.
   * For USB it will not mean we can actually charge from it
 @@ -570,10 +584,10 @@ static int ab8500_charger_usb_cv(struct ab8500_charger 
 *di)
   * Returns an integer value, that means,
   * NO_PW_CONN  no power supply is connected
   * AC_PW_CONN  if the AC power supply is connected
 - * USB_PW_CONN  if the USB power supply is connected
 + * USB_PW_CONN  if the USB power supply is connected
 
 Cosmetic change... doesn't belong to this patch, I guess.
 
   * AC_PW_CONN + USB_PW_CONN if USB and AC power supplies are both connected
   */
 -static int ab8500_charger_detect_chargers(struct ab8500_charger *di)
 +static int ab8500_charger_detect_chargers(struct ab8500_charger *di, bool 
 probe)
  {
  int result = NO_PW_CONN;
  int ret;
 @@ -591,6 +605,15 @@ static int ab8500_charger_detect_chargers(struct 
 ab8500_charger *di)
  result = AC_PW_CONN;
  
  /* Check for USB charger */
 +if (!probe) {
 +/*
 + * AB8500 says VBUS_DET_DBNC1  VBUS_DET_DBNC100
 + * when disconnecting ACA even though no
 + * charger was connected. Try waiting a little
 + * longer than the 100 ms of VBUS_DET_DBNC100...
 + */
 +msleep(110);
 +}
  ret = abx500_get_register_interruptible(di-dev, AB8500_CHARGER,
  AB8500_CH_USBCH_STAT1_REG, val);
  if (ret  0) {
 @@ -598,6 +621,9 @@ static int ab8500_charger_detect_chargers(struct 
 ab8500_charger *di)
  return ret;
  }
  
 +dev_dbg(di-dev,
 +%s AB8500_CH_USBCH_STAT1_REG %x\n, __func__, val);
 +
  if ((val  VBUS_DET_DBNC1)  (val  VBUS_DET_DBNC100))
  result |= USB_PW_CONN;
  
 @@ -620,33 +646,47 @@ static int ab8500_charger_max_usb_curr(struct 
 ab8500_charger *di,
  
  di-usb_device_is_unrecognised = false;
  
 +/*
 + * Platform only supports USB 2.0.
 + * This means that charging current from USB source
 + * is maximum 500 mA. Every occurence of USB_STAT_*_HOST_*
 + * should set USB_CH_IP_CUR_LVL_0P5.
 + */
 +
  switch (link_status) {
  case USB_STAT_STD_HOST_NC:
  case USB_STAT_STD_HOST_C_NS:
  case USB_STAT_STD_HOST_C_S:
  dev_dbg(di-dev, USB Type - Standard host is );
  dev_dbg(di-dev, detected through USB driver\n);
 -di-max_usb_in_curr = USB_CH_IP_CUR_LVL_0P09;
 +di-max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5;
 +di-is_usb_host = true;
 +di-is_aca_rid = 0;
  break;
  case USB_STAT_HOST_CHG_HS_CHIRP:
  di-max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5;
 -dev_dbg(di-dev, USB Type - 0x%02x MaxCurr: %d, link_status

Re: [PATCH 17/57] power: ab8500_bm: Added support for BATT_OVV

2012-09-28 Thread Mathieu Poirier
On 12-09-26 09:36 PM, Anton Vorontsov wrote:
 On Tue, Sep 25, 2012 at 10:12:14AM -0600, mathieu.poir...@linaro.org wrote:
 From: Hakan Berg hakan.b...@stericsson.com

 Add support for the battery over-voltage situation

 Signed-off-by: Hakan Berg hakan.b...@stericsson.com
 Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
 Reviewed-by: Karl KOMIEROWSKI karl.komierow...@stericsson.com
 ---
  drivers/power/ab8500_fg.c |   32 
  1 files changed, 16 insertions(+), 16 deletions(-)

 diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
 index c4d9307..8507254 100644
 --- a/drivers/power/ab8500_fg.c
 +++ b/drivers/power/ab8500_fg.c
 @@ -1842,24 +1842,26 @@ static void ab8500_fg_check_hw_failure_work(struct 
 work_struct *work)
   * If we have had a battery over-voltage situation,
   * check ovv-bit to see if it should be reset.
   */
 -if (di-flags.bat_ovv) {
 -ret = abx500_get_register_interruptible(di-dev,
 -AB8500_CHARGER, AB8500_CH_STAT_REG,
 -reg_value);
 -if (ret  0) {
 -dev_err(di-dev, %s ab8500 read failed\n, __func__);
 -return;
 -}
 -if ((reg_value  BATT_OVV) != BATT_OVV) {
 -dev_dbg(di-dev, Battery recovered from OVV\n);
 -di-flags.bat_ovv = false;
 +ret = abx500_get_register_interruptible(di-dev,
 +AB8500_CHARGER, AB8500_CH_STAT_REG,
 +reg_value);
 +if (ret  0) {
 +dev_err(di-dev, %s ab8500 read failed\n, __func__);
 +return;
 +}
 +if ((reg_value  BATT_OVV) == BATT_OVV) {
 +if (!di-flags.bat_ovv) {
 +dev_dbg(di-dev, Battery OVV\n);
 +di-flags.bat_ovv = true;
  power_supply_changed(di-fg_psy);
 -return;
  }
 -
  /* Not yet recovered from ovv, reschedule this test */
  queue_delayed_work(di-fg_wq, di-fg_check_hw_failure_work,
 -   round_jiffies(HZ));
 +HZ);
 
 Why this change? I.e. round_jiffies(HZ) - HZ?
 
 Yes, it seems like round_jiffies(HZ) is not needed since HZ itself is a
 full second.. But the change itself does not belong to this patch.

I agree with your point of view.  How do we fix it now ?  Do you think
it's worth crafting a one-line patch ?

 
 +} else {
 +dev_dbg(di-dev, Battery recovered from OVV\n);
 +di-flags.bat_ovv = false;
 +power_supply_changed(di-fg_psy);
  }
  }
  
 @@ -2039,8 +2041,6 @@ static irqreturn_t ab8500_fg_batt_ovv_handler(int irq, 
 void *_di)
  struct ab8500_fg *di = _di;
  
  dev_dbg(di-dev, Battery OVV\n);
 -di-flags.bat_ovv = true;
 -power_supply_changed(di-fg_psy);
  
  /* Schedule a new HW failure check */
  queue_delayed_work(di-fg_wq, di-fg_check_hw_failure_work, 0);
 -- 
 1.7.5.4

--
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/


Re: [PATCH 18/57] power: Add sysfs interfaces for capacity

2012-09-28 Thread Mathieu Poirier
On 12-09-27 01:08 AM, Anton Vorontsov wrote:
 On Tue, Sep 25, 2012 at 10:12:15AM -0600, mathieu.poir...@linaro.org wrote:
 From: Daniel WILLERUD daniel.wille...@stericsson.com

 Switchable depending on whether capacity scaling is enabled

 Signed-off-by: Marcus Cooper marcus.xm.coo...@stericsson.com
 Signed-off-by: Daniel WILLERUD daniel.wille...@stericsson.com
 Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
 Reviewed-by: Jonas ABERG jonas.ab...@stericsson.com
 ---
  drivers/power/ab8500_fg.c |   57 
 -
  1 files changed, 56 insertions(+), 1 deletions(-)

 diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
 index 8507254..46010ec 100644
 --- a/drivers/power/ab8500_fg.c
 +++ b/drivers/power/ab8500_fg.c
 @@ -266,7 +266,6 @@ static enum power_supply_property ab8500_fg_props[] = {
  POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
  POWER_SUPPLY_PROP_CHARGE_FULL,
  POWER_SUPPLY_PROP_CHARGE_NOW,
 -POWER_SUPPLY_PROP_CAPACITY,
 [...]
 +static struct device_attribute ab8500_fg_sysfs_psy_attrs[] = {
 +__ATTR(capacity, S_IRUGO, ab8500_show_capacity, NULL),
 +};
 
 I don't understand the rationale behind this patch. Why remove normal
 power supply property, and make your own with the same name? Something
 isn't right...

The similarity in the naming convention it a coincidence here.  In one
case it's a enum and the other sysfs attribute.  Could you expand on
your suspicions ?

 

--
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/


Re: [PATCH 27/57] power: sysfs interface update

2012-09-28 Thread Mathieu Poirier
On 12-09-27 01:20 AM, Anton Vorontsov wrote:
 On Tue, Sep 25, 2012 at 10:12:24AM -0600, mathieu.poir...@linaro.org wrote:
 From: Michel JAOUEN michel.jao...@stericsson.com

 Add new sysfs interface to get current charge status

 Signed-off-by: Michel JAOUEN michel.jao...@stericsson.com
 Signed-off-by: Loic Pallardy loic.palla...@stericsson.com
 Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
 Reviewed-by: Marcus COOPER marcus.xm.coo...@stericsson.com
 Reviewed-by: Olivier CLERGEAUD olivier.clerge...@stericsson.com
 Reviewed-by: Jonas ABERG jonas.ab...@stericsson.com
 ---
  drivers/power/ab8500_charger.c  |3 +++
  drivers/power/abx500_chargalg.c |   24 +++-
  2 files changed, 26 insertions(+), 1 deletions(-)

 diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
 index 4129599..0a781a0 100644
 --- a/drivers/power/ab8500_charger.c
 +++ b/drivers/power/ab8500_charger.c
 @@ -2759,6 +2759,9 @@ static int ab8500_charger_usb_notifier_call(struct 
 notifier_block *nb,
  enum ab8500_usb_state bm_usb_state;
  unsigned mA = *((unsigned *)power);
  
 +if (di == NULL)
 +return NOTIFY_DONE;
 +
 
 I'd write !di.

Not sure I agree with you here.  If di is NULL there is nothing to work
with and as such, exit.

 
 [...]
 +static ssize_t abx500_chargalg_sysfs_show(struct kobject *kobj,
 +struct attribute *attr, char *buf)
 +{
 +struct abx500_chargalg *di = container_of(kobj,
 +struct abx500_chargalg, chargalg_kobject);
 +
 +if ((di-susp_status.ac_suspended == true) 
 +(di-susp_status.usb_suspended == true))
 +return sprintf(buf, 0\n);
 +else
 +return sprintf(buf, 1\n);
 
 just
 
 return sprintf(buf, %d\n, di-susp_status.ac_suspended 
   di-susp_status.usb_suspended);

Much cleaner yes.

 
 +}
 +
  /* Exposure to the sysfs interface */
  
  /**
 @@ -1749,7 +1770,7 @@ static ssize_t abx500_chargalg_sysfs_charger(struct 
 kobject *kobj,
  static struct attribute abx500_chargalg_en_charger = \
  {
  .name = chargalg,
 -.mode = S_IWUGO,
 +.mode = S_IRUGO | S_IWUSR,
  };
  
  static struct attribute *abx500_chargalg_chg[] = {
 @@ -1758,6 +1779,7 @@ static struct attribute *abx500_chargalg_chg[] = {
  };
  
  static const struct sysfs_ops abx500_chargalg_sysfs_ops = {
 +.show = abx500_chargalg_sysfs_show,
  .store = abx500_chargalg_sysfs_charger,
  };
  
 -- 
 1.7.5.4

--
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/


Re: [PATCH 30/57] power: ab8500: Flush sync all works

2012-09-28 Thread Mathieu Poirier
On 12-09-27 01:23 AM, Anton Vorontsov wrote:
 On Tue, Sep 25, 2012 at 10:12:27AM -0600, mathieu.poir...@linaro.org wrote:
 From: Jonas Aaberg jonas.ab...@stericsson.com

 Flush and sync all workqueues at suspend to avoid
 that we suspend in the middle of a work.

 Signed-off-by: Jonas Aaberg jonas.ab...@stericsson.com
 Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
 Reviewed-by: Marcus COOPER marcus.xm.coo...@stericsson.com
 ---
  drivers/power/ab8500_charger.c |   11 +++
  drivers/power/ab8500_fg.c  |5 +
  2 files changed, 16 insertions(+), 0 deletions(-)

 diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
 index ee5ad7b..071c7c2 100644
 --- a/drivers/power/ab8500_charger.c
 +++ b/drivers/power/ab8500_charger.c
 @@ -2862,6 +2862,17 @@ static int ab8500_charger_suspend(struct 
 platform_device *pdev,
  if (delayed_work_pending(di-check_hw_failure_work))
  cancel_delayed_work(di-check_hw_failure_work);
  
 +flush_delayed_work_sync(di-attach_work);
 +flush_delayed_work_sync(di-usb_charger_attached_work);
 +flush_delayed_work_sync(di-ac_charger_attached_work);
 +flush_delayed_work_sync(di-check_usbchgnotok_work);
 +flush_delayed_work_sync(di-check_vbat_work);
 +flush_delayed_work_sync(di-kick_wd_work);
 +
 +flush_work_sync(di-usb_link_status_work);
 +flush_work_sync(di-ac_work);
 +flush_work_sync(di-detect_usb_type_work);
 
 I belive each of these have to be added by the patches that add the
 appropriate work structs. But really, it's better to avoid these many
 delayed work.

Agreed - on the flip side they were added over multiple patches spanning
many centuries.  Tracking all this work down would be impossible as
history was re-written many time over.  What would you like to see
happening here ?

 
  return 0;
  }
  #else
 diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
 index e7a0e1f..0e71e7e 100644
 --- a/drivers/power/ab8500_fg.c
 +++ b/drivers/power/ab8500_fg.c
 @@ -2626,6 +2626,11 @@ static int ab8500_fg_suspend(struct platform_device 
 *pdev,
  struct ab8500_fg *di = platform_get_drvdata(pdev);
  
  flush_delayed_work_sync(di-fg_periodic_work);
 +flush_work_sync(di-fg_work);
 +flush_work_sync(di-fg_acc_cur_work);
 +flush_delayed_work_sync(di-fg_reinit_work);
 +flush_delayed_work_sync(di-fg_low_bat_work);
 +flush_delayed_work_sync(di-fg_check_hw_failure_work);
  
  /*
   * If the FG is enabled we will disable it before going to suspend
 -- 
 1.7.5.4



--
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/


Re: [PATCH 38/57] power: l9540: Charge only mode fixes

2012-09-28 Thread Mathieu Poirier
On 12-09-27 06:27 PM, Anton Vorontsov wrote:
 On Tue, Sep 25, 2012 at 10:12:35AM -0600, mathieu.poir...@linaro.org wrote:
 From: Rupesh Kumar rupesh.ku...@stericsson.com

 Fix for: charging not getting enabled in
 charge only mode by external charger.
 
 Subject says l9540.. what is this?
 
 Signed-off-by: Rupesh Kumar rupesh.ku...@stericsson.com
 Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
 Reviewed-by: Marcus COOPER marcus.xm.coo...@stericsson.com
 Reviewed-by: Michel JAOUEN michel.jao...@stericsson.com
 Reviewed-by: Philippe LANGLAIS philippe.langl...@stericsson.com
 Reviewed-by: Philippe LANGLAIS philippe.langl...@stericsson.com
 ---
  drivers/power/ab8500_charger.c|   42 
 +
  drivers/power/abx500_chargalg.c   |   14 +
  include/linux/mfd/abx500/ux500_chargalg.h |2 +
  3 files changed, 58 insertions(+), 0 deletions(-)

 diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
 index 70e7c5e..ebeb068 100644
 --- a/drivers/power/ab8500_charger.c
 +++ b/drivers/power/ab8500_charger.c
 @@ -15,6 +15,7 @@
  #include linux/device.h
  #include linux/interrupt.h
  #include linux/delay.h
 +#include linux/notifier.h
  #include linux/slab.h
  #include linux/platform_device.h
  #include linux/power_supply.h
 @@ -94,6 +95,10 @@
  #define AB8500_SW_CONTROL_FALLBACK  0x03
  /* Wait for enumeration before charging in us */
  #define WAIT_ACA_RID_ENUMERATION(5 * 1000)
 +/*External charger control*/
 +#define AB8500_SYS_CHARGER_CONTROL_REG  0x52
 +#define EXTERNAL_CHARGER_DISABLE_REG_VAL0x03
 +#define EXTERNAL_CHARGER_ENABLE_REG_VAL 0x07
  
  /* UsbLineStatus register - usb types */
  enum ab8500_charger_link_status {
 @@ -1672,6 +1677,29 @@ static int ab8500_charger_usb_en(struct ux500_charger 
 *charger,
  return ret;
  }
  
 +static int ab8500_external_charger_prepare(struct notifier_block 
 *charger_nb,
 +unsigned long event, void *data)
 +{
 +int ret;
 +struct device *dev = data;
 
 Need an empty line here.
 
 +/*Toggle External charger control pin*/
 
 Spaces after /* and before */.
 
 +ret = abx500_set_register_interruptible(dev, AB8500_SYS_CTRL1_BLOCK,
 +  AB8500_SYS_CHARGER_CONTROL_REG,
 +  EXTERNAL_CHARGER_DISABLE_REG_VAL);
 +if (ret  0) {
 +dev_err(dev, write reg failed %d\n, ret);
 +goto out;
 
 No need for goto.
 
 +}
 +ret = abx500_set_register_interruptible(dev, AB8500_SYS_CTRL1_BLOCK,
 +  AB8500_SYS_CHARGER_CONTROL_REG,
 +  EXTERNAL_CHARGER_ENABLE_REG_VAL);
 +if (ret  0)
 +dev_err(dev, Write reg failed %d\n, ret);
 +
 +out:
 +return ret;
 +}
 +
  /**
   * ab8500_charger_usb_check_enable() - enable usb charging
   * @charger:pointer to the ux500_charger structure
 @@ -3201,6 +3229,10 @@ static int ab8500_charger_suspend(struct 
 platform_device *pdev,
  #define ab8500_charger_resume   NULL
  #endif
  
 +static struct notifier_block charger_nb = {
 +.notifier_call = ab8500_external_charger_prepare,
 +};
 +
  static int __devexit ab8500_charger_remove(struct platform_device *pdev)
  {
  struct ab8500_charger *di = platform_get_drvdata(pdev);
 @@ -3233,6 +3265,11 @@ static int __devexit ab8500_charger_remove(struct 
 platform_device *pdev)
  /* Delete the work queue */
  destroy_workqueue(di-charger_wq);
  
 +/*Unregister external charger enable notifier*/
 
 Spaces.
 
 +if (!di-ac_chg.enabled)
 +blocking_notifier_chain_unregister(
 +charger_notifier_list, charger_nb);
 +
  flush_scheduled_work();
  if (di-usb_chg.enabled)
  power_supply_unregister(di-usb_chg.psy);
 @@ -3307,6 +3344,11 @@ static int __devinit ab8500_charger_probe(struct 
 platform_device *pdev)
  di-ac_chg.enabled = di-pdata-ac_enabled;
  di-ac_chg.external = false;
  
 +/*notifier for external charger enabling*/
 
 Spaces.
 
 +if (!di-ac_chg.enabled)
 +blocking_notifier_chain_register(
 +charger_notifier_list, charger_nb);
 +
  /* USB supply */
  /* power_supply base class */
  di-usb_chg.psy.name = ab8500_usb;
 diff --git a/drivers/power/abx500_chargalg.c 
 b/drivers/power/abx500_chargalg.c
 index 9568f63..3ca00dd 100644
 --- a/drivers/power/abx500_chargalg.c
 +++ b/drivers/power/abx500_chargalg.c
 @@ -24,6 +24,7 @@
  #include linux/mfd/abx500.h
  #include linux/mfd/abx500/ux500_chargalg.h
  #include linux/mfd/abx500/ab8500-bm.h
 +#include linux/notifier.h
  
  /* Watchdog kick interval */
  #define CHG_WD_INTERVAL (6 * HZ)
 @@ -255,6 +256,9 @@ static enum power_supply_property 
 abx500_chargalg_props[] = {
  POWER_SUPPLY_PROP_HEALTH,
  };
  
 +/*External charger prepare notifier*/
 +BLOCKING_NOTIFIER_HEAD(charger_notifier_list

Re: [PATCH 52/57] power: abx500_chargalg: Use hrtimer

2012-09-28 Thread Mathieu Poirier
On 12-09-27 08:47 PM, Anton Vorontsov wrote:
 On Tue, Sep 25, 2012 at 10:12:49AM -0600, mathieu.poir...@linaro.org wrote:
 From: Hakan Berg hakan.b...@stericsson.com

 Timers used for charging safety and maintenance must work even when
 CPU is power collapsed. By using hrtimers with realtime clock, system
 is able to trigger an alarm that wakes the CPU up and make it possible
 to handle the event.

 Allow a little slack of 5 minutes to the hrtimers to allow CPU to be
 waked up in a more optimal power saving way. A 5 minute delay to
 time out timers on hours does not impact on safety.

 Signed-off-by: Hakan Berg hakan.b...@stericsson.com
 Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
 Reviewed-by: Mian Yousaf KAUKAB mian.yousaf.kau...@stericsson.com
 ---
  drivers/power/abx500_chargalg.c |   94 
 ++-
  1 files changed, 53 insertions(+), 41 deletions(-)

 diff --git a/drivers/power/abx500_chargalg.c 
 b/drivers/power/abx500_chargalg.c
 index 636d970..c8849af 100644
 --- a/drivers/power/abx500_chargalg.c
 +++ b/drivers/power/abx500_chargalg.c
 @@ -1,5 +1,6 @@
  /*
   * Copyright (C) ST-Ericsson SA 2012
 + * Copyright (c) 2012 Sony Mobile Communications AB
   *
   * Charging algorithm driver for abx500 variants
   *
 @@ -8,11 +9,13 @@
   *  Johan Palsson johan.pals...@stericsson.com
   *  Karl Komierowski karl.komierow...@stericsson.com
   *  Arun R Murthy arun.mur...@stericsson.com
 + *  Imre Sunyi imre.su...@sonymobile.com
   */
  
  #include linux/init.h
  #include linux/module.h
  #include linux/device.h
 +#include linux/hrtimer.h
  #include linux/interrupt.h
  #include linux/delay.h
  #include linux/slab.h
 @@ -32,6 +35,12 @@
  /* End-of-charge criteria counter */
  #define EOC_COND_CNT10
  
 +/* One hour expressed in seconds */
 +#define ONE_HOUR_IN_SECONDS 3600
 +
 +/* Five minutes expressed in seconds */
 +#define FIVE_MINUTES_IN_SECONDS 300
 +
  #define to_abx500_chargalg_device_info(x) container_of((x), \
  struct abx500_chargalg, chargalg_psy);
  
 @@ -245,8 +254,8 @@ struct abx500_chargalg {
  struct delayed_work chargalg_periodic_work;
  struct delayed_work chargalg_wd_work;
  struct work_struct chargalg_work;
 -struct timer_list safety_timer;
 -struct timer_list maintenance_timer;
 +struct hrtimer safety_timer;
 +struct hrtimer maintenance_timer;
  struct kobject chargalg_kobject;
  };
  
 @@ -261,38 +270,47 @@ BLOCKING_NOTIFIER_HEAD(charger_notifier_list);
  
  /**
   * abx500_chargalg_safety_timer_expired() - Expiration of the safety timer
 - * @data:   pointer to the abx500_chargalg structure
 + * @timer:  pointer to the hrtimer structure
   *
   * This function gets called when the safety timer for the charger
   * expires
   */
 -static void abx500_chargalg_safety_timer_expired(unsigned long data)
 +static enum hrtimer_restart
 +abx500_chargalg_safety_timer_expired(struct hrtimer *timer)
  {
 -struct abx500_chargalg *di = (struct abx500_chargalg *) data;
 +struct abx500_chargalg *di = container_of(timer, struct abx500_chargalg,
 +safety_timer);
 
 Empty line here.
 
  dev_err(di-dev, Safety timer expired\n);
  di-events.safety_timer_expired = true;
  
  /* Trigger execution of the algorithm instantly */
  queue_work(di-chargalg_wq, di-chargalg_work);
 +
 +return HRTIMER_NORESTART;
  }
  
  /**
   * abx500_chargalg_maintenance_timer_expired() - Expiration of
   * the maintenance timer
 - * @i:  pointer to the abx500_chargalg structure
 + * @timer:  pointer to the timer structure
   *
   * This function gets called when the maintenence timer
   * expires
   */
 -static void abx500_chargalg_maintenance_timer_expired(unsigned long data)
 +static enum hrtimer_restart
 +abx500_chargalg_maintenance_timer_expired(struct hrtimer *timer)
 +
  {
  
 -struct abx500_chargalg *di = (struct abx500_chargalg *) data;
 +struct abx500_chargalg *di = container_of(timer, struct abx500_chargalg,
 +maintenance_timer);
  dev_dbg(di-dev, Maintenance timer expired\n);
  di-events.maintenance_timer_expired = true;
  
  /* Trigger execution of the algorithm instantly */
  queue_work(di-chargalg_wq, di-chargalg_work);
 +
 +return HRTIMER_NORESTART;
  }
  
  /**
 @@ -392,19 +410,16 @@ static int 
 abx500_chargalg_check_charger_connection(struct abx500_chargalg *di)
   */
  static void abx500_chargalg_start_safety_timer(struct abx500_chargalg *di)
  {
 -unsigned long timer_expiration = 0;
 +/* Charger-dependent expiration time in hours*/
 +int timer_expiration = 0;
  
  switch (di-chg_info.charger_type) {
  case AC_CHG:
 -timer_expiration =
 -round_jiffies(jiffies +
 -(di-bat-main_safety_tmr_h * 3600 * HZ));
 +timer_expiration = di-bat

[RFC PATCH 08/11] coresight: adding support for beagle board

2014-05-30 Thread mathieu . poirier
From: Panchaxari Prasannamurthy panchaxari.prasannamur...@linaro.org

Added support for coresight device in dts for Beagle Board, by adding
blocks of coresight, ETM, ETB blocks.

Signed-off-by: Panchaxari Prasannamurthy panchaxari.prasannamur...@linaro.org
---
 arch/arm/boot/dts/omap3-beagle.dts | 30 ++
 1 file changed, 30 insertions(+)

diff --git a/arch/arm/boot/dts/omap3-beagle.dts 
b/arch/arm/boot/dts/omap3-beagle.dts
index 5053766..0017084 100644
--- a/arch/arm/boot/dts/omap3-beagle.dts
+++ b/arch/arm/boot/dts/omap3-beagle.dts
@@ -80,6 +80,36 @@
};
 
};
+
+   coresight {
+   compatible = arm,coresight;
+   #address-cells = 1;
+   #size-cells = 1;
+   clocks = emu_src_ck;
+   ranges;
+
+   etb: etb@54000 {
+   compatible = arm,coresight-etb;
+   reg = 0x5401b000 0x1000;
+
+   coresight-id = 0;
+   coresight-name = coresight-etb;
+   coresight-nr-inports = 1;
+   coresight-default-sink;
+   };
+
+   etm@5401 {
+   compatible = arm,coresight-etm;
+   reg = 0x5401 0x1000;
+
+   coresight-id = 1;
+   coresight-name = coresight-etm;
+   coresight-nr-inports = 0;
+   coresight-outports = 0;
+   coresight-child-list = etb;
+   coresight-child-ports = 0;
+   };
+   };
 };
 
 omap3_pmx_wkup {
-- 
1.9.1

--
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 06/11] coresight: add CoreSight Replicator driver

2014-05-30 Thread mathieu . poirier
From: Pratik Patel prat...@codeaurora.org

This driver manages CoreSight Replicator that takes single input
trace data stream and replicates it to produce two identical
trace data output streams. Replicators are typically used to
route single interleaved trace data stream to two or more sinks.

Signed-off-by: Pratik Patel prat...@codeaurora.org
Signed-off-by: Panchaxari Prasannamurthy panchaxari.prasannamur...@linaro.org
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
---
 drivers/coresight/Makefile   |   2 +-
 drivers/coresight/coresight-replicator.c | 130 +++
 2 files changed, 131 insertions(+), 1 deletion(-)
 create mode 100644 drivers/coresight/coresight-replicator.c

diff --git a/drivers/coresight/Makefile b/drivers/coresight/Makefile
index 1f66804..25296a2 100644
--- a/drivers/coresight/Makefile
+++ b/drivers/coresight/Makefile
@@ -4,4 +4,4 @@
 obj-$(CONFIG_CORESIGHT) += coresight.o
 obj-$(CONFIG_OF) += of_coresight.o
 obj-$(CONFIG_CORESIGHT_LINKS_AND_SINKS) += coresight-tmc.o coresight-tpiu.o \
-  coresight-etb.o coresight-funnel.o
+  coresight-etb.o coresight-funnel.o \
diff --git a/drivers/coresight/coresight-replicator.c 
b/drivers/coresight/coresight-replicator.c
new file mode 100644
index 000..1cbb288
--- /dev/null
+++ b/drivers/coresight/coresight-replicator.c
@@ -0,0 +1,130 @@
+/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include linux/kernel.h
+#include linux/module.h
+#include linux/init.h
+#include linux/device.h
+#include linux/platform_device.h
+#include linux/io.h
+#include linux/err.h
+#include linux/slab.h
+#include linux/clk.h
+#include linux/of_coresight.h
+#include linux/coresight.h
+
+#include coresight-priv.h
+
+struct replicator_drvdata {
+   struct device   *dev;
+   struct coresight_device *csdev;
+};
+
+static int replicator_enable(struct coresight_device *csdev, int inport,
+int outport)
+{
+   struct replicator_drvdata *drvdata = dev_get_drvdata(csdev-dev.parent);
+   dev_info(drvdata-dev, REPLICATOR enabled\n);
+
+   return 0;
+}
+
+static void replicator_disable(struct coresight_device *csdev, int inport,
+  int outport)
+{
+   struct replicator_drvdata *drvdata = dev_get_drvdata(csdev-dev.parent);
+   dev_info(drvdata-dev, REPLICATOR disabled\n);
+}
+
+static const struct coresight_ops_link replicator_link_ops = {
+   .enable = replicator_enable,
+   .disable= replicator_disable,
+};
+
+static const struct coresight_ops replicator_cs_ops = {
+   .link_ops   = replicator_link_ops,
+};
+
+static int replicator_probe(struct platform_device *pdev)
+{
+   struct device *dev = pdev-dev;
+   struct coresight_platform_data *pdata;
+   struct replicator_drvdata *drvdata;
+   struct coresight_desc *desc;
+
+   if (pdev-dev.of_node) {
+   pdata = of_get_coresight_platform_data(dev, pdev-dev.of_node);
+   if (IS_ERR(pdata))
+   return PTR_ERR(pdata);
+   pdev-dev.platform_data = pdata;
+   }
+
+   drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+   if (!drvdata)
+   return -ENOMEM;
+   drvdata-dev = pdev-dev;
+   platform_set_drvdata(pdev, drvdata);
+
+   desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+   if (!desc)
+   return -ENOMEM;
+   desc-type = CORESIGHT_DEV_TYPE_LINK;
+   desc-subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_LINK_SPLIT;
+   desc-ops = replicator_cs_ops;
+   desc-pdata = pdev-dev.platform_data;
+   desc-dev = pdev-dev;
+   desc-owner = THIS_MODULE;
+   drvdata-csdev = coresight_register(desc);
+   if (IS_ERR(drvdata-csdev))
+   return PTR_ERR(drvdata-csdev);
+
+   dev_info(dev, REPLICATOR initialized\n);
+   return 0;
+}
+
+static int replicator_remove(struct platform_device *pdev)
+{
+   struct replicator_drvdata *drvdata = platform_get_drvdata(pdev);
+
+   coresight_unregister(drvdata-csdev);
+   return 0;
+}
+
+static struct of_device_id replicator_match[] = {
+   {.compatible = arm,coresight-replicator},
+   {}
+};
+
+static struct platform_driver replicator_driver = {
+   .probe  = replicator_probe,
+   .remove = replicator_remove,
+   .driver

[RFC PATCH 00/11] CoreSight framework and drivers

2014-05-30 Thread mathieu . poirier
From: Mathieu Poirier mathieu.poir...@linaro.org

This RFC is rescucitating the work submitted by Pratik Patel in 
2012 [1].  

This set is addressing comments gathered from the initial RFC
and enhance the framework in a few areas.  More specifically:

. Sysfs entries have been moved to debugfs.
. The removal of the bus concept.
. Setting the size of the ETB in accordance to HW capabilities.
. Adding a status entry in debugfs to better debug ETM configurations.
. Adding cpu affinity for ETM/PTMs.
. Tying of each IP block to a specific and configurable clock.
. Adjusted the ETM/PTM power up sequence.
. Adding support for beagle/beagleXM and ARM's TC2 platform.

Support for other platforms will be coming shortly but we felt 
confident the current code base was mature enough to suscitate 
comments.  More advanced features like CTI and STMs present in 
the original patchset was intentionally left out to concentrate
on the foundation.  They will be added at a later stage when the 
initial framework has been ironned-out.

Regards,
Mathieu


[1]. 
http://lists.infradead.org/pipermail/linux-arm-kernel/2012-December/138028.html

Mathieu Poirier (3):
  coresight: adding basic support for Vexpress TC2
  coresight: adding support for beagleXM
  ARM: moving support for etb/etm to the drivers directory

Panchaxari Prasannamurthy (1):
  coresight: adding support for beagle board

Pratik Patel (7):
  coresight: add CoreSight core layer framework
  coresight: add CoreSight TMC driver
  coresight: add CoreSight TPIU driver
  coresight: add CoreSight ETB driver
  coresight: add CoreSight Funnel driver
  coresight: add CoreSight Replicator driver
  coresight: add CoreSight ETM driver

 .../devicetree/bindings/arm/coresight.txt  |  138 ++
 arch/arm/boot/dts/omap3-beagle-xm.dts  |   30 +
 arch/arm/boot/dts/omap3-beagle.dts |   30 +
 arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts |  122 +
 arch/arm/include/asm/hardware/coresight.h  |  157 --
 arch/arm/include/asm/hardware/cp14.h   |  540 +
 arch/arm/kernel/Makefile   |1 -
 arch/arm/kernel/etm.c  |  654 --
 arch/arm/kernel/hw_breakpoint.c|4 +-
 arch/arm/mach-omap2/Kconfig|8 -
 arch/arm/mach-omap2/Makefile   |1 -
 arch/arm/mach-omap2/emu.c  |   50 -
 drivers/Kconfig|2 +
 drivers/Makefile   |1 +
 drivers/coresight/Kconfig  |   37 +
 drivers/coresight/Makefile |8 +
 drivers/coresight/coresight-etb.c  |  586 +
 drivers/coresight/coresight-etm-cp14.c |  511 +
 drivers/coresight/coresight-etm.c  | 2360 
 drivers/coresight/coresight-funnel.c   |  310 +++
 drivers/coresight/coresight-priv.h |   46 +
 drivers/coresight/coresight-replicator.c   |  130 ++
 drivers/coresight/coresight-tmc.c  |  796 +++
 drivers/coresight/coresight-tpiu.c |  229 ++
 drivers/coresight/coresight.c  |  739 ++
 drivers/coresight/of_coresight.c   |  124 +
 include/linux/coresight.h  |  181 ++
 include/linux/of_coresight.h   |   27 +
 28 files changed, 6949 insertions(+), 873 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/coresight.txt
 delete mode 100644 arch/arm/include/asm/hardware/coresight.h
 create mode 100644 arch/arm/include/asm/hardware/cp14.h
 delete mode 100644 arch/arm/kernel/etm.c
 delete mode 100644 arch/arm/mach-omap2/emu.c
 create mode 100644 drivers/coresight/Kconfig
 create mode 100644 drivers/coresight/Makefile
 create mode 100644 drivers/coresight/coresight-etb.c
 create mode 100644 drivers/coresight/coresight-etm-cp14.c
 create mode 100644 drivers/coresight/coresight-etm.c
 create mode 100644 drivers/coresight/coresight-funnel.c
 create mode 100644 drivers/coresight/coresight-priv.h
 create mode 100644 drivers/coresight/coresight-replicator.c
 create mode 100644 drivers/coresight/coresight-tmc.c
 create mode 100644 drivers/coresight/coresight-tpiu.c
 create mode 100644 drivers/coresight/coresight.c
 create mode 100644 drivers/coresight/of_coresight.c
 create mode 100644 include/linux/coresight.h
 create mode 100644 include/linux/of_coresight.h

-- 
1.9.1

--
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 10/11] coresight: adding support for beagleXM

2014-05-30 Thread mathieu . poirier
From: Mathieu Poirier mathieu.poir...@linaro.org

Currently supporting ETM and ETB.  Support for TPIU
and SDTI are yet to be added.

Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
---
 arch/arm/boot/dts/omap3-beagle-xm.dts | 30 ++
 1 file changed, 30 insertions(+)

diff --git a/arch/arm/boot/dts/omap3-beagle-xm.dts 
b/arch/arm/boot/dts/omap3-beagle-xm.dts
index 447e714..b39bede 100644
--- a/arch/arm/boot/dts/omap3-beagle-xm.dts
+++ b/arch/arm/boot/dts/omap3-beagle-xm.dts
@@ -86,6 +86,36 @@
reset-gpios = gpio5 19 GPIO_ACTIVE_LOW; /* gpio_147 */
vcc-supply = hsusb2_power;
};
+
+   coresight {
+   compatible = arm,coresight;
+   #address-cells = 1;
+   #size-cells = 1;
+   clocks = emu_src_ck;
+   ranges;
+
+   etb: etb@54000 {
+   compatible = arm,coresight-etb;
+   reg = 0x5401b000 0x1000;
+
+   coresight-id = 0;
+   coresight-name = coresight-etb;
+   coresight-nr-inports = 1;
+   coresight-default-sink;
+   };
+
+   etm@5401 {
+   compatible = arm,coresight-etm;
+   reg = 0x5401 0x1000;
+
+   coresight-id = 1;
+   coresight-name = coresight-etm;
+   coresight-nr-inports = 0;
+   coresight-outports = 0;
+   coresight-child-list = etb;
+   coresight-child-ports = 0;
+   };
+   };
 };
 
 omap3_pmx_wkup {
-- 
1.9.1

--
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 11/11] ARM: moving support for etb/etm to the drivers directory

2014-05-30 Thread mathieu . poirier
From: Mathieu Poirier mathieu.poir...@linaro.org

Removing minimal support for etb/etm to favour an implentation
that is more flexible, extensible and capable of handling more
platforms.

Also removing the only client of the old driver.  That code can
easily be replaced by entries for etb/etm in the device tree.

Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
---
 arch/arm/include/asm/hardware/coresight.h | 157 ---
 arch/arm/kernel/Makefile  |   1 -
 arch/arm/kernel/etm.c | 654 --
 arch/arm/kernel/hw_breakpoint.c   |   4 +-
 arch/arm/mach-omap2/Kconfig   |   8 -
 arch/arm/mach-omap2/Makefile  |   1 -
 arch/arm/mach-omap2/emu.c |  50 ---
 7 files changed, 2 insertions(+), 873 deletions(-)
 delete mode 100644 arch/arm/include/asm/hardware/coresight.h
 delete mode 100644 arch/arm/kernel/etm.c
 delete mode 100644 arch/arm/mach-omap2/emu.c

diff --git a/arch/arm/include/asm/hardware/coresight.h 
b/arch/arm/include/asm/hardware/coresight.h
deleted file mode 100644
index ad774f3..000
--- a/arch/arm/include/asm/hardware/coresight.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * linux/arch/arm/include/asm/hardware/coresight.h
- *
- * CoreSight components' registers
- *
- * Copyright (C) 2009 Nokia Corporation.
- * Alexander Shishkin
- *
- * 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.
- */
-
-#ifndef __ASM_HARDWARE_CORESIGHT_H
-#define __ASM_HARDWARE_CORESIGHT_H
-
-#define TRACER_ACCESSED_BIT0
-#define TRACER_RUNNING_BIT 1
-#define TRACER_CYCLE_ACC_BIT   2
-#define TRACER_ACCESSEDBIT(TRACER_ACCESSED_BIT)
-#define TRACER_RUNNING BIT(TRACER_RUNNING_BIT)
-#define TRACER_CYCLE_ACC   BIT(TRACER_CYCLE_ACC_BIT)
-
-#define TRACER_TIMEOUT 1
-
-#define etm_writel(t, v, x) \
-   (writel_relaxed((v), (t)-etm_regs + (x)))
-#define etm_readl(t, x) (readl_relaxed((t)-etm_regs + (x)))
-
-/* CoreSight Management Registers */
-#define CSMR_LOCKACCESS 0xfb0
-#define CSMR_LOCKSTATUS 0xfb4
-#define CSMR_AUTHSTATUS 0xfb8
-#define CSMR_DEVID 0xfc8
-#define CSMR_DEVTYPE   0xfcc
-/* CoreSight Component Registers */
-#define CSCR_CLASS 0xff4
-
-#define CS_LAR_KEY 0xc5acce55
-
-/* ETM control register, ETM Architecture, 3.3.1 */
-#define ETMR_CTRL  0
-#define ETMCTRL_POWERDOWN  1
-#define ETMCTRL_PROGRAM(1  10)
-#define ETMCTRL_PORTSEL(1  11)
-#define ETMCTRL_DO_CONTEXTID   (3  14)
-#define ETMCTRL_PORTMASK1  (7  4)
-#define ETMCTRL_PORTMASK2  (1  21)
-#define ETMCTRL_PORTMASK   (ETMCTRL_PORTMASK1 | ETMCTRL_PORTMASK2)
-#define ETMCTRL_PORTSIZE(x) x)  7)  4) | (!!((x)  8))  21)
-#define ETMCTRL_DO_CPRT(1  1)
-#define ETMCTRL_DATAMASK   (3  2)
-#define ETMCTRL_DATA_DO_DATA   (1  2)
-#define ETMCTRL_DATA_DO_ADDR   (1  3)
-#define ETMCTRL_DATA_DO_BOTH   (ETMCTRL_DATA_DO_DATA | ETMCTRL_DATA_DO_ADDR)
-#define ETMCTRL_BRANCH_OUTPUT  (1  8)
-#define ETMCTRL_CYCLEACCURATE  (1  12)
-
-/* ETM configuration code register */
-#define ETMR_CONFCODE  (0x04)
-
-/* ETM trace start/stop resource control register */
-#define ETMR_TRACESSCTRL   (0x18)
-
-/* ETM trigger event register */
-#define ETMR_TRIGEVT   (0x08)
-
-/* address access type register bits, ETM architecture,
- * table 3-27 */
-/* - access type */
-#define ETMAAT_IFETCH  0
-#define ETMAAT_IEXEC   1
-#define ETMAAT_IEXECPASS   2
-#define ETMAAT_IEXECFAIL   3
-#define ETMAAT_DLOADSTORE  4
-#define ETMAAT_DLOAD   5
-#define ETMAAT_DSTORE  6
-/* - comparison access size */
-#define ETMAAT_JAVA(0  3)
-#define ETMAAT_THUMB   (1  3)
-#define ETMAAT_ARM (3  3)
-/* - data value comparison control */
-#define ETMAAT_NOVALCMP(0  5)
-#define ETMAAT_VALMATCH(1  5)
-#define ETMAAT_VALNOMATCH  (3  5)
-/* - exact match */
-#define ETMAAT_EXACTMATCH  (1  7)
-/* - context id comparator control */
-#define ETMAAT_IGNCONTEXTID(0  8)
-#define ETMAAT_VALUE1  (1  8)
-#define ETMAAT_VALUE2  (2  8)
-#define ETMAAT_VALUE3  (3  8)
-/* - security level control */
-#define ETMAAT_IGNSECURITY (0  10)
-#define ETMAAT_NSONLY  (1  10)
-#define ETMAAT_SONLY   (2  10)
-
-#define ETMR_COMP_VAL(x)   (0x40 + (x) * 4)
-#define ETMR_COMP_ACC_TYPE(x)  (0x80 + (x) * 4)
-
-/* ETM status register, ETM Architecture, 3.3.2 */
-#define ETMR_STATUS(0x10)
-#define ETMST_OVERFLOW BIT(0)
-#define ETMST_PROGBIT  BIT(1)
-#define ETMST_STARTSTOPBIT(2)
-#define ETMST_TRIGGER  BIT(3)
-
-#define etm_progbit(t) (etm_readl((t), ETMR_STATUS)  ETMST_PROGBIT)
-#define etm_started(t) (etm_readl((t

[RFC PATCH 04/11] coresight: add CoreSight ETB driver

2014-05-30 Thread mathieu . poirier
From: Pratik Patel prat...@codeaurora.org

This driver manages CoreSight ETB (Embedded Trace Buffer) which
acts as a circular buffer sink collecting generated trace data.

Signed-off-by: Pratik Patel prat...@codeaurora.org
Signed-off-by: Panchaxari Prasannamurthy panchaxari.prasannamur...@linaro.org
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
---
 drivers/coresight/Makefile|   3 +-
 drivers/coresight/coresight-etb.c | 586 ++
 2 files changed, 588 insertions(+), 1 deletion(-)
 create mode 100644 drivers/coresight/coresight-etb.c

diff --git a/drivers/coresight/Makefile b/drivers/coresight/Makefile
index 540df99..8d4443b 100644
--- a/drivers/coresight/Makefile
+++ b/drivers/coresight/Makefile
@@ -3,4 +3,5 @@
 #
 obj-$(CONFIG_CORESIGHT) += coresight.o
 obj-$(CONFIG_OF) += of_coresight.o
-obj-$(CONFIG_CORESIGHT_LINKS_AND_SINKS) += coresight-tmc.o coresight-tpiu.o
+obj-$(CONFIG_CORESIGHT_LINKS_AND_SINKS) += coresight-tmc.o coresight-tpiu.o \
+  coresight-etb.o
diff --git a/drivers/coresight/coresight-etb.c 
b/drivers/coresight/coresight-etb.c
new file mode 100644
index 000..5cb0dcb
--- /dev/null
+++ b/drivers/coresight/coresight-etb.c
@@ -0,0 +1,586 @@
+/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include linux/kernel.h
+#include linux/module.h
+#include linux/init.h
+#include linux/types.h
+#include linux/device.h
+#include linux/platform_device.h
+#include linux/io.h
+#include linux/err.h
+#include linux/fs.h
+#include linux/miscdevice.h
+#include linux/uaccess.h
+#include linux/slab.h
+#include linux/delay.h
+#include linux/spinlock.h
+#include linux/clk.h
+#include linux/of_coresight.h
+#include linux/coresight.h
+
+#include coresight-priv.h
+
+#define etb_writel(drvdata, val, off)  __raw_writel((val), drvdata-base + off)
+#define etb_readl(drvdata, off)__raw_readl(drvdata-base + off)
+
+#define ETB_LOCK(drvdata)  \
+do {   \
+   /* wait for things to settle */ \
+   mb();   \
+   etb_writel(drvdata, 0x0, CORESIGHT_LAR);\
+} while (0)
+#define ETB_UNLOCK(drvdata)\
+do {   \
+   etb_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR);   \
+   /* make sure eveyone has seen this */   \
+   mb();   \
+} while (0)
+
+#define ETB_RAM_DEPTH_REG  (0x004)
+#define ETB_STATUS_REG (0x00C)
+#define ETB_RAM_READ_DATA_REG  (0x010)
+#define ETB_RAM_READ_POINTER   (0x014)
+#define ETB_RAM_WRITE_POINTER  (0x018)
+#define ETB_TRG(0x01C)
+#define ETB_CTL_REG(0x020)
+#define ETB_RWD_REG(0x024)
+#define ETB_FFSR   (0x300)
+#define ETB_FFCR   (0x304)
+#define ETB_ITMISCOP0  (0xEE0)
+#define ETB_ITTRFLINACK(0xEE4)
+#define ETB_ITTRFLIN   (0xEE8)
+#define ETB_ITATBDATA0 (0xEEC)
+#define ETB_ITATBCTR2  (0xEF0)
+#define ETB_ITATBCTR1  (0xEF4)
+#define ETB_ITATBCTR0  (0xEF8)
+
+#define BYTES_PER_WORD 4
+#define FRAME_SIZE_WORDS   4
+
+struct etb_drvdata {
+   void __iomem*base;
+   struct device   *dev;
+   struct coresight_device *csdev;
+   struct miscdevice   miscdev;
+   struct clk  *clk;
+   spinlock_t  spinlock;
+   boolreading;
+   atomic_tin_use;
+   uint8_t *buf;
+   uint32_tbuffer_depth;
+   boolenable;
+   uint32_ttrigger_cntr;
+};
+
+static unsigned int etb_get_buffer_depth(struct etb_drvdata *drvdata)
+{
+   int ret;
+   uint32_t depth = 0;
+
+   ret = clk_prepare_enable(drvdata-clk);
+   if (ret)
+   return ret;
+
+   /* RO registers don't need locking */
+   depth = etb_readl(drvdata, ETB_RAM_DEPTH_REG);
+
+   clk_disable_unprepare(drvdata-clk);
+   return depth;
+}
+
+static void __etb_enable(struct etb_drvdata *drvdata)
+{
+   int i;
+   uint32_t depth;
+
+   ETB_UNLOCK

[RFC PATCH 09/11] coresight: adding basic support for Vexpress TC2

2014-05-30 Thread mathieu . poirier
From: Mathieu Poirier mathieu.poir...@linaro.org

Support for the 2 PTMs, 3 ETMs, funnel, TPIU and replicator
connected to the ETB are included.  Proper handling of the
ITM and the replicator linked to it along with the CTIs
and SWO are not included.

Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
---
 arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts | 122 +
 1 file changed, 122 insertions(+)

diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts 
b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
index 15f98cb..18de06e 100644
--- a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
+++ b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
@@ -334,6 +334,128 @@
};
};
 
+   coresight {
+   compatible = arm,coresight;
+   #address-cells = 1;
+   #size-cells = 1;
+   ranges = 0x2001 0 0x2001 0x1000
+ 0x2003 0 0x2003 0x1000
+ 0x2004 0 0x2004 0x1000
+ 0x2201c000 0 0x2201c000 0x1000
+ 0x2201d000 0 0x2201d000 0x1000
+ 0x2203c000 0 0x2203c000 0x1000
+ 0x2203d000 0 0x2203d000 0x1000
+ 0x2203e000 0 0x2203e000 0x1000;
+
+   etb: etb@2001 {
+   compatible = arm,coresight-etb;
+   reg = 0x2001 0x1000;
+
+   coresight-id = 0;
+   coresight-name = coresight-etb;
+   coresight-nr-inports = 1;
+   coresight-default-sink;
+   };
+
+   etb_replicator: replicator {
+   compatible = arm,coresight-replicator;
+
+   coresight-id = 1;
+   coresight-name = coresight-etb-replicator;
+   coresight-nr-inports = 1;
+   coresight-outports = 0 1;
+   coresight-child-list = etb tpiu;
+   coresight-child-ports = 0 0;
+   };
+
+   tpiu: tpiu@2003 {
+   compatible = arm,coresight-tpiu;
+   reg = 0x2003 0x1000;
+
+   coresight-id = 2;
+   coresight-name = coresight-tpiu;
+   coresight-nr-inports = 1;
+   };
+
+   funnel: funnel@2004 {
+   compatible = arm,coresight-funnel;
+   reg = 0x2004 0x1000;
+
+   coresight-id = 3;
+   coresight-name = coresight-funnel;
+   coresight-nr-inports = 1;
+   coresight-outports = 0;
+   coresight-child-list = etb_replicator;
+   coresight-child-ports = 0;
+   };
+
+   ptm0: ptm@2201c000 {
+   compatible = arm,coresight-etm;
+   reg = 0x2201c000 0x1000;
+
+   coresight-id = 4;
+   coresight-name = coresight-ptm0;
+   cpu = cpu0;
+   coresight-nr-inports = 0;
+   coresight-outports = 0;
+   coresight-child-list = funnel;
+   coresight-child-ports = 0;
+   };
+
+   ptm1: ptm@2201d000 {
+   compatible = arm,coresight-etm;
+   reg = 0x2201d000 0x1000;
+
+   coresight-id = 5;
+   coresight-name = coresight-ptm1;
+   cpu = cpu1;
+   coresight-nr-inports = 0;
+   coresight-outports = 0;
+   coresight-child-list = funnel;
+   coresight-child-ports = 1;
+   };
+
+   etm0: etm@2203c000 {
+   compatible = arm,coresight-etm;
+   reg = 0x2203c000 0x1000;
+
+   coresight-id = 6;
+   coresight-name = coresight-etm0;
+   cpu = cpu2;
+   coresight-nr-inports = 0;
+   coresight-outports = 0;
+   coresight-child-list = funnel;
+   coresight-child-ports = 2;
+   };
+
+   etm1: etm@2203d000 {
+   compatible = arm,coresight-etm;
+   reg = 0x2203d000 0x1000;
+
+   coresight-id = 7;
+   coresight-name = coresight-etm1;
+   cpu = cpu3;
+   coresight-nr-inports = 0;
+   coresight-outports = 0;
+   coresight-child-list = funnel;
+   coresight-child-ports = 4;
+   };
+
+   etm2: etm@2203e000

[RFC PATCH 03/11] coresight: add CoreSight TPIU driver

2014-05-30 Thread mathieu . poirier
From: Pratik Patel prat...@codeaurora.org

This driver manages CoreSight TPIU (Trace Port Interface Unit)
which acts as a sink. TPIU is typically connected to some offchip
hardware hosting a storage buffer.

Signed-off-by: Pratik Patel prat...@codeaurora.org
Signed-off-by: Panchaxari Prasannamurthy panchaxari.prasannamur...@linaro.org
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
---
 drivers/coresight/Makefile |   2 +-
 drivers/coresight/coresight-tpiu.c | 229 +
 2 files changed, 230 insertions(+), 1 deletion(-)
 create mode 100644 drivers/coresight/coresight-tpiu.c

diff --git a/drivers/coresight/Makefile b/drivers/coresight/Makefile
index 16e26c5..540df99 100644
--- a/drivers/coresight/Makefile
+++ b/drivers/coresight/Makefile
@@ -3,4 +3,4 @@
 #
 obj-$(CONFIG_CORESIGHT) += coresight.o
 obj-$(CONFIG_OF) += of_coresight.o
-obj-$(CONFIG_CORESIGHT_LINKS_AND_SINKS) += coresight-tmc.o
+obj-$(CONFIG_CORESIGHT_LINKS_AND_SINKS) += coresight-tmc.o coresight-tpiu.o
diff --git a/drivers/coresight/coresight-tpiu.c 
b/drivers/coresight/coresight-tpiu.c
new file mode 100644
index 000..b552d1e
--- /dev/null
+++ b/drivers/coresight/coresight-tpiu.c
@@ -0,0 +1,229 @@
+/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include linux/kernel.h
+#include linux/module.h
+#include linux/init.h
+#include linux/device.h
+#include linux/platform_device.h
+#include linux/io.h
+#include linux/err.h
+#include linux/slab.h
+#include linux/clk.h
+#include linux/of_coresight.h
+#include linux/coresight.h
+
+#include coresight-priv.h
+
+#define tpiu_writel(drvdata, val, off) __raw_writel((val), drvdata-base + off)
+#define tpiu_readl(drvdata, off)   __raw_readl(drvdata-base + off)
+
+#define TPIU_LOCK(drvdata) \
+do {   \
+   /* wait for things to settle */ \
+   mb();   \
+   tpiu_writel(drvdata, 0x0, CORESIGHT_LAR);   \
+} while (0)
+#define TPIU_UNLOCK(drvdata)   \
+do {   \
+   tpiu_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR);  \
+   /* make sure everyone has seen this */  \
+   mb();   \
+} while (0)
+
+#define TPIU_SUPP_PORTSZ   (0x000)
+#define TPIU_CURR_PORTSZ   (0x004)
+#define TPIU_SUPP_TRIGMODES(0x100)
+#define TPIU_TRIG_CNTRVAL  (0x104)
+#define TPIU_TRIG_MULT (0x108)
+#define TPIU_SUPP_TESTPATM (0x200)
+#define TPIU_CURR_TESTPATM (0x204)
+#define TPIU_TEST_PATREPCNTR   (0x208)
+#define TPIU_FFSR  (0x300)
+#define TPIU_FFCR  (0x304)
+#define TPIU_FSYNC_CNTR(0x308)
+#define TPIU_EXTCTL_INPORT (0x400)
+#define TPIU_EXTCTL_OUTPORT(0x404)
+#define TPIU_ITTRFLINACK   (0xEE4)
+#define TPIU_ITTRFLIN  (0xEE8)
+#define TPIU_ITATBDATA0(0xEEC)
+#define TPIU_ITATBCTR2 (0xEF0)
+#define TPIU_ITATBCTR1 (0xEF4)
+#define TPIU_ITATBCTR0 (0xEF8)
+
+struct tpiu_drvdata {
+   void __iomem*base;
+   struct device   *dev;
+   struct coresight_device *csdev;
+   struct clk  *clk;
+};
+
+static void __tpiu_enable(struct tpiu_drvdata *drvdata)
+{
+   TPIU_UNLOCK(drvdata);
+
+   /* TODO: fill this up */
+
+   TPIU_LOCK(drvdata);
+}
+
+static int tpiu_enable(struct coresight_device *csdev)
+{
+   struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev-dev.parent);
+   int ret;
+
+   ret = clk_prepare_enable(drvdata-clk);
+   if (ret)
+   return ret;
+
+   __tpiu_enable(drvdata);
+
+   dev_info(drvdata-dev, TPIU enabled\n);
+   return 0;
+}
+
+static void __tpiu_disable(struct tpiu_drvdata *drvdata)
+{
+   TPIU_UNLOCK(drvdata);
+
+   tpiu_writel(drvdata, 0x3000, TPIU_FFCR);
+   tpiu_writel(drvdata, 0x3040, TPIU_FFCR);
+
+   TPIU_LOCK(drvdata);
+}
+
+static void tpiu_disable(struct coresight_device *csdev)
+{
+   struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev-dev.parent);
+
+   __tpiu_disable(drvdata);
+
+   clk_disable_unprepare(drvdata-clk);
+
+   dev_info(drvdata-dev, TPIU disabled\n);
+}
+
+static void

[RFC PATCH 01/11] coresight: add CoreSight core layer framework

2014-05-30 Thread mathieu . poirier
From: Pratik Patel prat...@codeaurora.org

CoreSight components are compliant with the ARM CoreSight
architecture specification and can be connected in various
topologies to suite a particular SoCs tracing needs. These trace
components can generally be classified as sources, links and
sinks. Trace data produced by one or more sources flows through
the intermediate links connecting the source to the currently
selected sink.

CoreSight framework provides an interface for the CoreSight trace
drivers to register themselves with. It's intended to build up a
topological view of the CoreSight components and configure the
right series of components on user input via debugfs.

For eg., when enabling a source, framework builds up a path
consisting of all the components connecting the source to the
currently selected sink and enables all of them.

Framework also supports switching between available sinks and
also provides status information to user space applications
through sysfs interface.

Signed-off-by: Pratik Patel prat...@codeaurora.org
Signed-off-by: Panchaxari Prasannamurthy panchaxari.prasannamur...@linaro.org
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
---
 .../devicetree/bindings/arm/coresight.txt  | 138 
 drivers/Kconfig|   2 +
 drivers/Makefile   |   1 +
 drivers/coresight/Kconfig  |   9 +
 drivers/coresight/Makefile |   5 +
 drivers/coresight/coresight-priv.h |  46 ++
 drivers/coresight/coresight.c  | 739 +
 drivers/coresight/of_coresight.c   | 124 
 include/linux/coresight.h  | 181 +
 include/linux/of_coresight.h   |  27 +
 10 files changed, 1272 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/coresight.txt
 create mode 100644 drivers/coresight/Kconfig
 create mode 100644 drivers/coresight/Makefile
 create mode 100644 drivers/coresight/coresight-priv.h
 create mode 100644 drivers/coresight/coresight.c
 create mode 100644 drivers/coresight/of_coresight.c
 create mode 100644 include/linux/coresight.h
 create mode 100644 include/linux/of_coresight.h

diff --git a/Documentation/devicetree/bindings/arm/coresight.txt 
b/Documentation/devicetree/bindings/arm/coresight.txt
new file mode 100644
index 000..3e21665
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/coresight.txt
@@ -0,0 +1,138 @@
+* CoreSight Components
+
+CoreSight components are compliant with the ARM CoreSight architecture
+specification and can be connected in various topologies to suite a particular
+SoCs tracing needs. These trace components can generally be classified as 
sinks,
+links and sources. Trace data produced by one or more sources flows through the
+intermediate links connecting the source to the currently selected sink. Each
+CoreSight component device should use these properties to describe its hardware
+characteristcs.
+
+Required properties:
+
+- compatible : name of the component used for driver matching
+- reg : physical base address and length of the register set(s) of the 
component
+- coresight-id : unique integer identifier for the component
+- coresight-name : unique descriptive name of the component
+- coresight-nr-inports : number of input ports on the component
+
+coresight-outports, coresight-child-list and coresight-child-ports lists will
+be of the same length and will have a one to one correspondence among the
+elements at the same list index.
+
+coresight-default-sink must be specified for one of the sink devices that is
+intended to be made the default sink. Other sink devices must not have this
+specified. Not specifying this property on any of the sinks is invalid.
+
+Optional properties:
+
+- coresight-outports : list of output port numbers of this component
+- coresight-child-list : list of phandles pointing to the children of this
+component
+- coresight-child-ports : list of input port numbers of the children
+- coresight-default-sink : represents the default compile time CoreSight sink
+- arm,buffer-size : size of contiguous buffer space for TMC ETR
+- arm,cp14 : cp14 access to ETM registers is implemented and should be used
+- clocks : the clock associated to the coresight entity.
+- cpu: only valid for ETM/PTMs - the cpu this ETM/PTM is affined to.
+
+Example:
+
+1. Bus declaration:
+   coresight {
+   compatible = arm,coresight;
+   #address-cells = 1;
+   #size-cells = 1;
+   ranges;
+   ...
+   ...
+   ...
+};
+
+coresight {
+   compatible = arm,coresight;
+   #address-cells = 1;
+   #size-cells = 1;
+   ranges = 0x2001 0 0x2001 0x1000
+ 0x2003 0 0x2003 0x1000

[RFC PATCH 05/11] coresight: add CoreSight Funnel driver

2014-05-30 Thread mathieu . poirier
From: Pratik Patel prat...@codeaurora.org

This driver manages CoreSight Funnel which acts as a link.
Funnels have multiple input ports (typically 8) each of which
represents an input trace data stream. These multiple input trace
data streams are interleaved into a single output stream coming
out of the Funnel.

Signed-off-by: Pratik Patel prat...@codeaurora.org
Signed-off-by: Panchaxari Prasannamurthy panchaxari.prasannamur...@linaro.org
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
---
 drivers/coresight/Makefile   |   2 +-
 drivers/coresight/coresight-funnel.c | 310 +++
 2 files changed, 311 insertions(+), 1 deletion(-)
 create mode 100644 drivers/coresight/coresight-funnel.c

diff --git a/drivers/coresight/Makefile b/drivers/coresight/Makefile
index 8d4443b..1f66804 100644
--- a/drivers/coresight/Makefile
+++ b/drivers/coresight/Makefile
@@ -4,4 +4,4 @@
 obj-$(CONFIG_CORESIGHT) += coresight.o
 obj-$(CONFIG_OF) += of_coresight.o
 obj-$(CONFIG_CORESIGHT_LINKS_AND_SINKS) += coresight-tmc.o coresight-tpiu.o \
-  coresight-etb.o
+  coresight-etb.o coresight-funnel.o
diff --git a/drivers/coresight/coresight-funnel.c 
b/drivers/coresight/coresight-funnel.c
new file mode 100644
index 000..c1024df
--- /dev/null
+++ b/drivers/coresight/coresight-funnel.c
@@ -0,0 +1,310 @@
+/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include linux/kernel.h
+#include linux/module.h
+#include linux/init.h
+#include linux/types.h
+#include linux/device.h
+#include linux/platform_device.h
+#include linux/io.h
+#include linux/err.h
+#include linux/fs.h
+#include linux/slab.h
+#include linux/clk.h
+#include linux/of_coresight.h
+#include linux/coresight.h
+
+#include coresight-priv.h
+
+#define funnel_writel(drvdata, val, off)   \
+   __raw_writel((val), drvdata-base + off)
+#define funnel_readl(drvdata, off) \
+   __raw_readl(drvdata-base + off)
+
+#define FUNNEL_LOCK(drvdata)   \
+do {   \
+   /* wait for things to settle */ \
+   mb();   \
+   funnel_writel(drvdata, 0x0, CORESIGHT_LAR); \
+} while (0)
+#define FUNNEL_UNLOCK(drvdata) \
+do {   \
+   funnel_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR);\
+   /* make sure everyone has seen this */  \
+   mb();   \
+} while (0)
+
+#define FUNNEL_FUNCTL  (0x000)
+#define FUNNEL_PRICTL  (0x004)
+
+#define FUNNEL_HOLDTIME_MASK   (0xF00)
+#define FUNNEL_HOLDTIME_SHFT   (0x8)
+#define FUNNEL_HOLDTIME(0x7  FUNNEL_HOLDTIME_SHFT)
+
+struct funnel_drvdata {
+   void __iomem*base;
+   struct device   *dev;
+   struct coresight_device *csdev;
+   struct clk  *clk;
+   uint32_tpriority;
+};
+
+static void __funnel_enable(struct funnel_drvdata *drvdata, int port)
+{
+   uint32_t functl;
+
+   FUNNEL_UNLOCK(drvdata);
+
+   functl = funnel_readl(drvdata, FUNNEL_FUNCTL);
+   functl = ~FUNNEL_HOLDTIME_MASK;
+   functl |= FUNNEL_HOLDTIME;
+   functl |= (1  port);
+   funnel_writel(drvdata, functl, FUNNEL_FUNCTL);
+   funnel_writel(drvdata, drvdata-priority, FUNNEL_PRICTL);
+
+   FUNNEL_LOCK(drvdata);
+}
+
+static int funnel_enable(struct coresight_device *csdev, int inport,
+int outport)
+{
+   struct funnel_drvdata *drvdata = dev_get_drvdata(csdev-dev.parent);
+   int ret;
+
+   ret = clk_prepare_enable(drvdata-clk);
+   if (ret)
+   return ret;
+
+   __funnel_enable(drvdata, inport);
+
+   dev_info(drvdata-dev, FUNNEL inport %d enabled\n, inport);
+   return 0;
+}
+
+static void __funnel_disable(struct funnel_drvdata *drvdata, int inport)
+{
+   uint32_t functl;
+
+   FUNNEL_UNLOCK(drvdata);
+
+   functl = funnel_readl(drvdata, FUNNEL_FUNCTL);
+   functl = ~(1  inport);
+   funnel_writel(drvdata, functl, FUNNEL_FUNCTL);
+
+   FUNNEL_LOCK(drvdata);
+}
+
+static void

[RFC PATCH 02/11] coresight: add CoreSight TMC driver

2014-05-30 Thread mathieu . poirier
From: Pratik Patel prat...@codeaurora.org

This driver manages CoreSight TMC (Trace Memory Controller) which
can act as a link or a sink depending upon its configuration. It
can present itself as an ETF (Embedded Trace FIFO) or ETR
(Embedded Trace Router).

ETF when configured in circular buffer mode acts as a trace
collection sink. When configured in HW fifo mode it acts as link.
ETR always acts as a sink and can be used to route data to memory
allocated in RAM.

Signed-off-by: Pratik Patel prat...@codeaurora.org
Signed-off-by: Panchaxari Prasannamurthy panchaxari.prasannamur...@linaro.org
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
---
 drivers/coresight/Kconfig |  11 +
 drivers/coresight/Makefile|   1 +
 drivers/coresight/coresight-tmc.c | 796 ++
 3 files changed, 808 insertions(+)
 create mode 100644 drivers/coresight/coresight-tmc.c

diff --git a/drivers/coresight/Kconfig b/drivers/coresight/Kconfig
index 88fd44a..224903b 100644
--- a/drivers/coresight/Kconfig
+++ b/drivers/coresight/Kconfig
@@ -7,3 +7,14 @@ menuconfig CORESIGHT
  the right series of components on user input via sysfs. It also
  provides status information to user space applications through
  the debugfs interface.
+
+if CORESIGHT
+
+config CORESIGHT_LINKS_AND_SINKS
+   bool CoreSight Link and Sink drivers
+   help
+ This enables support for CoreSight link and sink drivers that are
+ responsible for transporting and collecting the trace data
+ respectively.
+
+endif
diff --git a/drivers/coresight/Makefile b/drivers/coresight/Makefile
index 218e3b5..16e26c5 100644
--- a/drivers/coresight/Makefile
+++ b/drivers/coresight/Makefile
@@ -3,3 +3,4 @@
 #
 obj-$(CONFIG_CORESIGHT) += coresight.o
 obj-$(CONFIG_OF) += of_coresight.o
+obj-$(CONFIG_CORESIGHT_LINKS_AND_SINKS) += coresight-tmc.o
diff --git a/drivers/coresight/coresight-tmc.c 
b/drivers/coresight/coresight-tmc.c
new file mode 100644
index 000..afcab7c
--- /dev/null
+++ b/drivers/coresight/coresight-tmc.c
@@ -0,0 +1,796 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include linux/kernel.h
+#include linux/module.h
+#include linux/init.h
+#include linux/types.h
+#include linux/device.h
+#include linux/platform_device.h
+#include linux/io.h
+#include linux/err.h
+#include linux/fs.h
+#include linux/miscdevice.h
+#include linux/uaccess.h
+#include linux/slab.h
+#include linux/dma-mapping.h
+#include linux/delay.h
+#include linux/spinlock.h
+#include linux/clk.h
+#include linux/of.h
+#include linux/of_coresight.h
+#include linux/coresight.h
+
+#include coresight-priv.h
+
+#define tmc_writel(drvdata, val, off)  __raw_writel((val), drvdata-base + off)
+#define tmc_readl(drvdata, off)__raw_readl(drvdata-base + off)
+
+#define TMC_LOCK(drvdata)  \
+do {   \
+   /* settle everything first */   \
+   mb();   \
+   tmc_writel(drvdata, 0x0, CORESIGHT_LAR);\
+} while (0)
+#define TMC_UNLOCK(drvdata)\
+do {   \
+   tmc_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR);   \
+   /* make sure everyone sees this */  \
+   mb();   \
+} while (0)
+
+#define TMC_RSZ(0x004)
+#define TMC_STS(0x00C)
+#define TMC_RRD(0x010)
+#define TMC_RRP(0x014)
+#define TMC_RWP(0x018)
+#define TMC_TRG(0x01C)
+#define TMC_CTL(0x020)
+#define TMC_RWD(0x024)
+#define TMC_MODE   (0x028)
+#define TMC_LBUFLEVEL  (0x02C)
+#define TMC_CBUFLEVEL  (0x030)
+#define TMC_BUFWM  (0x034)
+#define TMC_RRPHI  (0x038)
+#define TMC_RWPHI  (0x03C)
+#define TMC_AXICTL (0x110)
+#define TMC_DBALO  (0x118)
+#define TMC_DBAHI  (0x11C)
+#define TMC_FFSR   (0x300)
+#define TMC_FFCR   (0x304)
+#define TMC_PSCR   (0x308)
+#define TMC_ITMISCOP0  (0xEE0

Re: [RFC PATCH 04/11] coresight: add CoreSight ETB driver

2014-05-30 Thread Mathieu Poirier
On 30 May 2014 07:53, Russell King - ARM Linux li...@arm.linux.org.uk wrote:
 NAK for all the reasons I mentioned in the previous submission in 2012.

 You partially did the right thing - you read through the previous
 submission, and you said in your cover message that you had addressed
 some of the comments from that submission.

 What I find extremely distasteful is that you seem to have chosen to
 completely ignore my comments - you haven't mentioned them in your
 covering message at all, and you've just gone ahead and converted ETM
 and ETB to be platform devices.

 That gets you a NAK for that change, because you have done nothing what
 so ever to address the concerns I raised.

From my initial reading of your assessment it wasn't clear to me that
your opinion leaned toward registering with the AMBA bus.  Now that
this point has been clarified I will go back to the AMBA interface for
my next submission.

Is there anything else not AMBA releated that you'd like to see modified?

Thanks,
Mathieu


 Since you seem to have ignored my comments, this is as far as I'm looking
 at your submission, and you can consider the entire submission NAK'd by
 me.

 Thanks.

 --
 FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
 improving, and getting towards what was expected from it.
--
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/


Re: [RFC PATCH 01/11] coresight: add CoreSight core layer framework

2014-05-30 Thread Mathieu Poirier
On 30 May 2014 11:25, Rob Herring robherri...@gmail.com wrote:
 On Fri, May 30, 2014 at 8:43 AM,  mathieu.poir...@linaro.org wrote:
 From: Pratik Patel prat...@codeaurora.org

 CoreSight components are compliant with the ARM CoreSight
 architecture specification and can be connected in various
 topologies to suite a particular SoCs tracing needs. These trace
 components can generally be classified as sources, links and
 sinks. Trace data produced by one or more sources flows through
 the intermediate links connecting the source to the currently
 selected sink.

 CoreSight framework provides an interface for the CoreSight trace
 drivers to register themselves with. It's intended to build up a
 topological view of the CoreSight components and configure the
 right series of components on user input via debugfs.

 For eg., when enabling a source, framework builds up a path
 consisting of all the components connecting the source to the
 currently selected sink and enables all of them.

 Framework also supports switching between available sinks and
 also provides status information to user space applications
 through sysfs interface.

 Signed-off-by: Pratik Patel prat...@codeaurora.org
 Signed-off-by: Panchaxari Prasannamurthy 
 panchaxari.prasannamur...@linaro.org
 Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
 ---
  .../devicetree/bindings/arm/coresight.txt  | 138 
  drivers/Kconfig|   2 +
  drivers/Makefile   |   1 +
  drivers/coresight/Kconfig  |   9 +
  drivers/coresight/Makefile |   5 +
  drivers/coresight/coresight-priv.h |  46 ++
  drivers/coresight/coresight.c  | 739 
 +
  drivers/coresight/of_coresight.c   | 124 
  include/linux/coresight.h  | 181 +
  include/linux/of_coresight.h   |  27 +
  10 files changed, 1272 insertions(+)
  create mode 100644 Documentation/devicetree/bindings/arm/coresight.txt
  create mode 100644 drivers/coresight/Kconfig
  create mode 100644 drivers/coresight/Makefile
  create mode 100644 drivers/coresight/coresight-priv.h
  create mode 100644 drivers/coresight/coresight.c
  create mode 100644 drivers/coresight/of_coresight.c
  create mode 100644 include/linux/coresight.h
  create mode 100644 include/linux/of_coresight.h

 diff --git a/Documentation/devicetree/bindings/arm/coresight.txt 
 b/Documentation/devicetree/bindings/arm/coresight.txt
 new file mode 100644
 index 000..3e21665
 --- /dev/null
 +++ b/Documentation/devicetree/bindings/arm/coresight.txt
 @@ -0,0 +1,138 @@
 +* CoreSight Components
 +
 +CoreSight components are compliant with the ARM CoreSight architecture
 +specification and can be connected in various topologies to suite a 
 particular
 +SoCs tracing needs. These trace components can generally be classified as 
 sinks,
 +links and sources. Trace data produced by one or more sources flows through 
 the
 +intermediate links connecting the source to the currently selected sink. 
 Each
 +CoreSight component device should use these properties to describe its 
 hardware
 +characteristcs.
 +
 +Required properties:
 +
 +- compatible : name of the component used for driver matching

 Where are the specific strings for components?

Coresight is made of multiple components with each component needing
a different driver.

 +- reg : physical base address and length of the register set(s) of the 
 component
 +- coresight-id : unique integer identifier for the component

 compatible + reg is a unique id.

Some coresight IP blocks like the replicator don't have a reg property
- the coresight-id and coresight-name are the only way to identify
them properly.


 +- coresight-name : unique descriptive name of the component

 compatible is a descriptive name.

That is what ends up under /sys/kernel/debug/coresight/.  Since there
can be multiple entity of the same type it is easier and more
convivial for users.  For instance: coresight-etb-replicator and
coresight-tpiu-replicator are easier to identify than
coresight-replicator0 and coresight-replicator1.

We need to keep coresight-id or coresight-name - I prefer the
former.  What is your take on this?


 +- coresight-nr-inports : number of input ports on the component
 +
 +coresight-outports, coresight-child-list and coresight-child-ports lists 
 will
 +be of the same length and will have a one to one correspondence among the
 +elements at the same list index.
 +
 +coresight-default-sink must be specified for one of the sink devices that is
 +intended to be made the default sink. Other sink devices must not have this
 +specified. Not specifying this property on any of the sinks is invalid.

 Why do you need the default-sink in DT? Isn't the configuration going
 to depend on the user?

Users can change this at will via debugfs.  It's a default boot time
configuration

Re: [RFC PATCH 02/11] coresight: add CoreSight TMC driver

2014-06-16 Thread Mathieu Poirier
Thanks for the review - please see comments in-lined.

Mathieu

On 3 June 2014 03:09, Linus Walleij linus.wall...@linaro.org wrote:
 On Fri, May 30, 2014 at 3:43 PM,  mathieu.poir...@linaro.org wrote:

 +#define tmc_writel(drvdata, val, off)  __raw_writel((val), drvdata-base + 
 off)
 +#define tmc_readl(drvdata, off)__raw_readl(drvdata-base + 
 off)

 Why not writel_relaxed()/readl_relaxed()?

Done.


 Using __raw* accessors seem a bit thick. (Applies to all such defines.)

 +#define TMC_LOCK(drvdata)  \
 +do {   \
 +   /* settle everything first */   \
 +   mb();   \
 +   tmc_writel(drvdata, 0x0, CORESIGHT_LAR);\
 +} while (0)
 +#define TMC_UNLOCK(drvdata)\
 +do {   \
 +   tmc_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR);   \
 +   /* make sure everyone sees this */  \
 +   mb();   \
 +} while (0)

 Convert these to static inlines. No need for them to be #defines
 at all really.

Done.


 +#define BYTES_PER_WORD 4

 But please. Just using the number 4 everywhere is clear enough.

 +struct tmc_drvdata {
 +   void __iomem*base;
 +   struct device   *dev;
 +   struct coresight_device *csdev;
 +   struct miscdevice   miscdev;
 +   struct clk  *clk;
 +   spinlock_t  spinlock;
 +   int read_count;

 Can this really be negative?

It is useful for debugging, as an example see tmc_release().  If the
count drops below '0' there is obviously a problem.  Do you see a cost
in keeping this as an 'int'?  What do you advise here?


 +   boolreading;
 +   char*buf;
 +   dma_addr_t  paddr;
 +   void __iomem*vaddr;
 +   uint32_tsize;

 Use u32

 +   boolenable;
 +   enum tmc_config_typeconfig_type;
 +   uint32_ttrigger_cntr;

 Use u32

 +};

 This struct overall could use some kerneldoc.

Would writing a comment for each field qualify?


 +static void tmc_flush_and_stop(struct tmc_drvdata *drvdata)
 +{
 +   int count;

 Why not call this variable i as per convention.

 +   uint32_t ffcr;

 u32

 +
 +   ffcr = tmc_readl(drvdata, TMC_FFCR);
 +   ffcr |= BIT(12);
 +   tmc_writel(drvdata, ffcr, TMC_FFCR);
 +   ffcr |= BIT(6);

 A bit unclear what bit 12 and 6 does. Either #define them or add comments.

 +   tmc_writel(drvdata, ffcr, TMC_FFCR);
 +   /* Ensure flush completes */
 +   for (count = TIMEOUT_US; BVAL(tmc_readl(drvdata, TMC_FFCR), 6) != 0
 +count  0; count--)
 +   udelay(1);
 +   WARN(count == 0, timeout while flushing TMC, TMC_FFCR: %#x\n,
 +tmc_readl(drvdata, TMC_FFCR));
 +
 +   tmc_wait_for_ready(drvdata);
 +}
 +
 +static void __tmc_enable(struct tmc_drvdata *drvdata)
 +{
 +   tmc_writel(drvdata, 0x1, TMC_CTL);
 +}
 +
 +static void __tmc_disable(struct tmc_drvdata *drvdata)
 +{
 +   tmc_writel(drvdata, 0x0, TMC_CTL);
 +}

 I actually understand what bit 0 does in this register, but could
 also be #defined.

 +static void __tmc_etb_enable(struct tmc_drvdata *drvdata)
 +{
 +   /* Zero out the memory to help with debug */
 +   memset(drvdata-buf, 0, drvdata-size);
 +
 +   TMC_UNLOCK(drvdata);
 +
 +   tmc_writel(drvdata, TMC_MODE_CIRCULAR_BUFFER, TMC_MODE);
 +   tmc_writel(drvdata, 0x133, TMC_FFCR);

 0x133? Que ce que c'est?

 +   tmc_writel(drvdata, drvdata-trigger_cntr, TMC_TRG);
 +   __tmc_enable(drvdata);
 +
 +   TMC_LOCK(drvdata);
 +}
 +
 +static void __tmc_etr_enable(struct tmc_drvdata *drvdata)
 +{
 +   uint32_t axictl;

 u32

 +   /* Zero out the memory to help with debug */
 +   memset(drvdata-vaddr, 0, drvdata-size);
 +
 +   TMC_UNLOCK(drvdata);
 +
 +   tmc_writel(drvdata, drvdata-size / BYTES_PER_WORD, TMC_RSZ);
 +   tmc_writel(drvdata, TMC_MODE_CIRCULAR_BUFFER, TMC_MODE);
 +
 +   axictl = tmc_readl(drvdata, TMC_AXICTL);
 +   axictl |= (0xF  8);
 +   tmc_writel(drvdata, axictl, TMC_AXICTL);
 +   axictl = ~(0x1  7);
 +   tmc_writel(drvdata, axictl, TMC_AXICTL);
 +   axictl = (axictl  ~0x3) | 0x2;
 +   tmc_writel(drvdata, axictl, TMC_AXICTL);

 I don't understand these bits and shifts either.

 +   tmc_writel(drvdata, drvdata-paddr, TMC_DBALO);
 +   tmc_writel(drvdata, 0x0, TMC_DBAHI);
 +   tmc_writel(drvdata, 0x133, TMC_FFCR);

 More magic...

 +   tmc_writel(drvdata, drvdata-trigger_cntr, 

[PATCH 9/9 v2] ARM: removing support for etb/etm in arch/arm/kernel/

2014-06-27 Thread mathieu . poirier
From: Mathieu Poirier mathieu.poir...@linaro.org

Removing minimal support for etb/etm to favour an implentation
that is more flexible, extensible and capable of handling more
platforms.

Also removing the only client of the old driver.  That code can
easily be replaced by entries for etb/etm in the device tree.

Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
---
 arch/arm/include/asm/hardware/coresight.h | 157 ---
 arch/arm/kernel/Makefile  |   1 -
 arch/arm/kernel/etm.c | 654 --
 arch/arm/kernel/hw_breakpoint.c   |   4 +-
 arch/arm/mach-omap2/Kconfig   |   8 -
 arch/arm/mach-omap2/Makefile  |   1 -
 arch/arm/mach-omap2/emu.c |  50 ---
 7 files changed, 2 insertions(+), 873 deletions(-)
 delete mode 100644 arch/arm/include/asm/hardware/coresight.h
 delete mode 100644 arch/arm/kernel/etm.c
 delete mode 100644 arch/arm/mach-omap2/emu.c

diff --git a/arch/arm/include/asm/hardware/coresight.h 
b/arch/arm/include/asm/hardware/coresight.h
deleted file mode 100644
index ad774f3..000
--- a/arch/arm/include/asm/hardware/coresight.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * linux/arch/arm/include/asm/hardware/coresight.h
- *
- * CoreSight components' registers
- *
- * Copyright (C) 2009 Nokia Corporation.
- * Alexander Shishkin
- *
- * 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.
- */
-
-#ifndef __ASM_HARDWARE_CORESIGHT_H
-#define __ASM_HARDWARE_CORESIGHT_H
-
-#define TRACER_ACCESSED_BIT0
-#define TRACER_RUNNING_BIT 1
-#define TRACER_CYCLE_ACC_BIT   2
-#define TRACER_ACCESSEDBIT(TRACER_ACCESSED_BIT)
-#define TRACER_RUNNING BIT(TRACER_RUNNING_BIT)
-#define TRACER_CYCLE_ACC   BIT(TRACER_CYCLE_ACC_BIT)
-
-#define TRACER_TIMEOUT 1
-
-#define etm_writel(t, v, x) \
-   (writel_relaxed((v), (t)-etm_regs + (x)))
-#define etm_readl(t, x) (readl_relaxed((t)-etm_regs + (x)))
-
-/* CoreSight Management Registers */
-#define CSMR_LOCKACCESS 0xfb0
-#define CSMR_LOCKSTATUS 0xfb4
-#define CSMR_AUTHSTATUS 0xfb8
-#define CSMR_DEVID 0xfc8
-#define CSMR_DEVTYPE   0xfcc
-/* CoreSight Component Registers */
-#define CSCR_CLASS 0xff4
-
-#define CS_LAR_KEY 0xc5acce55
-
-/* ETM control register, ETM Architecture, 3.3.1 */
-#define ETMR_CTRL  0
-#define ETMCTRL_POWERDOWN  1
-#define ETMCTRL_PROGRAM(1  10)
-#define ETMCTRL_PORTSEL(1  11)
-#define ETMCTRL_DO_CONTEXTID   (3  14)
-#define ETMCTRL_PORTMASK1  (7  4)
-#define ETMCTRL_PORTMASK2  (1  21)
-#define ETMCTRL_PORTMASK   (ETMCTRL_PORTMASK1 | ETMCTRL_PORTMASK2)
-#define ETMCTRL_PORTSIZE(x) x)  7)  4) | (!!((x)  8))  21)
-#define ETMCTRL_DO_CPRT(1  1)
-#define ETMCTRL_DATAMASK   (3  2)
-#define ETMCTRL_DATA_DO_DATA   (1  2)
-#define ETMCTRL_DATA_DO_ADDR   (1  3)
-#define ETMCTRL_DATA_DO_BOTH   (ETMCTRL_DATA_DO_DATA | ETMCTRL_DATA_DO_ADDR)
-#define ETMCTRL_BRANCH_OUTPUT  (1  8)
-#define ETMCTRL_CYCLEACCURATE  (1  12)
-
-/* ETM configuration code register */
-#define ETMR_CONFCODE  (0x04)
-
-/* ETM trace start/stop resource control register */
-#define ETMR_TRACESSCTRL   (0x18)
-
-/* ETM trigger event register */
-#define ETMR_TRIGEVT   (0x08)
-
-/* address access type register bits, ETM architecture,
- * table 3-27 */
-/* - access type */
-#define ETMAAT_IFETCH  0
-#define ETMAAT_IEXEC   1
-#define ETMAAT_IEXECPASS   2
-#define ETMAAT_IEXECFAIL   3
-#define ETMAAT_DLOADSTORE  4
-#define ETMAAT_DLOAD   5
-#define ETMAAT_DSTORE  6
-/* - comparison access size */
-#define ETMAAT_JAVA(0  3)
-#define ETMAAT_THUMB   (1  3)
-#define ETMAAT_ARM (3  3)
-/* - data value comparison control */
-#define ETMAAT_NOVALCMP(0  5)
-#define ETMAAT_VALMATCH(1  5)
-#define ETMAAT_VALNOMATCH  (3  5)
-/* - exact match */
-#define ETMAAT_EXACTMATCH  (1  7)
-/* - context id comparator control */
-#define ETMAAT_IGNCONTEXTID(0  8)
-#define ETMAAT_VALUE1  (1  8)
-#define ETMAAT_VALUE2  (2  8)
-#define ETMAAT_VALUE3  (3  8)
-/* - security level control */
-#define ETMAAT_IGNSECURITY (0  10)
-#define ETMAAT_NSONLY  (1  10)
-#define ETMAAT_SONLY   (2  10)
-
-#define ETMR_COMP_VAL(x)   (0x40 + (x) * 4)
-#define ETMR_COMP_ACC_TYPE(x)  (0x80 + (x) * 4)
-
-/* ETM status register, ETM Architecture, 3.3.2 */
-#define ETMR_STATUS(0x10)
-#define ETMST_OVERFLOW BIT(0)
-#define ETMST_PROGBIT  BIT(1)
-#define ETMST_STARTSTOPBIT(2)
-#define ETMST_TRIGGER  BIT(3)
-
-#define etm_progbit(t) (etm_readl((t), ETMR_STATUS)  ETMST_PROGBIT)
-#define etm_started(t) (etm_readl((t

[PATCH 7/9 v2] coresight: adding support for beagle and beagleXM

2014-06-27 Thread mathieu . poirier
From: Mathieu Poirier mathieu.poir...@linaro.org

Currently supporting ETM and ETB.  Support for TPIU
and SDTI are yet to be added.

Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
---
 arch/arm/boot/dts/omap3-beagle-xm.dts | 28 
 arch/arm/boot/dts/omap3-beagle.dts| 28 
 2 files changed, 56 insertions(+)

diff --git a/arch/arm/boot/dts/omap3-beagle-xm.dts 
b/arch/arm/boot/dts/omap3-beagle-xm.dts
index cf0be66..110ac3e 100644
--- a/arch/arm/boot/dts/omap3-beagle-xm.dts
+++ b/arch/arm/boot/dts/omap3-beagle-xm.dts
@@ -145,6 +145,34 @@
};
};
};
+
+   etb: etb@5401b000 {
+   compatible = arm,coresight-etb, arm,primecell;
+   reg = 0x5401b000 0x1000;
+
+   coresight-default-sink;
+   clocks = emu_src_ck;
+   clock-names = apb_pclk;
+   port {
+   etb_in: endpoint {
+   slave-mode;
+   remote-endpoint = etm_out;
+   };
+   };
+   };
+
+   etm@5401 {
+   compatible = arm,coresight-etm, arm,primecell;
+   reg = 0x5401 0x1000;
+
+   clocks = emu_src_ck;
+   clock-names = apb_pclk;
+   port {
+   etm_out: endpoint {
+   remote-endpoint = etb_in;
+   };
+   };
+   };
 };
 
 omap3_pmx_wkup {
diff --git a/arch/arm/boot/dts/omap3-beagle.dts 
b/arch/arm/boot/dts/omap3-beagle.dts
index 3c3e6da..dfd9a92 100644
--- a/arch/arm/boot/dts/omap3-beagle.dts
+++ b/arch/arm/boot/dts/omap3-beagle.dts
@@ -140,6 +140,34 @@
};
};
};
+
+   etb: etb@54000 {
+   compatible = arm,coresight-etb, arm,primecell;
+   reg = 0x5401b000 0x1000;
+
+   coresight-default-sink;
+   clocks = emu_src_ck;
+   clock-names = apb_pclk;
+   port {
+   etb_in: endpoint {
+   slave-mode;
+   remote-endpoint = etm_out;
+   };
+   };
+   };
+
+   etm@5401 {
+   compatible = arm,coresight-etm, arm,primecell;
+   reg = 0x5401 0x1000;
+
+   clocks = emu_src_ck;
+   clock-names = apb_pclk;
+   port {
+   etm_out: endpoint {
+   remote-endpoint = etb_in;
+   };
+   };
+   };
 };
 
 omap3_pmx_wkup {
-- 
1.9.1

--
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/9 v2] coresight-tmc: add CoreSight TMC driver

2014-06-27 Thread mathieu . poirier
From: Pratik Patel prat...@codeaurora.org

This driver manages CoreSight TMC (Trace Memory Controller) which
can act as a link or a sink depending upon its configuration. It
can present itself as an ETF (Embedded Trace FIFO) or ETR
(Embedded Trace Router).

ETF when configured in circular buffer mode acts as a trace
collection sink. When configured in HW fifo mode it acts as link.
ETR always acts as a sink and can be used to route data to memory
allocated in RAM.

Signed-off-by: Pratik Patel prat...@codeaurora.org
Signed-off-by: Panchaxari Prasannamurthy panchaxari.prasannamur...@linaro.org
Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
---
 drivers/coresight/Kconfig |  10 +
 drivers/coresight/Makefile|   1 +
 drivers/coresight/coresight-tmc.c | 791 ++
 3 files changed, 802 insertions(+)
 create mode 100644 drivers/coresight/coresight-tmc.c

diff --git a/drivers/coresight/Kconfig b/drivers/coresight/Kconfig
index fdd4d08..48a78bb 100644
--- a/drivers/coresight/Kconfig
+++ b/drivers/coresight/Kconfig
@@ -8,3 +8,13 @@ menuconfig CORESIGHT
  the right series of components on user input via sysfs. It also
  provides status information to user space applications through
  the debugfs interface.
+
+if CORESIGHT
+
+config CORESIGHT_LINKS_AND_SINKS
+   bool CoreSight Link and Sink drivers
+   help
+ This enables support for CoreSight link and sink drivers that are
+ responsible for transporting and collecting the trace data
+ respectively.
+endif
diff --git a/drivers/coresight/Makefile b/drivers/coresight/Makefile
index 218e3b5..16e26c5 100644
--- a/drivers/coresight/Makefile
+++ b/drivers/coresight/Makefile
@@ -3,3 +3,4 @@
 #
 obj-$(CONFIG_CORESIGHT) += coresight.o
 obj-$(CONFIG_OF) += of_coresight.o
+obj-$(CONFIG_CORESIGHT_LINKS_AND_SINKS) += coresight-tmc.o
diff --git a/drivers/coresight/coresight-tmc.c 
b/drivers/coresight/coresight-tmc.c
new file mode 100644
index 000..201cdac
--- /dev/null
+++ b/drivers/coresight/coresight-tmc.c
@@ -0,0 +1,791 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include linux/kernel.h
+#include linux/module.h
+#include linux/init.h
+#include linux/types.h
+#include linux/device.h
+#include linux/io.h
+#include linux/err.h
+#include linux/fs.h
+#include linux/miscdevice.h
+#include linux/uaccess.h
+#include linux/slab.h
+#include linux/dma-mapping.h
+#include linux/delay.h
+#include linux/spinlock.h
+#include linux/clk.h
+#include linux/of.h
+#include linux/of_coresight.h
+#include linux/coresight.h
+#include linux/amba/bus.h
+
+#include coresight-priv.h
+
+#define TMC_RSZ(0x004)
+#define TMC_STS(0x00C)
+#define TMC_RRD(0x010)
+#define TMC_RRP(0x014)
+#define TMC_RWP(0x018)
+#define TMC_TRG(0x01C)
+#define TMC_CTL(0x020)
+#define TMC_RWD(0x024)
+#define TMC_MODE   (0x028)
+#define TMC_LBUFLEVEL  (0x02C)
+#define TMC_CBUFLEVEL  (0x030)
+#define TMC_BUFWM  (0x034)
+#define TMC_RRPHI  (0x038)
+#define TMC_RWPHI  (0x03C)
+#define TMC_AXICTL (0x110)
+#define TMC_DBALO  (0x118)
+#define TMC_DBAHI  (0x11C)
+#define TMC_FFSR   (0x300)
+#define TMC_FFCR   (0x304)
+#define TMC_PSCR   (0x308)
+#define TMC_ITMISCOP0  (0xEE0)
+#define TMC_ITTRFLIN   (0xEE8)
+#define TMC_ITATBDATA0 (0xEEC)
+#define TMC_ITATBCTR2  (0xEF0)
+#define TMC_ITATBCTR1  (0xEF4)
+#define TMC_ITATBCTR0  (0xEF8)
+
+/** register description **/
+/* TMC_CTL - 0x020 */
+#define TMC_CTL_CAPT_ENBIT(0)
+/* TMC_STS - 0x00C */
+#define TMC_STS_TRIGGERED  BIT(1)
+/* TMC_AXICTL - 0x110 */
+#define TMC_AXICTL_PROT_CTL_B0 BIT(0)
+#define TMC_AXICTL_PROT_CTL_B1 BIT(1)
+#define TMC_AXICTL_SCT_GAT_MODEBIT(7)
+#define TMC_AXICTL_WR_BURST_LEN 0xF00
+/* TMC_FFCR - 0x304 */
+#define TMC_FFCR_EN_FMTBIT(0)
+#define TMC_FFCR_EN_TI BIT(1)
+#define TMC_FFCR_FON_FLIN  BIT(4)
+#define TMC_FFCR_FON_TRIG_EVT  BIT(5)
+#define TMC_FFCR_FLUSHMAN  BIT(6)
+#define TMC_FFCR_TRIGON_TRIGIN BIT(8)
+#define TMC_FFCR_STOP_ON_FLUSH BIT(12)
+
+#define TMC_STS_TRIGGERED_BIT  2
+#define TMC_FFCR_FLUSHMAN_BIT  6
+
+enum

[PATCH 0/9 v2] Coresight framework and drivers

2014-06-27 Thread mathieu . poirier
From: Mathieu Poirier mathieu.poir...@linaro.org

This set is addressing comments received after the May 30th
submission[1].  More specifically:

.All drivers have been converted to use the AMBA bus
 interface.
.Debugfs entries are now created with a macro.
.A header file was created for the ETM driver to allow
 for the reuse of constant definition.
.Error path on some drivers have been corrected.
.All types converted from uintX_t to uX.
.All numeric constant have been replaced with #defines and
 comments added where necessary.
.Removal of coresight-id and coresigh-name DT bindings.
.Move all DT connections specification to use the generic
 graph bindings.
.The removal of the replicator driver since it doesn't show
 on the AMBA bus.  Drivers for enhanced replicators that have
 a configuration space can be added when the need arises.

Regards,
Mathieu

[1]. http://thread.gmane.org/gmane.linux.kernel/1714785

Mathieu Poirier (3):
  coresight: adding support for beagle and beagleXM
  coresight: adding basic support for Vexpress TC2
  ARM: removing support for etb/etm in arch/arm/kernel/

Pratik Patel (6):
  coresight: add CoreSight core layer framework
  coresight-tmc: add CoreSight TMC driver
  coresight-tpiu: add CoreSight TPIU driver
  coresight-etb: add CoreSight ETB driver
  coresight-funnel: add CoreSight Funnel driver
  coresight-etm: add CoreSight ETM/PTM driver

 .../devicetree/bindings/arm/coresight.txt  |  141 ++
 arch/arm/boot/dts/omap3-beagle-xm.dts  |   28 +
 arch/arm/boot/dts/omap3-beagle.dts |   28 +
 arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts |  174 +++
 arch/arm/include/asm/hardware/coresight.h  |  157 --
 arch/arm/include/asm/hardware/cp14.h   |  540 +++
 arch/arm/kernel/Makefile   |1 -
 arch/arm/kernel/etm.c  |  654 -
 arch/arm/kernel/hw_breakpoint.c|4 +-
 arch/arm/mach-omap2/Kconfig|8 -
 arch/arm/mach-omap2/Makefile   |1 -
 arch/arm/mach-omap2/emu.c  |   50 -
 drivers/Kconfig|2 +
 drivers/Makefile   |1 +
 drivers/amba/bus.c |2 +-
 drivers/coresight/Kconfig  |   39 +
 drivers/coresight/Makefile |8 +
 drivers/coresight/coresight-etb.c  |  557 
 drivers/coresight/coresight-etm-cp14.c |  506 +++
 drivers/coresight/coresight-etm.c  | 1507 
 drivers/coresight/coresight-etm.h  |  192 +++
 drivers/coresight/coresight-funnel.c   |  252 
 drivers/coresight/coresight-priv.h |   69 +
 drivers/coresight/coresight-tmc.c  |  791 ++
 drivers/coresight/coresight-tpiu.c |  223 +++
 drivers/coresight/coresight.c  |  680 +
 drivers/coresight/of_coresight.c   |  207 +++
 include/linux/amba/bus.h   |1 +
 include/linux/coresight.h  |  190 +++
 include/linux/of_coresight.h   |   27 +
 30 files changed, 6166 insertions(+), 874 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/coresight.txt
 delete mode 100644 arch/arm/include/asm/hardware/coresight.h
 create mode 100644 arch/arm/include/asm/hardware/cp14.h
 delete mode 100644 arch/arm/kernel/etm.c
 delete mode 100644 arch/arm/mach-omap2/emu.c
 create mode 100644 drivers/coresight/Kconfig
 create mode 100644 drivers/coresight/Makefile
 create mode 100644 drivers/coresight/coresight-etb.c
 create mode 100644 drivers/coresight/coresight-etm-cp14.c
 create mode 100644 drivers/coresight/coresight-etm.c
 create mode 100644 drivers/coresight/coresight-etm.h
 create mode 100644 drivers/coresight/coresight-funnel.c
 create mode 100644 drivers/coresight/coresight-priv.h
 create mode 100644 drivers/coresight/coresight-tmc.c
 create mode 100644 drivers/coresight/coresight-tpiu.c
 create mode 100644 drivers/coresight/coresight.c
 create mode 100644 drivers/coresight/of_coresight.c
 create mode 100644 include/linux/coresight.h
 create mode 100644 include/linux/of_coresight.h

-- 
1.9.1

--
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 8/9 v2] coresight: adding basic support for Vexpress TC2

2014-06-27 Thread mathieu . poirier
From: Mathieu Poirier mathieu.poir...@linaro.org

Support for the 2 PTMs, 3 ETMs, funnel, TPIU and replicator
connected to the ETB are included.  Proper handling of the
ITM and the replicator linked to it along with the CTIs
and SWO are not included.

Signed-off-by: Mathieu Poirier mathieu.poir...@linaro.org
---
 arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts | 174 +
 1 file changed, 174 insertions(+)

diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts 
b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
index 15f98cb..390f2bb 100644
--- a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
+++ b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
@@ -334,6 +334,180 @@
};
};
 
+   etb: etb@2001 {
+   compatible = arm,coresight-etb, arm,primecell;
+   reg = 0 0x2001 0 0x1000;
+
+   coresight-default-sink;
+   clocks = oscclk6a;
+   clock-names = apb_pclk;
+   port {
+   etb_in_port: endpoint@0 {
+   slave-mode;
+   remote-endpoint = funnel_out_port0;
+   };
+   };
+   };
+
+   tpiu: tpiu@2003 {
+   compatible = arm,coresight-tpiu, arm,primecell;
+   reg = 0 0x2003 0 0x1000;
+
+   clocks = oscclk6a;
+   clock-names = apb_pclk;
+   port {
+   tpiu_in_port: endpoint@0 {
+   slave-mode;
+   remote-endpoint = funnel_out_port1;
+   };
+   };
+   };
+
+   funnel {
+   compatible = arm,coresight-funnel, arm,primecell;
+   reg = 0 0x2004 0 0x1000;
+
+   clocks = oscclk6a;
+   clock-names = apb_pclk;
+   ports {
+   #address-cells = 1;
+   #size-cells = 0;
+
+   /* The funnel is connected to a replicator - since
+* replicators are hardwired we simply treat the
+* funnel as a multiple-in and multiple out component.
+* The following two ports really belong to the
+* repicator but configured as par of the funnel.
+*/
+
+   /* replicator port */
+   port@0 {
+   reg = 0;
+   funnel_out_port0: endpoint {
+   remote-endpoint = etb_in_port;
+   };
+   };
+
+   /* replicator port */
+   port@1 {
+   reg = 1;
+   funnel_out_port1: endpoint {
+   remote-endpoint = tpiu_in_port;
+   };
+   };
+   /* funnel ports */
+   port@2 {
+   reg = 0;
+   funnel_in_port0: endpoint {
+   slave-mode;
+   remote-endpoint = ptm0_out_port;
+   };
+   };
+
+   port@3 {
+   reg = 1;
+   funnel_in_port1: endpoint {
+   slave-mode;
+   remote-endpoint = ptm1_out_port;
+   };
+   };
+
+   port@4 {
+   reg = 2;
+   funnel_in_port2: endpoint {
+   slave-mode;
+   remote-endpoint = etm0_out_port;
+   };
+   };
+
+   port@5 {
+   reg = 4;
+   funnel_in_port4: endpoint {
+   slave-mode;
+   remote-endpoint = etm1_out_port;
+   };
+   };
+
+   port@6 {
+   reg = 5;
+   funnel_in_port5: endpoint {
+   slave-mode;
+   remote-endpoint = etm2_out_port;
+   };
+   };
+};
+   };
+
+   ptm0: ptm@2201c000 {
+   compatible = arm,coresight-etm, arm,primecell;
+   reg = 0 0x2201c000 0 0x1000;
+
+   cpu = cpu0;
+   clocks = oscclk6a;
+   clock-names = apb_pclk;
+   port

  1   2   3   4   5   6   7   8   9   10   >