aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLee Jones <lee.jones@linaro.org>2012-05-31 10:16:36 -0400
committerLee Jones <lee.jones@linaro.org>2013-03-06 23:35:36 -0500
commit93ff722e88530b9719cbf53be4f3197722461394 (patch)
tree7803b080fdf52c91b50aa2719ee82f55a6165bc1
parent330b7ebfa59d70ea5b814a04a28b8c7d8e462a81 (diff)
ab8500-fg: Add power cut feature for ab8505 and ab8540
Add support for a power cut feature which allows user to configure when ab8505 and ab8540 based platforms should shut down system due to low battery. Signed-off-by: Lee Jones <lee.jones@linaro.org>
-rw-r--r--drivers/mfd/ab8500-core.c36
-rw-r--r--drivers/power/ab8500_bmdata.c5
-rw-r--r--drivers/power/ab8500_fg.c474
-rw-r--r--include/linux/mfd/abx500.h10
-rw-r--r--include/linux/mfd/abx500/ab8500-bm.h18
5 files changed, 543 insertions, 0 deletions
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
index c7ff55753a8f..f276352cc9ef 100644
--- a/drivers/mfd/ab8500-core.c
+++ b/drivers/mfd/ab8500-core.c
@@ -113,6 +113,7 @@
113#define AB8500_SWITCH_OFF_STATUS 0x00 113#define AB8500_SWITCH_OFF_STATUS 0x00
114 114
115#define AB8500_TURN_ON_STATUS 0x00 115#define AB8500_TURN_ON_STATUS 0x00
116#define AB8505_TURN_ON_STATUS_2 0x04
116 117
117#define AB8500_CH_USBCH_STAT1_REG 0x02 118#define AB8500_CH_USBCH_STAT1_REG 0x02
118#define VBUS_DET_DBNC100 0x02 119#define VBUS_DET_DBNC100 0x02
@@ -1401,6 +1402,21 @@ static ssize_t show_turn_on_status(struct device *dev,
1401 return sprintf(buf, "%#x\n", value); 1402 return sprintf(buf, "%#x\n", value);
1402} 1403}
1403 1404
1405static ssize_t show_turn_on_status_2(struct device *dev,
1406 struct device_attribute *attr, char *buf)
1407{
1408 int ret;
1409 u8 value;
1410 struct ab8500 *ab8500;
1411
1412 ab8500 = dev_get_drvdata(dev);
1413 ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK,
1414 AB8505_TURN_ON_STATUS_2, &value);
1415 if (ret < 0)
1416 return ret;
1417 return sprintf(buf, "%#x\n", (value & 0x1));
1418}
1419
1404static ssize_t show_ab9540_dbbrstn(struct device *dev, 1420static ssize_t show_ab9540_dbbrstn(struct device *dev,
1405 struct device_attribute *attr, char *buf) 1421 struct device_attribute *attr, char *buf)
1406{ 1422{
@@ -1457,6 +1473,7 @@ exit:
1457static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL); 1473static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL);
1458static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL); 1474static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL);
1459static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL); 1475static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL);
1476static DEVICE_ATTR(turn_on_status_2, S_IRUGO, show_turn_on_status_2, NULL);
1460static DEVICE_ATTR(dbbrstn, S_IRUGO | S_IWUSR, 1477static DEVICE_ATTR(dbbrstn, S_IRUGO | S_IWUSR,
1461 show_ab9540_dbbrstn, store_ab9540_dbbrstn); 1478 show_ab9540_dbbrstn, store_ab9540_dbbrstn);
1462 1479
@@ -1467,6 +1484,11 @@ static struct attribute *ab8500_sysfs_entries[] = {
1467 NULL, 1484 NULL,
1468}; 1485};
1469 1486
1487static struct attribute *ab8505_sysfs_entries[] = {
1488 &dev_attr_turn_on_status_2.attr,
1489 NULL,
1490};
1491
1470static struct attribute *ab9540_sysfs_entries[] = { 1492static struct attribute *ab9540_sysfs_entries[] = {
1471 &dev_attr_chip_id.attr, 1493 &dev_attr_chip_id.attr,
1472 &dev_attr_switch_off_status.attr, 1494 &dev_attr_switch_off_status.attr,
@@ -1479,6 +1501,10 @@ static struct attribute_group ab8500_attr_group = {
1479 .attrs = ab8500_sysfs_entries, 1501 .attrs = ab8500_sysfs_entries,
1480}; 1502};
1481 1503
1504static struct attribute_group ab8505_attr_group = {
1505 .attrs = ab8505_sysfs_entries,
1506};
1507
1482static struct attribute_group ab9540_attr_group = { 1508static struct attribute_group ab9540_attr_group = {
1483 .attrs = ab9540_sysfs_entries, 1509 .attrs = ab9540_sysfs_entries,
1484}; 1510};
@@ -1719,6 +1745,12 @@ static int ab8500_probe(struct platform_device *pdev)
1719 else 1745 else
1720 ret = sysfs_create_group(&ab8500->dev->kobj, 1746 ret = sysfs_create_group(&ab8500->dev->kobj,
1721 &ab8500_attr_group); 1747 &ab8500_attr_group);
1748
1749 if ((is_ab8505(ab8500) || is_ab9540(ab8500)) &&
1750 ab8500->chip_id >= AB8500_CUT2P0)
1751 ret = sysfs_create_group(&ab8500->dev->kobj,
1752 &ab8505_attr_group);
1753
1722 if (ret) 1754 if (ret)
1723 dev_err(ab8500->dev, "error creating sysfs entries\n"); 1755 dev_err(ab8500->dev, "error creating sysfs entries\n");
1724 1756
@@ -1735,6 +1767,10 @@ static int ab8500_remove(struct platform_device *pdev)
1735 else 1767 else
1736 sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group); 1768 sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group);
1737 1769
1770 if ((is_ab8505(ab8500) || is_ab9540(ab8500)) &&
1771 ab8500->chip_id >= AB8500_CUT2P0)
1772 sysfs_remove_group(&ab8500->dev->kobj, &ab8505_attr_group);
1773
1738 mfd_remove_devices(ab8500->dev); 1774 mfd_remove_devices(ab8500->dev);
1739 1775
1740 return 0; 1776 return 0;
diff --git a/drivers/power/ab8500_bmdata.c b/drivers/power/ab8500_bmdata.c
index 7a96c0650fbb..e8759763fbe0 100644
--- a/drivers/power/ab8500_bmdata.c
+++ b/drivers/power/ab8500_bmdata.c
@@ -407,6 +407,11 @@ static const struct abx500_fg_parameters fg = {
407 .battok_raising_th_sel1 = 2860, 407 .battok_raising_th_sel1 = 2860,
408 .maint_thres = 95, 408 .maint_thres = 95,
409 .user_cap_limit = 15, 409 .user_cap_limit = 15,
410 .pcut_enable = 1,
411 .pcut_max_time = 127,
412 .pcut_flag_time = 112,
413 .pcut_max_restart = 15,
414 .pcut_debounce_time = 2,
410}; 415};
411 416
412static const struct abx500_maxim_parameters maxi_params = { 417static const struct abx500_maxim_parameters maxi_params = {
diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
index 25dae4c4b0ef..92f342bcf188 100644
--- a/drivers/power/ab8500_fg.c
+++ b/drivers/power/ab8500_fg.c
@@ -2344,6 +2344,50 @@ static int ab8500_fg_init_hw_registers(struct ab8500_fg *di)
2344 dev_err(di->dev, "BattOk init write failed.\n"); 2344 dev_err(di->dev, "BattOk init write failed.\n");
2345 goto out; 2345 goto out;
2346 } 2346 }
2347
2348 if (((is_ab8505(di->parent) || is_ab9540(di->parent)) &&
2349 abx500_get_chip_id(di->dev) >= AB8500_CUT2P0)
2350 || is_ab8540(di->parent)) {
2351 ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
2352 AB8505_RTC_PCUT_MAX_TIME_REG, di->bm->fg_params->pcut_max_time);
2353
2354 if (ret) {
2355 dev_err(di->dev, "%s write failed AB8505_RTC_PCUT_MAX_TIME_REG\n", __func__);
2356 goto out;
2357 };
2358
2359 ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
2360 AB8505_RTC_PCUT_FLAG_TIME_REG, di->bm->fg_params->pcut_flag_time);
2361
2362 if (ret) {
2363 dev_err(di->dev, "%s write failed AB8505_RTC_PCUT_FLAG_TIME_REG\n", __func__);
2364 goto out;
2365 };
2366
2367 ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
2368 AB8505_RTC_PCUT_RESTART_REG, di->bm->fg_params->pcut_max_restart);
2369
2370 if (ret) {
2371 dev_err(di->dev, "%s write failed AB8505_RTC_PCUT_RESTART_REG\n", __func__);
2372 goto out;
2373 };
2374
2375 ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
2376 AB8505_RTC_PCUT_DEBOUNCE_REG, di->bm->fg_params->pcut_debounce_time);
2377
2378 if (ret) {
2379 dev_err(di->dev, "%s write failed AB8505_RTC_PCUT_DEBOUNCE_REG\n", __func__);
2380 goto out;
2381 };
2382
2383 ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
2384 AB8505_RTC_PCUT_CTL_STATUS_REG, di->bm->fg_params->pcut_enable);
2385
2386 if (ret) {
2387 dev_err(di->dev, "%s write failed AB8505_RTC_PCUT_CTL_STATUS_REG\n", __func__);
2388 goto out;
2389 };
2390 }
2347out: 2391out:
2348 return ret; 2392 return ret;
2349} 2393}
@@ -2546,6 +2590,428 @@ static int ab8500_fg_sysfs_init(struct ab8500_fg *di)
2546 2590
2547 return ret; 2591 return ret;
2548} 2592}
2593
2594static ssize_t ab8505_powercut_flagtime_read(struct device *dev,
2595 struct device_attribute *attr,
2596 char *buf)
2597{
2598 int ret;
2599 u8 reg_value;
2600 struct power_supply *psy = dev_get_drvdata(dev);
2601 struct ab8500_fg *di;
2602
2603 di = to_ab8500_fg_device_info(psy);
2604
2605 ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
2606 AB8505_RTC_PCUT_FLAG_TIME_REG, &reg_value);
2607
2608 if (ret < 0) {
2609 dev_err(dev, "Failed to read AB8505_RTC_PCUT_FLAG_TIME_REG\n");
2610 goto fail;
2611 }
2612
2613 return scnprintf(buf, PAGE_SIZE, "%d\n", (reg_value & 0x7F));
2614
2615fail:
2616 return ret;
2617}
2618
2619static ssize_t ab8505_powercut_flagtime_write(struct device *dev,
2620 struct device_attribute *attr,
2621 const char *buf, size_t count)
2622{
2623 int ret;
2624 long unsigned reg_value;
2625 struct power_supply *psy = dev_get_drvdata(dev);
2626 struct ab8500_fg *di;
2627
2628 di = to_ab8500_fg_device_info(psy);
2629
2630 reg_value = simple_strtoul(buf, NULL, 10);
2631
2632 if (reg_value > 0x7F) {
2633 dev_err(dev, "Incorrect parameter, echo 0 (1.98s) - 127 (15.625ms) for flagtime\n");
2634 goto fail;
2635 }
2636
2637 ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
2638 AB8505_RTC_PCUT_FLAG_TIME_REG, (u8)reg_value);
2639
2640 if (ret < 0)
2641 dev_err(dev, "Failed to set AB8505_RTC_PCUT_FLAG_TIME_REG\n");
2642
2643fail:
2644 return count;
2645}
2646
2647static ssize_t ab8505_powercut_maxtime_read(struct device *dev,
2648 struct device_attribute *attr,
2649 char *buf)
2650{
2651 int ret;
2652 u8 reg_value;
2653 struct power_supply *psy = dev_get_drvdata(dev);
2654 struct ab8500_fg *di;
2655
2656 di = to_ab8500_fg_device_info(psy);
2657
2658 ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
2659 AB8505_RTC_PCUT_MAX_TIME_REG, &reg_value);
2660
2661 if (ret < 0) {
2662 dev_err(dev, "Failed to read AB8505_RTC_PCUT_MAX_TIME_REG\n");
2663 goto fail;
2664 }
2665
2666 return scnprintf(buf, PAGE_SIZE, "%d\n", (reg_value & 0x7F));
2667
2668fail:
2669 return ret;
2670
2671}
2672
2673static ssize_t ab8505_powercut_maxtime_write(struct device *dev,
2674 struct device_attribute *attr,
2675 const char *buf, size_t count)
2676{
2677 int ret;
2678 int reg_value;
2679 struct power_supply *psy = dev_get_drvdata(dev);
2680 struct ab8500_fg *di;
2681
2682 di = to_ab8500_fg_device_info(psy);
2683
2684 reg_value = simple_strtoul(buf, NULL, 10);
2685 if (reg_value > 0x7F) {
2686 dev_err(dev, "Incorrect parameter, echo 0 (0.0s) - 127 (1.98s) for maxtime\n");
2687 goto fail;
2688 }
2689
2690 ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
2691 AB8505_RTC_PCUT_MAX_TIME_REG, (u8)reg_value);
2692
2693 if (ret < 0)
2694 dev_err(dev, "Failed to set AB8505_RTC_PCUT_MAX_TIME_REG\n");
2695
2696fail:
2697 return count;
2698}
2699
2700static ssize_t ab8505_powercut_restart_read(struct device *dev,
2701 struct device_attribute *attr,
2702 char *buf)
2703{
2704 int ret;
2705 u8 reg_value;
2706 struct power_supply *psy = dev_get_drvdata(dev);
2707 struct ab8500_fg *di;
2708
2709 di = to_ab8500_fg_device_info(psy);
2710
2711 ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
2712 AB8505_RTC_PCUT_RESTART_REG, &reg_value);
2713
2714 if (ret < 0) {
2715 dev_err(dev, "Failed to read AB8505_RTC_PCUT_RESTART_REG\n");
2716 goto fail;
2717 }
2718
2719 return scnprintf(buf, PAGE_SIZE, "%d\n", (reg_value & 0xF));
2720
2721fail:
2722 return ret;
2723}
2724
2725static ssize_t ab8505_powercut_restart_write(struct device *dev,
2726 struct device_attribute *attr,
2727 const char *buf, size_t count)
2728{
2729 int ret;
2730 int reg_value;
2731 struct power_supply *psy = dev_get_drvdata(dev);
2732 struct ab8500_fg *di;
2733
2734 di = to_ab8500_fg_device_info(psy);
2735
2736 reg_value = simple_strtoul(buf, NULL, 10);
2737 if (reg_value > 0xF) {
2738 dev_err(dev, "Incorrect parameter, echo 0 - 15 for number of restart\n");
2739 goto fail;
2740 }
2741
2742 ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
2743 AB8505_RTC_PCUT_RESTART_REG, (u8)reg_value);
2744
2745 if (ret < 0)
2746 dev_err(dev, "Failed to set AB8505_RTC_PCUT_RESTART_REG\n");
2747
2748fail:
2749 return count;
2750
2751}
2752
2753static ssize_t ab8505_powercut_timer_read(struct device *dev,
2754 struct device_attribute *attr,
2755 char *buf)
2756{
2757 int ret;
2758 u8 reg_value;
2759 struct power_supply *psy = dev_get_drvdata(dev);
2760 struct ab8500_fg *di;
2761
2762 di = to_ab8500_fg_device_info(psy);
2763
2764 ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
2765 AB8505_RTC_PCUT_TIME_REG, &reg_value);
2766
2767 if (ret < 0) {
2768 dev_err(dev, "Failed to read AB8505_RTC_PCUT_TIME_REG\n");
2769 goto fail;
2770 }
2771
2772 return scnprintf(buf, PAGE_SIZE, "%d\n", (reg_value & 0x7F));
2773
2774fail:
2775 return ret;
2776}
2777
2778static ssize_t ab8505_powercut_restart_counter_read(struct device *dev,
2779 struct device_attribute *attr,
2780 char *buf)
2781{
2782 int ret;
2783 u8 reg_value;
2784 struct power_supply *psy = dev_get_drvdata(dev);
2785 struct ab8500_fg *di;
2786
2787 di = to_ab8500_fg_device_info(psy);
2788
2789 ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
2790 AB8505_RTC_PCUT_RESTART_REG, &reg_value);
2791
2792 if (ret < 0) {
2793 dev_err(dev, "Failed to read AB8505_RTC_PCUT_RESTART_REG\n");
2794 goto fail;
2795 }
2796
2797 return scnprintf(buf, PAGE_SIZE, "%d\n", (reg_value & 0xF0) >> 4);
2798
2799fail:
2800 return ret;
2801}
2802
2803static ssize_t ab8505_powercut_read(struct device *dev,
2804 struct device_attribute *attr,
2805 char *buf)
2806{
2807 int ret;
2808 u8 reg_value;
2809 struct power_supply *psy = dev_get_drvdata(dev);
2810 struct ab8500_fg *di;
2811
2812 di = to_ab8500_fg_device_info(psy);
2813
2814 ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
2815 AB8505_RTC_PCUT_CTL_STATUS_REG, &reg_value);
2816
2817 if (ret < 0)
2818 goto fail;
2819
2820 return scnprintf(buf, PAGE_SIZE, "%d\n", (reg_value & 0x1));
2821
2822fail:
2823 return ret;
2824}
2825
2826static ssize_t ab8505_powercut_write(struct device *dev,
2827 struct device_attribute *attr,
2828 const char *buf, size_t count)
2829{
2830 int ret;
2831 int reg_value;
2832 struct power_supply *psy = dev_get_drvdata(dev);
2833 struct ab8500_fg *di;
2834
2835 di = to_ab8500_fg_device_info(psy);
2836
2837 reg_value = simple_strtoul(buf, NULL, 10);
2838 if (reg_value > 0x1) {
2839 dev_err(dev, "Incorrect parameter, echo 0/1 to disable/enable Pcut feature\n");
2840 goto fail;
2841 }
2842
2843 ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
2844 AB8505_RTC_PCUT_CTL_STATUS_REG, (u8)reg_value);
2845
2846 if (ret < 0)
2847 dev_err(dev, "Failed to set AB8505_RTC_PCUT_CTL_STATUS_REG\n");
2848
2849fail:
2850 return count;
2851}
2852
2853static ssize_t ab8505_powercut_flag_read(struct device *dev,
2854 struct device_attribute *attr,
2855 char *buf)
2856{
2857
2858 int ret;
2859 u8 reg_value;
2860 struct power_supply *psy = dev_get_drvdata(dev);
2861 struct ab8500_fg *di;
2862
2863 di = to_ab8500_fg_device_info(psy);
2864
2865 ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
2866 AB8505_RTC_PCUT_CTL_STATUS_REG, &reg_value);
2867
2868 if (ret < 0) {
2869 dev_err(dev, "Failed to read AB8505_RTC_PCUT_CTL_STATUS_REG\n");
2870 goto fail;
2871 }
2872
2873 return scnprintf(buf, PAGE_SIZE, "%d\n", ((reg_value & 0x10) >> 4));
2874
2875fail:
2876 return ret;
2877}
2878
2879static ssize_t ab8505_powercut_debounce_read(struct device *dev,
2880 struct device_attribute *attr,
2881 char *buf)
2882{
2883 int ret;
2884 u8 reg_value;
2885 struct power_supply *psy = dev_get_drvdata(dev);
2886 struct ab8500_fg *di;
2887
2888 di = to_ab8500_fg_device_info(psy);
2889
2890 ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
2891 AB8505_RTC_PCUT_DEBOUNCE_REG, &reg_value);
2892
2893 if (ret < 0) {
2894 dev_err(dev, "Failed to read AB8505_RTC_PCUT_DEBOUNCE_REG\n");
2895 goto fail;
2896 }
2897
2898 return scnprintf(buf, PAGE_SIZE, "%d\n", (reg_value & 0x7));
2899
2900fail:
2901 return ret;
2902}
2903
2904static ssize_t ab8505_powercut_debounce_write(struct device *dev,
2905 struct device_attribute *attr,
2906 const char *buf, size_t count)
2907{
2908 int ret;
2909 int reg_value;
2910 struct power_supply *psy = dev_get_drvdata(dev);
2911 struct ab8500_fg *di;
2912
2913 di = to_ab8500_fg_device_info(psy);
2914
2915 reg_value = simple_strtoul(buf, NULL, 10);
2916 if (reg_value > 0x7) {
2917 dev_err(dev, "Incorrect parameter, echo 0 to 7 for debounce setting\n");
2918 goto fail;
2919 }
2920
2921 ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
2922 AB8505_RTC_PCUT_DEBOUNCE_REG, (u8)reg_value);
2923
2924 if (ret < 0)
2925 dev_err(dev, "Failed to set AB8505_RTC_PCUT_DEBOUNCE_REG\n");
2926
2927fail:
2928 return count;
2929}
2930
2931static ssize_t ab8505_powercut_enable_status_read(struct device *dev,
2932 struct device_attribute *attr,
2933 char *buf)
2934{
2935 int ret;
2936 u8 reg_value;
2937 struct power_supply *psy = dev_get_drvdata(dev);
2938 struct ab8500_fg *di;
2939
2940 di = to_ab8500_fg_device_info(psy);
2941
2942 ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
2943 AB8505_RTC_PCUT_CTL_STATUS_REG, &reg_value);
2944
2945 if (ret < 0) {
2946 dev_err(dev, "Failed to read AB8505_RTC_PCUT_CTL_STATUS_REG\n");
2947 goto fail;
2948 }
2949
2950 return scnprintf(buf, PAGE_SIZE, "%d\n", ((reg_value & 0x20) >> 5));
2951
2952fail:
2953 return ret;
2954}
2955
2956static struct device_attribute ab8505_fg_sysfs_psy_attrs[] = {
2957 __ATTR(powercut_flagtime, (S_IRUGO | S_IWUSR | S_IWGRP),
2958 ab8505_powercut_flagtime_read, ab8505_powercut_flagtime_write),
2959 __ATTR(powercut_maxtime, (S_IRUGO | S_IWUSR | S_IWGRP),
2960 ab8505_powercut_maxtime_read, ab8505_powercut_maxtime_write),
2961 __ATTR(powercut_restart_max, (S_IRUGO | S_IWUSR | S_IWGRP),
2962 ab8505_powercut_restart_read, ab8505_powercut_restart_write),
2963 __ATTR(powercut_timer, S_IRUGO, ab8505_powercut_timer_read, NULL),
2964 __ATTR(powercut_restart_counter, S_IRUGO,
2965 ab8505_powercut_restart_counter_read, NULL),
2966 __ATTR(powercut_enable, (S_IRUGO | S_IWUSR | S_IWGRP),
2967 ab8505_powercut_read, ab8505_powercut_write),
2968 __ATTR(powercut_flag, S_IRUGO, ab8505_powercut_flag_read, NULL),
2969 __ATTR(powercut_debounce_time, (S_IRUGO | S_IWUSR | S_IWGRP),
2970 ab8505_powercut_debounce_read, ab8505_powercut_debounce_write),
2971 __ATTR(powercut_enable_status, S_IRUGO,
2972 ab8505_powercut_enable_status_read, NULL),
2973};
2974
2975static int ab8500_fg_sysfs_psy_create_attrs(struct device *dev)
2976{
2977 unsigned int i, j;
2978 struct power_supply *psy = dev_get_drvdata(dev);
2979 struct ab8500_fg *di;
2980
2981 di = to_ab8500_fg_device_info(psy);
2982
2983 if (((is_ab8505(di->parent) || is_ab9540(di->parent)) &&
2984 abx500_get_chip_id(dev->parent) >= AB8500_CUT2P0)
2985 || is_ab8540(di->parent)) {
2986 for (j = 0; j < ARRAY_SIZE(ab8505_fg_sysfs_psy_attrs); j++)
2987 if (device_create_file(dev, &ab8505_fg_sysfs_psy_attrs[j]))
2988 goto sysfs_psy_create_attrs_failed_ab8505;
2989 }
2990 return 0;
2991sysfs_psy_create_attrs_failed_ab8505:
2992 dev_err(dev, "Failed creating sysfs psy attrs for ab8505.\n");
2993 while (j--)
2994 device_remove_file(dev, &ab8505_fg_sysfs_psy_attrs[i]);
2995
2996 return -EIO;
2997}
2998
2999static void ab8500_fg_sysfs_psy_remove_attrs(struct device *dev)
3000{
3001 unsigned int i;
3002 struct power_supply *psy = dev_get_drvdata(dev);
3003 struct ab8500_fg *di;
3004
3005 di = to_ab8500_fg_device_info(psy);
3006
3007 if (((is_ab8505(di->parent) || is_ab9540(di->parent)) &&
3008 abx500_get_chip_id(dev->parent) >= AB8500_CUT2P0)
3009 || is_ab8540(di->parent)) {
3010 for (i = 0; i < ARRAY_SIZE(ab8505_fg_sysfs_psy_attrs); i++)
3011 (void)device_remove_file(dev, &ab8505_fg_sysfs_psy_attrs[i]);
3012 }
3013}
3014
2549/* Exposure to the sysfs interface <<END>> */ 3015/* Exposure to the sysfs interface <<END>> */
2550 3016
2551#if defined(CONFIG_PM) 3017#if defined(CONFIG_PM)
@@ -2607,6 +3073,7 @@ static int ab8500_fg_remove(struct platform_device *pdev)
2607 ab8500_fg_sysfs_exit(di); 3073 ab8500_fg_sysfs_exit(di);
2608 3074
2609 flush_scheduled_work(); 3075 flush_scheduled_work();
3076 ab8500_fg_sysfs_psy_remove_attrs(di->fg_psy.dev);
2610 power_supply_unregister(&di->fg_psy); 3077 power_supply_unregister(&di->fg_psy);
2611 platform_set_drvdata(pdev, NULL); 3078 platform_set_drvdata(pdev, NULL);
2612 return ret; 3079 return ret;
@@ -2772,6 +3239,13 @@ static int ab8500_fg_probe(struct platform_device *pdev)
2772 goto free_irq; 3239 goto free_irq;
2773 } 3240 }
2774 3241
3242 ret = ab8500_fg_sysfs_psy_create_attrs(di->fg_psy.dev);
3243 if (ret) {
3244 dev_err(di->dev, "failed to create FG psy\n");
3245 ab8500_fg_sysfs_exit(di);
3246 goto free_irq;
3247 }
3248
2775 /* Calibrate the fg first time */ 3249 /* Calibrate the fg first time */
2776 di->flags.calibrate = true; 3250 di->flags.calibrate = true;
2777 di->calib_state = AB8500_FG_CALIB_INIT; 3251 di->calib_state = AB8500_FG_CALIB_INIT;
diff --git a/include/linux/mfd/abx500.h b/include/linux/mfd/abx500.h
index 9ead60bc66b7..188aedc322c2 100644
--- a/include/linux/mfd/abx500.h
+++ b/include/linux/mfd/abx500.h
@@ -89,6 +89,11 @@ struct abx500_fg;
89 * points. 89 * points.
90 * @maint_thres This is the threshold where we stop reporting 90 * @maint_thres This is the threshold where we stop reporting
91 * battery full while in maintenance, in per cent 91 * battery full while in maintenance, in per cent
92 * @pcut_enable: Enable power cut feature in ab8505
93 * @pcut_max_time: Max time threshold
94 * @pcut_flag_time: Flagtime threshold
95 * @pcut_max_restart: Max number of restarts
96 * @pcut_debounce_time: Sets battery debounce time
92 */ 97 */
93struct abx500_fg_parameters { 98struct abx500_fg_parameters {
94 int recovery_sleep_timer; 99 int recovery_sleep_timer;
@@ -106,6 +111,11 @@ struct abx500_fg_parameters {
106 int battok_raising_th_sel1; 111 int battok_raising_th_sel1;
107 int user_cap_limit; 112 int user_cap_limit;
108 int maint_thres; 113 int maint_thres;
114 bool pcut_enable;
115 u8 pcut_max_time;
116 u8 pcut_flag_time;
117 u8 pcut_max_restart;
118 u8 pcut_debounce_time;
109}; 119};
110 120
111/** 121/**
diff --git a/include/linux/mfd/abx500/ab8500-bm.h b/include/linux/mfd/abx500/ab8500-bm.h
index 8d35bfe164c8..0efbe0efee7f 100644
--- a/include/linux/mfd/abx500/ab8500-bm.h
+++ b/include/linux/mfd/abx500/ab8500-bm.h
@@ -235,6 +235,14 @@
235/* Battery type */ 235/* Battery type */
236#define BATTERY_UNKNOWN 00 236#define BATTERY_UNKNOWN 00
237 237
238/* Registers for pcut feature in ab8505 and ab9540 */
239#define AB8505_RTC_PCUT_CTL_STATUS_REG 0x12
240#define AB8505_RTC_PCUT_TIME_REG 0x13
241#define AB8505_RTC_PCUT_MAX_TIME_REG 0x14
242#define AB8505_RTC_PCUT_FLAG_TIME_REG 0x15
243#define AB8505_RTC_PCUT_RESTART_REG 0x16
244#define AB8505_RTC_PCUT_DEBOUNCE_REG 0x17
245
238/** 246/**
239 * struct res_to_temp - defines one point in a temp to res curve. To 247 * struct res_to_temp - defines one point in a temp to res curve. To
240 * be used in battery packs that combines the identification resistor with a 248 * be used in battery packs that combines the identification resistor with a
@@ -283,6 +291,11 @@ struct ab8500_fg;
283 * points. 291 * points.
284 * @maint_thres This is the threshold where we stop reporting 292 * @maint_thres This is the threshold where we stop reporting
285 * battery full while in maintenance, in per cent 293 * battery full while in maintenance, in per cent
294 * @pcut_enable: Enable power cut feature in ab8505
295 * @pcut_max_time: Max time threshold
296 * @pcut_flag_time: Flagtime threshold
297 * @pcut_max_restart: Max number of restarts
298 * @pcut_debunce_time: Sets battery debounce time
286 */ 299 */
287struct ab8500_fg_parameters { 300struct ab8500_fg_parameters {
288 int recovery_sleep_timer; 301 int recovery_sleep_timer;
@@ -299,6 +312,11 @@ struct ab8500_fg_parameters {
299 int battok_raising_th_sel1; 312 int battok_raising_th_sel1;
300 int user_cap_limit; 313 int user_cap_limit;
301 int maint_thres; 314 int maint_thres;
315 bool pcut_enable;
316 u8 pcut_max_time;
317 u8 pcut_flag_time;
318 u8 pcut_max_restart;
319 u8 pcut_debunce_time;
302}; 320};
303 321
304/** 322/**