diff options
author | Samuel Ortiz <sameo@linux.intel.com> | 2013-04-08 05:19:40 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2013-04-08 05:20:34 -0400 |
commit | 8b5fd8516cfdd187f35c45f5f818da94aa3b42e9 (patch) | |
tree | 5a2d4a3143f3573aafa2fa180991485e45ac5f8e /drivers | |
parent | 9d66b568a215fe2da2a9db736ebf9b8d66082d88 (diff) | |
parent | b09f86dbfc20d9420dac43dba016cb65b582c983 (diff) |
Merge branch 'for-mfd-and-power' of git://git.linaro.org/people/ljones/linux-3.0-ux500
Conflicts:
drivers/mfd/ab8500-gpadc.c
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mfd/ab8500-core.c | 544 | ||||
-rw-r--r-- | drivers/mfd/ab8500-debugfs.c | 1741 | ||||
-rw-r--r-- | drivers/mfd/ab8500-gpadc.c | 559 | ||||
-rw-r--r-- | drivers/mfd/ab8500-sysctrl.c | 98 | ||||
-rw-r--r-- | drivers/power/Kconfig | 7 | ||||
-rw-r--r-- | drivers/power/Makefile | 3 | ||||
-rw-r--r-- | drivers/power/ab8500_bmdata.c | 96 | ||||
-rw-r--r-- | drivers/power/ab8500_btemp.c | 75 | ||||
-rw-r--r-- | drivers/power/ab8500_charger.c | 699 | ||||
-rw-r--r-- | drivers/power/ab8500_fg.c | 497 | ||||
-rw-r--r-- | drivers/power/abx500_chargalg.c | 455 | ||||
-rw-r--r-- | drivers/power/pm2301_charger.c | 371 | ||||
-rw-r--r-- | drivers/power/pm2301_charger.h | 23 |
13 files changed, 4276 insertions, 892 deletions
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index 7c84ced2e01b..f276352cc9ef 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c | |||
@@ -95,6 +95,7 @@ | |||
95 | #define AB8500_IT_MASK22_REG 0x55 | 95 | #define AB8500_IT_MASK22_REG 0x55 |
96 | #define AB8500_IT_MASK23_REG 0x56 | 96 | #define AB8500_IT_MASK23_REG 0x56 |
97 | #define AB8500_IT_MASK24_REG 0x57 | 97 | #define AB8500_IT_MASK24_REG 0x57 |
98 | #define AB8500_IT_MASK25_REG 0x58 | ||
98 | 99 | ||
99 | /* | 100 | /* |
100 | * latch hierarchy registers | 101 | * latch hierarchy registers |
@@ -102,15 +103,25 @@ | |||
102 | #define AB8500_IT_LATCHHIER1_REG 0x60 | 103 | #define AB8500_IT_LATCHHIER1_REG 0x60 |
103 | #define AB8500_IT_LATCHHIER2_REG 0x61 | 104 | #define AB8500_IT_LATCHHIER2_REG 0x61 |
104 | #define AB8500_IT_LATCHHIER3_REG 0x62 | 105 | #define AB8500_IT_LATCHHIER3_REG 0x62 |
106 | #define AB8540_IT_LATCHHIER4_REG 0x63 | ||
105 | 107 | ||
106 | #define AB8500_IT_LATCHHIER_NUM 3 | 108 | #define AB8500_IT_LATCHHIER_NUM 3 |
109 | #define AB8540_IT_LATCHHIER_NUM 4 | ||
107 | 110 | ||
108 | #define AB8500_REV_REG 0x80 | 111 | #define AB8500_REV_REG 0x80 |
109 | #define AB8500_IC_NAME_REG 0x82 | 112 | #define AB8500_IC_NAME_REG 0x82 |
110 | #define AB8500_SWITCH_OFF_STATUS 0x00 | 113 | #define AB8500_SWITCH_OFF_STATUS 0x00 |
111 | 114 | ||
112 | #define AB8500_TURN_ON_STATUS 0x00 | 115 | #define AB8500_TURN_ON_STATUS 0x00 |
116 | #define AB8505_TURN_ON_STATUS_2 0x04 | ||
113 | 117 | ||
118 | #define AB8500_CH_USBCH_STAT1_REG 0x02 | ||
119 | #define VBUS_DET_DBNC100 0x02 | ||
120 | #define VBUS_DET_DBNC1 0x01 | ||
121 | |||
122 | static DEFINE_SPINLOCK(on_stat_lock); | ||
123 | static u8 turn_on_stat_mask = 0xFF; | ||
124 | static u8 turn_on_stat_set; | ||
114 | static bool no_bm; /* No battery management */ | 125 | static bool no_bm; /* No battery management */ |
115 | module_param(no_bm, bool, S_IRUGO); | 126 | module_param(no_bm, bool, S_IRUGO); |
116 | 127 | ||
@@ -130,9 +141,15 @@ static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = { | |||
130 | 0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, | 141 | 0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, |
131 | }; | 142 | }; |
132 | 143 | ||
133 | /* AB9540 support */ | 144 | /* AB9540 / AB8505 support */ |
134 | static const int ab9540_irq_regoffset[AB9540_NUM_IRQ_REGS] = { | 145 | static const int ab9540_irq_regoffset[AB9540_NUM_IRQ_REGS] = { |
135 | 0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, 12, 13, 24, | 146 | 0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, 12, 13, 24, 5, 22, 23 |
147 | }; | ||
148 | |||
149 | /* AB8540 support */ | ||
150 | static const int ab8540_irq_regoffset[AB8540_NUM_IRQ_REGS] = { | ||
151 | 0, 1, 2, 3, 4, -1, -1, -1, -1, 11, 18, 19, 20, 21, 12, 13, 24, 5, 22, 23, | ||
152 | 25, 26, 27, 28, 29, 30, 31, | ||
136 | }; | 153 | }; |
137 | 154 | ||
138 | static const char ab8500_version_str[][7] = { | 155 | static const char ab8500_version_str[][7] = { |
@@ -352,6 +369,9 @@ static void ab8500_irq_sync_unlock(struct irq_data *data) | |||
352 | is_ab8500_1p1_or_earlier(ab8500)) | 369 | is_ab8500_1p1_or_earlier(ab8500)) |
353 | continue; | 370 | continue; |
354 | 371 | ||
372 | if (ab8500->irq_reg_offset[i] < 0) | ||
373 | continue; | ||
374 | |||
355 | ab8500->oldmask[i] = new; | 375 | ab8500->oldmask[i] = new; |
356 | 376 | ||
357 | reg = AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i]; | 377 | reg = AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i]; |
@@ -423,6 +443,18 @@ static struct irq_chip ab8500_irq_chip = { | |||
423 | .irq_set_type = ab8500_irq_set_type, | 443 | .irq_set_type = ab8500_irq_set_type, |
424 | }; | 444 | }; |
425 | 445 | ||
446 | static void update_latch_offset(u8 *offset, int i) | ||
447 | { | ||
448 | /* Fix inconsistent ITFromLatch25 bit mapping... */ | ||
449 | if (unlikely(*offset == 17)) | ||
450 | *offset = 24; | ||
451 | /* Fix inconsistent ab8540 bit mapping... */ | ||
452 | if (unlikely(*offset == 16)) | ||
453 | *offset = 25; | ||
454 | if ((i==3) && (*offset >= 24)) | ||
455 | *offset += 2; | ||
456 | } | ||
457 | |||
426 | static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500, | 458 | static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500, |
427 | int latch_offset, u8 latch_val) | 459 | int latch_offset, u8 latch_val) |
428 | { | 460 | { |
@@ -474,9 +506,7 @@ static int ab8500_handle_hierarchical_latch(struct ab8500 *ab8500, | |||
474 | latch_bit = __ffs(hier_val); | 506 | latch_bit = __ffs(hier_val); |
475 | latch_offset = (hier_offset << 3) + latch_bit; | 507 | latch_offset = (hier_offset << 3) + latch_bit; |
476 | 508 | ||
477 | /* Fix inconsistent ITFromLatch25 bit mapping... */ | 509 | update_latch_offset(&latch_offset, hier_offset); |
478 | if (unlikely(latch_offset == 17)) | ||
479 | latch_offset = 24; | ||
480 | 510 | ||
481 | status = get_register_interruptible(ab8500, | 511 | status = get_register_interruptible(ab8500, |
482 | AB8500_INTERRUPT, | 512 | AB8500_INTERRUPT, |
@@ -504,7 +534,7 @@ static irqreturn_t ab8500_hierarchical_irq(int irq, void *dev) | |||
504 | dev_vdbg(ab8500->dev, "interrupt\n"); | 534 | dev_vdbg(ab8500->dev, "interrupt\n"); |
505 | 535 | ||
506 | /* Hierarchical interrupt version */ | 536 | /* Hierarchical interrupt version */ |
507 | for (i = 0; i < AB8500_IT_LATCHHIER_NUM; i++) { | 537 | for (i = 0; i < (ab8500->it_latchhier_num); i++) { |
508 | int status; | 538 | int status; |
509 | u8 hier_val; | 539 | u8 hier_val; |
510 | 540 | ||
@@ -520,63 +550,6 @@ static irqreturn_t ab8500_hierarchical_irq(int irq, void *dev) | |||
520 | return IRQ_HANDLED; | 550 | return IRQ_HANDLED; |
521 | } | 551 | } |
522 | 552 | ||
523 | /** | ||
524 | * ab8500_irq_get_virq(): Map an interrupt on a chip to a virtual IRQ | ||
525 | * | ||
526 | * @ab8500: ab8500_irq controller to operate on. | ||
527 | * @irq: index of the interrupt requested in the chip IRQs | ||
528 | * | ||
529 | * Useful for drivers to request their own IRQs. | ||
530 | */ | ||
531 | static int ab8500_irq_get_virq(struct ab8500 *ab8500, int irq) | ||
532 | { | ||
533 | if (!ab8500) | ||
534 | return -EINVAL; | ||
535 | |||
536 | return irq_create_mapping(ab8500->domain, irq); | ||
537 | } | ||
538 | |||
539 | static irqreturn_t ab8500_irq(int irq, void *dev) | ||
540 | { | ||
541 | struct ab8500 *ab8500 = dev; | ||
542 | int i; | ||
543 | |||
544 | dev_vdbg(ab8500->dev, "interrupt\n"); | ||
545 | |||
546 | atomic_inc(&ab8500->transfer_ongoing); | ||
547 | |||
548 | for (i = 0; i < ab8500->mask_size; i++) { | ||
549 | int regoffset = ab8500->irq_reg_offset[i]; | ||
550 | int status; | ||
551 | u8 value; | ||
552 | |||
553 | /* | ||
554 | * Interrupt register 12 doesn't exist prior to AB8500 version | ||
555 | * 2.0 | ||
556 | */ | ||
557 | if (regoffset == 11 && is_ab8500_1p1_or_earlier(ab8500)) | ||
558 | continue; | ||
559 | |||
560 | status = get_register_interruptible(ab8500, AB8500_INTERRUPT, | ||
561 | AB8500_IT_LATCH1_REG + regoffset, &value); | ||
562 | if (status < 0 || value == 0) | ||
563 | continue; | ||
564 | |||
565 | do { | ||
566 | int bit = __ffs(value); | ||
567 | int line = i * 8 + bit; | ||
568 | int virq = ab8500_irq_get_virq(ab8500, line); | ||
569 | |||
570 | handle_nested_irq(virq); | ||
571 | ab8500_debug_register_interrupt(line); | ||
572 | value &= ~(1 << bit); | ||
573 | |||
574 | } while (value); | ||
575 | } | ||
576 | atomic_dec(&ab8500->transfer_ongoing); | ||
577 | return IRQ_HANDLED; | ||
578 | } | ||
579 | |||
580 | static int ab8500_irq_map(struct irq_domain *d, unsigned int virq, | 553 | static int ab8500_irq_map(struct irq_domain *d, unsigned int virq, |
581 | irq_hw_number_t hwirq) | 554 | irq_hw_number_t hwirq) |
582 | { | 555 | { |
@@ -607,7 +580,9 @@ static int ab8500_irq_init(struct ab8500 *ab8500, struct device_node *np) | |||
607 | { | 580 | { |
608 | int num_irqs; | 581 | int num_irqs; |
609 | 582 | ||
610 | if (is_ab9540(ab8500)) | 583 | if (is_ab8540(ab8500)) |
584 | num_irqs = AB8540_NR_IRQS; | ||
585 | else if (is_ab9540(ab8500)) | ||
611 | num_irqs = AB9540_NR_IRQS; | 586 | num_irqs = AB9540_NR_IRQS; |
612 | else if (is_ab8505(ab8500)) | 587 | else if (is_ab8505(ab8500)) |
613 | num_irqs = AB8505_NR_IRQS; | 588 | num_irqs = AB8505_NR_IRQS; |
@@ -650,6 +625,15 @@ static struct resource ab8500_gpadc_resources[] = { | |||
650 | }, | 625 | }, |
651 | }; | 626 | }; |
652 | 627 | ||
628 | static struct resource ab8505_gpadc_resources[] = { | ||
629 | { | ||
630 | .name = "SW_CONV_END", | ||
631 | .start = AB8500_INT_GP_SW_ADC_CONV_END, | ||
632 | .end = AB8500_INT_GP_SW_ADC_CONV_END, | ||
633 | .flags = IORESOURCE_IRQ, | ||
634 | }, | ||
635 | }; | ||
636 | |||
653 | static struct resource ab8500_rtc_resources[] = { | 637 | static struct resource ab8500_rtc_resources[] = { |
654 | { | 638 | { |
655 | .name = "60S", | 639 | .name = "60S", |
@@ -973,6 +957,30 @@ static struct resource ab8505_iddet_resources[] = { | |||
973 | .end = AB8505_INT_KEYSTUCK, | 957 | .end = AB8505_INT_KEYSTUCK, |
974 | .flags = IORESOURCE_IRQ, | 958 | .flags = IORESOURCE_IRQ, |
975 | }, | 959 | }, |
960 | { | ||
961 | .name = "VBUS_DET_R", | ||
962 | .start = AB8500_INT_VBUS_DET_R, | ||
963 | .end = AB8500_INT_VBUS_DET_R, | ||
964 | .flags = IORESOURCE_IRQ, | ||
965 | }, | ||
966 | { | ||
967 | .name = "VBUS_DET_F", | ||
968 | .start = AB8500_INT_VBUS_DET_F, | ||
969 | .end = AB8500_INT_VBUS_DET_F, | ||
970 | .flags = IORESOURCE_IRQ, | ||
971 | }, | ||
972 | { | ||
973 | .name = "ID_DET_PLUGR", | ||
974 | .start = AB8500_INT_ID_DET_PLUGR, | ||
975 | .end = AB8500_INT_ID_DET_PLUGR, | ||
976 | .flags = IORESOURCE_IRQ, | ||
977 | }, | ||
978 | { | ||
979 | .name = "ID_DET_PLUGF", | ||
980 | .start = AB8500_INT_ID_DET_PLUGF, | ||
981 | .end = AB8500_INT_ID_DET_PLUGF, | ||
982 | .flags = IORESOURCE_IRQ, | ||
983 | }, | ||
976 | }; | 984 | }; |
977 | 985 | ||
978 | static struct resource ab8500_temp_resources[] = { | 986 | static struct resource ab8500_temp_resources[] = { |
@@ -984,7 +992,42 @@ static struct resource ab8500_temp_resources[] = { | |||
984 | }, | 992 | }, |
985 | }; | 993 | }; |
986 | 994 | ||
987 | static struct mfd_cell abx500_common_devs[] = { | 995 | static struct mfd_cell ab8500_bm_devs[] = { |
996 | { | ||
997 | .name = "ab8500-charger", | ||
998 | .of_compatible = "stericsson,ab8500-charger", | ||
999 | .num_resources = ARRAY_SIZE(ab8500_charger_resources), | ||
1000 | .resources = ab8500_charger_resources, | ||
1001 | .platform_data = &ab8500_bm_data, | ||
1002 | .pdata_size = sizeof(ab8500_bm_data), | ||
1003 | }, | ||
1004 | { | ||
1005 | .name = "ab8500-btemp", | ||
1006 | .of_compatible = "stericsson,ab8500-btemp", | ||
1007 | .num_resources = ARRAY_SIZE(ab8500_btemp_resources), | ||
1008 | .resources = ab8500_btemp_resources, | ||
1009 | .platform_data = &ab8500_bm_data, | ||
1010 | .pdata_size = sizeof(ab8500_bm_data), | ||
1011 | }, | ||
1012 | { | ||
1013 | .name = "ab8500-fg", | ||
1014 | .of_compatible = "stericsson,ab8500-fg", | ||
1015 | .num_resources = ARRAY_SIZE(ab8500_fg_resources), | ||
1016 | .resources = ab8500_fg_resources, | ||
1017 | .platform_data = &ab8500_bm_data, | ||
1018 | .pdata_size = sizeof(ab8500_bm_data), | ||
1019 | }, | ||
1020 | { | ||
1021 | .name = "ab8500-chargalg", | ||
1022 | .of_compatible = "stericsson,ab8500-chargalg", | ||
1023 | .num_resources = ARRAY_SIZE(ab8500_chargalg_resources), | ||
1024 | .resources = ab8500_chargalg_resources, | ||
1025 | .platform_data = &ab8500_bm_data, | ||
1026 | .pdata_size = sizeof(ab8500_bm_data), | ||
1027 | }, | ||
1028 | }; | ||
1029 | |||
1030 | static struct mfd_cell ab8500_devs[] = { | ||
988 | #ifdef CONFIG_DEBUG_FS | 1031 | #ifdef CONFIG_DEBUG_FS |
989 | { | 1032 | { |
990 | .name = "ab8500-debug", | 1033 | .name = "ab8500-debug", |
@@ -1007,7 +1050,6 @@ static struct mfd_cell abx500_common_devs[] = { | |||
1007 | }, | 1050 | }, |
1008 | { | 1051 | { |
1009 | .name = "ab8500-gpadc", | 1052 | .name = "ab8500-gpadc", |
1010 | .of_compatible = "stericsson,ab8500-gpadc", | ||
1011 | .num_resources = ARRAY_SIZE(ab8500_gpadc_resources), | 1053 | .num_resources = ARRAY_SIZE(ab8500_gpadc_resources), |
1012 | .resources = ab8500_gpadc_resources, | 1054 | .resources = ab8500_gpadc_resources, |
1013 | }, | 1055 | }, |
@@ -1024,6 +1066,7 @@ static struct mfd_cell abx500_common_devs[] = { | |||
1024 | .resources = ab8500_av_acc_detect_resources, | 1066 | .resources = ab8500_av_acc_detect_resources, |
1025 | }, | 1067 | }, |
1026 | { | 1068 | { |
1069 | |||
1027 | .name = "ab8500-poweron-key", | 1070 | .name = "ab8500-poweron-key", |
1028 | .of_compatible = "stericsson,ab8500-poweron-key", | 1071 | .of_compatible = "stericsson,ab8500-poweron-key", |
1029 | .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources), | 1072 | .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources), |
@@ -1053,82 +1096,220 @@ static struct mfd_cell abx500_common_devs[] = { | |||
1053 | .of_compatible = "stericsson,ab8500-denc", | 1096 | .of_compatible = "stericsson,ab8500-denc", |
1054 | }, | 1097 | }, |
1055 | { | 1098 | { |
1099 | .name = "ab8500-gpio", | ||
1100 | .of_compatible = "stericsson,ab8500-gpio", | ||
1101 | }, | ||
1102 | { | ||
1056 | .name = "abx500-temp", | 1103 | .name = "abx500-temp", |
1057 | .of_compatible = "stericsson,abx500-temp", | 1104 | .of_compatible = "stericsson,abx500-temp", |
1058 | .num_resources = ARRAY_SIZE(ab8500_temp_resources), | 1105 | .num_resources = ARRAY_SIZE(ab8500_temp_resources), |
1059 | .resources = ab8500_temp_resources, | 1106 | .resources = ab8500_temp_resources, |
1060 | }, | 1107 | }, |
1108 | { | ||
1109 | .name = "ab8500-usb", | ||
1110 | .num_resources = ARRAY_SIZE(ab8500_usb_resources), | ||
1111 | .resources = ab8500_usb_resources, | ||
1112 | }, | ||
1113 | { | ||
1114 | .name = "ab8500-codec", | ||
1115 | }, | ||
1061 | }; | 1116 | }; |
1062 | 1117 | ||
1063 | static struct mfd_cell ab8500_bm_devs[] = { | 1118 | static struct mfd_cell ab9540_devs[] = { |
1119 | #ifdef CONFIG_DEBUG_FS | ||
1064 | { | 1120 | { |
1065 | .name = "ab8500-charger", | 1121 | .name = "ab8500-debug", |
1066 | .of_compatible = "stericsson,ab8500-charger", | 1122 | .num_resources = ARRAY_SIZE(ab8500_debug_resources), |
1067 | .num_resources = ARRAY_SIZE(ab8500_charger_resources), | 1123 | .resources = ab8500_debug_resources, |
1068 | .resources = ab8500_charger_resources, | ||
1069 | .platform_data = &ab8500_bm_data, | ||
1070 | .pdata_size = sizeof(ab8500_bm_data), | ||
1071 | }, | 1124 | }, |
1125 | #endif | ||
1072 | { | 1126 | { |
1073 | .name = "ab8500-btemp", | 1127 | .name = "ab8500-sysctrl", |
1074 | .of_compatible = "stericsson,ab8500-btemp", | ||
1075 | .num_resources = ARRAY_SIZE(ab8500_btemp_resources), | ||
1076 | .resources = ab8500_btemp_resources, | ||
1077 | .platform_data = &ab8500_bm_data, | ||
1078 | .pdata_size = sizeof(ab8500_bm_data), | ||
1079 | }, | 1128 | }, |
1080 | { | 1129 | { |
1081 | .name = "ab8500-fg", | 1130 | .name = "ab8500-regulator", |
1082 | .of_compatible = "stericsson,ab8500-fg", | ||
1083 | .num_resources = ARRAY_SIZE(ab8500_fg_resources), | ||
1084 | .resources = ab8500_fg_resources, | ||
1085 | .platform_data = &ab8500_bm_data, | ||
1086 | .pdata_size = sizeof(ab8500_bm_data), | ||
1087 | }, | 1131 | }, |
1088 | { | 1132 | { |
1089 | .name = "ab8500-chargalg", | 1133 | .name = "abx500-clk", |
1090 | .of_compatible = "stericsson,ab8500-chargalg", | 1134 | .of_compatible = "stericsson,abx500-clk", |
1091 | .num_resources = ARRAY_SIZE(ab8500_chargalg_resources), | 1135 | }, |
1092 | .resources = ab8500_chargalg_resources, | 1136 | { |
1093 | .platform_data = &ab8500_bm_data, | 1137 | .name = "ab8500-gpadc", |
1094 | .pdata_size = sizeof(ab8500_bm_data), | 1138 | .of_compatible = "stericsson,ab8500-gpadc", |
1139 | .num_resources = ARRAY_SIZE(ab8500_gpadc_resources), | ||
1140 | .resources = ab8500_gpadc_resources, | ||
1141 | }, | ||
1142 | { | ||
1143 | .name = "ab8500-rtc", | ||
1144 | .num_resources = ARRAY_SIZE(ab8500_rtc_resources), | ||
1145 | .resources = ab8500_rtc_resources, | ||
1146 | }, | ||
1147 | { | ||
1148 | .name = "ab8500-acc-det", | ||
1149 | .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources), | ||
1150 | .resources = ab8500_av_acc_detect_resources, | ||
1151 | }, | ||
1152 | { | ||
1153 | .name = "ab8500-poweron-key", | ||
1154 | .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources), | ||
1155 | .resources = ab8500_poweronkey_db_resources, | ||
1156 | }, | ||
1157 | { | ||
1158 | .name = "ab8500-pwm", | ||
1159 | .id = 1, | ||
1160 | }, | ||
1161 | { | ||
1162 | .name = "ab8500-leds", | ||
1163 | }, | ||
1164 | { | ||
1165 | .name = "abx500-temp", | ||
1166 | .num_resources = ARRAY_SIZE(ab8500_temp_resources), | ||
1167 | .resources = ab8500_temp_resources, | ||
1168 | }, | ||
1169 | { | ||
1170 | .name = "pinctrl-ab9540", | ||
1171 | .of_compatible = "stericsson,ab9540-gpio", | ||
1172 | }, | ||
1173 | { | ||
1174 | .name = "ab9540-usb", | ||
1175 | .num_resources = ARRAY_SIZE(ab8500_usb_resources), | ||
1176 | .resources = ab8500_usb_resources, | ||
1177 | }, | ||
1178 | { | ||
1179 | .name = "ab9540-codec", | ||
1180 | }, | ||
1181 | { | ||
1182 | .name = "ab-iddet", | ||
1183 | .num_resources = ARRAY_SIZE(ab8505_iddet_resources), | ||
1184 | .resources = ab8505_iddet_resources, | ||
1095 | }, | 1185 | }, |
1096 | }; | 1186 | }; |
1097 | 1187 | ||
1098 | static struct mfd_cell ab8500_devs[] = { | 1188 | /* Device list for ab8505 */ |
1189 | static struct mfd_cell ab8505_devs[] = { | ||
1190 | #ifdef CONFIG_DEBUG_FS | ||
1099 | { | 1191 | { |
1100 | .name = "pinctrl-ab8500", | 1192 | .name = "ab8500-debug", |
1101 | .of_compatible = "stericsson,ab8500-gpio", | 1193 | .num_resources = ARRAY_SIZE(ab8500_debug_resources), |
1194 | .resources = ab8500_debug_resources, | ||
1195 | }, | ||
1196 | #endif | ||
1197 | { | ||
1198 | .name = "ab8500-sysctrl", | ||
1199 | }, | ||
1200 | { | ||
1201 | .name = "ab8500-regulator", | ||
1202 | }, | ||
1203 | { | ||
1204 | .name = "abx500-clk", | ||
1205 | .of_compatible = "stericsson,abx500-clk", | ||
1206 | }, | ||
1207 | { | ||
1208 | .name = "ab8500-gpadc", | ||
1209 | .num_resources = ARRAY_SIZE(ab8505_gpadc_resources), | ||
1210 | .resources = ab8505_gpadc_resources, | ||
1211 | }, | ||
1212 | { | ||
1213 | .name = "ab8500-rtc", | ||
1214 | .num_resources = ARRAY_SIZE(ab8500_rtc_resources), | ||
1215 | .resources = ab8500_rtc_resources, | ||
1216 | }, | ||
1217 | { | ||
1218 | .name = "ab8500-acc-det", | ||
1219 | .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources), | ||
1220 | .resources = ab8500_av_acc_detect_resources, | ||
1221 | }, | ||
1222 | { | ||
1223 | .name = "ab8500-poweron-key", | ||
1224 | .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources), | ||
1225 | .resources = ab8500_poweronkey_db_resources, | ||
1226 | }, | ||
1227 | { | ||
1228 | .name = "ab8500-pwm", | ||
1229 | .id = 1, | ||
1230 | }, | ||
1231 | { | ||
1232 | .name = "ab8500-leds", | ||
1233 | }, | ||
1234 | { | ||
1235 | .name = "ab8500-gpio", | ||
1102 | }, | 1236 | }, |
1103 | { | 1237 | { |
1104 | .name = "ab8500-usb", | 1238 | .name = "ab8500-usb", |
1105 | .of_compatible = "stericsson,ab8500-usb", | ||
1106 | .num_resources = ARRAY_SIZE(ab8500_usb_resources), | 1239 | .num_resources = ARRAY_SIZE(ab8500_usb_resources), |
1107 | .resources = ab8500_usb_resources, | 1240 | .resources = ab8500_usb_resources, |
1108 | }, | 1241 | }, |
1109 | { | 1242 | { |
1110 | .name = "ab8500-codec", | 1243 | .name = "ab8500-codec", |
1111 | .of_compatible = "stericsson,ab8500-codec", | 1244 | }, |
1245 | { | ||
1246 | .name = "ab-iddet", | ||
1247 | .num_resources = ARRAY_SIZE(ab8505_iddet_resources), | ||
1248 | .resources = ab8505_iddet_resources, | ||
1112 | }, | 1249 | }, |
1113 | }; | 1250 | }; |
1114 | 1251 | ||
1115 | static struct mfd_cell ab9540_devs[] = { | 1252 | static struct mfd_cell ab8540_devs[] = { |
1253 | #ifdef CONFIG_DEBUG_FS | ||
1116 | { | 1254 | { |
1117 | .name = "pinctrl-ab9540", | 1255 | .name = "ab8500-debug", |
1118 | .of_compatible = "stericsson,ab9540-gpio", | 1256 | .num_resources = ARRAY_SIZE(ab8500_debug_resources), |
1257 | .resources = ab8500_debug_resources, | ||
1258 | }, | ||
1259 | #endif | ||
1260 | { | ||
1261 | .name = "ab8500-sysctrl", | ||
1119 | }, | 1262 | }, |
1120 | { | 1263 | { |
1121 | .name = "ab9540-usb", | 1264 | .name = "ab8500-regulator", |
1265 | }, | ||
1266 | { | ||
1267 | .name = "abx500-clk", | ||
1268 | .of_compatible = "stericsson,abx500-clk", | ||
1269 | }, | ||
1270 | { | ||
1271 | .name = "ab8500-gpadc", | ||
1272 | .num_resources = ARRAY_SIZE(ab8505_gpadc_resources), | ||
1273 | .resources = ab8505_gpadc_resources, | ||
1274 | }, | ||
1275 | { | ||
1276 | .name = "ab8500-rtc", | ||
1277 | .num_resources = ARRAY_SIZE(ab8500_rtc_resources), | ||
1278 | .resources = ab8500_rtc_resources, | ||
1279 | }, | ||
1280 | { | ||
1281 | .name = "ab8500-acc-det", | ||
1282 | .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources), | ||
1283 | .resources = ab8500_av_acc_detect_resources, | ||
1284 | }, | ||
1285 | { | ||
1286 | .name = "ab8500-poweron-key", | ||
1287 | .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources), | ||
1288 | .resources = ab8500_poweronkey_db_resources, | ||
1289 | }, | ||
1290 | { | ||
1291 | .name = "ab8500-pwm", | ||
1292 | .id = 1, | ||
1293 | }, | ||
1294 | { | ||
1295 | .name = "ab8500-leds", | ||
1296 | }, | ||
1297 | { | ||
1298 | .name = "abx500-temp", | ||
1299 | .num_resources = ARRAY_SIZE(ab8500_temp_resources), | ||
1300 | .resources = ab8500_temp_resources, | ||
1301 | }, | ||
1302 | { | ||
1303 | .name = "ab8500-gpio", | ||
1304 | }, | ||
1305 | { | ||
1306 | .name = "ab8540-usb", | ||
1122 | .num_resources = ARRAY_SIZE(ab8500_usb_resources), | 1307 | .num_resources = ARRAY_SIZE(ab8500_usb_resources), |
1123 | .resources = ab8500_usb_resources, | 1308 | .resources = ab8500_usb_resources, |
1124 | }, | 1309 | }, |
1125 | { | 1310 | { |
1126 | .name = "ab9540-codec", | 1311 | .name = "ab8540-codec", |
1127 | }, | 1312 | }, |
1128 | }; | ||
1129 | |||
1130 | /* Device list common to ab9540 and ab8505 */ | ||
1131 | static struct mfd_cell ab9540_ab8505_devs[] = { | ||
1132 | { | 1313 | { |
1133 | .name = "ab-iddet", | 1314 | .name = "ab-iddet", |
1134 | .num_resources = ARRAY_SIZE(ab8505_iddet_resources), | 1315 | .num_resources = ARRAY_SIZE(ab8505_iddet_resources), |
@@ -1142,6 +1323,7 @@ static ssize_t show_chip_id(struct device *dev, | |||
1142 | struct ab8500 *ab8500; | 1323 | struct ab8500 *ab8500; |
1143 | 1324 | ||
1144 | ab8500 = dev_get_drvdata(dev); | 1325 | ab8500 = dev_get_drvdata(dev); |
1326 | |||
1145 | return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL); | 1327 | return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL); |
1146 | } | 1328 | } |
1147 | 1329 | ||
@@ -1171,6 +1353,15 @@ static ssize_t show_switch_off_status(struct device *dev, | |||
1171 | return sprintf(buf, "%#x\n", value); | 1353 | return sprintf(buf, "%#x\n", value); |
1172 | } | 1354 | } |
1173 | 1355 | ||
1356 | /* use mask and set to override the register turn_on_stat value */ | ||
1357 | void ab8500_override_turn_on_stat(u8 mask, u8 set) | ||
1358 | { | ||
1359 | spin_lock(&on_stat_lock); | ||
1360 | turn_on_stat_mask = mask; | ||
1361 | turn_on_stat_set = set; | ||
1362 | spin_unlock(&on_stat_lock); | ||
1363 | } | ||
1364 | |||
1174 | /* | 1365 | /* |
1175 | * ab8500 has turned on due to (TURN_ON_STATUS): | 1366 | * ab8500 has turned on due to (TURN_ON_STATUS): |
1176 | * 0x01 PORnVbat | 1367 | * 0x01 PORnVbat |
@@ -1194,9 +1385,38 @@ static ssize_t show_turn_on_status(struct device *dev, | |||
1194 | AB8500_TURN_ON_STATUS, &value); | 1385 | AB8500_TURN_ON_STATUS, &value); |
1195 | if (ret < 0) | 1386 | if (ret < 0) |
1196 | return ret; | 1387 | return ret; |
1388 | |||
1389 | /* | ||
1390 | * In L9540, turn_on_status register is not updated correctly if | ||
1391 | * the device is rebooted with AC/USB charger connected. Due to | ||
1392 | * this, the device boots android instead of entering into charge | ||
1393 | * only mode. Read the AC/USB status register to detect the charger | ||
1394 | * presence and update the turn on status manually. | ||
1395 | */ | ||
1396 | if (is_ab9540(ab8500)) { | ||
1397 | spin_lock(&on_stat_lock); | ||
1398 | value = (value & turn_on_stat_mask) | turn_on_stat_set; | ||
1399 | spin_unlock(&on_stat_lock); | ||
1400 | } | ||
1401 | |||
1197 | return sprintf(buf, "%#x\n", value); | 1402 | return sprintf(buf, "%#x\n", value); |
1198 | } | 1403 | } |
1199 | 1404 | ||
1405 | static 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 | |||
1200 | static ssize_t show_ab9540_dbbrstn(struct device *dev, | 1420 | static ssize_t show_ab9540_dbbrstn(struct device *dev, |
1201 | struct device_attribute *attr, char *buf) | 1421 | struct device_attribute *attr, char *buf) |
1202 | { | 1422 | { |
@@ -1253,6 +1473,7 @@ exit: | |||
1253 | static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL); | 1473 | static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL); |
1254 | static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL); | 1474 | static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL); |
1255 | static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL); | 1475 | static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL); |
1476 | static DEVICE_ATTR(turn_on_status_2, S_IRUGO, show_turn_on_status_2, NULL); | ||
1256 | static DEVICE_ATTR(dbbrstn, S_IRUGO | S_IWUSR, | 1477 | static DEVICE_ATTR(dbbrstn, S_IRUGO | S_IWUSR, |
1257 | show_ab9540_dbbrstn, store_ab9540_dbbrstn); | 1478 | show_ab9540_dbbrstn, store_ab9540_dbbrstn); |
1258 | 1479 | ||
@@ -1263,6 +1484,11 @@ static struct attribute *ab8500_sysfs_entries[] = { | |||
1263 | NULL, | 1484 | NULL, |
1264 | }; | 1485 | }; |
1265 | 1486 | ||
1487 | static struct attribute *ab8505_sysfs_entries[] = { | ||
1488 | &dev_attr_turn_on_status_2.attr, | ||
1489 | NULL, | ||
1490 | }; | ||
1491 | |||
1266 | static struct attribute *ab9540_sysfs_entries[] = { | 1492 | static struct attribute *ab9540_sysfs_entries[] = { |
1267 | &dev_attr_chip_id.attr, | 1493 | &dev_attr_chip_id.attr, |
1268 | &dev_attr_switch_off_status.attr, | 1494 | &dev_attr_switch_off_status.attr, |
@@ -1275,6 +1501,10 @@ static struct attribute_group ab8500_attr_group = { | |||
1275 | .attrs = ab8500_sysfs_entries, | 1501 | .attrs = ab8500_sysfs_entries, |
1276 | }; | 1502 | }; |
1277 | 1503 | ||
1504 | static struct attribute_group ab8505_attr_group = { | ||
1505 | .attrs = ab8505_sysfs_entries, | ||
1506 | }; | ||
1507 | |||
1278 | static struct attribute_group ab9540_attr_group = { | 1508 | static struct attribute_group ab9540_attr_group = { |
1279 | .attrs = ab9540_sysfs_entries, | 1509 | .attrs = ab9540_sysfs_entries, |
1280 | }; | 1510 | }; |
@@ -1290,6 +1520,15 @@ static int ab8500_probe(struct platform_device *pdev) | |||
1290 | "Battery level lower than power on reset threshold", | 1520 | "Battery level lower than power on reset threshold", |
1291 | "Power on key 1 pressed longer than 10 seconds", | 1521 | "Power on key 1 pressed longer than 10 seconds", |
1292 | "DB8500 thermal shutdown"}; | 1522 | "DB8500 thermal shutdown"}; |
1523 | static char *turn_on_status[] = { | ||
1524 | "Battery rising (Vbat)", | ||
1525 | "Power On Key 1 dbF", | ||
1526 | "Power On Key 2 dbF", | ||
1527 | "RTC Alarm", | ||
1528 | "Main Charger Detect", | ||
1529 | "Vbus Detect (USB)", | ||
1530 | "USB ID Detect", | ||
1531 | "UART Factory Mode Detect"}; | ||
1293 | struct ab8500_platform_data *plat = dev_get_platdata(&pdev->dev); | 1532 | struct ab8500_platform_data *plat = dev_get_platdata(&pdev->dev); |
1294 | const struct platform_device_id *platid = platform_get_device_id(pdev); | 1533 | const struct platform_device_id *platid = platform_get_device_id(pdev); |
1295 | enum ab8500_version version = AB8500_VERSION_UNDEFINED; | 1534 | enum ab8500_version version = AB8500_VERSION_UNDEFINED; |
@@ -1351,13 +1590,20 @@ static int ab8500_probe(struct platform_device *pdev) | |||
1351 | ab8500->chip_id >> 4, | 1590 | ab8500->chip_id >> 4, |
1352 | ab8500->chip_id & 0x0F); | 1591 | ab8500->chip_id & 0x0F); |
1353 | 1592 | ||
1354 | /* Configure AB8500 or AB9540 IRQ */ | 1593 | /* Configure AB8540 */ |
1355 | if (is_ab9540(ab8500) || is_ab8505(ab8500)) { | 1594 | if (is_ab8540(ab8500)) { |
1595 | ab8500->mask_size = AB8540_NUM_IRQ_REGS; | ||
1596 | ab8500->irq_reg_offset = ab8540_irq_regoffset; | ||
1597 | ab8500->it_latchhier_num = AB8540_IT_LATCHHIER_NUM; | ||
1598 | }/* Configure AB8500 or AB9540 IRQ */ | ||
1599 | else if (is_ab9540(ab8500) || is_ab8505(ab8500)) { | ||
1356 | ab8500->mask_size = AB9540_NUM_IRQ_REGS; | 1600 | ab8500->mask_size = AB9540_NUM_IRQ_REGS; |
1357 | ab8500->irq_reg_offset = ab9540_irq_regoffset; | 1601 | ab8500->irq_reg_offset = ab9540_irq_regoffset; |
1602 | ab8500->it_latchhier_num = AB8500_IT_LATCHHIER_NUM; | ||
1358 | } else { | 1603 | } else { |
1359 | ab8500->mask_size = AB8500_NUM_IRQ_REGS; | 1604 | ab8500->mask_size = AB8500_NUM_IRQ_REGS; |
1360 | ab8500->irq_reg_offset = ab8500_irq_regoffset; | 1605 | ab8500->irq_reg_offset = ab8500_irq_regoffset; |
1606 | ab8500->it_latchhier_num = AB8500_IT_LATCHHIER_NUM; | ||
1361 | } | 1607 | } |
1362 | ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL); | 1608 | ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL); |
1363 | if (!ab8500->mask) | 1609 | if (!ab8500->mask) |
@@ -1396,10 +1642,36 @@ static int ab8500_probe(struct platform_device *pdev) | |||
1396 | } else { | 1642 | } else { |
1397 | printk(KERN_CONT " None\n"); | 1643 | printk(KERN_CONT " None\n"); |
1398 | } | 1644 | } |
1645 | ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK, | ||
1646 | AB8500_TURN_ON_STATUS, &value); | ||
1647 | if (ret < 0) | ||
1648 | return ret; | ||
1649 | dev_info(ab8500->dev, "turn on reason(s) (%#x): ", value); | ||
1650 | |||
1651 | if (value) { | ||
1652 | for (i = 0; i < ARRAY_SIZE(turn_on_status); i++) { | ||
1653 | if (value & 1) | ||
1654 | printk("\"%s\" ", turn_on_status[i]); | ||
1655 | value = value >> 1; | ||
1656 | } | ||
1657 | printk("\n"); | ||
1658 | } else { | ||
1659 | printk("None\n"); | ||
1660 | } | ||
1399 | 1661 | ||
1400 | if (plat && plat->init) | 1662 | if (plat && plat->init) |
1401 | plat->init(ab8500); | 1663 | plat->init(ab8500); |
1402 | 1664 | ||
1665 | if (is_ab9540(ab8500)) { | ||
1666 | ret = get_register_interruptible(ab8500, AB8500_CHARGER, | ||
1667 | AB8500_CH_USBCH_STAT1_REG, &value); | ||
1668 | if (ret < 0) | ||
1669 | return ret; | ||
1670 | if ((value & VBUS_DET_DBNC1) && (value & VBUS_DET_DBNC100)) | ||
1671 | ab8500_override_turn_on_stat(~AB8500_POW_KEY_1_ON, | ||
1672 | AB8500_VBUS_DET); | ||
1673 | } | ||
1674 | |||
1403 | /* Clear and mask all interrupts */ | 1675 | /* Clear and mask all interrupts */ |
1404 | for (i = 0; i < ab8500->mask_size; i++) { | 1676 | for (i = 0; i < ab8500->mask_size; i++) { |
1405 | /* | 1677 | /* |
@@ -1410,6 +1682,9 @@ static int ab8500_probe(struct platform_device *pdev) | |||
1410 | is_ab8500_1p1_or_earlier(ab8500)) | 1682 | is_ab8500_1p1_or_earlier(ab8500)) |
1411 | continue; | 1683 | continue; |
1412 | 1684 | ||
1685 | if (ab8500->irq_reg_offset[i] < 0) | ||
1686 | continue; | ||
1687 | |||
1413 | get_register_interruptible(ab8500, AB8500_INTERRUPT, | 1688 | get_register_interruptible(ab8500, AB8500_INTERRUPT, |
1414 | AB8500_IT_LATCH1_REG + ab8500->irq_reg_offset[i], | 1689 | AB8500_IT_LATCH1_REG + ab8500->irq_reg_offset[i], |
1415 | &value); | 1690 | &value); |
@@ -1428,26 +1703,10 @@ static int ab8500_probe(struct platform_device *pdev) | |||
1428 | if (ret) | 1703 | if (ret) |
1429 | return ret; | 1704 | return ret; |
1430 | 1705 | ||
1431 | /* Activate this feature only in ab9540 */ | 1706 | ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL, |
1432 | /* till tests are done on ab8500 1p2 or later*/ | 1707 | ab8500_hierarchical_irq, |
1433 | if (is_ab9540(ab8500)) { | 1708 | IRQF_ONESHOT | IRQF_NO_SUSPEND, |
1434 | ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL, | 1709 | "ab8500", ab8500); |
1435 | ab8500_hierarchical_irq, | ||
1436 | IRQF_ONESHOT | IRQF_NO_SUSPEND, | ||
1437 | "ab8500", ab8500); | ||
1438 | } | ||
1439 | else { | ||
1440 | ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL, | ||
1441 | ab8500_irq, | ||
1442 | IRQF_ONESHOT | IRQF_NO_SUSPEND, | ||
1443 | "ab8500", ab8500); | ||
1444 | if (ret) | ||
1445 | return ret; | ||
1446 | } | ||
1447 | |||
1448 | ret = mfd_add_devices(ab8500->dev, 0, abx500_common_devs, | ||
1449 | ARRAY_SIZE(abx500_common_devs), NULL, | ||
1450 | ab8500->irq_base, ab8500->domain); | ||
1451 | if (ret) | 1710 | if (ret) |
1452 | return ret; | 1711 | return ret; |
1453 | 1712 | ||
@@ -1455,6 +1714,14 @@ static int ab8500_probe(struct platform_device *pdev) | |||
1455 | ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs, | 1714 | ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs, |
1456 | ARRAY_SIZE(ab9540_devs), NULL, | 1715 | ARRAY_SIZE(ab9540_devs), NULL, |
1457 | ab8500->irq_base, ab8500->domain); | 1716 | ab8500->irq_base, ab8500->domain); |
1717 | else if (is_ab8540(ab8500)) | ||
1718 | ret = mfd_add_devices(ab8500->dev, 0, ab8540_devs, | ||
1719 | ARRAY_SIZE(ab8540_devs), NULL, | ||
1720 | ab8500->irq_base, ab8500->domain); | ||
1721 | else if (is_ab8505(ab8500)) | ||
1722 | ret = mfd_add_devices(ab8500->dev, 0, ab8505_devs, | ||
1723 | ARRAY_SIZE(ab8505_devs), NULL, | ||
1724 | ab8500->irq_base, ab8500->domain); | ||
1458 | else | 1725 | else |
1459 | ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs, | 1726 | ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs, |
1460 | ARRAY_SIZE(ab8500_devs), NULL, | 1727 | ARRAY_SIZE(ab8500_devs), NULL, |
@@ -1462,13 +1729,6 @@ static int ab8500_probe(struct platform_device *pdev) | |||
1462 | if (ret) | 1729 | if (ret) |
1463 | return ret; | 1730 | return ret; |
1464 | 1731 | ||
1465 | if (is_ab9540(ab8500) || is_ab8505(ab8500)) | ||
1466 | ret = mfd_add_devices(ab8500->dev, 0, ab9540_ab8505_devs, | ||
1467 | ARRAY_SIZE(ab9540_ab8505_devs), NULL, | ||
1468 | ab8500->irq_base, ab8500->domain); | ||
1469 | if (ret) | ||
1470 | return ret; | ||
1471 | |||
1472 | if (!no_bm) { | 1732 | if (!no_bm) { |
1473 | /* Add battery management devices */ | 1733 | /* Add battery management devices */ |
1474 | ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs, | 1734 | ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs, |
@@ -1478,12 +1738,19 @@ static int ab8500_probe(struct platform_device *pdev) | |||
1478 | dev_err(ab8500->dev, "error adding bm devices\n"); | 1738 | dev_err(ab8500->dev, "error adding bm devices\n"); |
1479 | } | 1739 | } |
1480 | 1740 | ||
1481 | if (is_ab9540(ab8500)) | 1741 | if (((is_ab8505(ab8500) || is_ab9540(ab8500)) && |
1742 | ab8500->chip_id >= AB8500_CUT2P0) || is_ab8540(ab8500)) | ||
1482 | ret = sysfs_create_group(&ab8500->dev->kobj, | 1743 | ret = sysfs_create_group(&ab8500->dev->kobj, |
1483 | &ab9540_attr_group); | 1744 | &ab9540_attr_group); |
1484 | else | 1745 | else |
1485 | ret = sysfs_create_group(&ab8500->dev->kobj, | 1746 | ret = sysfs_create_group(&ab8500->dev->kobj, |
1486 | &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 | |||
1487 | if (ret) | 1754 | if (ret) |
1488 | dev_err(ab8500->dev, "error creating sysfs entries\n"); | 1755 | dev_err(ab8500->dev, "error creating sysfs entries\n"); |
1489 | 1756 | ||
@@ -1494,11 +1761,16 @@ static int ab8500_remove(struct platform_device *pdev) | |||
1494 | { | 1761 | { |
1495 | struct ab8500 *ab8500 = platform_get_drvdata(pdev); | 1762 | struct ab8500 *ab8500 = platform_get_drvdata(pdev); |
1496 | 1763 | ||
1497 | if (is_ab9540(ab8500)) | 1764 | if (((is_ab8505(ab8500) || is_ab9540(ab8500)) && |
1765 | ab8500->chip_id >= AB8500_CUT2P0) || is_ab8540(ab8500)) | ||
1498 | sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group); | 1766 | sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group); |
1499 | else | 1767 | else |
1500 | sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group); | 1768 | sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group); |
1501 | 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 | |||
1502 | mfd_remove_devices(ab8500->dev); | 1774 | mfd_remove_devices(ab8500->dev); |
1503 | 1775 | ||
1504 | return 0; | 1776 | return 0; |
diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c index 45fe3c50eb03..b88bbbc15f1e 100644 --- a/drivers/mfd/ab8500-debugfs.c +++ b/drivers/mfd/ab8500-debugfs.c | |||
@@ -80,6 +80,7 @@ | |||
80 | #include <linux/interrupt.h> | 80 | #include <linux/interrupt.h> |
81 | #include <linux/kobject.h> | 81 | #include <linux/kobject.h> |
82 | #include <linux/slab.h> | 82 | #include <linux/slab.h> |
83 | #include <linux/irq.h> | ||
83 | 84 | ||
84 | #include <linux/mfd/abx500.h> | 85 | #include <linux/mfd/abx500.h> |
85 | #include <linux/mfd/abx500/ab8500.h> | 86 | #include <linux/mfd/abx500/ab8500.h> |
@@ -90,6 +91,9 @@ | |||
90 | #include <linux/ctype.h> | 91 | #include <linux/ctype.h> |
91 | #endif | 92 | #endif |
92 | 93 | ||
94 | /* TODO: this file should not reference IRQ_DB8500_AB8500! */ | ||
95 | #include <mach/irqs.h> | ||
96 | |||
93 | static u32 debug_bank; | 97 | static u32 debug_bank; |
94 | static u32 debug_address; | 98 | static u32 debug_address; |
95 | 99 | ||
@@ -101,6 +105,11 @@ static int num_irqs; | |||
101 | static struct device_attribute **dev_attr; | 105 | static struct device_attribute **dev_attr; |
102 | static char **event_name; | 106 | static char **event_name; |
103 | 107 | ||
108 | static u8 avg_sample = SAMPLE_16; | ||
109 | static u8 trig_edge = RISING_EDGE; | ||
110 | static u8 conv_type = ADC_SW; | ||
111 | static u8 trig_timer; | ||
112 | |||
104 | /** | 113 | /** |
105 | * struct ab8500_reg_range | 114 | * struct ab8500_reg_range |
106 | * @first: the first address of the range | 115 | * @first: the first address of the range |
@@ -150,7 +159,9 @@ static struct hwreg_cfg hwreg_cfg = { | |||
150 | 159 | ||
151 | #define AB8500_REV_REG 0x80 | 160 | #define AB8500_REV_REG 0x80 |
152 | 161 | ||
153 | static struct ab8500_prcmu_ranges debug_ranges[AB8500_NUM_BANKS] = { | 162 | static struct ab8500_prcmu_ranges *debug_ranges; |
163 | |||
164 | struct ab8500_prcmu_ranges ab8500_debug_ranges[AB8500_NUM_BANKS] = { | ||
154 | [0x0] = { | 165 | [0x0] = { |
155 | .num_ranges = 0, | 166 | .num_ranges = 0, |
156 | .range = NULL, | 167 | .range = NULL, |
@@ -354,7 +365,7 @@ static struct ab8500_prcmu_ranges debug_ranges[AB8500_NUM_BANKS] = { | |||
354 | }, | 365 | }, |
355 | { | 366 | { |
356 | .first = 0xf5, | 367 | .first = 0xf5, |
357 | .last = 0xf6, | 368 | .last = 0xf6, |
358 | }, | 369 | }, |
359 | }, | 370 | }, |
360 | }, | 371 | }, |
@@ -479,6 +490,781 @@ static struct ab8500_prcmu_ranges debug_ranges[AB8500_NUM_BANKS] = { | |||
479 | }, | 490 | }, |
480 | }; | 491 | }; |
481 | 492 | ||
493 | struct ab8500_prcmu_ranges ab8505_debug_ranges[AB8500_NUM_BANKS] = { | ||
494 | [0x0] = { | ||
495 | .num_ranges = 0, | ||
496 | .range = NULL, | ||
497 | }, | ||
498 | [AB8500_SYS_CTRL1_BLOCK] = { | ||
499 | .num_ranges = 5, | ||
500 | .range = (struct ab8500_reg_range[]) { | ||
501 | { | ||
502 | .first = 0x00, | ||
503 | .last = 0x04, | ||
504 | }, | ||
505 | { | ||
506 | .first = 0x42, | ||
507 | .last = 0x42, | ||
508 | }, | ||
509 | { | ||
510 | .first = 0x52, | ||
511 | .last = 0x52, | ||
512 | }, | ||
513 | { | ||
514 | .first = 0x54, | ||
515 | .last = 0x57, | ||
516 | }, | ||
517 | { | ||
518 | .first = 0x80, | ||
519 | .last = 0x83, | ||
520 | }, | ||
521 | }, | ||
522 | }, | ||
523 | [AB8500_SYS_CTRL2_BLOCK] = { | ||
524 | .num_ranges = 5, | ||
525 | .range = (struct ab8500_reg_range[]) { | ||
526 | { | ||
527 | .first = 0x00, | ||
528 | .last = 0x0D, | ||
529 | }, | ||
530 | { | ||
531 | .first = 0x0F, | ||
532 | .last = 0x17, | ||
533 | }, | ||
534 | { | ||
535 | .first = 0x20, | ||
536 | .last = 0x20, | ||
537 | }, | ||
538 | { | ||
539 | .first = 0x30, | ||
540 | .last = 0x30, | ||
541 | }, | ||
542 | { | ||
543 | .first = 0x32, | ||
544 | .last = 0x3A, | ||
545 | }, | ||
546 | }, | ||
547 | }, | ||
548 | [AB8500_REGU_CTRL1] = { | ||
549 | .num_ranges = 3, | ||
550 | .range = (struct ab8500_reg_range[]) { | ||
551 | { | ||
552 | .first = 0x00, | ||
553 | .last = 0x00, | ||
554 | }, | ||
555 | { | ||
556 | .first = 0x03, | ||
557 | .last = 0x11, | ||
558 | }, | ||
559 | { | ||
560 | .first = 0x80, | ||
561 | .last = 0x86, | ||
562 | }, | ||
563 | }, | ||
564 | }, | ||
565 | [AB8500_REGU_CTRL2] = { | ||
566 | .num_ranges = 6, | ||
567 | .range = (struct ab8500_reg_range[]) { | ||
568 | { | ||
569 | .first = 0x00, | ||
570 | .last = 0x06, | ||
571 | }, | ||
572 | { | ||
573 | .first = 0x08, | ||
574 | .last = 0x15, | ||
575 | }, | ||
576 | { | ||
577 | .first = 0x17, | ||
578 | .last = 0x19, | ||
579 | }, | ||
580 | { | ||
581 | .first = 0x1B, | ||
582 | .last = 0x1D, | ||
583 | }, | ||
584 | { | ||
585 | .first = 0x1F, | ||
586 | .last = 0x30, | ||
587 | }, | ||
588 | { | ||
589 | .first = 0x40, | ||
590 | .last = 0x48, | ||
591 | }, | ||
592 | /* 0x80-0x8B is SIM registers and should | ||
593 | * not be accessed from here */ | ||
594 | }, | ||
595 | }, | ||
596 | [AB8500_USB] = { | ||
597 | .num_ranges = 3, | ||
598 | .range = (struct ab8500_reg_range[]) { | ||
599 | { | ||
600 | .first = 0x80, | ||
601 | .last = 0x83, | ||
602 | }, | ||
603 | { | ||
604 | .first = 0x87, | ||
605 | .last = 0x8A, | ||
606 | }, | ||
607 | { | ||
608 | .first = 0x91, | ||
609 | .last = 0x94, | ||
610 | }, | ||
611 | }, | ||
612 | }, | ||
613 | [AB8500_TVOUT] = { | ||
614 | .num_ranges = 0, | ||
615 | .range = NULL, | ||
616 | }, | ||
617 | [AB8500_DBI] = { | ||
618 | .num_ranges = 0, | ||
619 | .range = NULL, | ||
620 | }, | ||
621 | [AB8500_ECI_AV_ACC] = { | ||
622 | .num_ranges = 1, | ||
623 | .range = (struct ab8500_reg_range[]) { | ||
624 | { | ||
625 | .first = 0x80, | ||
626 | .last = 0x82, | ||
627 | }, | ||
628 | }, | ||
629 | }, | ||
630 | [AB8500_RESERVED] = { | ||
631 | .num_ranges = 0, | ||
632 | .range = NULL, | ||
633 | }, | ||
634 | [AB8500_GPADC] = { | ||
635 | .num_ranges = 1, | ||
636 | .range = (struct ab8500_reg_range[]) { | ||
637 | { | ||
638 | .first = 0x00, | ||
639 | .last = 0x08, | ||
640 | }, | ||
641 | }, | ||
642 | }, | ||
643 | [AB8500_CHARGER] = { | ||
644 | .num_ranges = 9, | ||
645 | .range = (struct ab8500_reg_range[]) { | ||
646 | { | ||
647 | .first = 0x02, | ||
648 | .last = 0x03, | ||
649 | }, | ||
650 | { | ||
651 | .first = 0x05, | ||
652 | .last = 0x05, | ||
653 | }, | ||
654 | { | ||
655 | .first = 0x40, | ||
656 | .last = 0x44, | ||
657 | }, | ||
658 | { | ||
659 | .first = 0x50, | ||
660 | .last = 0x57, | ||
661 | }, | ||
662 | { | ||
663 | .first = 0x60, | ||
664 | .last = 0x60, | ||
665 | }, | ||
666 | { | ||
667 | .first = 0xA0, | ||
668 | .last = 0xA7, | ||
669 | }, | ||
670 | { | ||
671 | .first = 0xAF, | ||
672 | .last = 0xB2, | ||
673 | }, | ||
674 | { | ||
675 | .first = 0xC0, | ||
676 | .last = 0xC2, | ||
677 | }, | ||
678 | { | ||
679 | .first = 0xF5, | ||
680 | .last = 0xF5, | ||
681 | }, | ||
682 | }, | ||
683 | }, | ||
684 | [AB8500_GAS_GAUGE] = { | ||
685 | .num_ranges = 3, | ||
686 | .range = (struct ab8500_reg_range[]) { | ||
687 | { | ||
688 | .first = 0x00, | ||
689 | .last = 0x00, | ||
690 | }, | ||
691 | { | ||
692 | .first = 0x07, | ||
693 | .last = 0x0A, | ||
694 | }, | ||
695 | { | ||
696 | .first = 0x10, | ||
697 | .last = 0x14, | ||
698 | }, | ||
699 | }, | ||
700 | }, | ||
701 | [AB8500_AUDIO] = { | ||
702 | .num_ranges = 1, | ||
703 | .range = (struct ab8500_reg_range[]) { | ||
704 | { | ||
705 | .first = 0x00, | ||
706 | .last = 0x83, | ||
707 | }, | ||
708 | }, | ||
709 | }, | ||
710 | [AB8500_INTERRUPT] = { | ||
711 | .num_ranges = 11, | ||
712 | .range = (struct ab8500_reg_range[]) { | ||
713 | { | ||
714 | .first = 0x00, | ||
715 | .last = 0x04, | ||
716 | }, | ||
717 | { | ||
718 | .first = 0x06, | ||
719 | .last = 0x07, | ||
720 | }, | ||
721 | { | ||
722 | .first = 0x09, | ||
723 | .last = 0x09, | ||
724 | }, | ||
725 | { | ||
726 | .first = 0x0B, | ||
727 | .last = 0x0C, | ||
728 | }, | ||
729 | { | ||
730 | .first = 0x12, | ||
731 | .last = 0x15, | ||
732 | }, | ||
733 | { | ||
734 | .first = 0x18, | ||
735 | .last = 0x18, | ||
736 | }, | ||
737 | /* Latch registers should not be read here */ | ||
738 | { | ||
739 | .first = 0x40, | ||
740 | .last = 0x44, | ||
741 | }, | ||
742 | { | ||
743 | .first = 0x46, | ||
744 | .last = 0x49, | ||
745 | }, | ||
746 | { | ||
747 | .first = 0x4B, | ||
748 | .last = 0x4D, | ||
749 | }, | ||
750 | { | ||
751 | .first = 0x52, | ||
752 | .last = 0x55, | ||
753 | }, | ||
754 | { | ||
755 | .first = 0x58, | ||
756 | .last = 0x58, | ||
757 | }, | ||
758 | /* LatchHier registers should not be read here */ | ||
759 | }, | ||
760 | }, | ||
761 | [AB8500_RTC] = { | ||
762 | .num_ranges = 2, | ||
763 | .range = (struct ab8500_reg_range[]) { | ||
764 | { | ||
765 | .first = 0x00, | ||
766 | .last = 0x14, | ||
767 | }, | ||
768 | { | ||
769 | .first = 0x16, | ||
770 | .last = 0x17, | ||
771 | }, | ||
772 | }, | ||
773 | }, | ||
774 | [AB8500_MISC] = { | ||
775 | .num_ranges = 8, | ||
776 | .range = (struct ab8500_reg_range[]) { | ||
777 | { | ||
778 | .first = 0x00, | ||
779 | .last = 0x06, | ||
780 | }, | ||
781 | { | ||
782 | .first = 0x10, | ||
783 | .last = 0x16, | ||
784 | }, | ||
785 | { | ||
786 | .first = 0x20, | ||
787 | .last = 0x26, | ||
788 | }, | ||
789 | { | ||
790 | .first = 0x30, | ||
791 | .last = 0x36, | ||
792 | }, | ||
793 | { | ||
794 | .first = 0x40, | ||
795 | .last = 0x46, | ||
796 | }, | ||
797 | { | ||
798 | .first = 0x50, | ||
799 | .last = 0x50, | ||
800 | }, | ||
801 | { | ||
802 | .first = 0x60, | ||
803 | .last = 0x6B, | ||
804 | }, | ||
805 | { | ||
806 | .first = 0x80, | ||
807 | .last = 0x82, | ||
808 | }, | ||
809 | }, | ||
810 | }, | ||
811 | [AB8500_DEVELOPMENT] = { | ||
812 | .num_ranges = 2, | ||
813 | .range = (struct ab8500_reg_range[]) { | ||
814 | { | ||
815 | .first = 0x00, | ||
816 | .last = 0x00, | ||
817 | }, | ||
818 | { | ||
819 | .first = 0x05, | ||
820 | .last = 0x05, | ||
821 | }, | ||
822 | }, | ||
823 | }, | ||
824 | [AB8500_DEBUG] = { | ||
825 | .num_ranges = 1, | ||
826 | .range = (struct ab8500_reg_range[]) { | ||
827 | { | ||
828 | .first = 0x05, | ||
829 | .last = 0x07, | ||
830 | }, | ||
831 | }, | ||
832 | }, | ||
833 | [AB8500_PROD_TEST] = { | ||
834 | .num_ranges = 0, | ||
835 | .range = NULL, | ||
836 | }, | ||
837 | [AB8500_STE_TEST] = { | ||
838 | .num_ranges = 0, | ||
839 | .range = NULL, | ||
840 | }, | ||
841 | [AB8500_OTP_EMUL] = { | ||
842 | .num_ranges = 1, | ||
843 | .range = (struct ab8500_reg_range[]) { | ||
844 | { | ||
845 | .first = 0x01, | ||
846 | .last = 0x15, | ||
847 | }, | ||
848 | }, | ||
849 | }, | ||
850 | }; | ||
851 | |||
852 | struct ab8500_prcmu_ranges ab8540_debug_ranges[AB8500_NUM_BANKS] = { | ||
853 | [AB8500_M_FSM_RANK] = { | ||
854 | .num_ranges = 1, | ||
855 | .range = (struct ab8500_reg_range[]) { | ||
856 | { | ||
857 | .first = 0x00, | ||
858 | .last = 0x0B, | ||
859 | }, | ||
860 | }, | ||
861 | }, | ||
862 | [AB8500_SYS_CTRL1_BLOCK] = { | ||
863 | .num_ranges = 6, | ||
864 | .range = (struct ab8500_reg_range[]) { | ||
865 | { | ||
866 | .first = 0x00, | ||
867 | .last = 0x04, | ||
868 | }, | ||
869 | { | ||
870 | .first = 0x42, | ||
871 | .last = 0x42, | ||
872 | }, | ||
873 | { | ||
874 | .first = 0x50, | ||
875 | .last = 0x54, | ||
876 | }, | ||
877 | { | ||
878 | .first = 0x57, | ||
879 | .last = 0x57, | ||
880 | }, | ||
881 | { | ||
882 | .first = 0x80, | ||
883 | .last = 0x83, | ||
884 | }, | ||
885 | { | ||
886 | .first = 0x90, | ||
887 | .last = 0x90, | ||
888 | }, | ||
889 | }, | ||
890 | }, | ||
891 | [AB8500_SYS_CTRL2_BLOCK] = { | ||
892 | .num_ranges = 5, | ||
893 | .range = (struct ab8500_reg_range[]) { | ||
894 | { | ||
895 | .first = 0x00, | ||
896 | .last = 0x0D, | ||
897 | }, | ||
898 | { | ||
899 | .first = 0x0F, | ||
900 | .last = 0x10, | ||
901 | }, | ||
902 | { | ||
903 | .first = 0x20, | ||
904 | .last = 0x21, | ||
905 | }, | ||
906 | { | ||
907 | .first = 0x32, | ||
908 | .last = 0x3C, | ||
909 | }, | ||
910 | { | ||
911 | .first = 0x40, | ||
912 | .last = 0x42, | ||
913 | }, | ||
914 | }, | ||
915 | }, | ||
916 | [AB8500_REGU_CTRL1] = { | ||
917 | .num_ranges = 4, | ||
918 | .range = (struct ab8500_reg_range[]) { | ||
919 | { | ||
920 | .first = 0x03, | ||
921 | .last = 0x15, | ||
922 | }, | ||
923 | { | ||
924 | .first = 0x20, | ||
925 | .last = 0x20, | ||
926 | }, | ||
927 | { | ||
928 | .first = 0x80, | ||
929 | .last = 0x85, | ||
930 | }, | ||
931 | { | ||
932 | .first = 0x87, | ||
933 | .last = 0x88, | ||
934 | }, | ||
935 | }, | ||
936 | }, | ||
937 | [AB8500_REGU_CTRL2] = { | ||
938 | .num_ranges = 8, | ||
939 | .range = (struct ab8500_reg_range[]) { | ||
940 | { | ||
941 | .first = 0x00, | ||
942 | .last = 0x06, | ||
943 | }, | ||
944 | { | ||
945 | .first = 0x08, | ||
946 | .last = 0x15, | ||
947 | }, | ||
948 | { | ||
949 | .first = 0x17, | ||
950 | .last = 0x19, | ||
951 | }, | ||
952 | { | ||
953 | .first = 0x1B, | ||
954 | .last = 0x1D, | ||
955 | }, | ||
956 | { | ||
957 | .first = 0x1F, | ||
958 | .last = 0x2F, | ||
959 | }, | ||
960 | { | ||
961 | .first = 0x31, | ||
962 | .last = 0x3A, | ||
963 | }, | ||
964 | { | ||
965 | .first = 0x43, | ||
966 | .last = 0x44, | ||
967 | }, | ||
968 | { | ||
969 | .first = 0x48, | ||
970 | .last = 0x49, | ||
971 | }, | ||
972 | }, | ||
973 | }, | ||
974 | [AB8500_USB] = { | ||
975 | .num_ranges = 3, | ||
976 | .range = (struct ab8500_reg_range[]) { | ||
977 | { | ||
978 | .first = 0x80, | ||
979 | .last = 0x83, | ||
980 | }, | ||
981 | { | ||
982 | .first = 0x87, | ||
983 | .last = 0x8A, | ||
984 | }, | ||
985 | { | ||
986 | .first = 0x91, | ||
987 | .last = 0x94, | ||
988 | }, | ||
989 | }, | ||
990 | }, | ||
991 | [AB8500_TVOUT] = { | ||
992 | .num_ranges = 0, | ||
993 | .range = NULL | ||
994 | }, | ||
995 | [AB8500_DBI] = { | ||
996 | .num_ranges = 4, | ||
997 | .range = (struct ab8500_reg_range[]) { | ||
998 | { | ||
999 | .first = 0x00, | ||
1000 | .last = 0x07, | ||
1001 | }, | ||
1002 | { | ||
1003 | .first = 0x10, | ||
1004 | .last = 0x11, | ||
1005 | }, | ||
1006 | { | ||
1007 | .first = 0x20, | ||
1008 | .last = 0x21, | ||
1009 | }, | ||
1010 | { | ||
1011 | .first = 0x30, | ||
1012 | .last = 0x43, | ||
1013 | }, | ||
1014 | }, | ||
1015 | }, | ||
1016 | [AB8500_ECI_AV_ACC] = { | ||
1017 | .num_ranges = 2, | ||
1018 | .range = (struct ab8500_reg_range[]) { | ||
1019 | { | ||
1020 | .first = 0x00, | ||
1021 | .last = 0x03, | ||
1022 | }, | ||
1023 | { | ||
1024 | .first = 0x80, | ||
1025 | .last = 0x82, | ||
1026 | }, | ||
1027 | }, | ||
1028 | }, | ||
1029 | [AB8500_RESERVED] = { | ||
1030 | .num_ranges = 0, | ||
1031 | .range = NULL, | ||
1032 | }, | ||
1033 | [AB8500_GPADC] = { | ||
1034 | .num_ranges = 4, | ||
1035 | .range = (struct ab8500_reg_range[]) { | ||
1036 | { | ||
1037 | .first = 0x00, | ||
1038 | .last = 0x01, | ||
1039 | }, | ||
1040 | { | ||
1041 | .first = 0x04, | ||
1042 | .last = 0x06, | ||
1043 | }, | ||
1044 | { | ||
1045 | .first = 0x09, | ||
1046 | .last = 0x0A, | ||
1047 | }, | ||
1048 | { | ||
1049 | .first = 0x10, | ||
1050 | .last = 0x14, | ||
1051 | }, | ||
1052 | }, | ||
1053 | }, | ||
1054 | [AB8500_CHARGER] = { | ||
1055 | .num_ranges = 10, | ||
1056 | .range = (struct ab8500_reg_range[]) { | ||
1057 | { | ||
1058 | .first = 0x00, | ||
1059 | .last = 0x00, | ||
1060 | }, | ||
1061 | { | ||
1062 | .first = 0x02, | ||
1063 | .last = 0x05, | ||
1064 | }, | ||
1065 | { | ||
1066 | .first = 0x40, | ||
1067 | .last = 0x44, | ||
1068 | }, | ||
1069 | { | ||
1070 | .first = 0x50, | ||
1071 | .last = 0x57, | ||
1072 | }, | ||
1073 | { | ||
1074 | .first = 0x60, | ||
1075 | .last = 0x60, | ||
1076 | }, | ||
1077 | { | ||
1078 | .first = 0x70, | ||
1079 | .last = 0x70, | ||
1080 | }, | ||
1081 | { | ||
1082 | .first = 0xA0, | ||
1083 | .last = 0xA9, | ||
1084 | }, | ||
1085 | { | ||
1086 | .first = 0xAF, | ||
1087 | .last = 0xB2, | ||
1088 | }, | ||
1089 | { | ||
1090 | .first = 0xC0, | ||
1091 | .last = 0xC6, | ||
1092 | }, | ||
1093 | { | ||
1094 | .first = 0xF5, | ||
1095 | .last = 0xF5, | ||
1096 | }, | ||
1097 | }, | ||
1098 | }, | ||
1099 | [AB8500_GAS_GAUGE] = { | ||
1100 | .num_ranges = 3, | ||
1101 | .range = (struct ab8500_reg_range[]) { | ||
1102 | { | ||
1103 | .first = 0x00, | ||
1104 | .last = 0x00, | ||
1105 | }, | ||
1106 | { | ||
1107 | .first = 0x07, | ||
1108 | .last = 0x0A, | ||
1109 | }, | ||
1110 | { | ||
1111 | .first = 0x10, | ||
1112 | .last = 0x14, | ||
1113 | }, | ||
1114 | }, | ||
1115 | }, | ||
1116 | [AB8500_AUDIO] = { | ||
1117 | .num_ranges = 1, | ||
1118 | .range = (struct ab8500_reg_range[]) { | ||
1119 | { | ||
1120 | .first = 0x00, | ||
1121 | .last = 0x9f, | ||
1122 | }, | ||
1123 | }, | ||
1124 | }, | ||
1125 | [AB8500_INTERRUPT] = { | ||
1126 | .num_ranges = 6, | ||
1127 | .range = (struct ab8500_reg_range[]) { | ||
1128 | { | ||
1129 | .first = 0x00, | ||
1130 | .last = 0x05, | ||
1131 | }, | ||
1132 | { | ||
1133 | .first = 0x0B, | ||
1134 | .last = 0x0D, | ||
1135 | }, | ||
1136 | { | ||
1137 | .first = 0x12, | ||
1138 | .last = 0x20, | ||
1139 | }, | ||
1140 | /* Latch registers should not be read here */ | ||
1141 | { | ||
1142 | .first = 0x40, | ||
1143 | .last = 0x45, | ||
1144 | }, | ||
1145 | { | ||
1146 | .first = 0x4B, | ||
1147 | .last = 0x4D, | ||
1148 | }, | ||
1149 | { | ||
1150 | .first = 0x52, | ||
1151 | .last = 0x60, | ||
1152 | }, | ||
1153 | /* LatchHier registers should not be read here */ | ||
1154 | }, | ||
1155 | }, | ||
1156 | [AB8500_RTC] = { | ||
1157 | .num_ranges = 3, | ||
1158 | .range = (struct ab8500_reg_range[]) { | ||
1159 | { | ||
1160 | .first = 0x00, | ||
1161 | .last = 0x07, | ||
1162 | }, | ||
1163 | { | ||
1164 | .first = 0x0B, | ||
1165 | .last = 0x18, | ||
1166 | }, | ||
1167 | { | ||
1168 | .first = 0x20, | ||
1169 | .last = 0x25, | ||
1170 | }, | ||
1171 | }, | ||
1172 | }, | ||
1173 | [AB8500_MISC] = { | ||
1174 | .num_ranges = 9, | ||
1175 | .range = (struct ab8500_reg_range[]) { | ||
1176 | { | ||
1177 | .first = 0x00, | ||
1178 | .last = 0x06, | ||
1179 | }, | ||
1180 | { | ||
1181 | .first = 0x10, | ||
1182 | .last = 0x16, | ||
1183 | }, | ||
1184 | { | ||
1185 | .first = 0x20, | ||
1186 | .last = 0x26, | ||
1187 | }, | ||
1188 | { | ||
1189 | .first = 0x30, | ||
1190 | .last = 0x36, | ||
1191 | }, | ||
1192 | { | ||
1193 | .first = 0x40, | ||
1194 | .last = 0x49, | ||
1195 | }, | ||
1196 | { | ||
1197 | .first = 0x50, | ||
1198 | .last = 0x50, | ||
1199 | }, | ||
1200 | { | ||
1201 | .first = 0x60, | ||
1202 | .last = 0x6B, | ||
1203 | }, | ||
1204 | { | ||
1205 | .first = 0x70, | ||
1206 | .last = 0x74, | ||
1207 | }, | ||
1208 | { | ||
1209 | .first = 0x80, | ||
1210 | .last = 0x82, | ||
1211 | }, | ||
1212 | }, | ||
1213 | }, | ||
1214 | [AB8500_DEVELOPMENT] = { | ||
1215 | .num_ranges = 3, | ||
1216 | .range = (struct ab8500_reg_range[]) { | ||
1217 | { | ||
1218 | .first = 0x00, | ||
1219 | .last = 0x01, | ||
1220 | }, | ||
1221 | { | ||
1222 | .first = 0x06, | ||
1223 | .last = 0x06, | ||
1224 | }, | ||
1225 | { | ||
1226 | .first = 0x10, | ||
1227 | .last = 0x21, | ||
1228 | }, | ||
1229 | }, | ||
1230 | }, | ||
1231 | [AB8500_DEBUG] = { | ||
1232 | .num_ranges = 3, | ||
1233 | .range = (struct ab8500_reg_range[]) { | ||
1234 | { | ||
1235 | .first = 0x01, | ||
1236 | .last = 0x0C, | ||
1237 | }, | ||
1238 | { | ||
1239 | .first = 0x0E, | ||
1240 | .last = 0x11, | ||
1241 | }, | ||
1242 | { | ||
1243 | .first = 0x80, | ||
1244 | .last = 0x81, | ||
1245 | }, | ||
1246 | }, | ||
1247 | }, | ||
1248 | [AB8500_PROD_TEST] = { | ||
1249 | .num_ranges = 0, | ||
1250 | .range = NULL, | ||
1251 | }, | ||
1252 | [AB8500_STE_TEST] = { | ||
1253 | .num_ranges = 0, | ||
1254 | .range = NULL, | ||
1255 | }, | ||
1256 | [AB8500_OTP_EMUL] = { | ||
1257 | .num_ranges = 1, | ||
1258 | .range = (struct ab8500_reg_range[]) { | ||
1259 | { | ||
1260 | .first = 0x00, | ||
1261 | .last = 0x3F, | ||
1262 | }, | ||
1263 | }, | ||
1264 | }, | ||
1265 | }; | ||
1266 | |||
1267 | |||
482 | static irqreturn_t ab8500_debug_handler(int irq, void *data) | 1268 | static irqreturn_t ab8500_debug_handler(int irq, void *data) |
483 | { | 1269 | { |
484 | char buf[16]; | 1270 | char buf[16]; |
@@ -520,19 +1306,16 @@ static int ab8500_registers_print(struct device *dev, u32 bank, | |||
520 | } | 1306 | } |
521 | 1307 | ||
522 | if (s) { | 1308 | if (s) { |
523 | err = seq_printf(s, " [%u/0x%02X]: 0x%02X\n", | 1309 | err = seq_printf(s, " [0x%02X/0x%02X]: 0x%02X\n", |
524 | bank, reg, value); | 1310 | bank, reg, value); |
525 | if (err < 0) { | 1311 | if (err < 0) { |
526 | dev_err(dev, | ||
527 | "seq_printf overflow bank=%d reg=%d\n", | ||
528 | bank, reg); | ||
529 | /* Error is not returned here since | 1312 | /* Error is not returned here since |
530 | * the output is wanted in any case */ | 1313 | * the output is wanted in any case */ |
531 | return 0; | 1314 | return 0; |
532 | } | 1315 | } |
533 | } else { | 1316 | } else { |
534 | printk(KERN_INFO" [%u/0x%02X]: 0x%02X\n", bank, | 1317 | printk(KERN_INFO" [0x%02X/0x%02X]: 0x%02X\n", |
535 | reg, value); | 1318 | bank, reg, value); |
536 | } | 1319 | } |
537 | } | 1320 | } |
538 | } | 1321 | } |
@@ -546,7 +1329,7 @@ static int ab8500_print_bank_registers(struct seq_file *s, void *p) | |||
546 | 1329 | ||
547 | seq_printf(s, AB8500_NAME_STRING " register values:\n"); | 1330 | seq_printf(s, AB8500_NAME_STRING " register values:\n"); |
548 | 1331 | ||
549 | seq_printf(s, " bank %u:\n", bank); | 1332 | seq_printf(s, " bank 0x%02X:\n", bank); |
550 | 1333 | ||
551 | ab8500_registers_print(dev, bank, s); | 1334 | ab8500_registers_print(dev, bank, s); |
552 | return 0; | 1335 | return 0; |
@@ -573,10 +1356,8 @@ static int ab8500_print_all_banks(struct seq_file *s, void *p) | |||
573 | 1356 | ||
574 | seq_printf(s, AB8500_NAME_STRING " register values:\n"); | 1357 | seq_printf(s, AB8500_NAME_STRING " register values:\n"); |
575 | 1358 | ||
576 | for (i = 1; i < AB8500_NUM_BANKS; i++) { | 1359 | for (i = 0; i < AB8500_NUM_BANKS; i++) { |
577 | err = seq_printf(s, " bank %u:\n", i); | 1360 | err = seq_printf(s, " bank 0x%02X:\n", i); |
578 | if (err < 0) | ||
579 | dev_err(dev, "seq_printf overflow, bank=%d\n", i); | ||
580 | 1361 | ||
581 | ab8500_registers_print(dev, i, s); | 1362 | ab8500_registers_print(dev, i, s); |
582 | } | 1363 | } |
@@ -591,11 +1372,68 @@ void ab8500_dump_all_banks(struct device *dev) | |||
591 | printk(KERN_INFO"ab8500 register values:\n"); | 1372 | printk(KERN_INFO"ab8500 register values:\n"); |
592 | 1373 | ||
593 | for (i = 1; i < AB8500_NUM_BANKS; i++) { | 1374 | for (i = 1; i < AB8500_NUM_BANKS; i++) { |
594 | printk(KERN_INFO" bank %u:\n", i); | 1375 | printk(KERN_INFO" bank 0x%02X:\n", i); |
595 | ab8500_registers_print(dev, i, NULL); | 1376 | ab8500_registers_print(dev, i, NULL); |
596 | } | 1377 | } |
597 | } | 1378 | } |
598 | 1379 | ||
1380 | /* Space for 500 registers. */ | ||
1381 | #define DUMP_MAX_REGS 700 | ||
1382 | struct ab8500_register_dump | ||
1383 | { | ||
1384 | u8 bank; | ||
1385 | u8 reg; | ||
1386 | u8 value; | ||
1387 | } ab8500_complete_register_dump[DUMP_MAX_REGS]; | ||
1388 | |||
1389 | extern int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size); | ||
1390 | |||
1391 | /* This shall only be called upon kernel panic! */ | ||
1392 | void ab8500_dump_all_banks_to_mem(void) | ||
1393 | { | ||
1394 | int i, r = 0; | ||
1395 | u8 bank; | ||
1396 | int err = 0; | ||
1397 | |||
1398 | pr_info("Saving all ABB registers at \"ab8500_complete_register_dump\" " | ||
1399 | "for crash analyze.\n"); | ||
1400 | |||
1401 | for (bank = 0; bank < AB8500_NUM_BANKS; bank++) { | ||
1402 | for (i = 0; i < debug_ranges[bank].num_ranges; i++) { | ||
1403 | u8 reg; | ||
1404 | |||
1405 | for (reg = debug_ranges[bank].range[i].first; | ||
1406 | reg <= debug_ranges[bank].range[i].last; | ||
1407 | reg++) { | ||
1408 | u8 value; | ||
1409 | |||
1410 | err = prcmu_abb_read(bank, reg, &value, 1); | ||
1411 | |||
1412 | if (err < 0) | ||
1413 | goto out; | ||
1414 | |||
1415 | ab8500_complete_register_dump[r].bank = bank; | ||
1416 | ab8500_complete_register_dump[r].reg = reg; | ||
1417 | ab8500_complete_register_dump[r].value = value; | ||
1418 | |||
1419 | r++; | ||
1420 | |||
1421 | if (r >= DUMP_MAX_REGS) { | ||
1422 | pr_err("%s: too many register to dump!\n", | ||
1423 | __func__); | ||
1424 | err = -EINVAL; | ||
1425 | goto out; | ||
1426 | } | ||
1427 | } | ||
1428 | } | ||
1429 | } | ||
1430 | out: | ||
1431 | if (err >= 0) | ||
1432 | pr_info("Saved all ABB registers.\n"); | ||
1433 | else | ||
1434 | pr_info("Failed to save all ABB registers.\n"); | ||
1435 | } | ||
1436 | |||
599 | static int ab8500_all_banks_open(struct inode *inode, struct file *file) | 1437 | static int ab8500_all_banks_open(struct inode *inode, struct file *file) |
600 | { | 1438 | { |
601 | struct seq_file *s; | 1439 | struct seq_file *s; |
@@ -625,7 +1463,7 @@ static const struct file_operations ab8500_all_banks_fops = { | |||
625 | 1463 | ||
626 | static int ab8500_bank_print(struct seq_file *s, void *p) | 1464 | static int ab8500_bank_print(struct seq_file *s, void *p) |
627 | { | 1465 | { |
628 | return seq_printf(s, "%d\n", debug_bank); | 1466 | return seq_printf(s, "0x%02X\n", debug_bank); |
629 | } | 1467 | } |
630 | 1468 | ||
631 | static int ab8500_bank_open(struct inode *inode, struct file *file) | 1469 | static int ab8500_bank_open(struct inode *inode, struct file *file) |
@@ -641,7 +1479,6 @@ static ssize_t ab8500_bank_write(struct file *file, | |||
641 | unsigned long user_bank; | 1479 | unsigned long user_bank; |
642 | int err; | 1480 | int err; |
643 | 1481 | ||
644 | /* Get userspace string and assure termination */ | ||
645 | err = kstrtoul_from_user(user_buf, count, 0, &user_bank); | 1482 | err = kstrtoul_from_user(user_buf, count, 0, &user_bank); |
646 | if (err) | 1483 | if (err) |
647 | return err; | 1484 | return err; |
@@ -667,14 +1504,13 @@ static int ab8500_address_open(struct inode *inode, struct file *file) | |||
667 | } | 1504 | } |
668 | 1505 | ||
669 | static ssize_t ab8500_address_write(struct file *file, | 1506 | static ssize_t ab8500_address_write(struct file *file, |
670 | const char __user *user_buf, | 1507 | const char __user *user_buf, |
671 | size_t count, loff_t *ppos) | 1508 | size_t count, loff_t *ppos) |
672 | { | 1509 | { |
673 | struct device *dev = ((struct seq_file *)(file->private_data))->private; | 1510 | struct device *dev = ((struct seq_file *)(file->private_data))->private; |
674 | unsigned long user_address; | 1511 | unsigned long user_address; |
675 | int err; | 1512 | int err; |
676 | 1513 | ||
677 | /* Get userspace string and assure termination */ | ||
678 | err = kstrtoul_from_user(user_buf, count, 0, &user_address); | 1514 | err = kstrtoul_from_user(user_buf, count, 0, &user_address); |
679 | if (err) | 1515 | if (err) |
680 | return err; | 1516 | return err; |
@@ -684,6 +1520,7 @@ static ssize_t ab8500_address_write(struct file *file, | |||
684 | return -EINVAL; | 1520 | return -EINVAL; |
685 | } | 1521 | } |
686 | debug_address = user_address; | 1522 | debug_address = user_address; |
1523 | |||
687 | return count; | 1524 | return count; |
688 | } | 1525 | } |
689 | 1526 | ||
@@ -711,14 +1548,13 @@ static int ab8500_val_open(struct inode *inode, struct file *file) | |||
711 | } | 1548 | } |
712 | 1549 | ||
713 | static ssize_t ab8500_val_write(struct file *file, | 1550 | static ssize_t ab8500_val_write(struct file *file, |
714 | const char __user *user_buf, | 1551 | const char __user *user_buf, |
715 | size_t count, loff_t *ppos) | 1552 | size_t count, loff_t *ppos) |
716 | { | 1553 | { |
717 | struct device *dev = ((struct seq_file *)(file->private_data))->private; | 1554 | struct device *dev = ((struct seq_file *)(file->private_data))->private; |
718 | unsigned long user_val; | 1555 | unsigned long user_val; |
719 | int err; | 1556 | int err; |
720 | 1557 | ||
721 | /* Get userspace string and assure termination */ | ||
722 | err = kstrtoul_from_user(user_buf, count, 0, &user_val); | 1558 | err = kstrtoul_from_user(user_buf, count, 0, &user_val); |
723 | if (err) | 1559 | if (err) |
724 | return err; | 1560 | return err; |
@@ -741,22 +1577,46 @@ static ssize_t ab8500_val_write(struct file *file, | |||
741 | * Interrupt status | 1577 | * Interrupt status |
742 | */ | 1578 | */ |
743 | static u32 num_interrupts[AB8500_MAX_NR_IRQS]; | 1579 | static u32 num_interrupts[AB8500_MAX_NR_IRQS]; |
1580 | static u32 num_wake_interrupts[AB8500_MAX_NR_IRQS]; | ||
744 | static int num_interrupt_lines; | 1581 | static int num_interrupt_lines; |
745 | 1582 | ||
1583 | bool __attribute__((weak)) suspend_test_wake_cause_interrupt_is_mine(u32 my_int) | ||
1584 | { | ||
1585 | return false; | ||
1586 | } | ||
1587 | |||
746 | void ab8500_debug_register_interrupt(int line) | 1588 | void ab8500_debug_register_interrupt(int line) |
747 | { | 1589 | { |
748 | if (line < num_interrupt_lines) | 1590 | if (line < num_interrupt_lines) { |
749 | num_interrupts[line]++; | 1591 | num_interrupts[line]++; |
1592 | if (suspend_test_wake_cause_interrupt_is_mine(IRQ_DB8500_AB8500)) | ||
1593 | num_wake_interrupts[line]++; | ||
1594 | } | ||
750 | } | 1595 | } |
751 | 1596 | ||
752 | static int ab8500_interrupts_print(struct seq_file *s, void *p) | 1597 | static int ab8500_interrupts_print(struct seq_file *s, void *p) |
753 | { | 1598 | { |
754 | int line; | 1599 | int line; |
755 | 1600 | ||
756 | seq_printf(s, "irq: number of\n"); | 1601 | seq_printf(s, "name: number: number of: wake:\n"); |
757 | 1602 | ||
758 | for (line = 0; line < num_interrupt_lines; line++) | 1603 | for (line = 0; line < num_interrupt_lines; line++) { |
759 | seq_printf(s, "%3i: %6i\n", line, num_interrupts[line]); | 1604 | struct irq_desc *desc = irq_to_desc(line + irq_first); |
1605 | struct irqaction *action = desc->action; | ||
1606 | |||
1607 | seq_printf(s, "%3i: %6i %4i", line, | ||
1608 | num_interrupts[line], | ||
1609 | num_wake_interrupts[line]); | ||
1610 | |||
1611 | if (desc && desc->name) | ||
1612 | seq_printf(s, "-%-8s", desc->name); | ||
1613 | if (action) { | ||
1614 | seq_printf(s, " %s", action->name); | ||
1615 | while ((action = action->next) != NULL) | ||
1616 | seq_printf(s, ", %s", action->name); | ||
1617 | } | ||
1618 | seq_putc(s, '\n'); | ||
1619 | } | ||
760 | 1620 | ||
761 | return 0; | 1621 | return 0; |
762 | } | 1622 | } |
@@ -801,6 +1661,79 @@ static int ab8500_hwreg_open(struct inode *inode, struct file *file) | |||
801 | return single_open(file, ab8500_hwreg_print, inode->i_private); | 1661 | return single_open(file, ab8500_hwreg_print, inode->i_private); |
802 | } | 1662 | } |
803 | 1663 | ||
1664 | #define AB8500_SUPPLY_CONTROL_CONFIG_1 0x01 | ||
1665 | #define AB8500_SUPPLY_CONTROL_REG 0x00 | ||
1666 | #define AB8500_FIRST_SIM_REG 0x80 | ||
1667 | #define AB8500_LAST_SIM_REG 0x8B | ||
1668 | #define AB8505_LAST_SIM_REG 0x8C | ||
1669 | |||
1670 | static int ab8500_print_modem_registers(struct seq_file *s, void *p) | ||
1671 | { | ||
1672 | struct device *dev = s->private; | ||
1673 | struct ab8500 *ab8500; | ||
1674 | int err; | ||
1675 | u8 value; | ||
1676 | u8 orig_value; | ||
1677 | u32 bank = AB8500_REGU_CTRL2; | ||
1678 | u32 last_sim_reg = AB8500_LAST_SIM_REG; | ||
1679 | u32 reg; | ||
1680 | |||
1681 | ab8500 = dev_get_drvdata(dev->parent); | ||
1682 | dev_warn(dev, "WARNING! This operation can interfer with modem side\n" | ||
1683 | "and should only be done with care\n"); | ||
1684 | |||
1685 | err = abx500_get_register_interruptible(dev, | ||
1686 | AB8500_REGU_CTRL1, AB8500_SUPPLY_CONTROL_REG, &orig_value); | ||
1687 | if (err < 0) { | ||
1688 | dev_err(dev, "ab->read fail %d\n", err); | ||
1689 | return err; | ||
1690 | } | ||
1691 | /* Config 1 will allow APE side to read SIM registers */ | ||
1692 | err = abx500_set_register_interruptible(dev, | ||
1693 | AB8500_REGU_CTRL1, AB8500_SUPPLY_CONTROL_REG, | ||
1694 | AB8500_SUPPLY_CONTROL_CONFIG_1); | ||
1695 | if (err < 0) { | ||
1696 | dev_err(dev, "ab->write fail %d\n", err); | ||
1697 | return err; | ||
1698 | } | ||
1699 | |||
1700 | seq_printf(s, " bank 0x%02X:\n", bank); | ||
1701 | |||
1702 | if (is_ab9540(ab8500) || is_ab8505(ab8500)) | ||
1703 | last_sim_reg = AB8505_LAST_SIM_REG; | ||
1704 | |||
1705 | for (reg = AB8500_FIRST_SIM_REG; reg <= last_sim_reg; reg++) { | ||
1706 | err = abx500_get_register_interruptible(dev, | ||
1707 | bank, reg, &value); | ||
1708 | if (err < 0) { | ||
1709 | dev_err(dev, "ab->read fail %d\n", err); | ||
1710 | return err; | ||
1711 | } | ||
1712 | err = seq_printf(s, " [0x%02X/0x%02X]: 0x%02X\n", | ||
1713 | bank, reg, value); | ||
1714 | } | ||
1715 | err = abx500_set_register_interruptible(dev, | ||
1716 | AB8500_REGU_CTRL1, AB8500_SUPPLY_CONTROL_REG, orig_value); | ||
1717 | if (err < 0) { | ||
1718 | dev_err(dev, "ab->write fail %d\n", err); | ||
1719 | return err; | ||
1720 | } | ||
1721 | return 0; | ||
1722 | } | ||
1723 | |||
1724 | static int ab8500_modem_open(struct inode *inode, struct file *file) | ||
1725 | { | ||
1726 | return single_open(file, ab8500_print_modem_registers, inode->i_private); | ||
1727 | } | ||
1728 | |||
1729 | static const struct file_operations ab8500_modem_fops = { | ||
1730 | .open = ab8500_modem_open, | ||
1731 | .read = seq_read, | ||
1732 | .llseek = seq_lseek, | ||
1733 | .release = single_release, | ||
1734 | .owner = THIS_MODULE, | ||
1735 | }; | ||
1736 | |||
804 | static int ab8500_gpadc_bat_ctrl_print(struct seq_file *s, void *p) | 1737 | static int ab8500_gpadc_bat_ctrl_print(struct seq_file *s, void *p) |
805 | { | 1738 | { |
806 | int bat_ctrl_raw; | 1739 | int bat_ctrl_raw; |
@@ -808,12 +1741,13 @@ static int ab8500_gpadc_bat_ctrl_print(struct seq_file *s, void *p) | |||
808 | struct ab8500_gpadc *gpadc; | 1741 | struct ab8500_gpadc *gpadc; |
809 | 1742 | ||
810 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | 1743 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); |
811 | bat_ctrl_raw = ab8500_gpadc_read_raw(gpadc, BAT_CTRL); | 1744 | bat_ctrl_raw = ab8500_gpadc_read_raw(gpadc, BAT_CTRL, |
1745 | avg_sample, trig_edge, trig_timer, conv_type); | ||
812 | bat_ctrl_convert = ab8500_gpadc_ad_to_voltage(gpadc, | 1746 | bat_ctrl_convert = ab8500_gpadc_ad_to_voltage(gpadc, |
813 | BAT_CTRL, bat_ctrl_raw); | 1747 | BAT_CTRL, bat_ctrl_raw); |
814 | 1748 | ||
815 | return seq_printf(s, "%d,0x%X\n", | 1749 | return seq_printf(s, "%d,0x%X\n", |
816 | bat_ctrl_convert, bat_ctrl_raw); | 1750 | bat_ctrl_convert, bat_ctrl_raw); |
817 | } | 1751 | } |
818 | 1752 | ||
819 | static int ab8500_gpadc_bat_ctrl_open(struct inode *inode, struct file *file) | 1753 | static int ab8500_gpadc_bat_ctrl_open(struct inode *inode, struct file *file) |
@@ -836,16 +1770,17 @@ static int ab8500_gpadc_btemp_ball_print(struct seq_file *s, void *p) | |||
836 | struct ab8500_gpadc *gpadc; | 1770 | struct ab8500_gpadc *gpadc; |
837 | 1771 | ||
838 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | 1772 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); |
839 | btemp_ball_raw = ab8500_gpadc_read_raw(gpadc, BTEMP_BALL); | 1773 | btemp_ball_raw = ab8500_gpadc_read_raw(gpadc, BTEMP_BALL, |
1774 | avg_sample, trig_edge, trig_timer, conv_type); | ||
840 | btemp_ball_convert = ab8500_gpadc_ad_to_voltage(gpadc, BTEMP_BALL, | 1775 | btemp_ball_convert = ab8500_gpadc_ad_to_voltage(gpadc, BTEMP_BALL, |
841 | btemp_ball_raw); | 1776 | btemp_ball_raw); |
842 | 1777 | ||
843 | return seq_printf(s, | 1778 | return seq_printf(s, |
844 | "%d,0x%X\n", btemp_ball_convert, btemp_ball_raw); | 1779 | "%d,0x%X\n", btemp_ball_convert, btemp_ball_raw); |
845 | } | 1780 | } |
846 | 1781 | ||
847 | static int ab8500_gpadc_btemp_ball_open(struct inode *inode, | 1782 | static int ab8500_gpadc_btemp_ball_open(struct inode *inode, |
848 | struct file *file) | 1783 | struct file *file) |
849 | { | 1784 | { |
850 | return single_open(file, ab8500_gpadc_btemp_ball_print, inode->i_private); | 1785 | return single_open(file, ab8500_gpadc_btemp_ball_print, inode->i_private); |
851 | } | 1786 | } |
@@ -865,19 +1800,20 @@ static int ab8500_gpadc_main_charger_v_print(struct seq_file *s, void *p) | |||
865 | struct ab8500_gpadc *gpadc; | 1800 | struct ab8500_gpadc *gpadc; |
866 | 1801 | ||
867 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | 1802 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); |
868 | main_charger_v_raw = ab8500_gpadc_read_raw(gpadc, MAIN_CHARGER_V); | 1803 | main_charger_v_raw = ab8500_gpadc_read_raw(gpadc, MAIN_CHARGER_V, |
1804 | avg_sample, trig_edge, trig_timer, conv_type); | ||
869 | main_charger_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, | 1805 | main_charger_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, |
870 | MAIN_CHARGER_V, main_charger_v_raw); | 1806 | MAIN_CHARGER_V, main_charger_v_raw); |
871 | 1807 | ||
872 | return seq_printf(s, "%d,0x%X\n", | 1808 | return seq_printf(s, "%d,0x%X\n", |
873 | main_charger_v_convert, main_charger_v_raw); | 1809 | main_charger_v_convert, main_charger_v_raw); |
874 | } | 1810 | } |
875 | 1811 | ||
876 | static int ab8500_gpadc_main_charger_v_open(struct inode *inode, | 1812 | static int ab8500_gpadc_main_charger_v_open(struct inode *inode, |
877 | struct file *file) | 1813 | struct file *file) |
878 | { | 1814 | { |
879 | return single_open(file, ab8500_gpadc_main_charger_v_print, | 1815 | return single_open(file, ab8500_gpadc_main_charger_v_print, |
880 | inode->i_private); | 1816 | inode->i_private); |
881 | } | 1817 | } |
882 | 1818 | ||
883 | static const struct file_operations ab8500_gpadc_main_charger_v_fops = { | 1819 | static const struct file_operations ab8500_gpadc_main_charger_v_fops = { |
@@ -895,19 +1831,20 @@ static int ab8500_gpadc_acc_detect1_print(struct seq_file *s, void *p) | |||
895 | struct ab8500_gpadc *gpadc; | 1831 | struct ab8500_gpadc *gpadc; |
896 | 1832 | ||
897 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | 1833 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); |
898 | acc_detect1_raw = ab8500_gpadc_read_raw(gpadc, ACC_DETECT1); | 1834 | acc_detect1_raw = ab8500_gpadc_read_raw(gpadc, ACC_DETECT1, |
1835 | avg_sample, trig_edge, trig_timer, conv_type); | ||
899 | acc_detect1_convert = ab8500_gpadc_ad_to_voltage(gpadc, ACC_DETECT1, | 1836 | acc_detect1_convert = ab8500_gpadc_ad_to_voltage(gpadc, ACC_DETECT1, |
900 | acc_detect1_raw); | 1837 | acc_detect1_raw); |
901 | 1838 | ||
902 | return seq_printf(s, "%d,0x%X\n", | 1839 | return seq_printf(s, "%d,0x%X\n", |
903 | acc_detect1_convert, acc_detect1_raw); | 1840 | acc_detect1_convert, acc_detect1_raw); |
904 | } | 1841 | } |
905 | 1842 | ||
906 | static int ab8500_gpadc_acc_detect1_open(struct inode *inode, | 1843 | static int ab8500_gpadc_acc_detect1_open(struct inode *inode, |
907 | struct file *file) | 1844 | struct file *file) |
908 | { | 1845 | { |
909 | return single_open(file, ab8500_gpadc_acc_detect1_print, | 1846 | return single_open(file, ab8500_gpadc_acc_detect1_print, |
910 | inode->i_private); | 1847 | inode->i_private); |
911 | } | 1848 | } |
912 | 1849 | ||
913 | static const struct file_operations ab8500_gpadc_acc_detect1_fops = { | 1850 | static const struct file_operations ab8500_gpadc_acc_detect1_fops = { |
@@ -925,19 +1862,20 @@ static int ab8500_gpadc_acc_detect2_print(struct seq_file *s, void *p) | |||
925 | struct ab8500_gpadc *gpadc; | 1862 | struct ab8500_gpadc *gpadc; |
926 | 1863 | ||
927 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | 1864 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); |
928 | acc_detect2_raw = ab8500_gpadc_read_raw(gpadc, ACC_DETECT2); | 1865 | acc_detect2_raw = ab8500_gpadc_read_raw(gpadc, ACC_DETECT2, |
1866 | avg_sample, trig_edge, trig_timer, conv_type); | ||
929 | acc_detect2_convert = ab8500_gpadc_ad_to_voltage(gpadc, | 1867 | acc_detect2_convert = ab8500_gpadc_ad_to_voltage(gpadc, |
930 | ACC_DETECT2, acc_detect2_raw); | 1868 | ACC_DETECT2, acc_detect2_raw); |
931 | 1869 | ||
932 | return seq_printf(s, "%d,0x%X\n", | 1870 | return seq_printf(s, "%d,0x%X\n", |
933 | acc_detect2_convert, acc_detect2_raw); | 1871 | acc_detect2_convert, acc_detect2_raw); |
934 | } | 1872 | } |
935 | 1873 | ||
936 | static int ab8500_gpadc_acc_detect2_open(struct inode *inode, | 1874 | static int ab8500_gpadc_acc_detect2_open(struct inode *inode, |
937 | struct file *file) | 1875 | struct file *file) |
938 | { | 1876 | { |
939 | return single_open(file, ab8500_gpadc_acc_detect2_print, | 1877 | return single_open(file, ab8500_gpadc_acc_detect2_print, |
940 | inode->i_private); | 1878 | inode->i_private); |
941 | } | 1879 | } |
942 | 1880 | ||
943 | static const struct file_operations ab8500_gpadc_acc_detect2_fops = { | 1881 | static const struct file_operations ab8500_gpadc_acc_detect2_fops = { |
@@ -955,12 +1893,13 @@ static int ab8500_gpadc_aux1_print(struct seq_file *s, void *p) | |||
955 | struct ab8500_gpadc *gpadc; | 1893 | struct ab8500_gpadc *gpadc; |
956 | 1894 | ||
957 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | 1895 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); |
958 | aux1_raw = ab8500_gpadc_read_raw(gpadc, ADC_AUX1); | 1896 | aux1_raw = ab8500_gpadc_read_raw(gpadc, ADC_AUX1, |
1897 | avg_sample, trig_edge, trig_timer, conv_type); | ||
959 | aux1_convert = ab8500_gpadc_ad_to_voltage(gpadc, ADC_AUX1, | 1898 | aux1_convert = ab8500_gpadc_ad_to_voltage(gpadc, ADC_AUX1, |
960 | aux1_raw); | 1899 | aux1_raw); |
961 | 1900 | ||
962 | return seq_printf(s, "%d,0x%X\n", | 1901 | return seq_printf(s, "%d,0x%X\n", |
963 | aux1_convert, aux1_raw); | 1902 | aux1_convert, aux1_raw); |
964 | } | 1903 | } |
965 | 1904 | ||
966 | static int ab8500_gpadc_aux1_open(struct inode *inode, struct file *file) | 1905 | static int ab8500_gpadc_aux1_open(struct inode *inode, struct file *file) |
@@ -983,9 +1922,10 @@ static int ab8500_gpadc_aux2_print(struct seq_file *s, void *p) | |||
983 | struct ab8500_gpadc *gpadc; | 1922 | struct ab8500_gpadc *gpadc; |
984 | 1923 | ||
985 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | 1924 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); |
986 | aux2_raw = ab8500_gpadc_read_raw(gpadc, ADC_AUX2); | 1925 | aux2_raw = ab8500_gpadc_read_raw(gpadc, ADC_AUX2, |
1926 | avg_sample, trig_edge, trig_timer, conv_type); | ||
987 | aux2_convert = ab8500_gpadc_ad_to_voltage(gpadc, ADC_AUX2, | 1927 | aux2_convert = ab8500_gpadc_ad_to_voltage(gpadc, ADC_AUX2, |
988 | aux2_raw); | 1928 | aux2_raw); |
989 | 1929 | ||
990 | return seq_printf(s, "%d,0x%X\n", | 1930 | return seq_printf(s, "%d,0x%X\n", |
991 | aux2_convert, aux2_raw); | 1931 | aux2_convert, aux2_raw); |
@@ -1011,16 +1951,17 @@ static int ab8500_gpadc_main_bat_v_print(struct seq_file *s, void *p) | |||
1011 | struct ab8500_gpadc *gpadc; | 1951 | struct ab8500_gpadc *gpadc; |
1012 | 1952 | ||
1013 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | 1953 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); |
1014 | main_bat_v_raw = ab8500_gpadc_read_raw(gpadc, MAIN_BAT_V); | 1954 | main_bat_v_raw = ab8500_gpadc_read_raw(gpadc, MAIN_BAT_V, |
1955 | avg_sample, trig_edge, trig_timer, conv_type); | ||
1015 | main_bat_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, MAIN_BAT_V, | 1956 | main_bat_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, MAIN_BAT_V, |
1016 | main_bat_v_raw); | 1957 | main_bat_v_raw); |
1017 | 1958 | ||
1018 | return seq_printf(s, "%d,0x%X\n", | 1959 | return seq_printf(s, "%d,0x%X\n", |
1019 | main_bat_v_convert, main_bat_v_raw); | 1960 | main_bat_v_convert, main_bat_v_raw); |
1020 | } | 1961 | } |
1021 | 1962 | ||
1022 | static int ab8500_gpadc_main_bat_v_open(struct inode *inode, | 1963 | static int ab8500_gpadc_main_bat_v_open(struct inode *inode, |
1023 | struct file *file) | 1964 | struct file *file) |
1024 | { | 1965 | { |
1025 | return single_open(file, ab8500_gpadc_main_bat_v_print, inode->i_private); | 1966 | return single_open(file, ab8500_gpadc_main_bat_v_print, inode->i_private); |
1026 | } | 1967 | } |
@@ -1040,12 +1981,13 @@ static int ab8500_gpadc_vbus_v_print(struct seq_file *s, void *p) | |||
1040 | struct ab8500_gpadc *gpadc; | 1981 | struct ab8500_gpadc *gpadc; |
1041 | 1982 | ||
1042 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | 1983 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); |
1043 | vbus_v_raw = ab8500_gpadc_read_raw(gpadc, VBUS_V); | 1984 | vbus_v_raw = ab8500_gpadc_read_raw(gpadc, VBUS_V, |
1985 | avg_sample, trig_edge, trig_timer, conv_type); | ||
1044 | vbus_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, VBUS_V, | 1986 | vbus_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, VBUS_V, |
1045 | vbus_v_raw); | 1987 | vbus_v_raw); |
1046 | 1988 | ||
1047 | return seq_printf(s, "%d,0x%X\n", | 1989 | return seq_printf(s, "%d,0x%X\n", |
1048 | vbus_v_convert, vbus_v_raw); | 1990 | vbus_v_convert, vbus_v_raw); |
1049 | } | 1991 | } |
1050 | 1992 | ||
1051 | static int ab8500_gpadc_vbus_v_open(struct inode *inode, struct file *file) | 1993 | static int ab8500_gpadc_vbus_v_open(struct inode *inode, struct file *file) |
@@ -1068,19 +2010,20 @@ static int ab8500_gpadc_main_charger_c_print(struct seq_file *s, void *p) | |||
1068 | struct ab8500_gpadc *gpadc; | 2010 | struct ab8500_gpadc *gpadc; |
1069 | 2011 | ||
1070 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | 2012 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); |
1071 | main_charger_c_raw = ab8500_gpadc_read_raw(gpadc, MAIN_CHARGER_C); | 2013 | main_charger_c_raw = ab8500_gpadc_read_raw(gpadc, MAIN_CHARGER_C, |
2014 | avg_sample, trig_edge, trig_timer, conv_type); | ||
1072 | main_charger_c_convert = ab8500_gpadc_ad_to_voltage(gpadc, | 2015 | main_charger_c_convert = ab8500_gpadc_ad_to_voltage(gpadc, |
1073 | MAIN_CHARGER_C, main_charger_c_raw); | 2016 | MAIN_CHARGER_C, main_charger_c_raw); |
1074 | 2017 | ||
1075 | return seq_printf(s, "%d,0x%X\n", | 2018 | return seq_printf(s, "%d,0x%X\n", |
1076 | main_charger_c_convert, main_charger_c_raw); | 2019 | main_charger_c_convert, main_charger_c_raw); |
1077 | } | 2020 | } |
1078 | 2021 | ||
1079 | static int ab8500_gpadc_main_charger_c_open(struct inode *inode, | 2022 | static int ab8500_gpadc_main_charger_c_open(struct inode *inode, |
1080 | struct file *file) | 2023 | struct file *file) |
1081 | { | 2024 | { |
1082 | return single_open(file, ab8500_gpadc_main_charger_c_print, | 2025 | return single_open(file, ab8500_gpadc_main_charger_c_print, |
1083 | inode->i_private); | 2026 | inode->i_private); |
1084 | } | 2027 | } |
1085 | 2028 | ||
1086 | static const struct file_operations ab8500_gpadc_main_charger_c_fops = { | 2029 | static const struct file_operations ab8500_gpadc_main_charger_c_fops = { |
@@ -1098,19 +2041,20 @@ static int ab8500_gpadc_usb_charger_c_print(struct seq_file *s, void *p) | |||
1098 | struct ab8500_gpadc *gpadc; | 2041 | struct ab8500_gpadc *gpadc; |
1099 | 2042 | ||
1100 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | 2043 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); |
1101 | usb_charger_c_raw = ab8500_gpadc_read_raw(gpadc, USB_CHARGER_C); | 2044 | usb_charger_c_raw = ab8500_gpadc_read_raw(gpadc, USB_CHARGER_C, |
2045 | avg_sample, trig_edge, trig_timer, conv_type); | ||
1102 | usb_charger_c_convert = ab8500_gpadc_ad_to_voltage(gpadc, | 2046 | usb_charger_c_convert = ab8500_gpadc_ad_to_voltage(gpadc, |
1103 | USB_CHARGER_C, usb_charger_c_raw); | 2047 | USB_CHARGER_C, usb_charger_c_raw); |
1104 | 2048 | ||
1105 | return seq_printf(s, "%d,0x%X\n", | 2049 | return seq_printf(s, "%d,0x%X\n", |
1106 | usb_charger_c_convert, usb_charger_c_raw); | 2050 | usb_charger_c_convert, usb_charger_c_raw); |
1107 | } | 2051 | } |
1108 | 2052 | ||
1109 | static int ab8500_gpadc_usb_charger_c_open(struct inode *inode, | 2053 | static int ab8500_gpadc_usb_charger_c_open(struct inode *inode, |
1110 | struct file *file) | 2054 | struct file *file) |
1111 | { | 2055 | { |
1112 | return single_open(file, ab8500_gpadc_usb_charger_c_print, | 2056 | return single_open(file, ab8500_gpadc_usb_charger_c_print, |
1113 | inode->i_private); | 2057 | inode->i_private); |
1114 | } | 2058 | } |
1115 | 2059 | ||
1116 | static const struct file_operations ab8500_gpadc_usb_charger_c_fops = { | 2060 | static const struct file_operations ab8500_gpadc_usb_charger_c_fops = { |
@@ -1128,12 +2072,13 @@ static int ab8500_gpadc_bk_bat_v_print(struct seq_file *s, void *p) | |||
1128 | struct ab8500_gpadc *gpadc; | 2072 | struct ab8500_gpadc *gpadc; |
1129 | 2073 | ||
1130 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | 2074 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); |
1131 | bk_bat_v_raw = ab8500_gpadc_read_raw(gpadc, BK_BAT_V); | 2075 | bk_bat_v_raw = ab8500_gpadc_read_raw(gpadc, BK_BAT_V, |
2076 | avg_sample, trig_edge, trig_timer, conv_type); | ||
1132 | bk_bat_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, | 2077 | bk_bat_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, |
1133 | BK_BAT_V, bk_bat_v_raw); | 2078 | BK_BAT_V, bk_bat_v_raw); |
1134 | 2079 | ||
1135 | return seq_printf(s, "%d,0x%X\n", | 2080 | return seq_printf(s, "%d,0x%X\n", |
1136 | bk_bat_v_convert, bk_bat_v_raw); | 2081 | bk_bat_v_convert, bk_bat_v_raw); |
1137 | } | 2082 | } |
1138 | 2083 | ||
1139 | static int ab8500_gpadc_bk_bat_v_open(struct inode *inode, struct file *file) | 2084 | static int ab8500_gpadc_bk_bat_v_open(struct inode *inode, struct file *file) |
@@ -1156,12 +2101,13 @@ static int ab8500_gpadc_die_temp_print(struct seq_file *s, void *p) | |||
1156 | struct ab8500_gpadc *gpadc; | 2101 | struct ab8500_gpadc *gpadc; |
1157 | 2102 | ||
1158 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | 2103 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); |
1159 | die_temp_raw = ab8500_gpadc_read_raw(gpadc, DIE_TEMP); | 2104 | die_temp_raw = ab8500_gpadc_read_raw(gpadc, DIE_TEMP, |
2105 | avg_sample, trig_edge, trig_timer, conv_type); | ||
1160 | die_temp_convert = ab8500_gpadc_ad_to_voltage(gpadc, DIE_TEMP, | 2106 | die_temp_convert = ab8500_gpadc_ad_to_voltage(gpadc, DIE_TEMP, |
1161 | die_temp_raw); | 2107 | die_temp_raw); |
1162 | 2108 | ||
1163 | return seq_printf(s, "%d,0x%X\n", | 2109 | return seq_printf(s, "%d,0x%X\n", |
1164 | die_temp_convert, die_temp_raw); | 2110 | die_temp_convert, die_temp_raw); |
1165 | } | 2111 | } |
1166 | 2112 | ||
1167 | static int ab8500_gpadc_die_temp_open(struct inode *inode, struct file *file) | 2113 | static int ab8500_gpadc_die_temp_open(struct inode *inode, struct file *file) |
@@ -1177,6 +2123,453 @@ static const struct file_operations ab8500_gpadc_die_temp_fops = { | |||
1177 | .owner = THIS_MODULE, | 2123 | .owner = THIS_MODULE, |
1178 | }; | 2124 | }; |
1179 | 2125 | ||
2126 | static int ab8500_gpadc_usb_id_print(struct seq_file *s, void *p) | ||
2127 | { | ||
2128 | int usb_id_raw; | ||
2129 | int usb_id_convert; | ||
2130 | struct ab8500_gpadc *gpadc; | ||
2131 | |||
2132 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | ||
2133 | usb_id_raw = ab8500_gpadc_read_raw(gpadc, USB_ID, | ||
2134 | avg_sample, trig_edge, trig_timer, conv_type); | ||
2135 | usb_id_convert = ab8500_gpadc_ad_to_voltage(gpadc, USB_ID, | ||
2136 | usb_id_raw); | ||
2137 | |||
2138 | return seq_printf(s, "%d,0x%X\n", | ||
2139 | usb_id_convert, usb_id_raw); | ||
2140 | } | ||
2141 | |||
2142 | static int ab8500_gpadc_usb_id_open(struct inode *inode, struct file *file) | ||
2143 | { | ||
2144 | return single_open(file, ab8500_gpadc_usb_id_print, inode->i_private); | ||
2145 | } | ||
2146 | |||
2147 | static const struct file_operations ab8500_gpadc_usb_id_fops = { | ||
2148 | .open = ab8500_gpadc_usb_id_open, | ||
2149 | .read = seq_read, | ||
2150 | .llseek = seq_lseek, | ||
2151 | .release = single_release, | ||
2152 | .owner = THIS_MODULE, | ||
2153 | }; | ||
2154 | |||
2155 | static int ab8540_gpadc_xtal_temp_print(struct seq_file *s, void *p) | ||
2156 | { | ||
2157 | int xtal_temp_raw; | ||
2158 | int xtal_temp_convert; | ||
2159 | struct ab8500_gpadc *gpadc; | ||
2160 | |||
2161 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | ||
2162 | xtal_temp_raw = ab8500_gpadc_read_raw(gpadc, XTAL_TEMP, | ||
2163 | avg_sample, trig_edge, trig_timer, conv_type); | ||
2164 | xtal_temp_convert = ab8500_gpadc_ad_to_voltage(gpadc, XTAL_TEMP, | ||
2165 | xtal_temp_raw); | ||
2166 | |||
2167 | return seq_printf(s, "%d,0x%X\n", | ||
2168 | xtal_temp_convert, xtal_temp_raw); | ||
2169 | } | ||
2170 | |||
2171 | static int ab8540_gpadc_xtal_temp_open(struct inode *inode, struct file *file) | ||
2172 | { | ||
2173 | return single_open(file, ab8540_gpadc_xtal_temp_print, | ||
2174 | inode->i_private); | ||
2175 | } | ||
2176 | |||
2177 | static const struct file_operations ab8540_gpadc_xtal_temp_fops = { | ||
2178 | .open = ab8540_gpadc_xtal_temp_open, | ||
2179 | .read = seq_read, | ||
2180 | .llseek = seq_lseek, | ||
2181 | .release = single_release, | ||
2182 | .owner = THIS_MODULE, | ||
2183 | }; | ||
2184 | |||
2185 | static int ab8540_gpadc_vbat_true_meas_print(struct seq_file *s, void *p) | ||
2186 | { | ||
2187 | int vbat_true_meas_raw; | ||
2188 | int vbat_true_meas_convert; | ||
2189 | struct ab8500_gpadc *gpadc; | ||
2190 | |||
2191 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | ||
2192 | vbat_true_meas_raw = ab8500_gpadc_read_raw(gpadc, VBAT_TRUE_MEAS, | ||
2193 | avg_sample, trig_edge, trig_timer, conv_type); | ||
2194 | vbat_true_meas_convert = ab8500_gpadc_ad_to_voltage(gpadc, VBAT_TRUE_MEAS, | ||
2195 | vbat_true_meas_raw); | ||
2196 | |||
2197 | return seq_printf(s, "%d,0x%X\n", | ||
2198 | vbat_true_meas_convert, vbat_true_meas_raw); | ||
2199 | } | ||
2200 | |||
2201 | static int ab8540_gpadc_vbat_true_meas_open(struct inode *inode, | ||
2202 | struct file *file) | ||
2203 | { | ||
2204 | return single_open(file, ab8540_gpadc_vbat_true_meas_print, | ||
2205 | inode->i_private); | ||
2206 | } | ||
2207 | |||
2208 | static const struct file_operations ab8540_gpadc_vbat_true_meas_fops = { | ||
2209 | .open = ab8540_gpadc_vbat_true_meas_open, | ||
2210 | .read = seq_read, | ||
2211 | .llseek = seq_lseek, | ||
2212 | .release = single_release, | ||
2213 | .owner = THIS_MODULE, | ||
2214 | }; | ||
2215 | |||
2216 | static int ab8540_gpadc_bat_ctrl_and_ibat_print(struct seq_file *s, void *p) | ||
2217 | { | ||
2218 | int bat_ctrl_raw; | ||
2219 | int bat_ctrl_convert; | ||
2220 | int ibat_raw; | ||
2221 | int ibat_convert; | ||
2222 | struct ab8500_gpadc *gpadc; | ||
2223 | |||
2224 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | ||
2225 | bat_ctrl_raw = ab8500_gpadc_double_read_raw(gpadc, BAT_CTRL_AND_IBAT, | ||
2226 | avg_sample, trig_edge, trig_timer, conv_type, &ibat_raw); | ||
2227 | |||
2228 | bat_ctrl_convert = ab8500_gpadc_ad_to_voltage(gpadc, BAT_CTRL, | ||
2229 | bat_ctrl_raw); | ||
2230 | ibat_convert = ab8500_gpadc_ad_to_voltage(gpadc, IBAT_VIRTUAL_CHANNEL, | ||
2231 | ibat_raw); | ||
2232 | |||
2233 | return seq_printf(s, "%d,0x%X\n" "%d,0x%X\n", | ||
2234 | bat_ctrl_convert, bat_ctrl_raw, | ||
2235 | ibat_convert, ibat_raw); | ||
2236 | } | ||
2237 | |||
2238 | static int ab8540_gpadc_bat_ctrl_and_ibat_open(struct inode *inode, | ||
2239 | struct file *file) | ||
2240 | { | ||
2241 | return single_open(file, ab8540_gpadc_bat_ctrl_and_ibat_print, | ||
2242 | inode->i_private); | ||
2243 | } | ||
2244 | |||
2245 | static const struct file_operations ab8540_gpadc_bat_ctrl_and_ibat_fops = { | ||
2246 | .open = ab8540_gpadc_bat_ctrl_and_ibat_open, | ||
2247 | .read = seq_read, | ||
2248 | .llseek = seq_lseek, | ||
2249 | .release = single_release, | ||
2250 | .owner = THIS_MODULE, | ||
2251 | }; | ||
2252 | |||
2253 | static int ab8540_gpadc_vbat_meas_and_ibat_print(struct seq_file *s, void *p) | ||
2254 | { | ||
2255 | int vbat_meas_raw; | ||
2256 | int vbat_meas_convert; | ||
2257 | int ibat_raw; | ||
2258 | int ibat_convert; | ||
2259 | struct ab8500_gpadc *gpadc; | ||
2260 | |||
2261 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | ||
2262 | vbat_meas_raw = ab8500_gpadc_double_read_raw(gpadc, VBAT_MEAS_AND_IBAT, | ||
2263 | avg_sample, trig_edge, trig_timer, conv_type, &ibat_raw); | ||
2264 | vbat_meas_convert = ab8500_gpadc_ad_to_voltage(gpadc, MAIN_BAT_V, | ||
2265 | vbat_meas_raw); | ||
2266 | ibat_convert = ab8500_gpadc_ad_to_voltage(gpadc, IBAT_VIRTUAL_CHANNEL, | ||
2267 | ibat_raw); | ||
2268 | |||
2269 | return seq_printf(s, "%d,0x%X\n" "%d,0x%X\n", | ||
2270 | vbat_meas_convert, vbat_meas_raw, | ||
2271 | ibat_convert, ibat_raw); | ||
2272 | } | ||
2273 | |||
2274 | static int ab8540_gpadc_vbat_meas_and_ibat_open(struct inode *inode, | ||
2275 | struct file *file) | ||
2276 | { | ||
2277 | return single_open(file, ab8540_gpadc_vbat_meas_and_ibat_print, | ||
2278 | inode->i_private); | ||
2279 | } | ||
2280 | |||
2281 | static const struct file_operations ab8540_gpadc_vbat_meas_and_ibat_fops = { | ||
2282 | .open = ab8540_gpadc_vbat_meas_and_ibat_open, | ||
2283 | .read = seq_read, | ||
2284 | .llseek = seq_lseek, | ||
2285 | .release = single_release, | ||
2286 | .owner = THIS_MODULE, | ||
2287 | }; | ||
2288 | |||
2289 | static int ab8540_gpadc_vbat_true_meas_and_ibat_print(struct seq_file *s, void *p) | ||
2290 | { | ||
2291 | int vbat_true_meas_raw; | ||
2292 | int vbat_true_meas_convert; | ||
2293 | int ibat_raw; | ||
2294 | int ibat_convert; | ||
2295 | struct ab8500_gpadc *gpadc; | ||
2296 | |||
2297 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | ||
2298 | vbat_true_meas_raw = ab8500_gpadc_double_read_raw(gpadc, | ||
2299 | VBAT_TRUE_MEAS_AND_IBAT, avg_sample, trig_edge, | ||
2300 | trig_timer, conv_type, &ibat_raw); | ||
2301 | vbat_true_meas_convert = ab8500_gpadc_ad_to_voltage(gpadc, | ||
2302 | VBAT_TRUE_MEAS, vbat_true_meas_raw); | ||
2303 | ibat_convert = ab8500_gpadc_ad_to_voltage(gpadc, IBAT_VIRTUAL_CHANNEL, | ||
2304 | ibat_raw); | ||
2305 | |||
2306 | return seq_printf(s, "%d,0x%X\n" "%d,0x%X\n", | ||
2307 | vbat_true_meas_convert, vbat_true_meas_raw, | ||
2308 | ibat_convert, ibat_raw); | ||
2309 | } | ||
2310 | |||
2311 | static int ab8540_gpadc_vbat_true_meas_and_ibat_open(struct inode *inode, | ||
2312 | struct file *file) | ||
2313 | { | ||
2314 | return single_open(file, ab8540_gpadc_vbat_true_meas_and_ibat_print, | ||
2315 | inode->i_private); | ||
2316 | } | ||
2317 | |||
2318 | static const struct file_operations ab8540_gpadc_vbat_true_meas_and_ibat_fops = { | ||
2319 | .open = ab8540_gpadc_vbat_true_meas_and_ibat_open, | ||
2320 | .read = seq_read, | ||
2321 | .llseek = seq_lseek, | ||
2322 | .release = single_release, | ||
2323 | .owner = THIS_MODULE, | ||
2324 | }; | ||
2325 | |||
2326 | static int ab8540_gpadc_bat_temp_and_ibat_print(struct seq_file *s, void *p) | ||
2327 | { | ||
2328 | int bat_temp_raw; | ||
2329 | int bat_temp_convert; | ||
2330 | int ibat_raw; | ||
2331 | int ibat_convert; | ||
2332 | struct ab8500_gpadc *gpadc; | ||
2333 | |||
2334 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | ||
2335 | bat_temp_raw = ab8500_gpadc_double_read_raw(gpadc, BAT_TEMP_AND_IBAT, | ||
2336 | avg_sample, trig_edge, trig_timer, conv_type, &ibat_raw); | ||
2337 | bat_temp_convert = ab8500_gpadc_ad_to_voltage(gpadc, BTEMP_BALL, | ||
2338 | bat_temp_raw); | ||
2339 | ibat_convert = ab8500_gpadc_ad_to_voltage(gpadc, IBAT_VIRTUAL_CHANNEL, | ||
2340 | ibat_raw); | ||
2341 | |||
2342 | return seq_printf(s, "%d,0x%X\n" "%d,0x%X\n", | ||
2343 | bat_temp_convert, bat_temp_raw, | ||
2344 | ibat_convert, ibat_raw); | ||
2345 | } | ||
2346 | |||
2347 | static int ab8540_gpadc_bat_temp_and_ibat_open(struct inode *inode, | ||
2348 | struct file *file) | ||
2349 | { | ||
2350 | return single_open(file, ab8540_gpadc_bat_temp_and_ibat_print, | ||
2351 | inode->i_private); | ||
2352 | } | ||
2353 | |||
2354 | static const struct file_operations ab8540_gpadc_bat_temp_and_ibat_fops = { | ||
2355 | .open = ab8540_gpadc_bat_temp_and_ibat_open, | ||
2356 | .read = seq_read, | ||
2357 | .llseek = seq_lseek, | ||
2358 | .release = single_release, | ||
2359 | .owner = THIS_MODULE, | ||
2360 | }; | ||
2361 | |||
2362 | static int ab8540_gpadc_otp_cal_print(struct seq_file *s, void *p) | ||
2363 | { | ||
2364 | struct ab8500_gpadc *gpadc; | ||
2365 | u16 vmain_l, vmain_h, btemp_l, btemp_h; | ||
2366 | u16 vbat_l, vbat_h, ibat_l, ibat_h; | ||
2367 | |||
2368 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | ||
2369 | ab8540_gpadc_get_otp(gpadc, &vmain_l, &vmain_h, &btemp_l, &btemp_h, | ||
2370 | &vbat_l, &vbat_h, &ibat_l, &ibat_h); | ||
2371 | return seq_printf(s, "VMAIN_L:0x%X\n" | ||
2372 | "VMAIN_H:0x%X\n" | ||
2373 | "BTEMP_L:0x%X\n" | ||
2374 | "BTEMP_H:0x%X\n" | ||
2375 | "VBAT_L:0x%X\n" | ||
2376 | "VBAT_H:0x%X\n" | ||
2377 | "IBAT_L:0x%X\n" | ||
2378 | "IBAT_H:0x%X\n", | ||
2379 | vmain_l, vmain_h, btemp_l, btemp_h, vbat_l, vbat_h, ibat_l, ibat_h); | ||
2380 | } | ||
2381 | |||
2382 | static int ab8540_gpadc_otp_cal_open(struct inode *inode, struct file *file) | ||
2383 | { | ||
2384 | return single_open(file, ab8540_gpadc_otp_cal_print, inode->i_private); | ||
2385 | } | ||
2386 | |||
2387 | static const struct file_operations ab8540_gpadc_otp_calib_fops = { | ||
2388 | .open = ab8540_gpadc_otp_cal_open, | ||
2389 | .read = seq_read, | ||
2390 | .llseek = seq_lseek, | ||
2391 | .release = single_release, | ||
2392 | .owner = THIS_MODULE, | ||
2393 | }; | ||
2394 | |||
2395 | static int ab8500_gpadc_avg_sample_print(struct seq_file *s, void *p) | ||
2396 | { | ||
2397 | return seq_printf(s, "%d\n", avg_sample); | ||
2398 | } | ||
2399 | |||
2400 | static int ab8500_gpadc_avg_sample_open(struct inode *inode, struct file *file) | ||
2401 | { | ||
2402 | return single_open(file, ab8500_gpadc_avg_sample_print, | ||
2403 | inode->i_private); | ||
2404 | } | ||
2405 | |||
2406 | static ssize_t ab8500_gpadc_avg_sample_write(struct file *file, | ||
2407 | const char __user *user_buf, | ||
2408 | size_t count, loff_t *ppos) | ||
2409 | { | ||
2410 | struct device *dev = ((struct seq_file *)(file->private_data))->private; | ||
2411 | unsigned long user_avg_sample; | ||
2412 | int err; | ||
2413 | |||
2414 | err = kstrtoul_from_user(user_buf, count, 0, &user_avg_sample); | ||
2415 | if (err) | ||
2416 | return err; | ||
2417 | |||
2418 | if ((user_avg_sample == SAMPLE_1) || (user_avg_sample == SAMPLE_4) | ||
2419 | || (user_avg_sample == SAMPLE_8) | ||
2420 | || (user_avg_sample == SAMPLE_16)) { | ||
2421 | avg_sample = (u8) user_avg_sample; | ||
2422 | } else { | ||
2423 | dev_err(dev, "debugfs error input: " | ||
2424 | "should be egal to 1, 4, 8 or 16\n"); | ||
2425 | return -EINVAL; | ||
2426 | } | ||
2427 | |||
2428 | return count; | ||
2429 | } | ||
2430 | |||
2431 | static const struct file_operations ab8500_gpadc_avg_sample_fops = { | ||
2432 | .open = ab8500_gpadc_avg_sample_open, | ||
2433 | .read = seq_read, | ||
2434 | .write = ab8500_gpadc_avg_sample_write, | ||
2435 | .llseek = seq_lseek, | ||
2436 | .release = single_release, | ||
2437 | .owner = THIS_MODULE, | ||
2438 | }; | ||
2439 | |||
2440 | static int ab8500_gpadc_trig_edge_print(struct seq_file *s, void *p) | ||
2441 | { | ||
2442 | return seq_printf(s, "%d\n", trig_edge); | ||
2443 | } | ||
2444 | |||
2445 | static int ab8500_gpadc_trig_edge_open(struct inode *inode, struct file *file) | ||
2446 | { | ||
2447 | return single_open(file, ab8500_gpadc_trig_edge_print, | ||
2448 | inode->i_private); | ||
2449 | } | ||
2450 | |||
2451 | static ssize_t ab8500_gpadc_trig_edge_write(struct file *file, | ||
2452 | const char __user *user_buf, | ||
2453 | size_t count, loff_t *ppos) | ||
2454 | { | ||
2455 | struct device *dev = ((struct seq_file *)(file->private_data))->private; | ||
2456 | unsigned long user_trig_edge; | ||
2457 | int err; | ||
2458 | |||
2459 | err = kstrtoul_from_user(user_buf, count, 0, &user_trig_edge); | ||
2460 | if (err) | ||
2461 | return err; | ||
2462 | |||
2463 | if ((user_trig_edge == RISING_EDGE) | ||
2464 | || (user_trig_edge == FALLING_EDGE)) { | ||
2465 | trig_edge = (u8) user_trig_edge; | ||
2466 | } else { | ||
2467 | dev_err(dev, "Wrong input:\n" | ||
2468 | "Enter 0. Rising edge\n" | ||
2469 | "Enter 1. Falling edge\n"); | ||
2470 | return -EINVAL; | ||
2471 | } | ||
2472 | |||
2473 | return count; | ||
2474 | } | ||
2475 | |||
2476 | static const struct file_operations ab8500_gpadc_trig_edge_fops = { | ||
2477 | .open = ab8500_gpadc_trig_edge_open, | ||
2478 | .read = seq_read, | ||
2479 | .write = ab8500_gpadc_trig_edge_write, | ||
2480 | .llseek = seq_lseek, | ||
2481 | .release = single_release, | ||
2482 | .owner = THIS_MODULE, | ||
2483 | }; | ||
2484 | |||
2485 | static int ab8500_gpadc_trig_timer_print(struct seq_file *s, void *p) | ||
2486 | { | ||
2487 | return seq_printf(s, "%d\n", trig_timer); | ||
2488 | } | ||
2489 | |||
2490 | static int ab8500_gpadc_trig_timer_open(struct inode *inode, struct file *file) | ||
2491 | { | ||
2492 | return single_open(file, ab8500_gpadc_trig_timer_print, | ||
2493 | inode->i_private); | ||
2494 | } | ||
2495 | |||
2496 | static ssize_t ab8500_gpadc_trig_timer_write(struct file *file, | ||
2497 | const char __user *user_buf, | ||
2498 | size_t count, loff_t *ppos) | ||
2499 | { | ||
2500 | struct device *dev = ((struct seq_file *)(file->private_data))->private; | ||
2501 | unsigned long user_trig_timer; | ||
2502 | int err; | ||
2503 | |||
2504 | err = kstrtoul_from_user(user_buf, count, 0, &user_trig_timer); | ||
2505 | if (err) | ||
2506 | return err; | ||
2507 | |||
2508 | if ((user_trig_timer >= 0) && (user_trig_timer <= 255)) { | ||
2509 | trig_timer = (u8) user_trig_timer; | ||
2510 | } else { | ||
2511 | dev_err(dev, "debugfs error input: " | ||
2512 | "should be beetween 0 to 255\n"); | ||
2513 | return -EINVAL; | ||
2514 | } | ||
2515 | |||
2516 | return count; | ||
2517 | } | ||
2518 | |||
2519 | static const struct file_operations ab8500_gpadc_trig_timer_fops = { | ||
2520 | .open = ab8500_gpadc_trig_timer_open, | ||
2521 | .read = seq_read, | ||
2522 | .write = ab8500_gpadc_trig_timer_write, | ||
2523 | .llseek = seq_lseek, | ||
2524 | .release = single_release, | ||
2525 | .owner = THIS_MODULE, | ||
2526 | }; | ||
2527 | |||
2528 | static int ab8500_gpadc_conv_type_print(struct seq_file *s, void *p) | ||
2529 | { | ||
2530 | return seq_printf(s, "%d\n", conv_type); | ||
2531 | } | ||
2532 | |||
2533 | static int ab8500_gpadc_conv_type_open(struct inode *inode, struct file *file) | ||
2534 | { | ||
2535 | return single_open(file, ab8500_gpadc_conv_type_print, | ||
2536 | inode->i_private); | ||
2537 | } | ||
2538 | |||
2539 | static ssize_t ab8500_gpadc_conv_type_write(struct file *file, | ||
2540 | const char __user *user_buf, | ||
2541 | size_t count, loff_t *ppos) | ||
2542 | { | ||
2543 | struct device *dev = ((struct seq_file *)(file->private_data))->private; | ||
2544 | unsigned long user_conv_type; | ||
2545 | int err; | ||
2546 | |||
2547 | err = kstrtoul_from_user(user_buf, count, 0, &user_conv_type); | ||
2548 | if (err) | ||
2549 | return err; | ||
2550 | |||
2551 | if ((user_conv_type == ADC_SW) | ||
2552 | || (user_conv_type == ADC_HW)) { | ||
2553 | conv_type = (u8) user_conv_type; | ||
2554 | } else { | ||
2555 | dev_err(dev, "Wrong input:\n" | ||
2556 | "Enter 0. ADC SW conversion\n" | ||
2557 | "Enter 1. ADC HW conversion\n"); | ||
2558 | return -EINVAL; | ||
2559 | } | ||
2560 | |||
2561 | return count; | ||
2562 | } | ||
2563 | |||
2564 | static const struct file_operations ab8500_gpadc_conv_type_fops = { | ||
2565 | .open = ab8500_gpadc_conv_type_open, | ||
2566 | .read = seq_read, | ||
2567 | .write = ab8500_gpadc_conv_type_write, | ||
2568 | .llseek = seq_lseek, | ||
2569 | .release = single_release, | ||
2570 | .owner = THIS_MODULE, | ||
2571 | }; | ||
2572 | |||
1180 | /* | 2573 | /* |
1181 | * return length of an ASCII numerical value, 0 is string is not a | 2574 | * return length of an ASCII numerical value, 0 is string is not a |
1182 | * numerical value. | 2575 | * numerical value. |
@@ -1352,7 +2745,7 @@ static int ab8500_subscribe_unsubscribe_open(struct inode *inode, | |||
1352 | struct file *file) | 2745 | struct file *file) |
1353 | { | 2746 | { |
1354 | return single_open(file, ab8500_subscribe_unsubscribe_print, | 2747 | return single_open(file, ab8500_subscribe_unsubscribe_print, |
1355 | inode->i_private); | 2748 | inode->i_private); |
1356 | } | 2749 | } |
1357 | 2750 | ||
1358 | /* | 2751 | /* |
@@ -1382,21 +2775,14 @@ static ssize_t ab8500_subscribe_write(struct file *file, | |||
1382 | size_t count, loff_t *ppos) | 2775 | size_t count, loff_t *ppos) |
1383 | { | 2776 | { |
1384 | struct device *dev = ((struct seq_file *)(file->private_data))->private; | 2777 | struct device *dev = ((struct seq_file *)(file->private_data))->private; |
1385 | char buf[32]; | ||
1386 | int buf_size; | ||
1387 | unsigned long user_val; | 2778 | unsigned long user_val; |
1388 | int err; | 2779 | int err; |
1389 | unsigned int irq_index; | 2780 | unsigned int irq_index; |
1390 | 2781 | ||
1391 | /* Get userspace string and assure termination */ | 2782 | err = kstrtoul_from_user(user_buf, count, 0, &user_val); |
1392 | buf_size = min(count, (sizeof(buf)-1)); | ||
1393 | if (copy_from_user(buf, user_buf, buf_size)) | ||
1394 | return -EFAULT; | ||
1395 | buf[buf_size] = 0; | ||
1396 | |||
1397 | err = strict_strtoul(buf, 0, &user_val); | ||
1398 | if (err) | 2783 | if (err) |
1399 | return -EINVAL; | 2784 | return err; |
2785 | |||
1400 | if (user_val < irq_first) { | 2786 | if (user_val < irq_first) { |
1401 | dev_err(dev, "debugfs error input < %d\n", irq_first); | 2787 | dev_err(dev, "debugfs error input < %d\n", irq_first); |
1402 | return -EINVAL; | 2788 | return -EINVAL; |
@@ -1416,7 +2802,7 @@ static ssize_t ab8500_subscribe_write(struct file *file, | |||
1416 | */ | 2802 | */ |
1417 | dev_attr[irq_index] = kmalloc(sizeof(struct device_attribute), | 2803 | dev_attr[irq_index] = kmalloc(sizeof(struct device_attribute), |
1418 | GFP_KERNEL); | 2804 | GFP_KERNEL); |
1419 | event_name[irq_index] = kmalloc(buf_size, GFP_KERNEL); | 2805 | event_name[irq_index] = kmalloc(count, GFP_KERNEL); |
1420 | sprintf(event_name[irq_index], "%lu", user_val); | 2806 | sprintf(event_name[irq_index], "%lu", user_val); |
1421 | dev_attr[irq_index]->show = show_irq; | 2807 | dev_attr[irq_index]->show = show_irq; |
1422 | dev_attr[irq_index]->store = NULL; | 2808 | dev_attr[irq_index]->store = NULL; |
@@ -1438,7 +2824,7 @@ static ssize_t ab8500_subscribe_write(struct file *file, | |||
1438 | return err; | 2824 | return err; |
1439 | } | 2825 | } |
1440 | 2826 | ||
1441 | return buf_size; | 2827 | return count; |
1442 | } | 2828 | } |
1443 | 2829 | ||
1444 | static ssize_t ab8500_unsubscribe_write(struct file *file, | 2830 | static ssize_t ab8500_unsubscribe_write(struct file *file, |
@@ -1446,21 +2832,14 @@ static ssize_t ab8500_unsubscribe_write(struct file *file, | |||
1446 | size_t count, loff_t *ppos) | 2832 | size_t count, loff_t *ppos) |
1447 | { | 2833 | { |
1448 | struct device *dev = ((struct seq_file *)(file->private_data))->private; | 2834 | struct device *dev = ((struct seq_file *)(file->private_data))->private; |
1449 | char buf[32]; | ||
1450 | int buf_size; | ||
1451 | unsigned long user_val; | 2835 | unsigned long user_val; |
1452 | int err; | 2836 | int err; |
1453 | unsigned int irq_index; | 2837 | unsigned int irq_index; |
1454 | 2838 | ||
1455 | /* Get userspace string and assure termination */ | 2839 | err = kstrtoul_from_user(user_buf, count, 0, &user_val); |
1456 | buf_size = min(count, (sizeof(buf)-1)); | ||
1457 | if (copy_from_user(buf, user_buf, buf_size)) | ||
1458 | return -EFAULT; | ||
1459 | buf[buf_size] = 0; | ||
1460 | |||
1461 | err = strict_strtoul(buf, 0, &user_val); | ||
1462 | if (err) | 2840 | if (err) |
1463 | return -EINVAL; | 2841 | return err; |
2842 | |||
1464 | if (user_val < irq_first) { | 2843 | if (user_val < irq_first) { |
1465 | dev_err(dev, "debugfs error input < %d\n", irq_first); | 2844 | dev_err(dev, "debugfs error input < %d\n", irq_first); |
1466 | return -EINVAL; | 2845 | return -EINVAL; |
@@ -1485,7 +2864,7 @@ static ssize_t ab8500_unsubscribe_write(struct file *file, | |||
1485 | kfree(event_name[irq_index]); | 2864 | kfree(event_name[irq_index]); |
1486 | kfree(dev_attr[irq_index]); | 2865 | kfree(dev_attr[irq_index]); |
1487 | 2866 | ||
1488 | return buf_size; | 2867 | return count; |
1489 | } | 2868 | } |
1490 | 2869 | ||
1491 | /* | 2870 | /* |
@@ -1583,7 +2962,7 @@ static int ab8500_debug_probe(struct platform_device *plf) | |||
1583 | irq_first = platform_get_irq_byname(plf, "IRQ_FIRST"); | 2962 | irq_first = platform_get_irq_byname(plf, "IRQ_FIRST"); |
1584 | if (irq_first < 0) { | 2963 | if (irq_first < 0) { |
1585 | dev_err(&plf->dev, "First irq not found, err %d\n", | 2964 | dev_err(&plf->dev, "First irq not found, err %d\n", |
1586 | irq_first); | 2965 | irq_first); |
1587 | ret = irq_first; | 2966 | ret = irq_first; |
1588 | goto out_freeevent_name; | 2967 | goto out_freeevent_name; |
1589 | } | 2968 | } |
@@ -1591,9 +2970,9 @@ static int ab8500_debug_probe(struct platform_device *plf) | |||
1591 | irq_last = platform_get_irq_byname(plf, "IRQ_LAST"); | 2970 | irq_last = platform_get_irq_byname(plf, "IRQ_LAST"); |
1592 | if (irq_last < 0) { | 2971 | if (irq_last < 0) { |
1593 | dev_err(&plf->dev, "Last irq not found, err %d\n", | 2972 | dev_err(&plf->dev, "Last irq not found, err %d\n", |
1594 | irq_last); | 2973 | irq_last); |
1595 | ret = irq_last; | 2974 | ret = irq_last; |
1596 | goto out_freeevent_name; | 2975 | goto out_freeevent_name; |
1597 | } | 2976 | } |
1598 | 2977 | ||
1599 | ab8500_dir = debugfs_create_dir(AB8500_NAME_STRING, NULL); | 2978 | ab8500_dir = debugfs_create_dir(AB8500_NAME_STRING, NULL); |
@@ -1601,124 +2980,198 @@ static int ab8500_debug_probe(struct platform_device *plf) | |||
1601 | goto err; | 2980 | goto err; |
1602 | 2981 | ||
1603 | ab8500_gpadc_dir = debugfs_create_dir(AB8500_ADC_NAME_STRING, | 2982 | ab8500_gpadc_dir = debugfs_create_dir(AB8500_ADC_NAME_STRING, |
1604 | ab8500_dir); | 2983 | ab8500_dir); |
1605 | if (!ab8500_gpadc_dir) | 2984 | if (!ab8500_gpadc_dir) |
1606 | goto err; | 2985 | goto err; |
1607 | 2986 | ||
1608 | file = debugfs_create_file("all-bank-registers", S_IRUGO, | 2987 | file = debugfs_create_file("all-bank-registers", S_IRUGO, |
1609 | ab8500_dir, &plf->dev, &ab8500_registers_fops); | 2988 | ab8500_dir, &plf->dev, &ab8500_registers_fops); |
1610 | if (!file) | 2989 | if (!file) |
1611 | goto err; | 2990 | goto err; |
1612 | 2991 | ||
1613 | file = debugfs_create_file("all-banks", S_IRUGO, | 2992 | file = debugfs_create_file("all-banks", S_IRUGO, |
1614 | ab8500_dir, &plf->dev, &ab8500_all_banks_fops); | 2993 | ab8500_dir, &plf->dev, &ab8500_all_banks_fops); |
1615 | if (!file) | 2994 | if (!file) |
1616 | goto err; | 2995 | goto err; |
1617 | 2996 | ||
1618 | file = debugfs_create_file("register-bank", (S_IRUGO | S_IWUSR), | 2997 | file = debugfs_create_file("register-bank", (S_IRUGO | S_IWUSR | S_IWGRP), |
1619 | ab8500_dir, &plf->dev, &ab8500_bank_fops); | 2998 | ab8500_dir, &plf->dev, &ab8500_bank_fops); |
1620 | if (!file) | 2999 | if (!file) |
1621 | goto err; | 3000 | goto err; |
1622 | 3001 | ||
1623 | file = debugfs_create_file("register-address", (S_IRUGO | S_IWUSR), | 3002 | file = debugfs_create_file("register-address", (S_IRUGO | S_IWUSR | S_IWGRP), |
1624 | ab8500_dir, &plf->dev, &ab8500_address_fops); | 3003 | ab8500_dir, &plf->dev, &ab8500_address_fops); |
1625 | if (!file) | 3004 | if (!file) |
1626 | goto err; | 3005 | goto err; |
1627 | 3006 | ||
1628 | file = debugfs_create_file("register-value", (S_IRUGO | S_IWUSR), | 3007 | file = debugfs_create_file("register-value", (S_IRUGO | S_IWUSR | S_IWGRP), |
1629 | ab8500_dir, &plf->dev, &ab8500_val_fops); | 3008 | ab8500_dir, &plf->dev, &ab8500_val_fops); |
1630 | if (!file) | 3009 | if (!file) |
1631 | goto err; | 3010 | goto err; |
1632 | 3011 | ||
1633 | file = debugfs_create_file("irq-subscribe", (S_IRUGO | S_IWUSR), | 3012 | file = debugfs_create_file("irq-subscribe", (S_IRUGO | S_IWUSR | S_IWGRP), |
1634 | ab8500_dir, &plf->dev, &ab8500_subscribe_fops); | 3013 | ab8500_dir, &plf->dev, &ab8500_subscribe_fops); |
1635 | if (!file) | 3014 | if (!file) |
1636 | goto err; | 3015 | goto err; |
1637 | 3016 | ||
1638 | if (is_ab8500(ab8500)) | 3017 | if (is_ab8500(ab8500)) { |
3018 | debug_ranges = ab8500_debug_ranges; | ||
1639 | num_interrupt_lines = AB8500_NR_IRQS; | 3019 | num_interrupt_lines = AB8500_NR_IRQS; |
1640 | else if (is_ab8505(ab8500)) | 3020 | } else if (is_ab8505(ab8500)) { |
3021 | debug_ranges = ab8505_debug_ranges; | ||
1641 | num_interrupt_lines = AB8505_NR_IRQS; | 3022 | num_interrupt_lines = AB8505_NR_IRQS; |
1642 | else if (is_ab9540(ab8500)) | 3023 | } else if (is_ab9540(ab8500)) { |
3024 | debug_ranges = ab8505_debug_ranges; | ||
1643 | num_interrupt_lines = AB9540_NR_IRQS; | 3025 | num_interrupt_lines = AB9540_NR_IRQS; |
3026 | } else if (is_ab8540(ab8500)) { | ||
3027 | debug_ranges = ab8540_debug_ranges; | ||
3028 | num_interrupt_lines = AB8540_NR_IRQS; | ||
3029 | } | ||
1644 | 3030 | ||
1645 | file = debugfs_create_file("interrupts", (S_IRUGO), | 3031 | file = debugfs_create_file("interrupts", (S_IRUGO), |
1646 | ab8500_dir, &plf->dev, &ab8500_interrupts_fops); | 3032 | ab8500_dir, &plf->dev, &ab8500_interrupts_fops); |
1647 | if (!file) | 3033 | if (!file) |
1648 | goto err; | 3034 | goto err; |
1649 | 3035 | ||
1650 | file = debugfs_create_file("irq-unsubscribe", (S_IRUGO | S_IWUSR), | 3036 | file = debugfs_create_file("irq-unsubscribe", (S_IRUGO | S_IWUSR | S_IWGRP), |
1651 | ab8500_dir, &plf->dev, &ab8500_unsubscribe_fops); | 3037 | ab8500_dir, &plf->dev, &ab8500_unsubscribe_fops); |
1652 | if (!file) | 3038 | if (!file) |
1653 | goto err; | 3039 | goto err; |
1654 | 3040 | ||
1655 | file = debugfs_create_file("hwreg", (S_IRUGO | S_IWUSR), | 3041 | file = debugfs_create_file("hwreg", (S_IRUGO | S_IWUSR | S_IWGRP), |
1656 | ab8500_dir, &plf->dev, &ab8500_hwreg_fops); | 3042 | ab8500_dir, &plf->dev, &ab8500_hwreg_fops); |
1657 | if (!file) | 3043 | if (!file) |
1658 | goto err; | 3044 | goto err; |
1659 | 3045 | ||
1660 | file = debugfs_create_file("bat_ctrl", (S_IRUGO | S_IWUSR), | 3046 | file = debugfs_create_file("all-modem-registers", (S_IRUGO | S_IWUSR | S_IWGRP), |
1661 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_bat_ctrl_fops); | 3047 | ab8500_dir, &plf->dev, &ab8500_modem_fops); |
1662 | if (!file) | 3048 | if (!file) |
1663 | goto err; | 3049 | goto err; |
1664 | 3050 | ||
1665 | file = debugfs_create_file("btemp_ball", (S_IRUGO | S_IWUSR), | 3051 | file = debugfs_create_file("bat_ctrl", (S_IRUGO | S_IWUSR | S_IWGRP), |
1666 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_btemp_ball_fops); | 3052 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_bat_ctrl_fops); |
1667 | if (!file) | 3053 | if (!file) |
1668 | goto err; | 3054 | goto err; |
1669 | 3055 | ||
1670 | file = debugfs_create_file("main_charger_v", (S_IRUGO | S_IWUSR), | 3056 | file = debugfs_create_file("btemp_ball", (S_IRUGO | S_IWUSR | S_IWGRP), |
1671 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_charger_v_fops); | 3057 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_btemp_ball_fops); |
1672 | if (!file) | 3058 | if (!file) |
1673 | goto err; | 3059 | goto err; |
1674 | 3060 | ||
1675 | file = debugfs_create_file("acc_detect1", (S_IRUGO | S_IWUSR), | 3061 | file = debugfs_create_file("main_charger_v", (S_IRUGO | S_IWUSR | S_IWGRP), |
1676 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_acc_detect1_fops); | 3062 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_charger_v_fops); |
1677 | if (!file) | 3063 | if (!file) |
1678 | goto err; | 3064 | goto err; |
1679 | 3065 | ||
1680 | file = debugfs_create_file("acc_detect2", (S_IRUGO | S_IWUSR), | 3066 | file = debugfs_create_file("acc_detect1", (S_IRUGO | S_IWUSR | S_IWGRP), |
1681 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_acc_detect2_fops); | 3067 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_acc_detect1_fops); |
1682 | if (!file) | 3068 | if (!file) |
1683 | goto err; | 3069 | goto err; |
1684 | 3070 | ||
1685 | file = debugfs_create_file("adc_aux1", (S_IRUGO | S_IWUSR), | 3071 | file = debugfs_create_file("acc_detect2", (S_IRUGO | S_IWUSR | S_IWGRP), |
1686 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_aux1_fops); | 3072 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_acc_detect2_fops); |
1687 | if (!file) | 3073 | if (!file) |
1688 | goto err; | 3074 | goto err; |
1689 | 3075 | ||
1690 | file = debugfs_create_file("adc_aux2", (S_IRUGO | S_IWUSR), | 3076 | file = debugfs_create_file("adc_aux1", (S_IRUGO | S_IWUSR | S_IWGRP), |
1691 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_aux2_fops); | 3077 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_aux1_fops); |
1692 | if (!file) | 3078 | if (!file) |
1693 | goto err; | 3079 | goto err; |
1694 | 3080 | ||
1695 | file = debugfs_create_file("main_bat_v", (S_IRUGO | S_IWUSR), | 3081 | file = debugfs_create_file("adc_aux2", (S_IRUGO | S_IWUSR | S_IWGRP), |
1696 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_bat_v_fops); | 3082 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_aux2_fops); |
1697 | if (!file) | 3083 | if (!file) |
1698 | goto err; | 3084 | goto err; |
1699 | 3085 | ||
1700 | file = debugfs_create_file("vbus_v", (S_IRUGO | S_IWUSR), | 3086 | file = debugfs_create_file("main_bat_v", (S_IRUGO | S_IWUSR | S_IWGRP), |
1701 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_vbus_v_fops); | 3087 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_bat_v_fops); |
1702 | if (!file) | 3088 | if (!file) |
1703 | goto err; | 3089 | goto err; |
1704 | 3090 | ||
1705 | file = debugfs_create_file("main_charger_c", (S_IRUGO | S_IWUSR), | 3091 | file = debugfs_create_file("vbus_v", (S_IRUGO | S_IWUSR | S_IWGRP), |
1706 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_charger_c_fops); | 3092 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_vbus_v_fops); |
3093 | if (!file) | ||
3094 | goto err; | ||
3095 | |||
3096 | file = debugfs_create_file("main_charger_c", (S_IRUGO | S_IWUSR | S_IWGRP), | ||
3097 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_charger_c_fops); | ||
3098 | if (!file) | ||
3099 | goto err; | ||
3100 | |||
3101 | file = debugfs_create_file("usb_charger_c", (S_IRUGO | S_IWUSR | S_IWGRP), | ||
3102 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_usb_charger_c_fops); | ||
3103 | if (!file) | ||
3104 | goto err; | ||
3105 | |||
3106 | file = debugfs_create_file("bk_bat_v", (S_IRUGO | S_IWUSR | S_IWGRP), | ||
3107 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_bk_bat_v_fops); | ||
3108 | if (!file) | ||
3109 | goto err; | ||
3110 | |||
3111 | file = debugfs_create_file("die_temp", (S_IRUGO | S_IWUSR | S_IWGRP), | ||
3112 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_die_temp_fops); | ||
3113 | if (!file) | ||
3114 | goto err; | ||
3115 | |||
3116 | file = debugfs_create_file("usb_id", (S_IRUGO | S_IWUSR | S_IWGRP), | ||
3117 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_usb_id_fops); | ||
3118 | if (!file) | ||
3119 | goto err; | ||
3120 | |||
3121 | if (is_ab8540(ab8500)) { | ||
3122 | file = debugfs_create_file("xtal_temp", (S_IRUGO | S_IWUSR | S_IWGRP), | ||
3123 | ab8500_gpadc_dir, &plf->dev, &ab8540_gpadc_xtal_temp_fops); | ||
3124 | if (!file) | ||
3125 | goto err; | ||
3126 | file = debugfs_create_file("vbattruemeas", (S_IRUGO | S_IWUSR | S_IWGRP), | ||
3127 | ab8500_gpadc_dir, &plf->dev, | ||
3128 | &ab8540_gpadc_vbat_true_meas_fops); | ||
3129 | if (!file) | ||
3130 | goto err; | ||
3131 | file = debugfs_create_file("batctrl_and_ibat", | ||
3132 | (S_IRUGO | S_IWUGO), ab8500_gpadc_dir, | ||
3133 | &plf->dev, &ab8540_gpadc_bat_ctrl_and_ibat_fops); | ||
3134 | if (!file) | ||
3135 | goto err; | ||
3136 | file = debugfs_create_file("vbatmeas_and_ibat", | ||
3137 | (S_IRUGO | S_IWUGO), ab8500_gpadc_dir, | ||
3138 | &plf->dev, | ||
3139 | &ab8540_gpadc_vbat_meas_and_ibat_fops); | ||
3140 | if (!file) | ||
3141 | goto err; | ||
3142 | file = debugfs_create_file("vbattruemeas_and_ibat", | ||
3143 | (S_IRUGO | S_IWUGO), ab8500_gpadc_dir, | ||
3144 | &plf->dev, | ||
3145 | &ab8540_gpadc_vbat_true_meas_and_ibat_fops); | ||
3146 | if (!file) | ||
3147 | goto err; | ||
3148 | file = debugfs_create_file("battemp_and_ibat", | ||
3149 | (S_IRUGO | S_IWUGO), ab8500_gpadc_dir, | ||
3150 | &plf->dev, &ab8540_gpadc_bat_temp_and_ibat_fops); | ||
3151 | if (!file) | ||
3152 | goto err; | ||
3153 | file = debugfs_create_file("otp_calib", (S_IRUGO | S_IWUSR | S_IWGRP), | ||
3154 | ab8500_gpadc_dir, &plf->dev, &ab8540_gpadc_otp_calib_fops); | ||
3155 | if (!file) | ||
3156 | goto err; | ||
3157 | } | ||
3158 | file = debugfs_create_file("avg_sample", (S_IRUGO | S_IWUSR | S_IWGRP), | ||
3159 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_avg_sample_fops); | ||
1707 | if (!file) | 3160 | if (!file) |
1708 | goto err; | 3161 | goto err; |
1709 | 3162 | ||
1710 | file = debugfs_create_file("usb_charger_c", (S_IRUGO | S_IWUSR), | 3163 | file = debugfs_create_file("trig_edge", (S_IRUGO | S_IWUSR | S_IWGRP), |
1711 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_usb_charger_c_fops); | 3164 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_trig_edge_fops); |
1712 | if (!file) | 3165 | if (!file) |
1713 | goto err; | 3166 | goto err; |
1714 | 3167 | ||
1715 | file = debugfs_create_file("bk_bat_v", (S_IRUGO | S_IWUSR), | 3168 | file = debugfs_create_file("trig_timer", (S_IRUGO | S_IWUSR | S_IWGRP), |
1716 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_bk_bat_v_fops); | 3169 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_trig_timer_fops); |
1717 | if (!file) | 3170 | if (!file) |
1718 | goto err; | 3171 | goto err; |
1719 | 3172 | ||
1720 | file = debugfs_create_file("die_temp", (S_IRUGO | S_IWUSR), | 3173 | file = debugfs_create_file("conv_type", (S_IRUGO | S_IWUSR | S_IWGRP), |
1721 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_die_temp_fops); | 3174 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_conv_type_fops); |
1722 | if (!file) | 3175 | if (!file) |
1723 | goto err; | 3176 | goto err; |
1724 | 3177 | ||
diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c index 5f341a50ee5a..65f72284185d 100644 --- a/drivers/mfd/ab8500-gpadc.c +++ b/drivers/mfd/ab8500-gpadc.c | |||
@@ -37,6 +37,13 @@ | |||
37 | #define AB8500_GPADC_AUTODATAL_REG 0x07 | 37 | #define AB8500_GPADC_AUTODATAL_REG 0x07 |
38 | #define AB8500_GPADC_AUTODATAH_REG 0x08 | 38 | #define AB8500_GPADC_AUTODATAH_REG 0x08 |
39 | #define AB8500_GPADC_MUX_CTRL_REG 0x09 | 39 | #define AB8500_GPADC_MUX_CTRL_REG 0x09 |
40 | #define AB8540_GPADC_MANDATA2L_REG 0x09 | ||
41 | #define AB8540_GPADC_MANDATA2H_REG 0x0A | ||
42 | #define AB8540_GPADC_APEAAX_REG 0x10 | ||
43 | #define AB8540_GPADC_APEAAT_REG 0x11 | ||
44 | #define AB8540_GPADC_APEAAM_REG 0x12 | ||
45 | #define AB8540_GPADC_APEAAH_REG 0x13 | ||
46 | #define AB8540_GPADC_APEAAL_REG 0x14 | ||
40 | 47 | ||
41 | /* | 48 | /* |
42 | * OTP register offsets | 49 | * OTP register offsets |
@@ -49,19 +56,29 @@ | |||
49 | #define AB8500_GPADC_CAL_5 0x13 | 56 | #define AB8500_GPADC_CAL_5 0x13 |
50 | #define AB8500_GPADC_CAL_6 0x14 | 57 | #define AB8500_GPADC_CAL_6 0x14 |
51 | #define AB8500_GPADC_CAL_7 0x15 | 58 | #define AB8500_GPADC_CAL_7 0x15 |
59 | /* New calibration for 8540 */ | ||
60 | #define AB8540_GPADC_OTP4_REG_7 0x38 | ||
61 | #define AB8540_GPADC_OTP4_REG_6 0x39 | ||
62 | #define AB8540_GPADC_OTP4_REG_5 0x3A | ||
52 | 63 | ||
53 | /* gpadc constants */ | 64 | /* gpadc constants */ |
54 | #define EN_VINTCORE12 0x04 | 65 | #define EN_VINTCORE12 0x04 |
55 | #define EN_VTVOUT 0x02 | 66 | #define EN_VTVOUT 0x02 |
56 | #define EN_GPADC 0x01 | 67 | #define EN_GPADC 0x01 |
57 | #define DIS_GPADC 0x00 | 68 | #define DIS_GPADC 0x00 |
58 | #define SW_AVG_16 0x60 | 69 | #define AVG_1 0x00 |
70 | #define AVG_4 0x20 | ||
71 | #define AVG_8 0x40 | ||
72 | #define AVG_16 0x60 | ||
59 | #define ADC_SW_CONV 0x04 | 73 | #define ADC_SW_CONV 0x04 |
60 | #define EN_ICHAR 0x80 | 74 | #define EN_ICHAR 0x80 |
61 | #define BTEMP_PULL_UP 0x08 | 75 | #define BTEMP_PULL_UP 0x08 |
62 | #define EN_BUF 0x40 | 76 | #define EN_BUF 0x40 |
63 | #define DIS_ZERO 0x00 | 77 | #define DIS_ZERO 0x00 |
64 | #define GPADC_BUSY 0x01 | 78 | #define GPADC_BUSY 0x01 |
79 | #define EN_FALLING 0x10 | ||
80 | #define EN_TRIG_EDGE 0x02 | ||
81 | #define EN_VBIAS_XTAL_TEMP 0x02 | ||
65 | 82 | ||
66 | /* GPADC constants from AB8500 spec, UM0836 */ | 83 | /* GPADC constants from AB8500 spec, UM0836 */ |
67 | #define ADC_RESOLUTION 1024 | 84 | #define ADC_RESOLUTION 1024 |
@@ -80,8 +97,21 @@ | |||
80 | #define ADC_CH_BKBAT_MIN 0 | 97 | #define ADC_CH_BKBAT_MIN 0 |
81 | #define ADC_CH_BKBAT_MAX 3200 | 98 | #define ADC_CH_BKBAT_MAX 3200 |
82 | 99 | ||
100 | /* GPADC constants from AB8540 spec */ | ||
101 | #define ADC_CH_IBAT_MIN (-6000) /* mA range measured by ADC for ibat*/ | ||
102 | #define ADC_CH_IBAT_MAX 6000 | ||
103 | #define ADC_CH_IBAT_MIN_V (-60) /* mV range measured by ADC for ibat*/ | ||
104 | #define ADC_CH_IBAT_MAX_V 60 | ||
105 | #define IBAT_VDROP_L (-56) /* mV */ | ||
106 | #define IBAT_VDROP_H 56 | ||
107 | |||
83 | /* This is used to not lose precision when dividing to get gain and offset */ | 108 | /* This is used to not lose precision when dividing to get gain and offset */ |
84 | #define CALIB_SCALE 1000 | 109 | #define CALIB_SCALE 1000 |
110 | /* | ||
111 | * Number of bits shift used to not lose precision | ||
112 | * when dividing to get ibat gain. | ||
113 | */ | ||
114 | #define CALIB_SHIFT_IBAT 20 | ||
85 | 115 | ||
86 | /* Time in ms before disabling regulator */ | 116 | /* Time in ms before disabling regulator */ |
87 | #define GPADC_AUDOSUSPEND_DELAY 1 | 117 | #define GPADC_AUDOSUSPEND_DELAY 1 |
@@ -92,6 +122,7 @@ enum cal_channels { | |||
92 | ADC_INPUT_VMAIN = 0, | 122 | ADC_INPUT_VMAIN = 0, |
93 | ADC_INPUT_BTEMP, | 123 | ADC_INPUT_BTEMP, |
94 | ADC_INPUT_VBAT, | 124 | ADC_INPUT_VBAT, |
125 | ADC_INPUT_IBAT, | ||
95 | NBR_CAL_INPUTS, | 126 | NBR_CAL_INPUTS, |
96 | }; | 127 | }; |
97 | 128 | ||
@@ -102,8 +133,10 @@ enum cal_channels { | |||
102 | * @offset: Offset of the ADC channel | 133 | * @offset: Offset of the ADC channel |
103 | */ | 134 | */ |
104 | struct adc_cal_data { | 135 | struct adc_cal_data { |
105 | u64 gain; | 136 | s64 gain; |
106 | u64 offset; | 137 | s64 offset; |
138 | u16 otp_calib_hi; | ||
139 | u16 otp_calib_lo; | ||
107 | }; | 140 | }; |
108 | 141 | ||
109 | /** | 142 | /** |
@@ -116,7 +149,10 @@ struct adc_cal_data { | |||
116 | * the completion of gpadc conversion | 149 | * the completion of gpadc conversion |
117 | * @ab8500_gpadc_lock: structure of type mutex | 150 | * @ab8500_gpadc_lock: structure of type mutex |
118 | * @regu: pointer to the struct regulator | 151 | * @regu: pointer to the struct regulator |
119 | * @irq: interrupt number that is used by gpadc | 152 | * @irq_sw: interrupt number that is used by gpadc for Sw |
153 | * conversion | ||
154 | * @irq_hw: interrupt number that is used by gpadc for Hw | ||
155 | * conversion | ||
120 | * @cal_data array of ADC calibration data structs | 156 | * @cal_data array of ADC calibration data structs |
121 | */ | 157 | */ |
122 | struct ab8500_gpadc { | 158 | struct ab8500_gpadc { |
@@ -126,7 +162,8 @@ struct ab8500_gpadc { | |||
126 | struct completion ab8500_gpadc_complete; | 162 | struct completion ab8500_gpadc_complete; |
127 | struct mutex ab8500_gpadc_lock; | 163 | struct mutex ab8500_gpadc_lock; |
128 | struct regulator *regu; | 164 | struct regulator *regu; |
129 | int irq; | 165 | int irq_sw; |
166 | int irq_hw; | ||
130 | struct adc_cal_data cal_data[NBR_CAL_INPUTS]; | 167 | struct adc_cal_data cal_data[NBR_CAL_INPUTS]; |
131 | }; | 168 | }; |
132 | 169 | ||
@@ -171,6 +208,7 @@ int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc, u8 channel, | |||
171 | gpadc->cal_data[ADC_INPUT_VMAIN].offset) / CALIB_SCALE; | 208 | gpadc->cal_data[ADC_INPUT_VMAIN].offset) / CALIB_SCALE; |
172 | break; | 209 | break; |
173 | 210 | ||
211 | case XTAL_TEMP: | ||
174 | case BAT_CTRL: | 212 | case BAT_CTRL: |
175 | case BTEMP_BALL: | 213 | case BTEMP_BALL: |
176 | case ACC_DETECT1: | 214 | case ACC_DETECT1: |
@@ -189,6 +227,7 @@ int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc, u8 channel, | |||
189 | break; | 227 | break; |
190 | 228 | ||
191 | case MAIN_BAT_V: | 229 | case MAIN_BAT_V: |
230 | case VBAT_TRUE_MEAS: | ||
192 | /* For some reason we don't have calibrated data */ | 231 | /* For some reason we don't have calibrated data */ |
193 | if (!gpadc->cal_data[ADC_INPUT_VBAT].gain) { | 232 | if (!gpadc->cal_data[ADC_INPUT_VBAT].gain) { |
194 | res = ADC_CH_VBAT_MIN + (ADC_CH_VBAT_MAX - | 233 | res = ADC_CH_VBAT_MIN + (ADC_CH_VBAT_MAX - |
@@ -232,6 +271,20 @@ int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc, u8 channel, | |||
232 | ADC_RESOLUTION; | 271 | ADC_RESOLUTION; |
233 | break; | 272 | break; |
234 | 273 | ||
274 | case IBAT_VIRTUAL_CHANNEL: | ||
275 | /* For some reason we don't have calibrated data */ | ||
276 | if (!gpadc->cal_data[ADC_INPUT_IBAT].gain) { | ||
277 | res = ADC_CH_IBAT_MIN + (ADC_CH_IBAT_MAX - | ||
278 | ADC_CH_IBAT_MIN) * ad_value / | ||
279 | ADC_RESOLUTION; | ||
280 | break; | ||
281 | } | ||
282 | /* Here we can use the calibrated data */ | ||
283 | res = (int) (ad_value * gpadc->cal_data[ADC_INPUT_IBAT].gain + | ||
284 | gpadc->cal_data[ADC_INPUT_IBAT].offset) | ||
285 | >> CALIB_SHIFT_IBAT; | ||
286 | break; | ||
287 | |||
235 | default: | 288 | default: |
236 | dev_err(gpadc->dev, | 289 | dev_err(gpadc->dev, |
237 | "unknown channel, not possible to convert\n"); | 290 | "unknown channel, not possible to convert\n"); |
@@ -244,25 +297,35 @@ int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc, u8 channel, | |||
244 | EXPORT_SYMBOL(ab8500_gpadc_ad_to_voltage); | 297 | EXPORT_SYMBOL(ab8500_gpadc_ad_to_voltage); |
245 | 298 | ||
246 | /** | 299 | /** |
247 | * ab8500_gpadc_convert() - gpadc conversion | 300 | * ab8500_gpadc_sw_hw_convert() - gpadc conversion |
248 | * @channel: analog channel to be converted to digital data | 301 | * @channel: analog channel to be converted to digital data |
302 | * @avg_sample: number of ADC sample to average | ||
303 | * @trig_egde: selected ADC trig edge | ||
304 | * @trig_timer: selected ADC trigger delay timer | ||
305 | * @conv_type: selected conversion type (HW or SW conversion) | ||
249 | * | 306 | * |
250 | * This function converts the selected analog i/p to digital | 307 | * This function converts the selected analog i/p to digital |
251 | * data. | 308 | * data. |
252 | */ | 309 | */ |
253 | int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 channel) | 310 | int ab8500_gpadc_sw_hw_convert(struct ab8500_gpadc *gpadc, u8 channel, |
311 | u8 avg_sample, u8 trig_edge, u8 trig_timer, u8 conv_type) | ||
254 | { | 312 | { |
255 | int ad_value; | 313 | int ad_value; |
256 | int voltage; | 314 | int voltage; |
257 | 315 | ||
258 | ad_value = ab8500_gpadc_read_raw(gpadc, channel); | 316 | ad_value = ab8500_gpadc_read_raw(gpadc, channel, avg_sample, |
259 | if (ad_value < 0) { | 317 | trig_edge, trig_timer, conv_type); |
260 | dev_err(gpadc->dev, "GPADC raw value failed ch: %d\n", channel); | 318 | /* On failure retry a second time */ |
319 | if (ad_value < 0) | ||
320 | ad_value = ab8500_gpadc_read_raw(gpadc, channel, avg_sample, | ||
321 | trig_edge, trig_timer, conv_type); | ||
322 | if (ad_value < 0) { | ||
323 | dev_err(gpadc->dev, "GPADC raw value failed ch: %d\n", | ||
324 | channel); | ||
261 | return ad_value; | 325 | return ad_value; |
262 | } | 326 | } |
263 | 327 | ||
264 | voltage = ab8500_gpadc_ad_to_voltage(gpadc, channel, ad_value); | 328 | voltage = ab8500_gpadc_ad_to_voltage(gpadc, channel, ad_value); |
265 | |||
266 | if (voltage < 0) | 329 | if (voltage < 0) |
267 | dev_err(gpadc->dev, "GPADC to voltage conversion failed ch:" | 330 | dev_err(gpadc->dev, "GPADC to voltage conversion failed ch:" |
268 | " %d AD: 0x%x\n", channel, ad_value); | 331 | " %d AD: 0x%x\n", channel, ad_value); |
@@ -274,21 +337,46 @@ EXPORT_SYMBOL(ab8500_gpadc_convert); | |||
274 | /** | 337 | /** |
275 | * ab8500_gpadc_read_raw() - gpadc read | 338 | * ab8500_gpadc_read_raw() - gpadc read |
276 | * @channel: analog channel to be read | 339 | * @channel: analog channel to be read |
340 | * @avg_sample: number of ADC sample to average | ||
341 | * @trig_edge: selected trig edge | ||
342 | * @trig_timer: selected ADC trigger delay timer | ||
343 | * @conv_type: selected conversion type (HW or SW conversion) | ||
277 | * | 344 | * |
278 | * This function obtains the raw ADC value, this then needs | 345 | * This function obtains the raw ADC value for an hardware conversion, |
279 | * to be converted by calling ab8500_gpadc_ad_to_voltage() | 346 | * this then needs to be converted by calling ab8500_gpadc_ad_to_voltage() |
280 | */ | 347 | */ |
281 | int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel) | 348 | int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel, |
349 | u8 avg_sample, u8 trig_edge, u8 trig_timer, u8 conv_type) | ||
350 | { | ||
351 | int raw_data; | ||
352 | raw_data = ab8500_gpadc_double_read_raw(gpadc, channel, | ||
353 | avg_sample, trig_edge, trig_timer, conv_type, NULL); | ||
354 | return raw_data; | ||
355 | } | ||
356 | |||
357 | int ab8500_gpadc_double_read_raw(struct ab8500_gpadc *gpadc, u8 channel, | ||
358 | u8 avg_sample, u8 trig_edge, u8 trig_timer, u8 conv_type, | ||
359 | int *ibat) | ||
282 | { | 360 | { |
283 | int ret; | 361 | int ret; |
284 | int looplimit = 0; | 362 | int looplimit = 0; |
285 | u8 val, low_data, high_data; | 363 | unsigned long completion_timeout; |
364 | u8 val, low_data, high_data, low_data2, high_data2; | ||
365 | u8 val_reg1 = 0; | ||
366 | unsigned int delay_min = 0; | ||
367 | unsigned int delay_max = 0; | ||
368 | u8 data_low_addr, data_high_addr; | ||
286 | 369 | ||
287 | if (!gpadc) | 370 | if (!gpadc) |
288 | return -ENODEV; | 371 | return -ENODEV; |
289 | 372 | ||
290 | mutex_lock(&gpadc->ab8500_gpadc_lock); | 373 | /* check if convertion is supported */ |
374 | if ((gpadc->irq_sw < 0) && (conv_type == ADC_SW)) | ||
375 | return -ENOTSUPP; | ||
376 | if ((gpadc->irq_hw < 0) && (conv_type == ADC_HW)) | ||
377 | return -ENOTSUPP; | ||
291 | 378 | ||
379 | mutex_lock(&gpadc->ab8500_gpadc_lock); | ||
292 | /* Enable VTVout LDO this is required for GPADC */ | 380 | /* Enable VTVout LDO this is required for GPADC */ |
293 | pm_runtime_get_sync(gpadc->dev); | 381 | pm_runtime_get_sync(gpadc->dev); |
294 | 382 | ||
@@ -309,16 +397,34 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel) | |||
309 | } | 397 | } |
310 | 398 | ||
311 | /* Enable GPADC */ | 399 | /* Enable GPADC */ |
312 | ret = abx500_mask_and_set_register_interruptible(gpadc->dev, | 400 | val_reg1 |= EN_GPADC; |
313 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, EN_GPADC, EN_GPADC); | 401 | |
314 | if (ret < 0) { | 402 | /* Select the channel source and set average samples */ |
315 | dev_err(gpadc->dev, "gpadc_conversion: enable gpadc failed\n"); | 403 | switch (avg_sample) { |
316 | goto out; | 404 | case SAMPLE_1: |
405 | val = channel | AVG_1; | ||
406 | break; | ||
407 | case SAMPLE_4: | ||
408 | val = channel | AVG_4; | ||
409 | break; | ||
410 | case SAMPLE_8: | ||
411 | val = channel | AVG_8; | ||
412 | break; | ||
413 | default: | ||
414 | val = channel | AVG_16; | ||
415 | break; | ||
317 | } | 416 | } |
318 | 417 | ||
319 | /* Select the channel source and set average samples to 16 */ | 418 | if (conv_type == ADC_HW) { |
320 | ret = abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC, | 419 | ret = abx500_set_register_interruptible(gpadc->dev, |
321 | AB8500_GPADC_CTRL2_REG, (channel | SW_AVG_16)); | 420 | AB8500_GPADC, AB8500_GPADC_CTRL3_REG, val); |
421 | val_reg1 |= EN_TRIG_EDGE; | ||
422 | if (trig_edge) | ||
423 | val_reg1 |= EN_FALLING; | ||
424 | } | ||
425 | else | ||
426 | ret = abx500_set_register_interruptible(gpadc->dev, | ||
427 | AB8500_GPADC, AB8500_GPADC_CTRL2_REG, val); | ||
322 | if (ret < 0) { | 428 | if (ret < 0) { |
323 | dev_err(gpadc->dev, | 429 | dev_err(gpadc->dev, |
324 | "gpadc_conversion: set avg samples failed\n"); | 430 | "gpadc_conversion: set avg samples failed\n"); |
@@ -333,71 +439,129 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel) | |||
333 | switch (channel) { | 439 | switch (channel) { |
334 | case MAIN_CHARGER_C: | 440 | case MAIN_CHARGER_C: |
335 | case USB_CHARGER_C: | 441 | case USB_CHARGER_C: |
336 | ret = abx500_mask_and_set_register_interruptible(gpadc->dev, | 442 | val_reg1 |= EN_BUF | EN_ICHAR; |
337 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, | ||
338 | EN_BUF | EN_ICHAR, | ||
339 | EN_BUF | EN_ICHAR); | ||
340 | break; | 443 | break; |
341 | case BTEMP_BALL: | 444 | case BTEMP_BALL: |
342 | if (!is_ab8500_2p0_or_earlier(gpadc->parent)) { | 445 | if (!is_ab8500_2p0_or_earlier(gpadc->parent)) { |
343 | /* Turn on btemp pull-up on ABB 3.0 */ | 446 | val_reg1 |= EN_BUF | BTEMP_PULL_UP; |
344 | ret = abx500_mask_and_set_register_interruptible( | 447 | /* |
345 | gpadc->dev, | 448 | * Delay might be needed for ABB8500 cut 3.0, if not, |
346 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, | 449 | * remove when hardware will be availible |
347 | EN_BUF | BTEMP_PULL_UP, | 450 | */ |
348 | EN_BUF | BTEMP_PULL_UP); | 451 | delay_min = 1000; /* Delay in micro seconds */ |
349 | 452 | delay_max = 10000; /* large range to optimise sleep mode */ | |
350 | /* | ||
351 | * Delay might be needed for ABB8500 cut 3.0, if not, remove | ||
352 | * when hardware will be available | ||
353 | */ | ||
354 | usleep_range(1000, 1000); | ||
355 | break; | 453 | break; |
356 | } | 454 | } |
357 | /* Intentional fallthrough */ | 455 | /* Intentional fallthrough */ |
358 | default: | 456 | default: |
359 | ret = abx500_mask_and_set_register_interruptible(gpadc->dev, | 457 | val_reg1 |= EN_BUF; |
360 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, EN_BUF, EN_BUF); | ||
361 | break; | 458 | break; |
362 | } | 459 | } |
460 | |||
461 | /* Write configuration to register */ | ||
462 | ret = abx500_set_register_interruptible(gpadc->dev, | ||
463 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, val_reg1); | ||
363 | if (ret < 0) { | 464 | if (ret < 0) { |
364 | dev_err(gpadc->dev, | 465 | dev_err(gpadc->dev, |
365 | "gpadc_conversion: select falling edge failed\n"); | 466 | "gpadc_conversion: set Control register failed\n"); |
366 | goto out; | 467 | goto out; |
367 | } | 468 | } |
368 | 469 | ||
369 | ret = abx500_mask_and_set_register_interruptible(gpadc->dev, | 470 | if (delay_min != 0) |
370 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, ADC_SW_CONV, ADC_SW_CONV); | 471 | usleep_range(delay_min, delay_max); |
371 | if (ret < 0) { | 472 | |
372 | dev_err(gpadc->dev, | 473 | if (conv_type == ADC_HW) { |
373 | "gpadc_conversion: start s/w conversion failed\n"); | 474 | /* Set trigger delay timer */ |
374 | goto out; | 475 | ret = abx500_set_register_interruptible(gpadc->dev, |
476 | AB8500_GPADC, AB8500_GPADC_AUTO_TIMER_REG, trig_timer); | ||
477 | if (ret < 0) { | ||
478 | dev_err(gpadc->dev, | ||
479 | "gpadc_conversion: trig timer failed\n"); | ||
480 | goto out; | ||
481 | } | ||
482 | completion_timeout = 2 * HZ; | ||
483 | data_low_addr = AB8500_GPADC_AUTODATAL_REG; | ||
484 | data_high_addr = AB8500_GPADC_AUTODATAH_REG; | ||
485 | } else { | ||
486 | /* Start SW conversion */ | ||
487 | ret = abx500_mask_and_set_register_interruptible(gpadc->dev, | ||
488 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, | ||
489 | ADC_SW_CONV, ADC_SW_CONV); | ||
490 | if (ret < 0) { | ||
491 | dev_err(gpadc->dev, | ||
492 | "gpadc_conversion: start s/w conv failed\n"); | ||
493 | goto out; | ||
494 | } | ||
495 | completion_timeout = msecs_to_jiffies(CONVERSION_TIME); | ||
496 | data_low_addr = AB8500_GPADC_MANDATAL_REG; | ||
497 | data_high_addr = AB8500_GPADC_MANDATAH_REG; | ||
375 | } | 498 | } |
499 | |||
376 | /* wait for completion of conversion */ | 500 | /* wait for completion of conversion */ |
377 | if (!wait_for_completion_timeout(&gpadc->ab8500_gpadc_complete, | 501 | if (!wait_for_completion_timeout(&gpadc->ab8500_gpadc_complete, |
378 | msecs_to_jiffies(CONVERSION_TIME))) { | 502 | completion_timeout)) { |
379 | dev_err(gpadc->dev, | 503 | dev_err(gpadc->dev, |
380 | "timeout: didn't receive GPADC conversion interrupt\n"); | 504 | "timeout didn't receive GPADC conv interrupt\n"); |
381 | ret = -EINVAL; | 505 | ret = -EINVAL; |
382 | goto out; | 506 | goto out; |
383 | } | 507 | } |
384 | 508 | ||
385 | /* Read the converted RAW data */ | 509 | /* Read the converted RAW data */ |
386 | ret = abx500_get_register_interruptible(gpadc->dev, AB8500_GPADC, | 510 | ret = abx500_get_register_interruptible(gpadc->dev, |
387 | AB8500_GPADC_MANDATAL_REG, &low_data); | 511 | AB8500_GPADC, data_low_addr, &low_data); |
388 | if (ret < 0) { | 512 | if (ret < 0) { |
389 | dev_err(gpadc->dev, "gpadc_conversion: read low data failed\n"); | 513 | dev_err(gpadc->dev, "gpadc_conversion: read low data failed\n"); |
390 | goto out; | 514 | goto out; |
391 | } | 515 | } |
392 | 516 | ||
393 | ret = abx500_get_register_interruptible(gpadc->dev, AB8500_GPADC, | 517 | ret = abx500_get_register_interruptible(gpadc->dev, |
394 | AB8500_GPADC_MANDATAH_REG, &high_data); | 518 | AB8500_GPADC, data_high_addr, &high_data); |
395 | if (ret < 0) { | 519 | if (ret < 0) { |
396 | dev_err(gpadc->dev, | 520 | dev_err(gpadc->dev, "gpadc_conversion: read high data failed\n"); |
397 | "gpadc_conversion: read high data failed\n"); | ||
398 | goto out; | 521 | goto out; |
399 | } | 522 | } |
400 | 523 | ||
524 | /* Check if double convertion is required */ | ||
525 | if ((channel == BAT_CTRL_AND_IBAT) || | ||
526 | (channel == VBAT_MEAS_AND_IBAT) || | ||
527 | (channel == VBAT_TRUE_MEAS_AND_IBAT) || | ||
528 | (channel == BAT_TEMP_AND_IBAT)) { | ||
529 | |||
530 | if (conv_type == ADC_HW) { | ||
531 | /* not supported */ | ||
532 | ret = -ENOTSUPP; | ||
533 | dev_err(gpadc->dev, | ||
534 | "gpadc_conversion: only SW double conversion supported\n"); | ||
535 | goto out; | ||
536 | } else { | ||
537 | /* Read the converted RAW data 2 */ | ||
538 | ret = abx500_get_register_interruptible(gpadc->dev, | ||
539 | AB8500_GPADC, AB8540_GPADC_MANDATA2L_REG, | ||
540 | &low_data2); | ||
541 | if (ret < 0) { | ||
542 | dev_err(gpadc->dev, | ||
543 | "gpadc_conversion: read sw low data 2 failed\n"); | ||
544 | goto out; | ||
545 | } | ||
546 | |||
547 | ret = abx500_get_register_interruptible(gpadc->dev, | ||
548 | AB8500_GPADC, AB8540_GPADC_MANDATA2H_REG, | ||
549 | &high_data2); | ||
550 | if (ret < 0) { | ||
551 | dev_err(gpadc->dev, | ||
552 | "gpadc_conversion: read sw high data 2 failed\n"); | ||
553 | goto out; | ||
554 | } | ||
555 | if (ibat != NULL) { | ||
556 | *ibat = (high_data2 << 8) | low_data2; | ||
557 | } else { | ||
558 | dev_warn(gpadc->dev, | ||
559 | "gpadc_conversion: ibat not stored\n"); | ||
560 | } | ||
561 | |||
562 | } | ||
563 | } | ||
564 | |||
401 | /* Disable GPADC */ | 565 | /* Disable GPADC */ |
402 | ret = abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC, | 566 | ret = abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC, |
403 | AB8500_GPADC_CTRL1_REG, DIS_GPADC); | 567 | AB8500_GPADC_CTRL1_REG, DIS_GPADC); |
@@ -406,6 +570,7 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel) | |||
406 | goto out; | 570 | goto out; |
407 | } | 571 | } |
408 | 572 | ||
573 | /* Disable VTVout LDO this is required for GPADC */ | ||
409 | pm_runtime_mark_last_busy(gpadc->dev); | 574 | pm_runtime_mark_last_busy(gpadc->dev); |
410 | pm_runtime_put_autosuspend(gpadc->dev); | 575 | pm_runtime_put_autosuspend(gpadc->dev); |
411 | 576 | ||
@@ -422,9 +587,7 @@ out: | |||
422 | */ | 587 | */ |
423 | (void) abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC, | 588 | (void) abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC, |
424 | AB8500_GPADC_CTRL1_REG, DIS_GPADC); | 589 | AB8500_GPADC_CTRL1_REG, DIS_GPADC); |
425 | |||
426 | pm_runtime_put(gpadc->dev); | 590 | pm_runtime_put(gpadc->dev); |
427 | |||
428 | mutex_unlock(&gpadc->ab8500_gpadc_lock); | 591 | mutex_unlock(&gpadc->ab8500_gpadc_lock); |
429 | dev_err(gpadc->dev, | 592 | dev_err(gpadc->dev, |
430 | "gpadc_conversion: Failed to AD convert channel %d\n", channel); | 593 | "gpadc_conversion: Failed to AD convert channel %d\n", channel); |
@@ -433,16 +596,16 @@ out: | |||
433 | EXPORT_SYMBOL(ab8500_gpadc_read_raw); | 596 | EXPORT_SYMBOL(ab8500_gpadc_read_raw); |
434 | 597 | ||
435 | /** | 598 | /** |
436 | * ab8500_bm_gpswadcconvend_handler() - isr for s/w gpadc conversion completion | 599 | * ab8500_bm_gpadcconvend_handler() - isr for gpadc conversion completion |
437 | * @irq: irq number | 600 | * @irq: irq number |
438 | * @data: pointer to the data passed during request irq | 601 | * @data: pointer to the data passed during request irq |
439 | * | 602 | * |
440 | * This is a interrupt service routine for s/w gpadc conversion completion. | 603 | * This is a interrupt service routine for gpadc conversion completion. |
441 | * Notifies the gpadc completion is completed and the converted raw value | 604 | * Notifies the gpadc completion is completed and the converted raw value |
442 | * can be read from the registers. | 605 | * can be read from the registers. |
443 | * Returns IRQ status(IRQ_HANDLED) | 606 | * Returns IRQ status(IRQ_HANDLED) |
444 | */ | 607 | */ |
445 | static irqreturn_t ab8500_bm_gpswadcconvend_handler(int irq, void *_gpadc) | 608 | static irqreturn_t ab8500_bm_gpadcconvend_handler(int irq, void *_gpadc) |
446 | { | 609 | { |
447 | struct ab8500_gpadc *gpadc = _gpadc; | 610 | struct ab8500_gpadc *gpadc = _gpadc; |
448 | 611 | ||
@@ -461,15 +624,27 @@ static int otp_cal_regs[] = { | |||
461 | AB8500_GPADC_CAL_7, | 624 | AB8500_GPADC_CAL_7, |
462 | }; | 625 | }; |
463 | 626 | ||
627 | static int otp4_cal_regs[] = { | ||
628 | AB8540_GPADC_OTP4_REG_7, | ||
629 | AB8540_GPADC_OTP4_REG_6, | ||
630 | AB8540_GPADC_OTP4_REG_5, | ||
631 | }; | ||
632 | |||
464 | static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc) | 633 | static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc) |
465 | { | 634 | { |
466 | int i; | 635 | int i; |
467 | int ret[ARRAY_SIZE(otp_cal_regs)]; | 636 | int ret[ARRAY_SIZE(otp_cal_regs)]; |
468 | u8 gpadc_cal[ARRAY_SIZE(otp_cal_regs)]; | 637 | u8 gpadc_cal[ARRAY_SIZE(otp_cal_regs)]; |
469 | 638 | int ret_otp4[ARRAY_SIZE(otp4_cal_regs)]; | |
639 | u8 gpadc_otp4[ARRAY_SIZE(otp4_cal_regs)]; | ||
470 | int vmain_high, vmain_low; | 640 | int vmain_high, vmain_low; |
471 | int btemp_high, btemp_low; | 641 | int btemp_high, btemp_low; |
472 | int vbat_high, vbat_low; | 642 | int vbat_high, vbat_low; |
643 | int ibat_high, ibat_low; | ||
644 | s64 V_gain, V_offset, V2A_gain, V2A_offset; | ||
645 | struct ab8500 *ab8500; | ||
646 | |||
647 | ab8500 = gpadc->parent; | ||
473 | 648 | ||
474 | /* First we read all OTP registers and store the error code */ | 649 | /* First we read all OTP registers and store the error code */ |
475 | for (i = 0; i < ARRAY_SIZE(otp_cal_regs); i++) { | 650 | for (i = 0; i < ARRAY_SIZE(otp_cal_regs); i++) { |
@@ -489,7 +664,7 @@ static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc) | |||
489 | * bt_h/l = btemp_high/low | 664 | * bt_h/l = btemp_high/low |
490 | * vb_h/l = vbat_high/low | 665 | * vb_h/l = vbat_high/low |
491 | * | 666 | * |
492 | * Data bits: | 667 | * Data bits 8500/9540: |
493 | * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 668 | * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
494 | * |.......|.......|.......|.......|.......|.......|.......|....... | 669 | * |.......|.......|.......|.......|.......|.......|.......|....... |
495 | * | | vm_h9 | vm_h8 | 670 | * | | vm_h9 | vm_h8 |
@@ -507,6 +682,35 @@ static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc) | |||
507 | * | vb_l5 | vb_l4 | vb_l3 | vb_l2 | vb_l1 | vb_l0 | | 682 | * | vb_l5 | vb_l4 | vb_l3 | vb_l2 | vb_l1 | vb_l0 | |
508 | * |.......|.......|.......|.......|.......|.......|.......|....... | 683 | * |.......|.......|.......|.......|.......|.......|.......|....... |
509 | * | 684 | * |
685 | * Data bits 8540: | ||
686 | * OTP2 | ||
687 | * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | ||
688 | * |.......|.......|.......|.......|.......|.......|.......|....... | ||
689 | * | | ||
690 | * |.......|.......|.......|.......|.......|.......|.......|....... | ||
691 | * | vm_h9 | vm_h8 | vm_h7 | vm_h6 | vm_h5 | vm_h4 | vm_h3 | vm_h2 | ||
692 | * |.......|.......|.......|.......|.......|.......|.......|....... | ||
693 | * | vm_h1 | vm_h0 | vm_l4 | vm_l3 | vm_l2 | vm_l1 | vm_l0 | bt_h9 | ||
694 | * |.......|.......|.......|.......|.......|.......|.......|....... | ||
695 | * | bt_h8 | bt_h7 | bt_h6 | bt_h5 | bt_h4 | bt_h3 | bt_h2 | bt_h1 | ||
696 | * |.......|.......|.......|.......|.......|.......|.......|....... | ||
697 | * | bt_h0 | bt_l4 | bt_l3 | bt_l2 | bt_l1 | bt_l0 | vb_h9 | vb_h8 | ||
698 | * |.......|.......|.......|.......|.......|.......|.......|....... | ||
699 | * | vb_h7 | vb_h6 | vb_h5 | vb_h4 | vb_h3 | vb_h2 | vb_h1 | vb_h0 | ||
700 | * |.......|.......|.......|.......|.......|.......|.......|....... | ||
701 | * | vb_l5 | vb_l4 | vb_l3 | vb_l2 | vb_l1 | vb_l0 | | ||
702 | * |.......|.......|.......|.......|.......|.......|.......|....... | ||
703 | * | ||
704 | * Data bits 8540: | ||
705 | * OTP4 | ||
706 | * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | ||
707 | * |.......|.......|.......|.......|.......|.......|.......|....... | ||
708 | * | | ib_h9 | ib_h8 | ib_h7 | ||
709 | * |.......|.......|.......|.......|.......|.......|.......|....... | ||
710 | * | ib_h6 | ib_h5 | ib_h4 | ib_h3 | ib_h2 | ib_h1 | ib_h0 | ib_l5 | ||
711 | * |.......|.......|.......|.......|.......|.......|.......|....... | ||
712 | * | ib_l4 | ib_l3 | ib_l2 | ib_l1 | ib_l0 | | ||
713 | * | ||
510 | * | 714 | * |
511 | * Ideal output ADC codes corresponding to injected input voltages | 715 | * Ideal output ADC codes corresponding to injected input voltages |
512 | * during manufacturing is: | 716 | * during manufacturing is: |
@@ -519,38 +723,116 @@ static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc) | |||
519 | * vbat_low: Vin = 2380mV / ADC ideal code = 33 | 723 | * vbat_low: Vin = 2380mV / ADC ideal code = 33 |
520 | */ | 724 | */ |
521 | 725 | ||
522 | /* Calculate gain and offset for VMAIN if all reads succeeded */ | 726 | if (is_ab8540(ab8500)) { |
523 | if (!(ret[0] < 0 || ret[1] < 0 || ret[2] < 0)) { | 727 | /* Calculate gain and offset for VMAIN if all reads succeeded*/ |
524 | vmain_high = (((gpadc_cal[0] & 0x03) << 8) | | 728 | if (!(ret[1] < 0 || ret[2] < 0)) { |
525 | ((gpadc_cal[1] & 0x3F) << 2) | | 729 | vmain_high = (((gpadc_cal[1] & 0xFF) << 2) | |
526 | ((gpadc_cal[2] & 0xC0) >> 6)); | 730 | ((gpadc_cal[2] & 0xC0) >> 6)); |
731 | vmain_low = ((gpadc_cal[2] & 0x3E) >> 1); | ||
732 | |||
733 | gpadc->cal_data[ADC_INPUT_VMAIN].otp_calib_hi = | ||
734 | (u16)vmain_high; | ||
735 | gpadc->cal_data[ADC_INPUT_VMAIN].otp_calib_lo = | ||
736 | (u16)vmain_low; | ||
737 | |||
738 | gpadc->cal_data[ADC_INPUT_VMAIN].gain = CALIB_SCALE * | ||
739 | (19500 - 315) / (vmain_high - vmain_low); | ||
740 | gpadc->cal_data[ADC_INPUT_VMAIN].offset = CALIB_SCALE * | ||
741 | 19500 - (CALIB_SCALE * (19500 - 315) / | ||
742 | (vmain_high - vmain_low)) * vmain_high; | ||
743 | } else { | ||
744 | gpadc->cal_data[ADC_INPUT_VMAIN].gain = 0; | ||
745 | } | ||
527 | 746 | ||
528 | vmain_low = ((gpadc_cal[2] & 0x3E) >> 1); | 747 | /* Read IBAT calibration Data */ |
748 | for (i = 0; i < ARRAY_SIZE(otp4_cal_regs); i++) { | ||
749 | ret_otp4[i] = abx500_get_register_interruptible( | ||
750 | gpadc->dev, AB8500_OTP_EMUL, | ||
751 | otp4_cal_regs[i], &gpadc_otp4[i]); | ||
752 | if (ret_otp4[i] < 0) | ||
753 | dev_err(gpadc->dev, | ||
754 | "%s: read otp4 reg 0x%02x failed\n", | ||
755 | __func__, otp4_cal_regs[i]); | ||
756 | } | ||
529 | 757 | ||
530 | gpadc->cal_data[ADC_INPUT_VMAIN].gain = CALIB_SCALE * | 758 | /* Calculate gain and offset for IBAT if all reads succeeded */ |
531 | (19500 - 315) / (vmain_high - vmain_low); | 759 | if (!(ret_otp4[0] < 0 || ret_otp4[1] < 0 || ret_otp4[2] < 0)) { |
760 | ibat_high = (((gpadc_otp4[0] & 0x07) << 7) | | ||
761 | ((gpadc_otp4[1] & 0xFE) >> 1)); | ||
762 | ibat_low = (((gpadc_otp4[1] & 0x01) << 5) | | ||
763 | ((gpadc_otp4[2] & 0xF8) >> 3)); | ||
764 | |||
765 | gpadc->cal_data[ADC_INPUT_IBAT].otp_calib_hi = | ||
766 | (u16)ibat_high; | ||
767 | gpadc->cal_data[ADC_INPUT_IBAT].otp_calib_lo = | ||
768 | (u16)ibat_low; | ||
769 | |||
770 | V_gain = ((IBAT_VDROP_H - IBAT_VDROP_L) | ||
771 | << CALIB_SHIFT_IBAT) / (ibat_high - ibat_low); | ||
772 | |||
773 | V_offset = (IBAT_VDROP_H << CALIB_SHIFT_IBAT) - | ||
774 | (((IBAT_VDROP_H - IBAT_VDROP_L) << | ||
775 | CALIB_SHIFT_IBAT) / (ibat_high - ibat_low)) | ||
776 | * ibat_high; | ||
777 | /* | ||
778 | * Result obtained is in mV (at a scale factor), | ||
779 | * we need to calculate gain and offset to get mA | ||
780 | */ | ||
781 | V2A_gain = (ADC_CH_IBAT_MAX - ADC_CH_IBAT_MIN)/ | ||
782 | (ADC_CH_IBAT_MAX_V - ADC_CH_IBAT_MIN_V); | ||
783 | V2A_offset = ((ADC_CH_IBAT_MAX_V * ADC_CH_IBAT_MIN - | ||
784 | ADC_CH_IBAT_MAX * ADC_CH_IBAT_MIN_V) | ||
785 | << CALIB_SHIFT_IBAT) | ||
786 | / (ADC_CH_IBAT_MAX_V - ADC_CH_IBAT_MIN_V); | ||
787 | |||
788 | gpadc->cal_data[ADC_INPUT_IBAT].gain = V_gain * V2A_gain; | ||
789 | gpadc->cal_data[ADC_INPUT_IBAT].offset = V_offset * | ||
790 | V2A_gain + V2A_offset; | ||
791 | } else { | ||
792 | gpadc->cal_data[ADC_INPUT_IBAT].gain = 0; | ||
793 | } | ||
532 | 794 | ||
533 | gpadc->cal_data[ADC_INPUT_VMAIN].offset = CALIB_SCALE * 19500 - | 795 | dev_dbg(gpadc->dev, "IBAT gain %llu offset %llu\n", |
534 | (CALIB_SCALE * (19500 - 315) / | 796 | gpadc->cal_data[ADC_INPUT_IBAT].gain, |
535 | (vmain_high - vmain_low)) * vmain_high; | 797 | gpadc->cal_data[ADC_INPUT_IBAT].offset); |
536 | } else { | 798 | } else { |
537 | gpadc->cal_data[ADC_INPUT_VMAIN].gain = 0; | 799 | /* Calculate gain and offset for VMAIN if all reads succeeded */ |
800 | if (!(ret[0] < 0 || ret[1] < 0 || ret[2] < 0)) { | ||
801 | vmain_high = (((gpadc_cal[0] & 0x03) << 8) | | ||
802 | ((gpadc_cal[1] & 0x3F) << 2) | | ||
803 | ((gpadc_cal[2] & 0xC0) >> 6)); | ||
804 | vmain_low = ((gpadc_cal[2] & 0x3E) >> 1); | ||
805 | |||
806 | gpadc->cal_data[ADC_INPUT_VMAIN].otp_calib_hi = | ||
807 | (u16)vmain_high; | ||
808 | gpadc->cal_data[ADC_INPUT_VMAIN].otp_calib_lo = | ||
809 | (u16)vmain_low; | ||
810 | |||
811 | gpadc->cal_data[ADC_INPUT_VMAIN].gain = CALIB_SCALE * | ||
812 | (19500 - 315) / (vmain_high - vmain_low); | ||
813 | |||
814 | gpadc->cal_data[ADC_INPUT_VMAIN].offset = CALIB_SCALE * | ||
815 | 19500 - (CALIB_SCALE * (19500 - 315) / | ||
816 | (vmain_high - vmain_low)) * vmain_high; | ||
817 | } else { | ||
818 | gpadc->cal_data[ADC_INPUT_VMAIN].gain = 0; | ||
819 | } | ||
538 | } | 820 | } |
539 | 821 | ||
540 | /* Calculate gain and offset for BTEMP if all reads succeeded */ | 822 | /* Calculate gain and offset for BTEMP if all reads succeeded */ |
541 | if (!(ret[2] < 0 || ret[3] < 0 || ret[4] < 0)) { | 823 | if (!(ret[2] < 0 || ret[3] < 0 || ret[4] < 0)) { |
542 | btemp_high = (((gpadc_cal[2] & 0x01) << 9) | | 824 | btemp_high = (((gpadc_cal[2] & 0x01) << 9) | |
543 | (gpadc_cal[3] << 1) | | 825 | (gpadc_cal[3] << 1) | ((gpadc_cal[4] & 0x80) >> 7)); |
544 | ((gpadc_cal[4] & 0x80) >> 7)); | ||
545 | |||
546 | btemp_low = ((gpadc_cal[4] & 0x7C) >> 2); | 826 | btemp_low = ((gpadc_cal[4] & 0x7C) >> 2); |
547 | 827 | ||
828 | gpadc->cal_data[ADC_INPUT_BTEMP].otp_calib_hi = (u16)btemp_high; | ||
829 | gpadc->cal_data[ADC_INPUT_BTEMP].otp_calib_lo = (u16)btemp_low; | ||
830 | |||
548 | gpadc->cal_data[ADC_INPUT_BTEMP].gain = | 831 | gpadc->cal_data[ADC_INPUT_BTEMP].gain = |
549 | CALIB_SCALE * (1300 - 21) / (btemp_high - btemp_low); | 832 | CALIB_SCALE * (1300 - 21) / (btemp_high - btemp_low); |
550 | |||
551 | gpadc->cal_data[ADC_INPUT_BTEMP].offset = CALIB_SCALE * 1300 - | 833 | gpadc->cal_data[ADC_INPUT_BTEMP].offset = CALIB_SCALE * 1300 - |
552 | (CALIB_SCALE * (1300 - 21) / | 834 | (CALIB_SCALE * (1300 - 21) / (btemp_high - btemp_low)) |
553 | (btemp_high - btemp_low)) * btemp_high; | 835 | * btemp_high; |
554 | } else { | 836 | } else { |
555 | gpadc->cal_data[ADC_INPUT_BTEMP].gain = 0; | 837 | gpadc->cal_data[ADC_INPUT_BTEMP].gain = 0; |
556 | } | 838 | } |
@@ -560,9 +842,11 @@ static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc) | |||
560 | vbat_high = (((gpadc_cal[4] & 0x03) << 8) | gpadc_cal[5]); | 842 | vbat_high = (((gpadc_cal[4] & 0x03) << 8) | gpadc_cal[5]); |
561 | vbat_low = ((gpadc_cal[6] & 0xFC) >> 2); | 843 | vbat_low = ((gpadc_cal[6] & 0xFC) >> 2); |
562 | 844 | ||
845 | gpadc->cal_data[ADC_INPUT_VBAT].otp_calib_hi = (u16)vbat_high; | ||
846 | gpadc->cal_data[ADC_INPUT_VBAT].otp_calib_lo = (u16)vbat_low; | ||
847 | |||
563 | gpadc->cal_data[ADC_INPUT_VBAT].gain = CALIB_SCALE * | 848 | gpadc->cal_data[ADC_INPUT_VBAT].gain = CALIB_SCALE * |
564 | (4700 - 2380) / (vbat_high - vbat_low); | 849 | (4700 - 2380) / (vbat_high - vbat_low); |
565 | |||
566 | gpadc->cal_data[ADC_INPUT_VBAT].offset = CALIB_SCALE * 4700 - | 850 | gpadc->cal_data[ADC_INPUT_VBAT].offset = CALIB_SCALE * 4700 - |
567 | (CALIB_SCALE * (4700 - 2380) / | 851 | (CALIB_SCALE * (4700 - 2380) / |
568 | (vbat_high - vbat_low)) * vbat_high; | 852 | (vbat_high - vbat_low)) * vbat_high; |
@@ -608,6 +892,31 @@ static int ab8500_gpadc_runtime_idle(struct device *dev) | |||
608 | return 0; | 892 | return 0; |
609 | } | 893 | } |
610 | 894 | ||
895 | static int ab8500_gpadc_suspend(struct device *dev) | ||
896 | { | ||
897 | struct ab8500_gpadc *gpadc = dev_get_drvdata(dev); | ||
898 | |||
899 | mutex_lock(&gpadc->ab8500_gpadc_lock); | ||
900 | |||
901 | pm_runtime_get_sync(dev); | ||
902 | |||
903 | regulator_disable(gpadc->regu); | ||
904 | return 0; | ||
905 | } | ||
906 | |||
907 | static int ab8500_gpadc_resume(struct device *dev) | ||
908 | { | ||
909 | struct ab8500_gpadc *gpadc = dev_get_drvdata(dev); | ||
910 | |||
911 | regulator_enable(gpadc->regu); | ||
912 | |||
913 | pm_runtime_mark_last_busy(gpadc->dev); | ||
914 | pm_runtime_put_autosuspend(gpadc->dev); | ||
915 | |||
916 | mutex_unlock(&gpadc->ab8500_gpadc_lock); | ||
917 | return 0; | ||
918 | } | ||
919 | |||
611 | static int ab8500_gpadc_probe(struct platform_device *pdev) | 920 | static int ab8500_gpadc_probe(struct platform_device *pdev) |
612 | { | 921 | { |
613 | int ret = 0; | 922 | int ret = 0; |
@@ -619,13 +928,13 @@ static int ab8500_gpadc_probe(struct platform_device *pdev) | |||
619 | return -ENOMEM; | 928 | return -ENOMEM; |
620 | } | 929 | } |
621 | 930 | ||
622 | gpadc->irq = platform_get_irq_byname(pdev, "SW_CONV_END"); | 931 | gpadc->irq_sw = platform_get_irq_byname(pdev, "SW_CONV_END"); |
623 | if (gpadc->irq < 0) { | 932 | if (gpadc->irq_sw < 0) |
624 | dev_err(&pdev->dev, "failed to get platform irq-%d\n", | 933 | dev_err(gpadc->dev, "failed to get platform sw_conv_end irq\n"); |
625 | gpadc->irq); | 934 | |
626 | ret = gpadc->irq; | 935 | gpadc->irq_hw = platform_get_irq_byname(pdev, "HW_CONV_END"); |
627 | goto fail; | 936 | if (gpadc->irq_hw < 0) |
628 | } | 937 | dev_err(gpadc->dev, "failed to get platform hw_conv_end irq\n"); |
629 | 938 | ||
630 | gpadc->dev = &pdev->dev; | 939 | gpadc->dev = &pdev->dev; |
631 | gpadc->parent = dev_get_drvdata(pdev->dev.parent); | 940 | gpadc->parent = dev_get_drvdata(pdev->dev.parent); |
@@ -634,15 +943,31 @@ static int ab8500_gpadc_probe(struct platform_device *pdev) | |||
634 | /* Initialize completion used to notify completion of conversion */ | 943 | /* Initialize completion used to notify completion of conversion */ |
635 | init_completion(&gpadc->ab8500_gpadc_complete); | 944 | init_completion(&gpadc->ab8500_gpadc_complete); |
636 | 945 | ||
637 | /* Register interrupt - SwAdcComplete */ | 946 | /* Register interrupts */ |
638 | ret = request_threaded_irq(gpadc->irq, NULL, | 947 | if (gpadc->irq_sw >= 0) { |
639 | ab8500_bm_gpswadcconvend_handler, | 948 | ret = request_threaded_irq(gpadc->irq_sw, NULL, |
640 | IRQF_ONESHOT | IRQF_NO_SUSPEND | IRQF_SHARED, | 949 | ab8500_bm_gpadcconvend_handler, |
641 | "ab8500-gpadc", gpadc); | 950 | IRQF_NO_SUSPEND | IRQF_SHARED, "ab8500-gpadc-sw", |
642 | if (ret < 0) { | 951 | gpadc); |
643 | dev_err(gpadc->dev, "Failed to register interrupt, irq: %d\n", | 952 | if (ret < 0) { |
644 | gpadc->irq); | 953 | dev_err(gpadc->dev, |
645 | goto fail; | 954 | "Failed to register interrupt irq: %d\n", |
955 | gpadc->irq_sw); | ||
956 | goto fail; | ||
957 | } | ||
958 | } | ||
959 | |||
960 | if (gpadc->irq_hw >= 0) { | ||
961 | ret = request_threaded_irq(gpadc->irq_hw, NULL, | ||
962 | ab8500_bm_gpadcconvend_handler, | ||
963 | IRQF_NO_SUSPEND | IRQF_SHARED, "ab8500-gpadc-hw", | ||
964 | gpadc); | ||
965 | if (ret < 0) { | ||
966 | dev_err(gpadc->dev, | ||
967 | "Failed to register interrupt irq: %d\n", | ||
968 | gpadc->irq_hw); | ||
969 | goto fail_irq; | ||
970 | } | ||
646 | } | 971 | } |
647 | 972 | ||
648 | /* VTVout LDO used to power up ab8500-GPADC */ | 973 | /* VTVout LDO used to power up ab8500-GPADC */ |
@@ -669,11 +994,13 @@ static int ab8500_gpadc_probe(struct platform_device *pdev) | |||
669 | ab8500_gpadc_read_calibration_data(gpadc); | 994 | ab8500_gpadc_read_calibration_data(gpadc); |
670 | list_add_tail(&gpadc->node, &ab8500_gpadc_list); | 995 | list_add_tail(&gpadc->node, &ab8500_gpadc_list); |
671 | dev_dbg(gpadc->dev, "probe success\n"); | 996 | dev_dbg(gpadc->dev, "probe success\n"); |
997 | |||
672 | return 0; | 998 | return 0; |
673 | 999 | ||
674 | fail_enable: | 1000 | fail_enable: |
675 | fail_irq: | 1001 | fail_irq: |
676 | free_irq(gpadc->irq, gpadc); | 1002 | free_irq(gpadc->irq_sw, gpadc); |
1003 | free_irq(gpadc->irq_hw, gpadc); | ||
677 | fail: | 1004 | fail: |
678 | kfree(gpadc); | 1005 | kfree(gpadc); |
679 | gpadc = NULL; | 1006 | gpadc = NULL; |
@@ -687,7 +1014,10 @@ static int ab8500_gpadc_remove(struct platform_device *pdev) | |||
687 | /* remove this gpadc entry from the list */ | 1014 | /* remove this gpadc entry from the list */ |
688 | list_del(&gpadc->node); | 1015 | list_del(&gpadc->node); |
689 | /* remove interrupt - completion of Sw ADC conversion */ | 1016 | /* remove interrupt - completion of Sw ADC conversion */ |
690 | free_irq(gpadc->irq, gpadc); | 1017 | if (gpadc->irq_sw >= 0) |
1018 | free_irq(gpadc->irq_sw, gpadc); | ||
1019 | if (gpadc->irq_hw >= 0) | ||
1020 | free_irq(gpadc->irq_hw, gpadc); | ||
691 | 1021 | ||
692 | pm_runtime_get_sync(gpadc->dev); | 1022 | pm_runtime_get_sync(gpadc->dev); |
693 | pm_runtime_disable(gpadc->dev); | 1023 | pm_runtime_disable(gpadc->dev); |
@@ -707,6 +1037,9 @@ static const struct dev_pm_ops ab8500_gpadc_pm_ops = { | |||
707 | SET_RUNTIME_PM_OPS(ab8500_gpadc_runtime_suspend, | 1037 | SET_RUNTIME_PM_OPS(ab8500_gpadc_runtime_suspend, |
708 | ab8500_gpadc_runtime_resume, | 1038 | ab8500_gpadc_runtime_resume, |
709 | ab8500_gpadc_runtime_idle) | 1039 | ab8500_gpadc_runtime_idle) |
1040 | SET_SYSTEM_SLEEP_PM_OPS(ab8500_gpadc_suspend, | ||
1041 | ab8500_gpadc_resume) | ||
1042 | |||
710 | }; | 1043 | }; |
711 | 1044 | ||
712 | static struct platform_driver ab8500_gpadc_driver = { | 1045 | static struct platform_driver ab8500_gpadc_driver = { |
@@ -729,10 +1062,30 @@ static void __exit ab8500_gpadc_exit(void) | |||
729 | platform_driver_unregister(&ab8500_gpadc_driver); | 1062 | platform_driver_unregister(&ab8500_gpadc_driver); |
730 | } | 1063 | } |
731 | 1064 | ||
1065 | /** | ||
1066 | * ab8540_gpadc_get_otp() - returns OTP values | ||
1067 | * | ||
1068 | */ | ||
1069 | void ab8540_gpadc_get_otp(struct ab8500_gpadc *gpadc, | ||
1070 | u16 *vmain_l, u16 *vmain_h, u16 *btemp_l, u16 *btemp_h, | ||
1071 | u16 *vbat_l, u16 *vbat_h, u16 *ibat_l, u16 *ibat_h) | ||
1072 | { | ||
1073 | *vmain_l = gpadc->cal_data[ADC_INPUT_VMAIN].otp_calib_lo; | ||
1074 | *vmain_h = gpadc->cal_data[ADC_INPUT_VMAIN].otp_calib_hi; | ||
1075 | *btemp_l = gpadc->cal_data[ADC_INPUT_BTEMP].otp_calib_lo; | ||
1076 | *btemp_h = gpadc->cal_data[ADC_INPUT_BTEMP].otp_calib_hi; | ||
1077 | *vbat_l = gpadc->cal_data[ADC_INPUT_VBAT].otp_calib_lo; | ||
1078 | *vbat_h = gpadc->cal_data[ADC_INPUT_VBAT].otp_calib_hi; | ||
1079 | *ibat_l = gpadc->cal_data[ADC_INPUT_IBAT].otp_calib_lo; | ||
1080 | *ibat_h = gpadc->cal_data[ADC_INPUT_IBAT].otp_calib_hi; | ||
1081 | return ; | ||
1082 | } | ||
1083 | |||
732 | subsys_initcall_sync(ab8500_gpadc_init); | 1084 | subsys_initcall_sync(ab8500_gpadc_init); |
733 | module_exit(ab8500_gpadc_exit); | 1085 | module_exit(ab8500_gpadc_exit); |
734 | 1086 | ||
735 | MODULE_LICENSE("GPL v2"); | 1087 | MODULE_LICENSE("GPL v2"); |
736 | MODULE_AUTHOR("Arun R Murthy, Daniel Willerud, Johan Palsson"); | 1088 | MODULE_AUTHOR("Arun R Murthy, Daniel Willerud, Johan Palsson," |
1089 | "M'boumba Cedric Madianga"); | ||
737 | MODULE_ALIAS("platform:ab8500_gpadc"); | 1090 | MODULE_ALIAS("platform:ab8500_gpadc"); |
738 | MODULE_DESCRIPTION("AB8500 GPADC driver"); | 1091 | MODULE_DESCRIPTION("AB8500 GPADC driver"); |
diff --git a/drivers/mfd/ab8500-sysctrl.c b/drivers/mfd/ab8500-sysctrl.c index 108fd86552f0..272479cdb107 100644 --- a/drivers/mfd/ab8500-sysctrl.c +++ b/drivers/mfd/ab8500-sysctrl.c | |||
@@ -15,19 +15,30 @@ | |||
15 | #include <linux/mfd/abx500/ab8500.h> | 15 | #include <linux/mfd/abx500/ab8500.h> |
16 | #include <linux/mfd/abx500/ab8500-sysctrl.h> | 16 | #include <linux/mfd/abx500/ab8500-sysctrl.h> |
17 | 17 | ||
18 | /* RtcCtrl bits */ | ||
19 | #define AB8500_ALARM_MIN_LOW 0x08 | ||
20 | #define AB8500_ALARM_MIN_MID 0x09 | ||
21 | #define RTC_CTRL 0x0B | ||
22 | #define RTC_ALARM_ENABLE 0x4 | ||
23 | |||
18 | static struct device *sysctrl_dev; | 24 | static struct device *sysctrl_dev; |
19 | 25 | ||
20 | void ab8500_power_off(void) | 26 | void ab8500_power_off(void) |
21 | { | 27 | { |
22 | sigset_t old; | 28 | sigset_t old; |
23 | sigset_t all; | 29 | sigset_t all; |
24 | static char *pss[] = {"ab8500_ac", "ab8500_usb"}; | 30 | static char *pss[] = {"ab8500_ac", "pm2301", "ab8500_usb"}; |
25 | int i; | 31 | int i; |
26 | bool charger_present = false; | 32 | bool charger_present = false; |
27 | union power_supply_propval val; | 33 | union power_supply_propval val; |
28 | struct power_supply *psy; | 34 | struct power_supply *psy; |
29 | int ret; | 35 | int ret; |
30 | 36 | ||
37 | if (sysctrl_dev == NULL) { | ||
38 | pr_err("%s: sysctrl not initialized\n", __func__); | ||
39 | return; | ||
40 | } | ||
41 | |||
31 | /* | 42 | /* |
32 | * If we have a charger connected and we're powering off, | 43 | * If we have a charger connected and we're powering off, |
33 | * reboot into charge-only mode. | 44 | * reboot into charge-only mode. |
@@ -74,6 +85,63 @@ shutdown: | |||
74 | } | 85 | } |
75 | } | 86 | } |
76 | 87 | ||
88 | /* | ||
89 | * Use the AB WD to reset the platform. It will perform a hard | ||
90 | * reset instead of a soft reset. Write the reset reason to | ||
91 | * the AB before reset, which can be read upon restart. | ||
92 | */ | ||
93 | void ab8500_restart(char mode, const char *cmd) | ||
94 | { | ||
95 | struct ab8500_platform_data *plat; | ||
96 | struct ab8500_sysctrl_platform_data *pdata; | ||
97 | u16 reason = 0; | ||
98 | u8 val; | ||
99 | |||
100 | if (sysctrl_dev == NULL) { | ||
101 | pr_err("%s: sysctrl not initialized\n", __func__); | ||
102 | return; | ||
103 | } | ||
104 | |||
105 | plat = dev_get_platdata(sysctrl_dev->parent); | ||
106 | pdata = plat->sysctrl; | ||
107 | if (pdata->reboot_reason_code) | ||
108 | reason = pdata->reboot_reason_code(cmd); | ||
109 | else | ||
110 | pr_warn("[%s] No reboot reason set. Default reason %d\n", | ||
111 | __func__, reason); | ||
112 | |||
113 | /* | ||
114 | * Disable RTC alarm, just a precaution so that no alarm | ||
115 | * is running when WD reset is executed. | ||
116 | */ | ||
117 | abx500_get_register_interruptible(sysctrl_dev, AB8500_RTC, | ||
118 | RTC_CTRL , &val); | ||
119 | abx500_set_register_interruptible(sysctrl_dev, AB8500_RTC, | ||
120 | RTC_CTRL , (val & ~RTC_ALARM_ENABLE)); | ||
121 | |||
122 | /* | ||
123 | * Android is not using the RTC alarm registers during reboot | ||
124 | * so we borrow them for writing the reason of reset | ||
125 | */ | ||
126 | |||
127 | /* reason[8 LSB] */ | ||
128 | val = reason & 0xFF; | ||
129 | abx500_set_register_interruptible(sysctrl_dev, AB8500_RTC, | ||
130 | AB8500_ALARM_MIN_LOW , val); | ||
131 | |||
132 | /* reason[8 MSB] */ | ||
133 | val = (reason>>8) & 0xFF; | ||
134 | abx500_set_register_interruptible(sysctrl_dev, AB8500_RTC, | ||
135 | AB8500_ALARM_MIN_MID , val); | ||
136 | |||
137 | /* Setting WD timeout to 0 */ | ||
138 | ab8500_sysctrl_write(AB8500_MAINWDOGTIMER, 0xFF, 0x0); | ||
139 | |||
140 | /* Setting the parameters to AB8500 WD*/ | ||
141 | ab8500_sysctrl_write(AB8500_MAINWDOGCTRL, 0xFF, (AB8500_ENABLE_WD | | ||
142 | AB8500_WD_RESTART_ON_EXPIRE | AB8500_KICK_WD)); | ||
143 | } | ||
144 | |||
77 | static inline bool valid_bank(u8 bank) | 145 | static inline bool valid_bank(u8 bank) |
78 | { | 146 | { |
79 | return ((bank == AB8500_SYS_CTRL1_BLOCK) || | 147 | return ((bank == AB8500_SYS_CTRL1_BLOCK) || |
@@ -85,7 +153,7 @@ int ab8500_sysctrl_read(u16 reg, u8 *value) | |||
85 | u8 bank; | 153 | u8 bank; |
86 | 154 | ||
87 | if (sysctrl_dev == NULL) | 155 | if (sysctrl_dev == NULL) |
88 | return -EAGAIN; | 156 | return -EINVAL; |
89 | 157 | ||
90 | bank = (reg >> 8); | 158 | bank = (reg >> 8); |
91 | if (!valid_bank(bank)) | 159 | if (!valid_bank(bank)) |
@@ -101,7 +169,7 @@ int ab8500_sysctrl_write(u16 reg, u8 mask, u8 value) | |||
101 | u8 bank; | 169 | u8 bank; |
102 | 170 | ||
103 | if (sysctrl_dev == NULL) | 171 | if (sysctrl_dev == NULL) |
104 | return -EAGAIN; | 172 | return -EINVAL; |
105 | 173 | ||
106 | bank = (reg >> 8); | 174 | bank = (reg >> 8); |
107 | if (!valid_bank(bank)) | 175 | if (!valid_bank(bank)) |
@@ -114,28 +182,36 @@ EXPORT_SYMBOL(ab8500_sysctrl_write); | |||
114 | 182 | ||
115 | static int ab8500_sysctrl_probe(struct platform_device *pdev) | 183 | static int ab8500_sysctrl_probe(struct platform_device *pdev) |
116 | { | 184 | { |
185 | struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); | ||
117 | struct ab8500_platform_data *plat; | 186 | struct ab8500_platform_data *plat; |
118 | struct ab8500_sysctrl_platform_data *pdata; | 187 | struct ab8500_sysctrl_platform_data *pdata; |
119 | 188 | ||
120 | sysctrl_dev = &pdev->dev; | ||
121 | plat = dev_get_platdata(pdev->dev.parent); | 189 | plat = dev_get_platdata(pdev->dev.parent); |
190 | |||
191 | if (!(plat && plat->sysctrl)) | ||
192 | return -EINVAL; | ||
193 | |||
122 | if (plat->pm_power_off) | 194 | if (plat->pm_power_off) |
123 | pm_power_off = ab8500_power_off; | 195 | pm_power_off = ab8500_power_off; |
124 | 196 | ||
125 | pdata = plat->sysctrl; | 197 | pdata = plat->sysctrl; |
126 | 198 | ||
127 | if (pdata) { | 199 | if (pdata) { |
128 | int ret, i, j; | 200 | int last, ret, i, j; |
201 | |||
202 | if (is_ab8505(ab8500)) | ||
203 | last = AB8500_SYSCLKREQ4RFCLKBUF; | ||
204 | else | ||
205 | last = AB8500_SYSCLKREQ8RFCLKBUF; | ||
129 | 206 | ||
130 | for (i = AB8500_SYSCLKREQ1RFCLKBUF; | 207 | for (i = AB8500_SYSCLKREQ1RFCLKBUF; i <= last; i++) { |
131 | i <= AB8500_SYSCLKREQ8RFCLKBUF; i++) { | ||
132 | j = i - AB8500_SYSCLKREQ1RFCLKBUF; | 208 | j = i - AB8500_SYSCLKREQ1RFCLKBUF; |
133 | ret = ab8500_sysctrl_write(i, 0xff, | 209 | ret = ab8500_sysctrl_write(i, 0xff, |
134 | pdata->initial_req_buf_config[j]); | 210 | pdata->initial_req_buf_config[j]); |
135 | dev_dbg(&pdev->dev, | 211 | dev_dbg(&pdev->dev, |
136 | "Setting SysClkReq%dRfClkBuf 0x%X\n", | 212 | "Setting SysClkReq%dRfClkBuf 0x%X\n", |
137 | j + 1, | 213 | j + 1, |
138 | pdata->initial_req_buf_config[j]); | 214 | pdata->initial_req_buf_config[j]); |
139 | if (ret < 0) { | 215 | if (ret < 0) { |
140 | dev_err(&pdev->dev, | 216 | dev_err(&pdev->dev, |
141 | "unable to set sysClkReq%dRfClkBuf: " | 217 | "unable to set sysClkReq%dRfClkBuf: " |
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 9e00c389e777..07e1a8f8d03e 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig | |||
@@ -353,13 +353,6 @@ config BATTERY_GOLDFISH | |||
353 | Say Y to enable support for the battery and AC power in the | 353 | Say Y to enable support for the battery and AC power in the |
354 | Goldfish emulator. | 354 | Goldfish emulator. |
355 | 355 | ||
356 | config CHARGER_PM2301 | ||
357 | bool "PM2301 Battery Charger Driver" | ||
358 | depends on AB8500_BM | ||
359 | help | ||
360 | Say Y to include support for PM2301 charger driver. | ||
361 | Depends on AB8500 battery management core. | ||
362 | |||
363 | source "drivers/power/reset/Kconfig" | 356 | source "drivers/power/reset/Kconfig" |
364 | 357 | ||
365 | endif # POWER_SUPPLY | 358 | endif # POWER_SUPPLY |
diff --git a/drivers/power/Makefile b/drivers/power/Makefile index 3f66436af45c..eb520ea74970 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile | |||
@@ -39,7 +39,7 @@ obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o | |||
39 | obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o | 39 | obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o |
40 | obj-$(CONFIG_BATTERY_INTEL_MID) += intel_mid_battery.o | 40 | obj-$(CONFIG_BATTERY_INTEL_MID) += intel_mid_battery.o |
41 | obj-$(CONFIG_BATTERY_RX51) += rx51_battery.o | 41 | obj-$(CONFIG_BATTERY_RX51) += rx51_battery.o |
42 | obj-$(CONFIG_AB8500_BM) += ab8500_bmdata.o ab8500_charger.o ab8500_fg.o ab8500_btemp.o abx500_chargalg.o | 42 | obj-$(CONFIG_AB8500_BM) += ab8500_bmdata.o ab8500_charger.o ab8500_fg.o ab8500_btemp.o abx500_chargalg.o pm2301_charger.o |
43 | obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o | 43 | obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o |
44 | obj-$(CONFIG_CHARGER_MAX8903) += max8903_charger.o | 44 | obj-$(CONFIG_CHARGER_MAX8903) += max8903_charger.o |
45 | obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o | 45 | obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o |
@@ -47,7 +47,6 @@ obj-$(CONFIG_CHARGER_LP8727) += lp8727_charger.o | |||
47 | obj-$(CONFIG_CHARGER_LP8788) += lp8788-charger.o | 47 | obj-$(CONFIG_CHARGER_LP8788) += lp8788-charger.o |
48 | obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o | 48 | obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o |
49 | obj-$(CONFIG_CHARGER_MANAGER) += charger-manager.o | 49 | obj-$(CONFIG_CHARGER_MANAGER) += charger-manager.o |
50 | obj-$(CONFIG_CHARGER_PM2301) += pm2301_charger.o | ||
51 | obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o | 50 | obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o |
52 | obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o | 51 | obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o |
53 | obj-$(CONFIG_CHARGER_BQ2415X) += bq2415x_charger.o | 52 | obj-$(CONFIG_CHARGER_BQ2415X) += bq2415x_charger.o |
diff --git a/drivers/power/ab8500_bmdata.c b/drivers/power/ab8500_bmdata.c index 7a96c0650fbb..85742a6d29ff 100644 --- a/drivers/power/ab8500_bmdata.c +++ b/drivers/power/ab8500_bmdata.c | |||
@@ -407,15 +407,27 @@ 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 | ||
412 | static const struct abx500_maxim_parameters maxi_params = { | 417 | static const struct abx500_maxim_parameters ab8500_maxi_params = { |
413 | .ena_maxi = true, | 418 | .ena_maxi = true, |
414 | .chg_curr = 910, | 419 | .chg_curr = 910, |
415 | .wait_cycles = 10, | 420 | .wait_cycles = 10, |
416 | .charger_curr_step = 100, | 421 | .charger_curr_step = 100, |
417 | }; | 422 | }; |
418 | 423 | ||
424 | static const struct abx500_maxim_parameters abx540_maxi_params = { | ||
425 | .ena_maxi = true, | ||
426 | .chg_curr = 3000, | ||
427 | .wait_cycles = 10, | ||
428 | .charger_curr_step = 200, | ||
429 | }; | ||
430 | |||
419 | static const struct abx500_bm_charger_parameters chg = { | 431 | static const struct abx500_bm_charger_parameters chg = { |
420 | .usb_volt_max = 5500, | 432 | .usb_volt_max = 5500, |
421 | .usb_curr_max = 1500, | 433 | .usb_curr_max = 1500, |
@@ -423,6 +435,46 @@ static const struct abx500_bm_charger_parameters chg = { | |||
423 | .ac_curr_max = 1500, | 435 | .ac_curr_max = 1500, |
424 | }; | 436 | }; |
425 | 437 | ||
438 | /* | ||
439 | * This array maps the raw hex value to charger output current used by the | ||
440 | * AB8500 values | ||
441 | */ | ||
442 | static int ab8500_charge_output_curr_map[] = { | ||
443 | 100, 200, 300, 400, 500, 600, 700, 800, | ||
444 | 900, 1000, 1100, 1200, 1300, 1400, 1500, 1500, | ||
445 | }; | ||
446 | |||
447 | static int ab8540_charge_output_curr_map[] = { | ||
448 | 0, 0, 0, 75, 100, 125, 150, 175, | ||
449 | 200, 225, 250, 275, 300, 325, 350, 375, | ||
450 | 400, 425, 450, 475, 500, 525, 550, 575, | ||
451 | 600, 625, 650, 675, 700, 725, 750, 775, | ||
452 | 800, 825, 850, 875, 900, 925, 950, 975, | ||
453 | 1000, 1025, 1050, 1075, 1100, 1125, 1150, 1175, | ||
454 | 1200, 1225, 1250, 1275, 1300, 1325, 1350, 1375, | ||
455 | 1400, 1425, 1450, 1500, 1600, 1700, 1900, 2000, | ||
456 | }; | ||
457 | |||
458 | /* | ||
459 | * This array maps the raw hex value to charger input current used by the | ||
460 | * AB8500 values | ||
461 | */ | ||
462 | static int ab8500_charge_input_curr_map[] = { | ||
463 | 50, 98, 193, 290, 380, 450, 500, 600, | ||
464 | 700, 800, 900, 1000, 1100, 1300, 1400, 1500, | ||
465 | }; | ||
466 | |||
467 | static int ab8540_charge_input_curr_map[] = { | ||
468 | 25, 50, 75, 100, 125, 150, 175, 200, | ||
469 | 225, 250, 275, 300, 325, 350, 375, 400, | ||
470 | 425, 450, 475, 500, 525, 550, 575, 600, | ||
471 | 625, 650, 675, 700, 725, 750, 775, 800, | ||
472 | 825, 850, 875, 900, 925, 950, 975, 1000, | ||
473 | 1025, 1050, 1075, 1100, 1125, 1150, 1175, 1200, | ||
474 | 1225, 1250, 1275, 1300, 1325, 1350, 1375, 1400, | ||
475 | 1425, 1450, 1475, 1500, 1500, 1500, 1500, 1500, | ||
476 | }; | ||
477 | |||
426 | struct abx500_bm_data ab8500_bm_data = { | 478 | struct abx500_bm_data ab8500_bm_data = { |
427 | .temp_under = 3, | 479 | .temp_under = 3, |
428 | .temp_low = 8, | 480 | .temp_low = 8, |
@@ -442,15 +494,53 @@ struct abx500_bm_data ab8500_bm_data = { | |||
442 | .fg_res = 100, | 494 | .fg_res = 100, |
443 | .cap_levels = &cap_levels, | 495 | .cap_levels = &cap_levels, |
444 | .bat_type = bat_type_thermistor, | 496 | .bat_type = bat_type_thermistor, |
445 | .n_btypes = 3, | 497 | .n_btypes = ARRAY_SIZE(bat_type_thermistor), |
446 | .batt_id = 0, | 498 | .batt_id = 0, |
447 | .interval_charging = 5, | 499 | .interval_charging = 5, |
448 | .interval_not_charging = 120, | 500 | .interval_not_charging = 120, |
449 | .temp_hysteresis = 3, | 501 | .temp_hysteresis = 3, |
450 | .gnd_lift_resistance = 34, | 502 | .gnd_lift_resistance = 34, |
451 | .maxi = &maxi_params, | 503 | .chg_output_curr = ab8500_charge_output_curr_map, |
504 | .n_chg_out_curr = ARRAY_SIZE(ab8500_charge_output_curr_map), | ||
505 | .maxi = &ab8500_maxi_params, | ||
452 | .chg_params = &chg, | 506 | .chg_params = &chg, |
453 | .fg_params = &fg, | 507 | .fg_params = &fg, |
508 | .chg_input_curr = ab8500_charge_input_curr_map, | ||
509 | .n_chg_in_curr = ARRAY_SIZE(ab8500_charge_input_curr_map), | ||
510 | }; | ||
511 | |||
512 | struct abx500_bm_data ab8540_bm_data = { | ||
513 | .temp_under = 3, | ||
514 | .temp_low = 8, | ||
515 | .temp_high = 43, | ||
516 | .temp_over = 48, | ||
517 | .main_safety_tmr_h = 4, | ||
518 | .temp_interval_chg = 20, | ||
519 | .temp_interval_nochg = 120, | ||
520 | .usb_safety_tmr_h = 4, | ||
521 | .bkup_bat_v = BUP_VCH_SEL_2P6V, | ||
522 | .bkup_bat_i = BUP_ICH_SEL_150UA, | ||
523 | .no_maintenance = false, | ||
524 | .capacity_scaling = false, | ||
525 | .adc_therm = ABx500_ADC_THERM_BATCTRL, | ||
526 | .chg_unknown_bat = false, | ||
527 | .enable_overshoot = false, | ||
528 | .fg_res = 100, | ||
529 | .cap_levels = &cap_levels, | ||
530 | .bat_type = bat_type_thermistor, | ||
531 | .n_btypes = ARRAY_SIZE(bat_type_thermistor), | ||
532 | .batt_id = 0, | ||
533 | .interval_charging = 5, | ||
534 | .interval_not_charging = 120, | ||
535 | .temp_hysteresis = 3, | ||
536 | .gnd_lift_resistance = 0, | ||
537 | .maxi = &abx540_maxi_params, | ||
538 | .chg_params = &chg, | ||
539 | .fg_params = &fg, | ||
540 | .chg_output_curr = ab8540_charge_output_curr_map, | ||
541 | .n_chg_out_curr = ARRAY_SIZE(ab8540_charge_output_curr_map), | ||
542 | .chg_input_curr = ab8540_charge_input_curr_map, | ||
543 | .n_chg_in_curr = ARRAY_SIZE(ab8540_charge_input_curr_map), | ||
454 | }; | 544 | }; |
455 | 545 | ||
456 | int ab8500_bm_of_probe(struct device *dev, | 546 | int ab8500_bm_of_probe(struct device *dev, |
diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c index 07689064996e..a9486f1a1b5b 100644 --- a/drivers/power/ab8500_btemp.c +++ b/drivers/power/ab8500_btemp.c | |||
@@ -42,6 +42,9 @@ | |||
42 | #define BTEMP_BATCTRL_CURR_SRC_16UA 16 | 42 | #define BTEMP_BATCTRL_CURR_SRC_16UA 16 |
43 | #define BTEMP_BATCTRL_CURR_SRC_18UA 18 | 43 | #define BTEMP_BATCTRL_CURR_SRC_18UA 18 |
44 | 44 | ||
45 | #define BTEMP_BATCTRL_CURR_SRC_60UA 60 | ||
46 | #define BTEMP_BATCTRL_CURR_SRC_120UA 120 | ||
47 | |||
45 | #define to_ab8500_btemp_device_info(x) container_of((x), \ | 48 | #define to_ab8500_btemp_device_info(x) container_of((x), \ |
46 | struct ab8500_btemp, btemp_psy); | 49 | struct ab8500_btemp, btemp_psy); |
47 | 50 | ||
@@ -76,8 +79,8 @@ struct ab8500_btemp_ranges { | |||
76 | * @dev: Pointer to the structure device | 79 | * @dev: Pointer to the structure device |
77 | * @node: List of AB8500 BTEMPs, hence prepared for reentrance | 80 | * @node: List of AB8500 BTEMPs, hence prepared for reentrance |
78 | * @curr_source: What current source we use, in uA | 81 | * @curr_source: What current source we use, in uA |
79 | * @bat_temp: Battery temperature in degree Celcius | 82 | * @bat_temp: Dispatched battery temperature in degree Celcius |
80 | * @prev_bat_temp Last dispatched battery temperature | 83 | * @prev_bat_temp Last measured battery temperature in degree Celcius |
81 | * @parent: Pointer to the struct ab8500 | 84 | * @parent: Pointer to the struct ab8500 |
82 | * @gpadc: Pointer to the struct gpadc | 85 | * @gpadc: Pointer to the struct gpadc |
83 | * @fg: Pointer to the struct fg | 86 | * @fg: Pointer to the struct fg |
@@ -155,7 +158,7 @@ static int ab8500_btemp_batctrl_volt_to_res(struct ab8500_btemp *di, | |||
155 | if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL) { | 158 | if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL) { |
156 | /* | 159 | /* |
157 | * If the battery has internal NTC, we use the current | 160 | * If the battery has internal NTC, we use the current |
158 | * source to calculate the resistance, 7uA or 20uA | 161 | * source to calculate the resistance. |
159 | */ | 162 | */ |
160 | rbs = (v_batctrl * 1000 | 163 | rbs = (v_batctrl * 1000 |
161 | - di->bm->gnd_lift_resistance * inst_curr) | 164 | - di->bm->gnd_lift_resistance * inst_curr) |
@@ -216,7 +219,12 @@ static int ab8500_btemp_curr_source_enable(struct ab8500_btemp *di, | |||
216 | /* Only do this for batteries with internal NTC */ | 219 | /* Only do this for batteries with internal NTC */ |
217 | if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && enable) { | 220 | if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && enable) { |
218 | 221 | ||
219 | if (is_ab9540(di->parent) || is_ab8505(di->parent)) { | 222 | if (is_ab8540(di->parent)) { |
223 | if (di->curr_source == BTEMP_BATCTRL_CURR_SRC_60UA) | ||
224 | curr = BAT_CTRL_60U_ENA; | ||
225 | else | ||
226 | curr = BAT_CTRL_120U_ENA; | ||
227 | } else if (is_ab9540(di->parent) || is_ab8505(di->parent)) { | ||
220 | if (di->curr_source == BTEMP_BATCTRL_CURR_SRC_16UA) | 228 | if (di->curr_source == BTEMP_BATCTRL_CURR_SRC_16UA) |
221 | curr = BAT_CTRL_16U_ENA; | 229 | curr = BAT_CTRL_16U_ENA; |
222 | else | 230 | else |
@@ -257,7 +265,14 @@ static int ab8500_btemp_curr_source_enable(struct ab8500_btemp *di, | |||
257 | } else if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && !enable) { | 265 | } else if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && !enable) { |
258 | dev_dbg(di->dev, "Disable BATCTRL curr source\n"); | 266 | dev_dbg(di->dev, "Disable BATCTRL curr source\n"); |
259 | 267 | ||
260 | if (is_ab9540(di->parent) || is_ab8505(di->parent)) { | 268 | if (is_ab8540(di->parent)) { |
269 | /* Write 0 to the curr bits */ | ||
270 | ret = abx500_mask_and_set_register_interruptible( | ||
271 | di->dev, | ||
272 | AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE, | ||
273 | BAT_CTRL_60U_ENA | BAT_CTRL_120U_ENA, | ||
274 | ~(BAT_CTRL_60U_ENA | BAT_CTRL_120U_ENA)); | ||
275 | } else if (is_ab9540(di->parent) || is_ab8505(di->parent)) { | ||
261 | /* Write 0 to the curr bits */ | 276 | /* Write 0 to the curr bits */ |
262 | ret = abx500_mask_and_set_register_interruptible( | 277 | ret = abx500_mask_and_set_register_interruptible( |
263 | di->dev, | 278 | di->dev, |
@@ -314,7 +329,13 @@ static int ab8500_btemp_curr_source_enable(struct ab8500_btemp *di, | |||
314 | * if we got an error above | 329 | * if we got an error above |
315 | */ | 330 | */ |
316 | disable_curr_source: | 331 | disable_curr_source: |
317 | if (is_ab9540(di->parent) || is_ab8505(di->parent)) { | 332 | if (is_ab8540(di->parent)) { |
333 | /* Write 0 to the curr bits */ | ||
334 | ret = abx500_mask_and_set_register_interruptible(di->dev, | ||
335 | AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE, | ||
336 | BAT_CTRL_60U_ENA | BAT_CTRL_120U_ENA, | ||
337 | ~(BAT_CTRL_60U_ENA | BAT_CTRL_120U_ENA)); | ||
338 | } else if (is_ab9540(di->parent) || is_ab8505(di->parent)) { | ||
318 | /* Write 0 to the curr bits */ | 339 | /* Write 0 to the curr bits */ |
319 | ret = abx500_mask_and_set_register_interruptible(di->dev, | 340 | ret = abx500_mask_and_set_register_interruptible(di->dev, |
320 | AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE, | 341 | AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE, |
@@ -541,7 +562,9 @@ static int ab8500_btemp_id(struct ab8500_btemp *di) | |||
541 | { | 562 | { |
542 | int res; | 563 | int res; |
543 | u8 i; | 564 | u8 i; |
544 | if (is_ab9540(di->parent) || is_ab8505(di->parent)) | 565 | if (is_ab8540(di->parent)) |
566 | di->curr_source = BTEMP_BATCTRL_CURR_SRC_60UA; | ||
567 | else if (is_ab9540(di->parent) || is_ab8505(di->parent)) | ||
545 | di->curr_source = BTEMP_BATCTRL_CURR_SRC_16UA; | 568 | di->curr_source = BTEMP_BATCTRL_CURR_SRC_16UA; |
546 | else | 569 | else |
547 | di->curr_source = BTEMP_BATCTRL_CURR_SRC_7UA; | 570 | di->curr_source = BTEMP_BATCTRL_CURR_SRC_7UA; |
@@ -579,12 +602,17 @@ static int ab8500_btemp_id(struct ab8500_btemp *di) | |||
579 | 602 | ||
580 | /* | 603 | /* |
581 | * We only have to change current source if the | 604 | * We only have to change current source if the |
582 | * detected type is Type 1, else we use the 7uA source | 605 | * detected type is Type 1. |
583 | */ | 606 | */ |
584 | if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && | 607 | if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && |
585 | di->bm->batt_id == 1) { | 608 | di->bm->batt_id == 1) { |
586 | if (is_ab9540(di->parent) || is_ab8505(di->parent)) { | 609 | if (is_ab8540(di->parent)) { |
587 | dev_dbg(di->dev, "Set BATCTRL current source to 16uA\n"); | 610 | dev_dbg(di->dev, |
611 | "Set BATCTRL current source to 60uA\n"); | ||
612 | di->curr_source = BTEMP_BATCTRL_CURR_SRC_60UA; | ||
613 | } else if (is_ab9540(di->parent) || is_ab8505(di->parent)) { | ||
614 | dev_dbg(di->dev, | ||
615 | "Set BATCTRL current source to 16uA\n"); | ||
588 | di->curr_source = BTEMP_BATCTRL_CURR_SRC_16UA; | 616 | di->curr_source = BTEMP_BATCTRL_CURR_SRC_16UA; |
589 | } else { | 617 | } else { |
590 | dev_dbg(di->dev, "Set BATCTRL current source to 20uA\n"); | 618 | dev_dbg(di->dev, "Set BATCTRL current source to 20uA\n"); |
@@ -604,22 +632,37 @@ static int ab8500_btemp_id(struct ab8500_btemp *di) | |||
604 | static void ab8500_btemp_periodic_work(struct work_struct *work) | 632 | static void ab8500_btemp_periodic_work(struct work_struct *work) |
605 | { | 633 | { |
606 | int interval; | 634 | int interval; |
635 | int bat_temp; | ||
607 | struct ab8500_btemp *di = container_of(work, | 636 | struct ab8500_btemp *di = container_of(work, |
608 | struct ab8500_btemp, btemp_periodic_work.work); | 637 | struct ab8500_btemp, btemp_periodic_work.work); |
609 | 638 | ||
610 | if (!di->initialized) { | 639 | if (!di->initialized) { |
611 | di->initialized = true; | ||
612 | /* Identify the battery */ | 640 | /* Identify the battery */ |
613 | if (ab8500_btemp_id(di) < 0) | 641 | if (ab8500_btemp_id(di) < 0) |
614 | dev_warn(di->dev, "failed to identify the battery\n"); | 642 | dev_warn(di->dev, "failed to identify the battery\n"); |
615 | } | 643 | } |
616 | 644 | ||
617 | di->bat_temp = ab8500_btemp_measure_temp(di); | 645 | bat_temp = ab8500_btemp_measure_temp(di); |
618 | 646 | /* | |
619 | if (di->bat_temp != di->prev_bat_temp) { | 647 | * Filter battery temperature. |
620 | di->prev_bat_temp = di->bat_temp; | 648 | * Allow direct updates on temperature only if two samples result in |
649 | * same temperature. Else only allow 1 degree change from previous | ||
650 | * reported value in the direction of the new measurement. | ||
651 | */ | ||
652 | if ((bat_temp == di->prev_bat_temp) || !di->initialized) { | ||
653 | if ((di->bat_temp != di->prev_bat_temp) || !di->initialized) { | ||
654 | di->initialized = true; | ||
655 | di->bat_temp = bat_temp; | ||
656 | power_supply_changed(&di->btemp_psy); | ||
657 | } | ||
658 | } else if (bat_temp < di->prev_bat_temp) { | ||
659 | di->bat_temp--; | ||
660 | power_supply_changed(&di->btemp_psy); | ||
661 | } else if (bat_temp > di->prev_bat_temp) { | ||
662 | di->bat_temp++; | ||
621 | power_supply_changed(&di->btemp_psy); | 663 | power_supply_changed(&di->btemp_psy); |
622 | } | 664 | } |
665 | di->prev_bat_temp = bat_temp; | ||
623 | 666 | ||
624 | if (di->events.ac_conn || di->events.usb_conn) | 667 | if (di->events.ac_conn || di->events.usb_conn) |
625 | interval = di->bm->temp_interval_chg; | 668 | interval = di->bm->temp_interval_chg; |
diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c index 24b30b7ea5ca..a558318b169c 100644 --- a/drivers/power/ab8500_charger.c +++ b/drivers/power/ab8500_charger.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/device.h> | 15 | #include <linux/device.h> |
16 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
17 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
18 | #include <linux/notifier.h> | ||
18 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
19 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
20 | #include <linux/power_supply.h> | 21 | #include <linux/power_supply.h> |
@@ -52,10 +53,15 @@ | |||
52 | #define VBUS_DET_DBNC100 0x02 | 53 | #define VBUS_DET_DBNC100 0x02 |
53 | #define VBUS_DET_DBNC1 0x01 | 54 | #define VBUS_DET_DBNC1 0x01 |
54 | #define OTP_ENABLE_WD 0x01 | 55 | #define OTP_ENABLE_WD 0x01 |
56 | #define DROP_COUNT_RESET 0x01 | ||
57 | #define USB_CH_DET 0x01 | ||
55 | 58 | ||
56 | #define MAIN_CH_INPUT_CURR_SHIFT 4 | 59 | #define MAIN_CH_INPUT_CURR_SHIFT 4 |
57 | #define VBUS_IN_CURR_LIM_SHIFT 4 | 60 | #define VBUS_IN_CURR_LIM_SHIFT 4 |
61 | #define AB8540_VBUS_IN_CURR_LIM_SHIFT 2 | ||
58 | #define AUTO_VBUS_IN_CURR_LIM_SHIFT 4 | 62 | #define AUTO_VBUS_IN_CURR_LIM_SHIFT 4 |
63 | #define AB8540_AUTO_VBUS_IN_CURR_MASK 0x3F | ||
64 | #define VBUS_IN_CURR_LIM_RETRY_SET_TIME 30 /* seconds */ | ||
59 | 65 | ||
60 | #define LED_INDICATOR_PWM_ENA 0x01 | 66 | #define LED_INDICATOR_PWM_ENA 0x01 |
61 | #define LED_INDICATOR_PWM_DIS 0x00 | 67 | #define LED_INDICATOR_PWM_DIS 0x00 |
@@ -77,7 +83,9 @@ | |||
77 | 83 | ||
78 | /* UsbLineStatus register bit masks */ | 84 | /* UsbLineStatus register bit masks */ |
79 | #define AB8500_USB_LINK_STATUS 0x78 | 85 | #define AB8500_USB_LINK_STATUS 0x78 |
86 | #define AB8505_USB_LINK_STATUS 0xF8 | ||
80 | #define AB8500_STD_HOST_SUSP 0x18 | 87 | #define AB8500_STD_HOST_SUSP 0x18 |
88 | #define USB_LINK_STATUS_SHIFT 3 | ||
81 | 89 | ||
82 | /* Watchdog timeout constant */ | 90 | /* Watchdog timeout constant */ |
83 | #define WD_TIMER 0x30 /* 4min */ | 91 | #define WD_TIMER 0x30 /* 4min */ |
@@ -96,6 +104,10 @@ | |||
96 | #define AB8500_SW_CONTROL_FALLBACK 0x03 | 104 | #define AB8500_SW_CONTROL_FALLBACK 0x03 |
97 | /* Wait for enumeration before charing in us */ | 105 | /* Wait for enumeration before charing in us */ |
98 | #define WAIT_ACA_RID_ENUMERATION (5 * 1000) | 106 | #define WAIT_ACA_RID_ENUMERATION (5 * 1000) |
107 | /*External charger control*/ | ||
108 | #define AB8500_SYS_CHARGER_CONTROL_REG 0x52 | ||
109 | #define EXTERNAL_CHARGER_DISABLE_REG_VAL 0x03 | ||
110 | #define EXTERNAL_CHARGER_ENABLE_REG_VAL 0x07 | ||
99 | 111 | ||
100 | /* UsbLineStatus register - usb types */ | 112 | /* UsbLineStatus register - usb types */ |
101 | enum ab8500_charger_link_status { | 113 | enum ab8500_charger_link_status { |
@@ -196,10 +208,15 @@ struct ab8500_charger_usb_state { | |||
196 | spinlock_t usb_lock; | 208 | spinlock_t usb_lock; |
197 | }; | 209 | }; |
198 | 210 | ||
211 | struct ab8500_charger_max_usb_in_curr { | ||
212 | int usb_type_max; | ||
213 | int set_max; | ||
214 | int calculated_max; | ||
215 | }; | ||
216 | |||
199 | /** | 217 | /** |
200 | * struct ab8500_charger - ab8500 Charger device information | 218 | * struct ab8500_charger - ab8500 Charger device information |
201 | * @dev: Pointer to the structure device | 219 | * @dev: Pointer to the structure device |
202 | * @max_usb_in_curr: Max USB charger input current | ||
203 | * @vbus_detected: VBUS detected | 220 | * @vbus_detected: VBUS detected |
204 | * @vbus_detected_start: | 221 | * @vbus_detected_start: |
205 | * VBUS detected during startup | 222 | * VBUS detected during startup |
@@ -214,7 +231,6 @@ struct ab8500_charger_usb_state { | |||
214 | * @autopower Indicate if we should have automatic pwron after pwrloss | 231 | * @autopower Indicate if we should have automatic pwron after pwrloss |
215 | * @autopower_cfg platform specific power config support for "pwron after pwrloss" | 232 | * @autopower_cfg platform specific power config support for "pwron after pwrloss" |
216 | * @invalid_charger_detect_state State when forcing AB to use invalid charger | 233 | * @invalid_charger_detect_state State when forcing AB to use invalid charger |
217 | * @is_usb_host: Indicate if last detected USB type is host | ||
218 | * @is_aca_rid: Incicate if accessory is ACA type | 234 | * @is_aca_rid: Incicate if accessory is ACA type |
219 | * @current_stepping_sessions: | 235 | * @current_stepping_sessions: |
220 | * Counter for current stepping sessions | 236 | * Counter for current stepping sessions |
@@ -223,6 +239,7 @@ struct ab8500_charger_usb_state { | |||
223 | * @bm: Platform specific battery management information | 239 | * @bm: Platform specific battery management information |
224 | * @flags: Structure for information about events triggered | 240 | * @flags: Structure for information about events triggered |
225 | * @usb_state: Structure for usb stack information | 241 | * @usb_state: Structure for usb stack information |
242 | * @max_usb_in_curr: Max USB charger input current | ||
226 | * @ac_chg: AC charger power supply | 243 | * @ac_chg: AC charger power supply |
227 | * @usb_chg: USB charger power supply | 244 | * @usb_chg: USB charger power supply |
228 | * @ac: Structure that holds the AC charger properties | 245 | * @ac: Structure that holds the AC charger properties |
@@ -254,7 +271,6 @@ struct ab8500_charger_usb_state { | |||
254 | */ | 271 | */ |
255 | struct ab8500_charger { | 272 | struct ab8500_charger { |
256 | struct device *dev; | 273 | struct device *dev; |
257 | int max_usb_in_curr; | ||
258 | bool vbus_detected; | 274 | bool vbus_detected; |
259 | bool vbus_detected_start; | 275 | bool vbus_detected_start; |
260 | bool ac_conn; | 276 | bool ac_conn; |
@@ -266,7 +282,6 @@ struct ab8500_charger { | |||
266 | bool autopower; | 282 | bool autopower; |
267 | bool autopower_cfg; | 283 | bool autopower_cfg; |
268 | int invalid_charger_detect_state; | 284 | int invalid_charger_detect_state; |
269 | bool is_usb_host; | ||
270 | int is_aca_rid; | 285 | int is_aca_rid; |
271 | atomic_t current_stepping_sessions; | 286 | atomic_t current_stepping_sessions; |
272 | struct ab8500 *parent; | 287 | struct ab8500 *parent; |
@@ -274,6 +289,7 @@ struct ab8500_charger { | |||
274 | struct abx500_bm_data *bm; | 289 | struct abx500_bm_data *bm; |
275 | struct ab8500_charger_event_flags flags; | 290 | struct ab8500_charger_event_flags flags; |
276 | struct ab8500_charger_usb_state usb_state; | 291 | struct ab8500_charger_usb_state usb_state; |
292 | struct ab8500_charger_max_usb_in_curr max_usb_in_curr; | ||
277 | struct ux500_charger ac_chg; | 293 | struct ux500_charger ac_chg; |
278 | struct ux500_charger usb_chg; | 294 | struct ux500_charger usb_chg; |
279 | struct ab8500_charger_info ac; | 295 | struct ab8500_charger_info ac; |
@@ -415,13 +431,18 @@ static void ab8500_charger_set_usb_connected(struct ab8500_charger *di, | |||
415 | if (connected != di->usb.charger_connected) { | 431 | if (connected != di->usb.charger_connected) { |
416 | dev_dbg(di->dev, "USB connected:%i\n", connected); | 432 | dev_dbg(di->dev, "USB connected:%i\n", connected); |
417 | di->usb.charger_connected = connected; | 433 | di->usb.charger_connected = connected; |
434 | |||
435 | if (!connected) | ||
436 | di->flags.vbus_drop_end = false; | ||
437 | |||
418 | sysfs_notify(&di->usb_chg.psy.dev->kobj, NULL, "present"); | 438 | sysfs_notify(&di->usb_chg.psy.dev->kobj, NULL, "present"); |
419 | 439 | ||
420 | if (connected) { | 440 | if (connected) { |
421 | mutex_lock(&di->charger_attached_mutex); | 441 | mutex_lock(&di->charger_attached_mutex); |
422 | mutex_unlock(&di->charger_attached_mutex); | 442 | mutex_unlock(&di->charger_attached_mutex); |
423 | 443 | ||
424 | queue_delayed_work(di->charger_wq, | 444 | if (is_ab8500(di->parent)) |
445 | queue_delayed_work(di->charger_wq, | ||
425 | &di->usb_charger_attached_work, | 446 | &di->usb_charger_attached_work, |
426 | HZ); | 447 | HZ); |
427 | } else { | 448 | } else { |
@@ -668,23 +689,19 @@ static int ab8500_charger_max_usb_curr(struct ab8500_charger *di, | |||
668 | case USB_STAT_STD_HOST_C_S: | 689 | case USB_STAT_STD_HOST_C_S: |
669 | dev_dbg(di->dev, "USB Type - Standard host is " | 690 | dev_dbg(di->dev, "USB Type - Standard host is " |
670 | "detected through USB driver\n"); | 691 | "detected through USB driver\n"); |
671 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5; | 692 | di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5; |
672 | di->is_usb_host = true; | ||
673 | di->is_aca_rid = 0; | 693 | di->is_aca_rid = 0; |
674 | break; | 694 | break; |
675 | case USB_STAT_HOST_CHG_HS_CHIRP: | 695 | case USB_STAT_HOST_CHG_HS_CHIRP: |
676 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5; | 696 | di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5; |
677 | di->is_usb_host = true; | ||
678 | di->is_aca_rid = 0; | 697 | di->is_aca_rid = 0; |
679 | break; | 698 | break; |
680 | case USB_STAT_HOST_CHG_HS: | 699 | case USB_STAT_HOST_CHG_HS: |
681 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5; | 700 | di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5; |
682 | di->is_usb_host = true; | ||
683 | di->is_aca_rid = 0; | 701 | di->is_aca_rid = 0; |
684 | break; | 702 | break; |
685 | case USB_STAT_ACA_RID_C_HS: | 703 | case USB_STAT_ACA_RID_C_HS: |
686 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P9; | 704 | di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P9; |
687 | di->is_usb_host = false; | ||
688 | di->is_aca_rid = 0; | 705 | di->is_aca_rid = 0; |
689 | break; | 706 | break; |
690 | case USB_STAT_ACA_RID_A: | 707 | case USB_STAT_ACA_RID_A: |
@@ -693,8 +710,7 @@ static int ab8500_charger_max_usb_curr(struct ab8500_charger *di, | |||
693 | * can consume (900mA). Closest level is 500mA | 710 | * can consume (900mA). Closest level is 500mA |
694 | */ | 711 | */ |
695 | dev_dbg(di->dev, "USB_STAT_ACA_RID_A detected\n"); | 712 | dev_dbg(di->dev, "USB_STAT_ACA_RID_A detected\n"); |
696 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5; | 713 | di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5; |
697 | di->is_usb_host = false; | ||
698 | di->is_aca_rid = 1; | 714 | di->is_aca_rid = 1; |
699 | break; | 715 | break; |
700 | case USB_STAT_ACA_RID_B: | 716 | case USB_STAT_ACA_RID_B: |
@@ -702,38 +718,35 @@ static int ab8500_charger_max_usb_curr(struct ab8500_charger *di, | |||
702 | * Dedicated charger level minus 120mA (20mA for ACA and | 718 | * Dedicated charger level minus 120mA (20mA for ACA and |
703 | * 100mA for potential accessory). Closest level is 1300mA | 719 | * 100mA for potential accessory). Closest level is 1300mA |
704 | */ | 720 | */ |
705 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_1P3; | 721 | di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_1P3; |
706 | dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", link_status, | 722 | dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", link_status, |
707 | di->max_usb_in_curr); | 723 | di->max_usb_in_curr.usb_type_max); |
708 | di->is_usb_host = false; | ||
709 | di->is_aca_rid = 1; | 724 | di->is_aca_rid = 1; |
710 | break; | 725 | break; |
711 | case USB_STAT_HOST_CHG_NM: | 726 | case USB_STAT_HOST_CHG_NM: |
712 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5; | 727 | di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5; |
713 | di->is_usb_host = true; | ||
714 | di->is_aca_rid = 0; | 728 | di->is_aca_rid = 0; |
715 | break; | 729 | break; |
716 | case USB_STAT_DEDICATED_CHG: | 730 | case USB_STAT_DEDICATED_CHG: |
717 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_1P5; | 731 | di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_1P5; |
718 | di->is_usb_host = false; | ||
719 | di->is_aca_rid = 0; | 732 | di->is_aca_rid = 0; |
720 | break; | 733 | break; |
721 | case USB_STAT_ACA_RID_C_HS_CHIRP: | 734 | case USB_STAT_ACA_RID_C_HS_CHIRP: |
722 | case USB_STAT_ACA_RID_C_NM: | 735 | case USB_STAT_ACA_RID_C_NM: |
723 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_1P5; | 736 | di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_1P5; |
724 | di->is_usb_host = false; | ||
725 | di->is_aca_rid = 1; | 737 | di->is_aca_rid = 1; |
726 | break; | 738 | break; |
727 | case USB_STAT_NOT_CONFIGURED: | 739 | case USB_STAT_NOT_CONFIGURED: |
728 | if (di->vbus_detected) { | 740 | if (di->vbus_detected) { |
729 | di->usb_device_is_unrecognised = true; | 741 | di->usb_device_is_unrecognised = true; |
730 | dev_dbg(di->dev, "USB Type - Legacy charger.\n"); | 742 | dev_dbg(di->dev, "USB Type - Legacy charger.\n"); |
731 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_1P5; | 743 | di->max_usb_in_curr.usb_type_max = |
744 | USB_CH_IP_CUR_LVL_1P5; | ||
732 | break; | 745 | break; |
733 | } | 746 | } |
734 | case USB_STAT_HM_IDGND: | 747 | case USB_STAT_HM_IDGND: |
735 | dev_err(di->dev, "USB Type - Charging not allowed\n"); | 748 | dev_err(di->dev, "USB Type - Charging not allowed\n"); |
736 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P05; | 749 | di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P05; |
737 | ret = -ENXIO; | 750 | ret = -ENXIO; |
738 | break; | 751 | break; |
739 | case USB_STAT_RESERVED: | 752 | case USB_STAT_RESERVED: |
@@ -743,12 +756,13 @@ static int ab8500_charger_max_usb_curr(struct ab8500_charger *di, | |||
743 | "VBUS has collapsed\n"); | 756 | "VBUS has collapsed\n"); |
744 | ret = -ENXIO; | 757 | ret = -ENXIO; |
745 | break; | 758 | break; |
746 | } | 759 | } else { |
747 | if (is_ab9540(di->parent) || is_ab8505(di->parent)) { | ||
748 | dev_dbg(di->dev, "USB Type - Charging not allowed\n"); | 760 | dev_dbg(di->dev, "USB Type - Charging not allowed\n"); |
749 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P05; | 761 | di->max_usb_in_curr.usb_type_max = |
762 | USB_CH_IP_CUR_LVL_0P05; | ||
750 | dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", | 763 | dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", |
751 | link_status, di->max_usb_in_curr); | 764 | link_status, |
765 | di->max_usb_in_curr.usb_type_max); | ||
752 | ret = -ENXIO; | 766 | ret = -ENXIO; |
753 | break; | 767 | break; |
754 | } | 768 | } |
@@ -757,23 +771,24 @@ static int ab8500_charger_max_usb_curr(struct ab8500_charger *di, | |||
757 | case USB_STAT_CARKIT_2: | 771 | case USB_STAT_CARKIT_2: |
758 | case USB_STAT_ACA_DOCK_CHARGER: | 772 | case USB_STAT_ACA_DOCK_CHARGER: |
759 | case USB_STAT_CHARGER_LINE_1: | 773 | case USB_STAT_CHARGER_LINE_1: |
760 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5; | 774 | di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5; |
761 | dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", link_status, | 775 | dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", link_status, |
762 | di->max_usb_in_curr); | 776 | di->max_usb_in_curr.usb_type_max); |
763 | case USB_STAT_NOT_VALID_LINK: | 777 | case USB_STAT_NOT_VALID_LINK: |
764 | dev_err(di->dev, "USB Type invalid - try charging anyway\n"); | 778 | dev_err(di->dev, "USB Type invalid - try charging anyway\n"); |
765 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5; | 779 | di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5; |
766 | break; | 780 | break; |
767 | 781 | ||
768 | default: | 782 | default: |
769 | dev_err(di->dev, "USB Type - Unknown\n"); | 783 | dev_err(di->dev, "USB Type - Unknown\n"); |
770 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P05; | 784 | di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P05; |
771 | ret = -ENXIO; | 785 | ret = -ENXIO; |
772 | break; | 786 | break; |
773 | }; | 787 | }; |
774 | 788 | ||
789 | di->max_usb_in_curr.set_max = di->max_usb_in_curr.usb_type_max; | ||
775 | dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", | 790 | dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", |
776 | link_status, di->max_usb_in_curr); | 791 | link_status, di->max_usb_in_curr.set_max); |
777 | 792 | ||
778 | return ret; | 793 | return ret; |
779 | } | 794 | } |
@@ -796,21 +811,22 @@ static int ab8500_charger_read_usb_type(struct ab8500_charger *di) | |||
796 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); | 811 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); |
797 | return ret; | 812 | return ret; |
798 | } | 813 | } |
799 | if (is_ab8500(di->parent)) { | 814 | if (is_ab8500(di->parent)) |
800 | ret = abx500_get_register_interruptible(di->dev, AB8500_USB, | 815 | ret = abx500_get_register_interruptible(di->dev, AB8500_USB, |
801 | AB8500_USB_LINE_STAT_REG, &val); | 816 | AB8500_USB_LINE_STAT_REG, &val); |
802 | } else { | 817 | else |
803 | if (is_ab9540(di->parent) || is_ab8505(di->parent)) | 818 | ret = abx500_get_register_interruptible(di->dev, |
804 | ret = abx500_get_register_interruptible(di->dev, | 819 | AB8500_USB, AB8500_USB_LINK1_STAT_REG, &val); |
805 | AB8500_USB, AB8500_USB_LINK1_STAT_REG, &val); | ||
806 | } | ||
807 | if (ret < 0) { | 820 | if (ret < 0) { |
808 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); | 821 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); |
809 | return ret; | 822 | return ret; |
810 | } | 823 | } |
811 | 824 | ||
812 | /* get the USB type */ | 825 | /* get the USB type */ |
813 | val = (val & AB8500_USB_LINK_STATUS) >> 3; | 826 | if (is_ab8500(di->parent)) |
827 | val = (val & AB8500_USB_LINK_STATUS) >> USB_LINK_STATUS_SHIFT; | ||
828 | else | ||
829 | val = (val & AB8505_USB_LINK_STATUS) >> USB_LINK_STATUS_SHIFT; | ||
814 | ret = ab8500_charger_max_usb_curr(di, | 830 | ret = ab8500_charger_max_usb_curr(di, |
815 | (enum ab8500_charger_link_status) val); | 831 | (enum ab8500_charger_link_status) val); |
816 | 832 | ||
@@ -865,7 +881,12 @@ static int ab8500_charger_detect_usb_type(struct ab8500_charger *di) | |||
865 | */ | 881 | */ |
866 | 882 | ||
867 | /* get the USB type */ | 883 | /* get the USB type */ |
868 | val = (val & AB8500_USB_LINK_STATUS) >> 3; | 884 | if (is_ab8500(di->parent)) |
885 | val = (val & AB8500_USB_LINK_STATUS) >> | ||
886 | USB_LINK_STATUS_SHIFT; | ||
887 | else | ||
888 | val = (val & AB8505_USB_LINK_STATUS) >> | ||
889 | USB_LINK_STATUS_SHIFT; | ||
869 | if (val) | 890 | if (val) |
870 | break; | 891 | break; |
871 | } | 892 | } |
@@ -960,51 +981,6 @@ static int ab8500_charger_voltage_map[] = { | |||
960 | 4600 , | 981 | 4600 , |
961 | }; | 982 | }; |
962 | 983 | ||
963 | /* | ||
964 | * This array maps the raw hex value to charger current used by the AB8500 | ||
965 | * Values taken from the UM0836 | ||
966 | */ | ||
967 | static int ab8500_charger_current_map[] = { | ||
968 | 100 , | ||
969 | 200 , | ||
970 | 300 , | ||
971 | 400 , | ||
972 | 500 , | ||
973 | 600 , | ||
974 | 700 , | ||
975 | 800 , | ||
976 | 900 , | ||
977 | 1000 , | ||
978 | 1100 , | ||
979 | 1200 , | ||
980 | 1300 , | ||
981 | 1400 , | ||
982 | 1500 , | ||
983 | }; | ||
984 | |||
985 | /* | ||
986 | * This array maps the raw hex value to VBUS input current used by the AB8500 | ||
987 | * Values taken from the UM0836 | ||
988 | */ | ||
989 | static int ab8500_charger_vbus_in_curr_map[] = { | ||
990 | USB_CH_IP_CUR_LVL_0P05, | ||
991 | USB_CH_IP_CUR_LVL_0P09, | ||
992 | USB_CH_IP_CUR_LVL_0P19, | ||
993 | USB_CH_IP_CUR_LVL_0P29, | ||
994 | USB_CH_IP_CUR_LVL_0P38, | ||
995 | USB_CH_IP_CUR_LVL_0P45, | ||
996 | USB_CH_IP_CUR_LVL_0P5, | ||
997 | USB_CH_IP_CUR_LVL_0P6, | ||
998 | USB_CH_IP_CUR_LVL_0P7, | ||
999 | USB_CH_IP_CUR_LVL_0P8, | ||
1000 | USB_CH_IP_CUR_LVL_0P9, | ||
1001 | USB_CH_IP_CUR_LVL_1P0, | ||
1002 | USB_CH_IP_CUR_LVL_1P1, | ||
1003 | USB_CH_IP_CUR_LVL_1P3, | ||
1004 | USB_CH_IP_CUR_LVL_1P4, | ||
1005 | USB_CH_IP_CUR_LVL_1P5, | ||
1006 | }; | ||
1007 | |||
1008 | static int ab8500_voltage_to_regval(int voltage) | 984 | static int ab8500_voltage_to_regval(int voltage) |
1009 | { | 985 | { |
1010 | int i; | 986 | int i; |
@@ -1026,41 +1002,41 @@ static int ab8500_voltage_to_regval(int voltage) | |||
1026 | return -1; | 1002 | return -1; |
1027 | } | 1003 | } |
1028 | 1004 | ||
1029 | static int ab8500_current_to_regval(int curr) | 1005 | static int ab8500_current_to_regval(struct ab8500_charger *di, int curr) |
1030 | { | 1006 | { |
1031 | int i; | 1007 | int i; |
1032 | 1008 | ||
1033 | if (curr < ab8500_charger_current_map[0]) | 1009 | if (curr < di->bm->chg_output_curr[0]) |
1034 | return 0; | 1010 | return 0; |
1035 | 1011 | ||
1036 | for (i = 0; i < ARRAY_SIZE(ab8500_charger_current_map); i++) { | 1012 | for (i = 0; i < di->bm->n_chg_out_curr; i++) { |
1037 | if (curr < ab8500_charger_current_map[i]) | 1013 | if (curr < di->bm->chg_output_curr[i]) |
1038 | return i - 1; | 1014 | return i - 1; |
1039 | } | 1015 | } |
1040 | 1016 | ||
1041 | /* If not last element, return error */ | 1017 | /* If not last element, return error */ |
1042 | i = ARRAY_SIZE(ab8500_charger_current_map) - 1; | 1018 | i = di->bm->n_chg_out_curr - 1; |
1043 | if (curr == ab8500_charger_current_map[i]) | 1019 | if (curr == di->bm->chg_output_curr[i]) |
1044 | return i; | 1020 | return i; |
1045 | else | 1021 | else |
1046 | return -1; | 1022 | return -1; |
1047 | } | 1023 | } |
1048 | 1024 | ||
1049 | static int ab8500_vbus_in_curr_to_regval(int curr) | 1025 | static int ab8500_vbus_in_curr_to_regval(struct ab8500_charger *di, int curr) |
1050 | { | 1026 | { |
1051 | int i; | 1027 | int i; |
1052 | 1028 | ||
1053 | if (curr < ab8500_charger_vbus_in_curr_map[0]) | 1029 | if (curr < di->bm->chg_input_curr[0]) |
1054 | return 0; | 1030 | return 0; |
1055 | 1031 | ||
1056 | for (i = 0; i < ARRAY_SIZE(ab8500_charger_vbus_in_curr_map); i++) { | 1032 | for (i = 0; i < di->bm->n_chg_in_curr; i++) { |
1057 | if (curr < ab8500_charger_vbus_in_curr_map[i]) | 1033 | if (curr < di->bm->chg_input_curr[i]) |
1058 | return i - 1; | 1034 | return i - 1; |
1059 | } | 1035 | } |
1060 | 1036 | ||
1061 | /* If not last element, return error */ | 1037 | /* If not last element, return error */ |
1062 | i = ARRAY_SIZE(ab8500_charger_vbus_in_curr_map) - 1; | 1038 | i = di->bm->n_chg_in_curr - 1; |
1063 | if (curr == ab8500_charger_vbus_in_curr_map[i]) | 1039 | if (curr == di->bm->chg_input_curr[i]) |
1064 | return i; | 1040 | return i; |
1065 | else | 1041 | else |
1066 | return -1; | 1042 | return -1; |
@@ -1077,28 +1053,48 @@ static int ab8500_vbus_in_curr_to_regval(int curr) | |||
1077 | */ | 1053 | */ |
1078 | static int ab8500_charger_get_usb_cur(struct ab8500_charger *di) | 1054 | static int ab8500_charger_get_usb_cur(struct ab8500_charger *di) |
1079 | { | 1055 | { |
1056 | int ret = 0; | ||
1080 | switch (di->usb_state.usb_current) { | 1057 | switch (di->usb_state.usb_current) { |
1081 | case 100: | 1058 | case 100: |
1082 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P09; | 1059 | di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P09; |
1083 | break; | 1060 | break; |
1084 | case 200: | 1061 | case 200: |
1085 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P19; | 1062 | di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P19; |
1086 | break; | 1063 | break; |
1087 | case 300: | 1064 | case 300: |
1088 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P29; | 1065 | di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P29; |
1089 | break; | 1066 | break; |
1090 | case 400: | 1067 | case 400: |
1091 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P38; | 1068 | di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P38; |
1092 | break; | 1069 | break; |
1093 | case 500: | 1070 | case 500: |
1094 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5; | 1071 | di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5; |
1095 | break; | 1072 | break; |
1096 | default: | 1073 | default: |
1097 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P05; | 1074 | di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P05; |
1098 | return -1; | 1075 | ret = -EPERM; |
1099 | break; | 1076 | break; |
1100 | }; | 1077 | }; |
1101 | return 0; | 1078 | di->max_usb_in_curr.set_max = di->max_usb_in_curr.usb_type_max; |
1079 | return ret; | ||
1080 | } | ||
1081 | |||
1082 | /** | ||
1083 | * ab8500_charger_check_continue_stepping() - Check to allow stepping | ||
1084 | * @di: pointer to the ab8500_charger structure | ||
1085 | * @reg: select what charger register to check | ||
1086 | * | ||
1087 | * Check if current stepping should be allowed to continue. | ||
1088 | * Checks if charger source has not collapsed. If it has, further stepping | ||
1089 | * is not allowed. | ||
1090 | */ | ||
1091 | static bool ab8500_charger_check_continue_stepping(struct ab8500_charger *di, | ||
1092 | int reg) | ||
1093 | { | ||
1094 | if (reg == AB8500_USBCH_IPT_CRNTLVL_REG) | ||
1095 | return !di->flags.vbus_drop_end; | ||
1096 | else | ||
1097 | return true; | ||
1102 | } | 1098 | } |
1103 | 1099 | ||
1104 | /** | 1100 | /** |
@@ -1118,7 +1114,7 @@ static int ab8500_charger_set_current(struct ab8500_charger *di, | |||
1118 | int ich, int reg) | 1114 | int ich, int reg) |
1119 | { | 1115 | { |
1120 | int ret = 0; | 1116 | int ret = 0; |
1121 | int auto_curr_index, curr_index, prev_curr_index, shift_value, i; | 1117 | int curr_index, prev_curr_index, shift_value, i; |
1122 | u8 reg_value; | 1118 | u8 reg_value; |
1123 | u32 step_udelay; | 1119 | u32 step_udelay; |
1124 | bool no_stepping = false; | 1120 | bool no_stepping = false; |
@@ -1136,39 +1132,27 @@ static int ab8500_charger_set_current(struct ab8500_charger *di, | |||
1136 | case AB8500_MCH_IPT_CURLVL_REG: | 1132 | case AB8500_MCH_IPT_CURLVL_REG: |
1137 | shift_value = MAIN_CH_INPUT_CURR_SHIFT; | 1133 | shift_value = MAIN_CH_INPUT_CURR_SHIFT; |
1138 | prev_curr_index = (reg_value >> shift_value); | 1134 | prev_curr_index = (reg_value >> shift_value); |
1139 | curr_index = ab8500_current_to_regval(ich); | 1135 | curr_index = ab8500_current_to_regval(di, ich); |
1140 | step_udelay = STEP_UDELAY; | 1136 | step_udelay = STEP_UDELAY; |
1141 | if (!di->ac.charger_connected) | 1137 | if (!di->ac.charger_connected) |
1142 | no_stepping = true; | 1138 | no_stepping = true; |
1143 | break; | 1139 | break; |
1144 | case AB8500_USBCH_IPT_CRNTLVL_REG: | 1140 | case AB8500_USBCH_IPT_CRNTLVL_REG: |
1145 | shift_value = VBUS_IN_CURR_LIM_SHIFT; | 1141 | if (is_ab8540(di->parent)) |
1142 | shift_value = AB8540_VBUS_IN_CURR_LIM_SHIFT; | ||
1143 | else | ||
1144 | shift_value = VBUS_IN_CURR_LIM_SHIFT; | ||
1146 | prev_curr_index = (reg_value >> shift_value); | 1145 | prev_curr_index = (reg_value >> shift_value); |
1147 | curr_index = ab8500_vbus_in_curr_to_regval(ich); | 1146 | curr_index = ab8500_vbus_in_curr_to_regval(di, ich); |
1148 | step_udelay = STEP_UDELAY * 100; | 1147 | step_udelay = STEP_UDELAY * 100; |
1149 | 1148 | ||
1150 | ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, | ||
1151 | AB8500_CH_USBCH_STAT2_REG, ®_value); | ||
1152 | if (ret < 0) { | ||
1153 | dev_err(di->dev, "%s read failed\n", __func__); | ||
1154 | goto exit_set_current; | ||
1155 | } | ||
1156 | auto_curr_index = | ||
1157 | reg_value >> AUTO_VBUS_IN_CURR_LIM_SHIFT; | ||
1158 | |||
1159 | dev_dbg(di->dev, "%s Auto VBUS curr is %d mA\n", | ||
1160 | __func__, | ||
1161 | ab8500_charger_vbus_in_curr_map[auto_curr_index]); | ||
1162 | |||
1163 | prev_curr_index = min(prev_curr_index, auto_curr_index); | ||
1164 | |||
1165 | if (!di->usb.charger_connected) | 1149 | if (!di->usb.charger_connected) |
1166 | no_stepping = true; | 1150 | no_stepping = true; |
1167 | break; | 1151 | break; |
1168 | case AB8500_CH_OPT_CRNTLVL_REG: | 1152 | case AB8500_CH_OPT_CRNTLVL_REG: |
1169 | shift_value = 0; | 1153 | shift_value = 0; |
1170 | prev_curr_index = (reg_value >> shift_value); | 1154 | prev_curr_index = (reg_value >> shift_value); |
1171 | curr_index = ab8500_current_to_regval(ich); | 1155 | curr_index = ab8500_current_to_regval(di, ich); |
1172 | step_udelay = STEP_UDELAY; | 1156 | step_udelay = STEP_UDELAY; |
1173 | if (curr_index && (curr_index - prev_curr_index) > 1) | 1157 | if (curr_index && (curr_index - prev_curr_index) > 1) |
1174 | step_udelay *= 100; | 1158 | step_udelay *= 100; |
@@ -1219,7 +1203,8 @@ static int ab8500_charger_set_current(struct ab8500_charger *di, | |||
1219 | usleep_range(step_udelay, step_udelay * 2); | 1203 | usleep_range(step_udelay, step_udelay * 2); |
1220 | } | 1204 | } |
1221 | } else { | 1205 | } else { |
1222 | for (i = prev_curr_index + 1; i <= curr_index; i++) { | 1206 | bool allow = true; |
1207 | for (i = prev_curr_index + 1; i <= curr_index && allow; i++) { | ||
1223 | dev_dbg(di->dev, "curr change_2 to: %x for 0x%02x\n", | 1208 | dev_dbg(di->dev, "curr change_2 to: %x for 0x%02x\n", |
1224 | (u8)i << shift_value, reg); | 1209 | (u8)i << shift_value, reg); |
1225 | ret = abx500_set_register_interruptible(di->dev, | 1210 | ret = abx500_set_register_interruptible(di->dev, |
@@ -1230,6 +1215,8 @@ static int ab8500_charger_set_current(struct ab8500_charger *di, | |||
1230 | } | 1215 | } |
1231 | if (i != curr_index) | 1216 | if (i != curr_index) |
1232 | usleep_range(step_udelay, step_udelay * 2); | 1217 | usleep_range(step_udelay, step_udelay * 2); |
1218 | |||
1219 | allow = ab8500_charger_check_continue_stepping(di, reg); | ||
1233 | } | 1220 | } |
1234 | } | 1221 | } |
1235 | 1222 | ||
@@ -1255,6 +1242,11 @@ static int ab8500_charger_set_vbus_in_curr(struct ab8500_charger *di, | |||
1255 | 1242 | ||
1256 | /* We should always use to lowest current limit */ | 1243 | /* We should always use to lowest current limit */ |
1257 | min_value = min(di->bm->chg_params->usb_curr_max, ich_in); | 1244 | min_value = min(di->bm->chg_params->usb_curr_max, ich_in); |
1245 | if (di->max_usb_in_curr.set_max > 0) | ||
1246 | min_value = min(di->max_usb_in_curr.set_max, min_value); | ||
1247 | |||
1248 | if (di->usb_state.usb_current >= 0) | ||
1249 | min_value = min(di->usb_state.usb_current, min_value); | ||
1258 | 1250 | ||
1259 | switch (min_value) { | 1251 | switch (min_value) { |
1260 | case 100: | 1252 | case 100: |
@@ -1400,8 +1392,8 @@ static int ab8500_charger_ac_en(struct ux500_charger *charger, | |||
1400 | 1392 | ||
1401 | /* Check if the requested voltage or current is valid */ | 1393 | /* Check if the requested voltage or current is valid */ |
1402 | volt_index = ab8500_voltage_to_regval(vset); | 1394 | volt_index = ab8500_voltage_to_regval(vset); |
1403 | curr_index = ab8500_current_to_regval(iset); | 1395 | curr_index = ab8500_current_to_regval(di, iset); |
1404 | input_curr_index = ab8500_current_to_regval( | 1396 | input_curr_index = ab8500_current_to_regval(di, |
1405 | di->bm->chg_params->ac_curr_max); | 1397 | di->bm->chg_params->ac_curr_max); |
1406 | if (volt_index < 0 || curr_index < 0 || input_curr_index < 0) { | 1398 | if (volt_index < 0 || curr_index < 0 || input_curr_index < 0) { |
1407 | dev_err(di->dev, | 1399 | dev_err(di->dev, |
@@ -1572,7 +1564,7 @@ static int ab8500_charger_usb_en(struct ux500_charger *charger, | |||
1572 | 1564 | ||
1573 | /* Check if the requested voltage or current is valid */ | 1565 | /* Check if the requested voltage or current is valid */ |
1574 | volt_index = ab8500_voltage_to_regval(vset); | 1566 | volt_index = ab8500_voltage_to_regval(vset); |
1575 | curr_index = ab8500_current_to_regval(ich_out); | 1567 | curr_index = ab8500_current_to_regval(di, ich_out); |
1576 | if (volt_index < 0 || curr_index < 0) { | 1568 | if (volt_index < 0 || curr_index < 0) { |
1577 | dev_err(di->dev, | 1569 | dev_err(di->dev, |
1578 | "Charger voltage or current too high, " | 1570 | "Charger voltage or current too high, " |
@@ -1609,7 +1601,8 @@ static int ab8500_charger_usb_en(struct ux500_charger *charger, | |||
1609 | di->usb.charger_online = 1; | 1601 | di->usb.charger_online = 1; |
1610 | 1602 | ||
1611 | /* USBChInputCurr: current that can be drawn from the usb */ | 1603 | /* USBChInputCurr: current that can be drawn from the usb */ |
1612 | ret = ab8500_charger_set_vbus_in_curr(di, di->max_usb_in_curr); | 1604 | ret = ab8500_charger_set_vbus_in_curr(di, |
1605 | di->max_usb_in_curr.usb_type_max); | ||
1613 | if (ret) { | 1606 | if (ret) { |
1614 | dev_err(di->dev, "setting USBChInputCurr failed\n"); | 1607 | dev_err(di->dev, "setting USBChInputCurr failed\n"); |
1615 | return ret; | 1608 | return ret; |
@@ -1668,8 +1661,7 @@ static int ab8500_charger_usb_en(struct ux500_charger *charger, | |||
1668 | dev_dbg(di->dev, "%s Disabled USB charging\n", __func__); | 1661 | dev_dbg(di->dev, "%s Disabled USB charging\n", __func__); |
1669 | 1662 | ||
1670 | /* Cancel any pending Vbat check work */ | 1663 | /* Cancel any pending Vbat check work */ |
1671 | if (delayed_work_pending(&di->check_vbat_work)) | 1664 | cancel_delayed_work(&di->check_vbat_work); |
1672 | cancel_delayed_work(&di->check_vbat_work); | ||
1673 | 1665 | ||
1674 | } | 1666 | } |
1675 | ab8500_power_supply_changed(di, &di->usb_chg.psy); | 1667 | ab8500_power_supply_changed(di, &di->usb_chg.psy); |
@@ -1677,6 +1669,128 @@ static int ab8500_charger_usb_en(struct ux500_charger *charger, | |||
1677 | return ret; | 1669 | return ret; |
1678 | } | 1670 | } |
1679 | 1671 | ||
1672 | static int ab8500_external_charger_prepare(struct notifier_block *charger_nb, | ||
1673 | unsigned long event, void *data) | ||
1674 | { | ||
1675 | int ret; | ||
1676 | struct device *dev = data; | ||
1677 | /*Toggle External charger control pin*/ | ||
1678 | ret = abx500_set_register_interruptible(dev, AB8500_SYS_CTRL1_BLOCK, | ||
1679 | AB8500_SYS_CHARGER_CONTROL_REG, | ||
1680 | EXTERNAL_CHARGER_DISABLE_REG_VAL); | ||
1681 | if (ret < 0) { | ||
1682 | dev_err(dev, "write reg failed %d\n", ret); | ||
1683 | goto out; | ||
1684 | } | ||
1685 | ret = abx500_set_register_interruptible(dev, AB8500_SYS_CTRL1_BLOCK, | ||
1686 | AB8500_SYS_CHARGER_CONTROL_REG, | ||
1687 | EXTERNAL_CHARGER_ENABLE_REG_VAL); | ||
1688 | if (ret < 0) | ||
1689 | dev_err(dev, "Write reg failed %d\n", ret); | ||
1690 | |||
1691 | out: | ||
1692 | return ret; | ||
1693 | } | ||
1694 | |||
1695 | /** | ||
1696 | * ab8500_charger_usb_check_enable() - enable usb charging | ||
1697 | * @charger: pointer to the ux500_charger structure | ||
1698 | * @vset: charging voltage | ||
1699 | * @iset: charger output current | ||
1700 | * | ||
1701 | * Check if the VBUS charger has been disconnected and reconnected without | ||
1702 | * AB8500 rising an interrupt. Returns 0 on success. | ||
1703 | */ | ||
1704 | static int ab8500_charger_usb_check_enable(struct ux500_charger *charger, | ||
1705 | int vset, int iset) | ||
1706 | { | ||
1707 | u8 usbch_ctrl1 = 0; | ||
1708 | int ret = 0; | ||
1709 | |||
1710 | struct ab8500_charger *di = to_ab8500_charger_usb_device_info(charger); | ||
1711 | |||
1712 | if (!di->usb.charger_connected) | ||
1713 | return ret; | ||
1714 | |||
1715 | ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, | ||
1716 | AB8500_USBCH_CTRL1_REG, &usbch_ctrl1); | ||
1717 | if (ret < 0) { | ||
1718 | dev_err(di->dev, "ab8500 read failed %d\n", __LINE__); | ||
1719 | return ret; | ||
1720 | } | ||
1721 | dev_dbg(di->dev, "USB charger ctrl: 0x%02x\n", usbch_ctrl1); | ||
1722 | |||
1723 | if (!(usbch_ctrl1 & USB_CH_ENA)) { | ||
1724 | dev_info(di->dev, "Charging has been disabled abnormally and will be re-enabled\n"); | ||
1725 | |||
1726 | ret = abx500_mask_and_set_register_interruptible(di->dev, | ||
1727 | AB8500_CHARGER, AB8500_CHARGER_CTRL, | ||
1728 | DROP_COUNT_RESET, DROP_COUNT_RESET); | ||
1729 | if (ret < 0) { | ||
1730 | dev_err(di->dev, "ab8500 write failed %d\n", __LINE__); | ||
1731 | return ret; | ||
1732 | } | ||
1733 | |||
1734 | ret = ab8500_charger_usb_en(&di->usb_chg, true, vset, iset); | ||
1735 | if (ret < 0) { | ||
1736 | dev_err(di->dev, "Failed to enable VBUS charger %d\n", | ||
1737 | __LINE__); | ||
1738 | return ret; | ||
1739 | } | ||
1740 | } | ||
1741 | return ret; | ||
1742 | } | ||
1743 | |||
1744 | /** | ||
1745 | * ab8500_charger_ac_check_enable() - enable usb charging | ||
1746 | * @charger: pointer to the ux500_charger structure | ||
1747 | * @vset: charging voltage | ||
1748 | * @iset: charger output current | ||
1749 | * | ||
1750 | * Check if the AC charger has been disconnected and reconnected without | ||
1751 | * AB8500 rising an interrupt. Returns 0 on success. | ||
1752 | */ | ||
1753 | static int ab8500_charger_ac_check_enable(struct ux500_charger *charger, | ||
1754 | int vset, int iset) | ||
1755 | { | ||
1756 | u8 mainch_ctrl1 = 0; | ||
1757 | int ret = 0; | ||
1758 | |||
1759 | struct ab8500_charger *di = to_ab8500_charger_ac_device_info(charger); | ||
1760 | |||
1761 | if (!di->ac.charger_connected) | ||
1762 | return ret; | ||
1763 | |||
1764 | ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, | ||
1765 | AB8500_MCH_CTRL1, &mainch_ctrl1); | ||
1766 | if (ret < 0) { | ||
1767 | dev_err(di->dev, "ab8500 read failed %d\n", __LINE__); | ||
1768 | return ret; | ||
1769 | } | ||
1770 | dev_dbg(di->dev, "AC charger ctrl: 0x%02x\n", mainch_ctrl1); | ||
1771 | |||
1772 | if (!(mainch_ctrl1 & MAIN_CH_ENA)) { | ||
1773 | dev_info(di->dev, "Charging has been disabled abnormally and will be re-enabled\n"); | ||
1774 | |||
1775 | ret = abx500_mask_and_set_register_interruptible(di->dev, | ||
1776 | AB8500_CHARGER, AB8500_CHARGER_CTRL, | ||
1777 | DROP_COUNT_RESET, DROP_COUNT_RESET); | ||
1778 | |||
1779 | if (ret < 0) { | ||
1780 | dev_err(di->dev, "ab8500 write failed %d\n", __LINE__); | ||
1781 | return ret; | ||
1782 | } | ||
1783 | |||
1784 | ret = ab8500_charger_ac_en(&di->usb_chg, true, vset, iset); | ||
1785 | if (ret < 0) { | ||
1786 | dev_err(di->dev, "failed to enable AC charger %d\n", | ||
1787 | __LINE__); | ||
1788 | return ret; | ||
1789 | } | ||
1790 | } | ||
1791 | return ret; | ||
1792 | } | ||
1793 | |||
1680 | /** | 1794 | /** |
1681 | * ab8500_charger_watchdog_kick() - kick charger watchdog | 1795 | * ab8500_charger_watchdog_kick() - kick charger watchdog |
1682 | * @di: pointer to the ab8500_charger structure | 1796 | * @di: pointer to the ab8500_charger structure |
@@ -1734,8 +1848,68 @@ static int ab8500_charger_update_charger_current(struct ux500_charger *charger, | |||
1734 | 1848 | ||
1735 | /* Reset the main and usb drop input current measurement counter */ | 1849 | /* Reset the main and usb drop input current measurement counter */ |
1736 | ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, | 1850 | ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, |
1737 | AB8500_CHARGER_CTRL, | 1851 | AB8500_CHARGER_CTRL, DROP_COUNT_RESET); |
1738 | 0x1); | 1852 | if (ret) { |
1853 | dev_err(di->dev, "%s write failed\n", __func__); | ||
1854 | return ret; | ||
1855 | } | ||
1856 | |||
1857 | return ret; | ||
1858 | } | ||
1859 | |||
1860 | /** | ||
1861 | * ab8540_charger_power_path_enable() - enable usb power path mode | ||
1862 | * @charger: pointer to the ux500_charger structure | ||
1863 | * @enable: enable/disable flag | ||
1864 | * | ||
1865 | * Enable or disable the power path for usb mode | ||
1866 | * Returns error code in case of failure else 0(on success) | ||
1867 | */ | ||
1868 | static int ab8540_charger_power_path_enable(struct ux500_charger *charger, | ||
1869 | bool enable) | ||
1870 | { | ||
1871 | int ret; | ||
1872 | struct ab8500_charger *di; | ||
1873 | |||
1874 | if (charger->psy.type == POWER_SUPPLY_TYPE_USB) | ||
1875 | di = to_ab8500_charger_usb_device_info(charger); | ||
1876 | else | ||
1877 | return -ENXIO; | ||
1878 | |||
1879 | ret = abx500_mask_and_set_register_interruptible(di->dev, | ||
1880 | AB8500_CHARGER, AB8540_USB_PP_MODE_REG, | ||
1881 | BUS_POWER_PATH_MODE_ENA, enable); | ||
1882 | if (ret) { | ||
1883 | dev_err(di->dev, "%s write failed\n", __func__); | ||
1884 | return ret; | ||
1885 | } | ||
1886 | |||
1887 | return ret; | ||
1888 | } | ||
1889 | |||
1890 | |||
1891 | /** | ||
1892 | * ab8540_charger_usb_pre_chg_enable() - enable usb pre change | ||
1893 | * @charger: pointer to the ux500_charger structure | ||
1894 | * @enable: enable/disable flag | ||
1895 | * | ||
1896 | * Enable or disable the pre-chage for usb mode | ||
1897 | * Returns error code in case of failure else 0(on success) | ||
1898 | */ | ||
1899 | static int ab8540_charger_usb_pre_chg_enable(struct ux500_charger *charger, | ||
1900 | bool enable) | ||
1901 | { | ||
1902 | int ret; | ||
1903 | struct ab8500_charger *di; | ||
1904 | |||
1905 | if (charger->psy.type == POWER_SUPPLY_TYPE_USB) | ||
1906 | di = to_ab8500_charger_usb_device_info(charger); | ||
1907 | else | ||
1908 | return -ENXIO; | ||
1909 | |||
1910 | ret = abx500_mask_and_set_register_interruptible(di->dev, | ||
1911 | AB8500_CHARGER, AB8540_USB_PP_CHR_REG, | ||
1912 | BUS_POWER_PATH_PRECHG_ENA, enable); | ||
1739 | if (ret) { | 1913 | if (ret) { |
1740 | dev_err(di->dev, "%s write failed\n", __func__); | 1914 | dev_err(di->dev, "%s write failed\n", __func__); |
1741 | return ret; | 1915 | return ret; |
@@ -1823,9 +1997,10 @@ static void ab8500_charger_check_vbat_work(struct work_struct *work) | |||
1823 | di->vbat > VBAT_TRESH_IP_CUR_RED))) { | 1997 | di->vbat > VBAT_TRESH_IP_CUR_RED))) { |
1824 | 1998 | ||
1825 | dev_dbg(di->dev, "Vbat did cross threshold, curr: %d, new: %d," | 1999 | dev_dbg(di->dev, "Vbat did cross threshold, curr: %d, new: %d," |
1826 | " old: %d\n", di->max_usb_in_curr, di->vbat, | 2000 | " old: %d\n", di->max_usb_in_curr.usb_type_max, |
1827 | di->old_vbat); | 2001 | di->vbat, di->old_vbat); |
1828 | ab8500_charger_set_vbus_in_curr(di, di->max_usb_in_curr); | 2002 | ab8500_charger_set_vbus_in_curr(di, |
2003 | di->max_usb_in_curr.usb_type_max); | ||
1829 | power_supply_changed(&di->usb_chg.psy); | 2004 | power_supply_changed(&di->usb_chg.psy); |
1830 | } | 2005 | } |
1831 | 2006 | ||
@@ -2105,7 +2280,8 @@ static void ab8500_charger_usb_link_attach_work(struct work_struct *work) | |||
2105 | 2280 | ||
2106 | /* Update maximum input current if USB enumeration is not detected */ | 2281 | /* Update maximum input current if USB enumeration is not detected */ |
2107 | if (!di->usb.charger_online) { | 2282 | if (!di->usb.charger_online) { |
2108 | ret = ab8500_charger_set_vbus_in_curr(di, di->max_usb_in_curr); | 2283 | ret = ab8500_charger_set_vbus_in_curr(di, |
2284 | di->max_usb_in_curr.usb_type_max); | ||
2109 | if (ret) | 2285 | if (ret) |
2110 | return; | 2286 | return; |
2111 | } | 2287 | } |
@@ -2125,6 +2301,7 @@ static void ab8500_charger_usb_link_status_work(struct work_struct *work) | |||
2125 | int detected_chargers; | 2301 | int detected_chargers; |
2126 | int ret; | 2302 | int ret; |
2127 | u8 val; | 2303 | u8 val; |
2304 | u8 link_status; | ||
2128 | 2305 | ||
2129 | struct ab8500_charger *di = container_of(work, | 2306 | struct ab8500_charger *di = container_of(work, |
2130 | struct ab8500_charger, usb_link_status_work); | 2307 | struct ab8500_charger, usb_link_status_work); |
@@ -2144,38 +2321,61 @@ static void ab8500_charger_usb_link_status_work(struct work_struct *work) | |||
2144 | * to start the charging process. but by jumping | 2321 | * to start the charging process. but by jumping |
2145 | * thru a few hoops it can be forced to start. | 2322 | * thru a few hoops it can be forced to start. |
2146 | */ | 2323 | */ |
2147 | ret = abx500_get_register_interruptible(di->dev, AB8500_USB, | 2324 | if (is_ab8500(di->parent)) |
2148 | AB8500_USB_LINE_STAT_REG, &val); | 2325 | ret = abx500_get_register_interruptible(di->dev, AB8500_USB, |
2326 | AB8500_USB_LINE_STAT_REG, &val); | ||
2327 | else | ||
2328 | ret = abx500_get_register_interruptible(di->dev, AB8500_USB, | ||
2329 | AB8500_USB_LINK1_STAT_REG, &val); | ||
2330 | |||
2149 | if (ret >= 0) | 2331 | if (ret >= 0) |
2150 | dev_dbg(di->dev, "UsbLineStatus register = 0x%02x\n", val); | 2332 | dev_dbg(di->dev, "UsbLineStatus register = 0x%02x\n", val); |
2151 | else | 2333 | else |
2152 | dev_dbg(di->dev, "Error reading USB link status\n"); | 2334 | dev_dbg(di->dev, "Error reading USB link status\n"); |
2153 | 2335 | ||
2336 | if (is_ab8500(di->parent)) | ||
2337 | link_status = AB8500_USB_LINK_STATUS; | ||
2338 | else | ||
2339 | link_status = AB8505_USB_LINK_STATUS; | ||
2340 | |||
2154 | if (detected_chargers & USB_PW_CONN) { | 2341 | if (detected_chargers & USB_PW_CONN) { |
2155 | if (((val & AB8500_USB_LINK_STATUS) >> 3) == USB_STAT_NOT_VALID_LINK && | 2342 | if (((val & link_status) >> USB_LINK_STATUS_SHIFT) == |
2343 | USB_STAT_NOT_VALID_LINK && | ||
2156 | di->invalid_charger_detect_state == 0) { | 2344 | di->invalid_charger_detect_state == 0) { |
2157 | dev_dbg(di->dev, "Invalid charger detected, state= 0\n"); | 2345 | dev_dbg(di->dev, |
2346 | "Invalid charger detected, state= 0\n"); | ||
2158 | /*Enable charger*/ | 2347 | /*Enable charger*/ |
2159 | abx500_mask_and_set_register_interruptible(di->dev, | 2348 | abx500_mask_and_set_register_interruptible(di->dev, |
2160 | AB8500_CHARGER, AB8500_USBCH_CTRL1_REG, 0x01, 0x01); | 2349 | AB8500_CHARGER, AB8500_USBCH_CTRL1_REG, |
2350 | USB_CH_ENA, USB_CH_ENA); | ||
2161 | /*Enable charger detection*/ | 2351 | /*Enable charger detection*/ |
2162 | abx500_mask_and_set_register_interruptible(di->dev, AB8500_USB, | 2352 | abx500_mask_and_set_register_interruptible(di->dev, |
2163 | AB8500_MCH_IPT_CURLVL_REG, 0x01, 0x01); | 2353 | AB8500_USB, AB8500_USB_LINE_CTRL2_REG, |
2354 | USB_CH_DET, USB_CH_DET); | ||
2164 | di->invalid_charger_detect_state = 1; | 2355 | di->invalid_charger_detect_state = 1; |
2165 | /*exit and wait for new link status interrupt.*/ | 2356 | /*exit and wait for new link status interrupt.*/ |
2166 | return; | 2357 | return; |
2167 | 2358 | ||
2168 | } | 2359 | } |
2169 | if (di->invalid_charger_detect_state == 1) { | 2360 | if (di->invalid_charger_detect_state == 1) { |
2170 | dev_dbg(di->dev, "Invalid charger detected, state= 1\n"); | 2361 | dev_dbg(di->dev, |
2362 | "Invalid charger detected, state= 1\n"); | ||
2171 | /*Stop charger detection*/ | 2363 | /*Stop charger detection*/ |
2172 | abx500_mask_and_set_register_interruptible(di->dev, AB8500_USB, | 2364 | abx500_mask_and_set_register_interruptible(di->dev, |
2173 | AB8500_MCH_IPT_CURLVL_REG, 0x01, 0x00); | 2365 | AB8500_USB, AB8500_USB_LINE_CTRL2_REG, |
2366 | USB_CH_DET, 0x00); | ||
2174 | /*Check link status*/ | 2367 | /*Check link status*/ |
2175 | ret = abx500_get_register_interruptible(di->dev, AB8500_USB, | 2368 | if (is_ab8500(di->parent)) |
2176 | AB8500_USB_LINE_STAT_REG, &val); | 2369 | ret = abx500_get_register_interruptible(di->dev, |
2370 | AB8500_USB, AB8500_USB_LINE_STAT_REG, | ||
2371 | &val); | ||
2372 | else | ||
2373 | ret = abx500_get_register_interruptible(di->dev, | ||
2374 | AB8500_USB, AB8500_USB_LINK1_STAT_REG, | ||
2375 | &val); | ||
2376 | |||
2177 | dev_dbg(di->dev, "USB link status= 0x%02x\n", | 2377 | dev_dbg(di->dev, "USB link status= 0x%02x\n", |
2178 | (val & AB8500_USB_LINK_STATUS) >> 3); | 2378 | (val & link_status) >> USB_LINK_STATUS_SHIFT); |
2179 | di->invalid_charger_detect_state = 2; | 2379 | di->invalid_charger_detect_state = 2; |
2180 | } | 2380 | } |
2181 | } else { | 2381 | } else { |
@@ -2273,7 +2473,7 @@ static void ab8500_charger_usb_state_changed_work(struct work_struct *work) | |||
2273 | if (!ab8500_charger_get_usb_cur(di)) { | 2473 | if (!ab8500_charger_get_usb_cur(di)) { |
2274 | /* Update maximum input current */ | 2474 | /* Update maximum input current */ |
2275 | ret = ab8500_charger_set_vbus_in_curr(di, | 2475 | ret = ab8500_charger_set_vbus_in_curr(di, |
2276 | di->max_usb_in_curr); | 2476 | di->max_usb_in_curr.usb_type_max); |
2277 | if (ret) | 2477 | if (ret) |
2278 | return; | 2478 | return; |
2279 | 2479 | ||
@@ -2422,7 +2622,9 @@ static irqreturn_t ab8500_charger_mainchplugdet_handler(int irq, void *_di) | |||
2422 | 2622 | ||
2423 | mutex_lock(&di->charger_attached_mutex); | 2623 | mutex_lock(&di->charger_attached_mutex); |
2424 | mutex_unlock(&di->charger_attached_mutex); | 2624 | mutex_unlock(&di->charger_attached_mutex); |
2425 | queue_delayed_work(di->charger_wq, | 2625 | |
2626 | if (is_ab8500(di->parent)) | ||
2627 | queue_delayed_work(di->charger_wq, | ||
2426 | &di->ac_charger_attached_work, | 2628 | &di->ac_charger_attached_work, |
2427 | HZ); | 2629 | HZ); |
2428 | return IRQ_HANDLED; | 2630 | return IRQ_HANDLED; |
@@ -2491,6 +2693,8 @@ static void ab8500_charger_vbus_drop_end_work(struct work_struct *work) | |||
2491 | { | 2693 | { |
2492 | struct ab8500_charger *di = container_of(work, | 2694 | struct ab8500_charger *di = container_of(work, |
2493 | struct ab8500_charger, vbus_drop_end_work.work); | 2695 | struct ab8500_charger, vbus_drop_end_work.work); |
2696 | int ret, curr; | ||
2697 | u8 reg_value; | ||
2494 | 2698 | ||
2495 | di->flags.vbus_drop_end = false; | 2699 | di->flags.vbus_drop_end = false; |
2496 | 2700 | ||
@@ -2498,8 +2702,45 @@ static void ab8500_charger_vbus_drop_end_work(struct work_struct *work) | |||
2498 | abx500_set_register_interruptible(di->dev, | 2702 | abx500_set_register_interruptible(di->dev, |
2499 | AB8500_CHARGER, AB8500_CHARGER_CTRL, 0x01); | 2703 | AB8500_CHARGER, AB8500_CHARGER_CTRL, 0x01); |
2500 | 2704 | ||
2705 | if (is_ab8540(di->parent)) | ||
2706 | ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, | ||
2707 | AB8540_CH_USBCH_STAT3_REG, ®_value); | ||
2708 | else | ||
2709 | ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, | ||
2710 | AB8500_CH_USBCH_STAT2_REG, ®_value); | ||
2711 | if (ret < 0) { | ||
2712 | dev_err(di->dev, "%s read failed\n", __func__); | ||
2713 | return; | ||
2714 | } | ||
2715 | |||
2716 | if (is_ab8540(di->parent)) | ||
2717 | curr = di->bm->chg_input_curr[ | ||
2718 | reg_value & AB8540_AUTO_VBUS_IN_CURR_MASK]; | ||
2719 | else | ||
2720 | curr = di->bm->chg_input_curr[ | ||
2721 | reg_value >> AUTO_VBUS_IN_CURR_LIM_SHIFT]; | ||
2722 | |||
2723 | if (di->max_usb_in_curr.calculated_max != curr) { | ||
2724 | /* USB source is collapsing */ | ||
2725 | di->max_usb_in_curr.calculated_max = curr; | ||
2726 | dev_dbg(di->dev, | ||
2727 | "VBUS input current limiting to %d mA\n", | ||
2728 | di->max_usb_in_curr.calculated_max); | ||
2729 | } else { | ||
2730 | /* | ||
2731 | * USB source can not give more than this amount. | ||
2732 | * Taking more will collapse the source. | ||
2733 | */ | ||
2734 | di->max_usb_in_curr.set_max = | ||
2735 | di->max_usb_in_curr.calculated_max; | ||
2736 | dev_dbg(di->dev, | ||
2737 | "VBUS input current limited to %d mA\n", | ||
2738 | di->max_usb_in_curr.set_max); | ||
2739 | } | ||
2740 | |||
2501 | if (di->usb.charger_connected) | 2741 | if (di->usb.charger_connected) |
2502 | ab8500_charger_set_vbus_in_curr(di, di->max_usb_in_curr); | 2742 | ab8500_charger_set_vbus_in_curr(di, |
2743 | di->max_usb_in_curr.usb_type_max); | ||
2503 | } | 2744 | } |
2504 | 2745 | ||
2505 | /** | 2746 | /** |
@@ -2654,8 +2895,13 @@ static irqreturn_t ab8500_charger_vbuschdropend_handler(int irq, void *_di) | |||
2654 | 2895 | ||
2655 | dev_dbg(di->dev, "VBUS charger drop ended\n"); | 2896 | dev_dbg(di->dev, "VBUS charger drop ended\n"); |
2656 | di->flags.vbus_drop_end = true; | 2897 | di->flags.vbus_drop_end = true; |
2898 | |||
2899 | /* | ||
2900 | * VBUS might have dropped due to bad connection. | ||
2901 | * Schedule a new input limit set to the value SW requests. | ||
2902 | */ | ||
2657 | queue_delayed_work(di->charger_wq, &di->vbus_drop_end_work, | 2903 | queue_delayed_work(di->charger_wq, &di->vbus_drop_end_work, |
2658 | round_jiffies(30 * HZ)); | 2904 | round_jiffies(VBUS_IN_CURR_LIM_RETRY_SET_TIME * HZ)); |
2659 | 2905 | ||
2660 | return IRQ_HANDLED; | 2906 | return IRQ_HANDLED; |
2661 | } | 2907 | } |
@@ -2836,6 +3082,7 @@ static int ab8500_charger_usb_get_property(struct power_supply *psy, | |||
2836 | static int ab8500_charger_init_hw_registers(struct ab8500_charger *di) | 3082 | static int ab8500_charger_init_hw_registers(struct ab8500_charger *di) |
2837 | { | 3083 | { |
2838 | int ret = 0; | 3084 | int ret = 0; |
3085 | u8 bup_vch_range = 0, vbup33_vrtcn = 0; | ||
2839 | 3086 | ||
2840 | /* Setup maximum charger current and voltage for ABB cut2.0 */ | 3087 | /* Setup maximum charger current and voltage for ABB cut2.0 */ |
2841 | if (!is_ab8500_1p1_or_earlier(di->parent)) { | 3088 | if (!is_ab8500_1p1_or_earlier(di->parent)) { |
@@ -2848,9 +3095,14 @@ static int ab8500_charger_init_hw_registers(struct ab8500_charger *di) | |||
2848 | goto out; | 3095 | goto out; |
2849 | } | 3096 | } |
2850 | 3097 | ||
2851 | ret = abx500_set_register_interruptible(di->dev, | 3098 | if (is_ab8540(di->parent)) |
2852 | AB8500_CHARGER, | 3099 | ret = abx500_set_register_interruptible(di->dev, |
2853 | AB8500_CH_OPT_CRNTLVL_MAX_REG, CH_OP_CUR_LVL_1P6); | 3100 | AB8500_CHARGER, AB8500_CH_OPT_CRNTLVL_MAX_REG, |
3101 | CH_OP_CUR_LVL_2P); | ||
3102 | else | ||
3103 | ret = abx500_set_register_interruptible(di->dev, | ||
3104 | AB8500_CHARGER, AB8500_CH_OPT_CRNTLVL_MAX_REG, | ||
3105 | CH_OP_CUR_LVL_1P6); | ||
2854 | if (ret) { | 3106 | if (ret) { |
2855 | dev_err(di->dev, | 3107 | dev_err(di->dev, |
2856 | "failed to set CH_OPT_CRNTLVL_MAX_REG\n"); | 3108 | "failed to set CH_OPT_CRNTLVL_MAX_REG\n"); |
@@ -2858,7 +3110,8 @@ static int ab8500_charger_init_hw_registers(struct ab8500_charger *di) | |||
2858 | } | 3110 | } |
2859 | } | 3111 | } |
2860 | 3112 | ||
2861 | if (is_ab9540_2p0(di->parent) || is_ab8505_2p0(di->parent)) | 3113 | if (is_ab9540_2p0(di->parent) || is_ab9540_3p0(di->parent) |
3114 | || is_ab8505_2p0(di->parent) || is_ab8540(di->parent)) | ||
2862 | ret = abx500_mask_and_set_register_interruptible(di->dev, | 3115 | ret = abx500_mask_and_set_register_interruptible(di->dev, |
2863 | AB8500_CHARGER, | 3116 | AB8500_CHARGER, |
2864 | AB8500_USBCH_CTRL2_REG, | 3117 | AB8500_USBCH_CTRL2_REG, |
@@ -2930,14 +3183,6 @@ static int ab8500_charger_init_hw_registers(struct ab8500_charger *di) | |||
2930 | goto out; | 3183 | goto out; |
2931 | } | 3184 | } |
2932 | 3185 | ||
2933 | /* Set charger watchdog timeout */ | ||
2934 | ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, | ||
2935 | AB8500_CH_WD_TIMER_REG, WD_TIMER); | ||
2936 | if (ret) { | ||
2937 | dev_err(di->dev, "failed to set charger watchdog timeout\n"); | ||
2938 | goto out; | ||
2939 | } | ||
2940 | |||
2941 | ret = ab8500_charger_led_en(di, false); | 3186 | ret = ab8500_charger_led_en(di, false); |
2942 | if (ret < 0) { | 3187 | if (ret < 0) { |
2943 | dev_err(di->dev, "failed to disable LED\n"); | 3188 | dev_err(di->dev, "failed to disable LED\n"); |
@@ -2945,15 +3190,30 @@ static int ab8500_charger_init_hw_registers(struct ab8500_charger *di) | |||
2945 | } | 3190 | } |
2946 | 3191 | ||
2947 | /* Backup battery voltage and current */ | 3192 | /* Backup battery voltage and current */ |
3193 | if (di->bm->bkup_bat_v > BUP_VCH_SEL_3P1V) | ||
3194 | bup_vch_range = BUP_VCH_RANGE; | ||
3195 | if (di->bm->bkup_bat_v == BUP_VCH_SEL_3P3V) | ||
3196 | vbup33_vrtcn = VBUP33_VRTCN; | ||
3197 | |||
2948 | ret = abx500_set_register_interruptible(di->dev, | 3198 | ret = abx500_set_register_interruptible(di->dev, |
2949 | AB8500_RTC, | 3199 | AB8500_RTC, |
2950 | AB8500_RTC_BACKUP_CHG_REG, | 3200 | AB8500_RTC_BACKUP_CHG_REG, |
2951 | di->bm->bkup_bat_v | | 3201 | (di->bm->bkup_bat_v & 0x3) | di->bm->bkup_bat_i); |
2952 | di->bm->bkup_bat_i); | ||
2953 | if (ret) { | 3202 | if (ret) { |
2954 | dev_err(di->dev, "failed to setup backup battery charging\n"); | 3203 | dev_err(di->dev, "failed to setup backup battery charging\n"); |
2955 | goto out; | 3204 | goto out; |
2956 | } | 3205 | } |
3206 | if (is_ab8540(di->parent)) { | ||
3207 | ret = abx500_set_register_interruptible(di->dev, | ||
3208 | AB8500_RTC, | ||
3209 | AB8500_RTC_CTRL1_REG, | ||
3210 | bup_vch_range | vbup33_vrtcn); | ||
3211 | if (ret) { | ||
3212 | dev_err(di->dev, | ||
3213 | "failed to setup backup battery charging\n"); | ||
3214 | goto out; | ||
3215 | } | ||
3216 | } | ||
2957 | 3217 | ||
2958 | /* Enable backup battery charging */ | 3218 | /* Enable backup battery charging */ |
2959 | abx500_mask_and_set_register_interruptible(di->dev, | 3219 | abx500_mask_and_set_register_interruptible(di->dev, |
@@ -2962,6 +3222,25 @@ static int ab8500_charger_init_hw_registers(struct ab8500_charger *di) | |||
2962 | if (ret < 0) | 3222 | if (ret < 0) |
2963 | dev_err(di->dev, "%s mask and set failed\n", __func__); | 3223 | dev_err(di->dev, "%s mask and set failed\n", __func__); |
2964 | 3224 | ||
3225 | if (is_ab8540(di->parent)) { | ||
3226 | ret = abx500_mask_and_set_register_interruptible(di->dev, | ||
3227 | AB8500_CHARGER, AB8540_USB_PP_MODE_REG, | ||
3228 | BUS_VSYS_VOL_SELECT_MASK, BUS_VSYS_VOL_SELECT_3P6V); | ||
3229 | if (ret) { | ||
3230 | dev_err(di->dev, | ||
3231 | "failed to setup usb power path vsys voltage\n"); | ||
3232 | goto out; | ||
3233 | } | ||
3234 | ret = abx500_mask_and_set_register_interruptible(di->dev, | ||
3235 | AB8500_CHARGER, AB8540_USB_PP_CHR_REG, | ||
3236 | BUS_PP_PRECHG_CURRENT_MASK, 0); | ||
3237 | if (ret) { | ||
3238 | dev_err(di->dev, | ||
3239 | "failed to setup usb power path prechage current\n"); | ||
3240 | goto out; | ||
3241 | } | ||
3242 | } | ||
3243 | |||
2965 | out: | 3244 | out: |
2966 | return ret; | 3245 | return ret; |
2967 | } | 3246 | } |
@@ -3055,11 +3334,8 @@ static int ab8500_charger_resume(struct platform_device *pdev) | |||
3055 | dev_err(di->dev, "Failed to kick WD!\n"); | 3334 | dev_err(di->dev, "Failed to kick WD!\n"); |
3056 | 3335 | ||
3057 | /* If not already pending start a new timer */ | 3336 | /* If not already pending start a new timer */ |
3058 | if (!delayed_work_pending( | 3337 | queue_delayed_work(di->charger_wq, &di->kick_wd_work, |
3059 | &di->kick_wd_work)) { | 3338 | round_jiffies(WD_KICK_INTERVAL)); |
3060 | queue_delayed_work(di->charger_wq, &di->kick_wd_work, | ||
3061 | round_jiffies(WD_KICK_INTERVAL)); | ||
3062 | } | ||
3063 | } | 3339 | } |
3064 | 3340 | ||
3065 | /* If we still have a HW failure, schedule a new check */ | 3341 | /* If we still have a HW failure, schedule a new check */ |
@@ -3079,12 +3355,9 @@ static int ab8500_charger_suspend(struct platform_device *pdev, | |||
3079 | { | 3355 | { |
3080 | struct ab8500_charger *di = platform_get_drvdata(pdev); | 3356 | struct ab8500_charger *di = platform_get_drvdata(pdev); |
3081 | 3357 | ||
3082 | /* Cancel any pending HW failure check */ | 3358 | /* Cancel any pending jobs */ |
3083 | if (delayed_work_pending(&di->check_hw_failure_work)) | 3359 | cancel_delayed_work(&di->check_hw_failure_work); |
3084 | cancel_delayed_work(&di->check_hw_failure_work); | 3360 | cancel_delayed_work(&di->vbus_drop_end_work); |
3085 | |||
3086 | if (delayed_work_pending(&di->vbus_drop_end_work)) | ||
3087 | cancel_delayed_work(&di->vbus_drop_end_work); | ||
3088 | 3361 | ||
3089 | flush_delayed_work(&di->attach_work); | 3362 | flush_delayed_work(&di->attach_work); |
3090 | flush_delayed_work(&di->usb_charger_attached_work); | 3363 | flush_delayed_work(&di->usb_charger_attached_work); |
@@ -3107,6 +3380,10 @@ static int ab8500_charger_suspend(struct platform_device *pdev, | |||
3107 | #define ab8500_charger_resume NULL | 3380 | #define ab8500_charger_resume NULL |
3108 | #endif | 3381 | #endif |
3109 | 3382 | ||
3383 | static struct notifier_block charger_nb = { | ||
3384 | .notifier_call = ab8500_external_charger_prepare, | ||
3385 | }; | ||
3386 | |||
3110 | static int ab8500_charger_remove(struct platform_device *pdev) | 3387 | static int ab8500_charger_remove(struct platform_device *pdev) |
3111 | { | 3388 | { |
3112 | struct ab8500_charger *di = platform_get_drvdata(pdev); | 3389 | struct ab8500_charger *di = platform_get_drvdata(pdev); |
@@ -3136,13 +3413,18 @@ static int ab8500_charger_remove(struct platform_device *pdev) | |||
3136 | /* Delete the work queue */ | 3413 | /* Delete the work queue */ |
3137 | destroy_workqueue(di->charger_wq); | 3414 | destroy_workqueue(di->charger_wq); |
3138 | 3415 | ||
3416 | /* Unregister external charger enable notifier */ | ||
3417 | if (!di->ac_chg.enabled) | ||
3418 | blocking_notifier_chain_unregister( | ||
3419 | &charger_notifier_list, &charger_nb); | ||
3420 | |||
3139 | flush_scheduled_work(); | 3421 | flush_scheduled_work(); |
3140 | if(di->usb_chg.enabled) | 3422 | if (di->usb_chg.enabled) |
3141 | power_supply_unregister(&di->usb_chg.psy); | 3423 | power_supply_unregister(&di->usb_chg.psy); |
3142 | #if !defined(CONFIG_CHARGER_PM2301) | 3424 | |
3143 | if(di->ac_chg.enabled) | 3425 | if (di->ac_chg.enabled && !di->ac_chg.external) |
3144 | power_supply_unregister(&di->ac_chg.psy); | 3426 | power_supply_unregister(&di->ac_chg.psy); |
3145 | #endif | 3427 | |
3146 | platform_set_drvdata(pdev, NULL); | 3428 | platform_set_drvdata(pdev, NULL); |
3147 | 3429 | ||
3148 | return 0; | 3430 | return 0; |
@@ -3206,16 +3488,22 @@ static int ab8500_charger_probe(struct platform_device *pdev) | |||
3206 | di->ac_chg.psy.num_supplicants = ARRAY_SIZE(supply_interface), | 3488 | di->ac_chg.psy.num_supplicants = ARRAY_SIZE(supply_interface), |
3207 | /* ux500_charger sub-class */ | 3489 | /* ux500_charger sub-class */ |
3208 | di->ac_chg.ops.enable = &ab8500_charger_ac_en; | 3490 | di->ac_chg.ops.enable = &ab8500_charger_ac_en; |
3491 | di->ac_chg.ops.check_enable = &ab8500_charger_ac_check_enable; | ||
3209 | di->ac_chg.ops.kick_wd = &ab8500_charger_watchdog_kick; | 3492 | di->ac_chg.ops.kick_wd = &ab8500_charger_watchdog_kick; |
3210 | di->ac_chg.ops.update_curr = &ab8500_charger_update_charger_current; | 3493 | di->ac_chg.ops.update_curr = &ab8500_charger_update_charger_current; |
3211 | di->ac_chg.max_out_volt = ab8500_charger_voltage_map[ | 3494 | di->ac_chg.max_out_volt = ab8500_charger_voltage_map[ |
3212 | ARRAY_SIZE(ab8500_charger_voltage_map) - 1]; | 3495 | ARRAY_SIZE(ab8500_charger_voltage_map) - 1]; |
3213 | di->ac_chg.max_out_curr = ab8500_charger_current_map[ | 3496 | di->ac_chg.max_out_curr = |
3214 | ARRAY_SIZE(ab8500_charger_current_map) - 1]; | 3497 | di->bm->chg_output_curr[di->bm->n_chg_out_curr - 1]; |
3215 | di->ac_chg.wdt_refresh = CHG_WD_INTERVAL; | 3498 | di->ac_chg.wdt_refresh = CHG_WD_INTERVAL; |
3216 | di->ac_chg.enabled = di->bm->ac_enabled; | 3499 | di->ac_chg.enabled = di->bm->ac_enabled; |
3217 | di->ac_chg.external = false; | 3500 | di->ac_chg.external = false; |
3218 | 3501 | ||
3502 | /*notifier for external charger enabling*/ | ||
3503 | if (!di->ac_chg.enabled) | ||
3504 | blocking_notifier_chain_register( | ||
3505 | &charger_notifier_list, &charger_nb); | ||
3506 | |||
3219 | /* USB supply */ | 3507 | /* USB supply */ |
3220 | /* power_supply base class */ | 3508 | /* power_supply base class */ |
3221 | di->usb_chg.psy.name = "ab8500_usb"; | 3509 | di->usb_chg.psy.name = "ab8500_usb"; |
@@ -3227,15 +3515,20 @@ static int ab8500_charger_probe(struct platform_device *pdev) | |||
3227 | di->usb_chg.psy.num_supplicants = ARRAY_SIZE(supply_interface), | 3515 | di->usb_chg.psy.num_supplicants = ARRAY_SIZE(supply_interface), |
3228 | /* ux500_charger sub-class */ | 3516 | /* ux500_charger sub-class */ |
3229 | di->usb_chg.ops.enable = &ab8500_charger_usb_en; | 3517 | di->usb_chg.ops.enable = &ab8500_charger_usb_en; |
3518 | di->usb_chg.ops.check_enable = &ab8500_charger_usb_check_enable; | ||
3230 | di->usb_chg.ops.kick_wd = &ab8500_charger_watchdog_kick; | 3519 | di->usb_chg.ops.kick_wd = &ab8500_charger_watchdog_kick; |
3231 | di->usb_chg.ops.update_curr = &ab8500_charger_update_charger_current; | 3520 | di->usb_chg.ops.update_curr = &ab8500_charger_update_charger_current; |
3521 | di->usb_chg.ops.pp_enable = &ab8540_charger_power_path_enable; | ||
3522 | di->usb_chg.ops.pre_chg_enable = &ab8540_charger_usb_pre_chg_enable; | ||
3232 | di->usb_chg.max_out_volt = ab8500_charger_voltage_map[ | 3523 | di->usb_chg.max_out_volt = ab8500_charger_voltage_map[ |
3233 | ARRAY_SIZE(ab8500_charger_voltage_map) - 1]; | 3524 | ARRAY_SIZE(ab8500_charger_voltage_map) - 1]; |
3234 | di->usb_chg.max_out_curr = ab8500_charger_current_map[ | 3525 | di->usb_chg.max_out_curr = |
3235 | ARRAY_SIZE(ab8500_charger_current_map) - 1]; | 3526 | di->bm->chg_output_curr[di->bm->n_chg_out_curr - 1]; |
3236 | di->usb_chg.wdt_refresh = CHG_WD_INTERVAL; | 3527 | di->usb_chg.wdt_refresh = CHG_WD_INTERVAL; |
3237 | di->usb_chg.enabled = di->bm->usb_enabled; | 3528 | di->usb_chg.enabled = di->bm->usb_enabled; |
3238 | di->usb_chg.external = false; | 3529 | di->usb_chg.external = false; |
3530 | di->usb_chg.power_path = di->bm->usb_power_path; | ||
3531 | di->usb_state.usb_current = -1; | ||
3239 | 3532 | ||
3240 | /* Create a work queue for the charger */ | 3533 | /* Create a work queue for the charger */ |
3241 | di->charger_wq = | 3534 | di->charger_wq = |
@@ -3316,7 +3609,7 @@ static int ab8500_charger_probe(struct platform_device *pdev) | |||
3316 | } | 3609 | } |
3317 | 3610 | ||
3318 | /* Register AC charger class */ | 3611 | /* Register AC charger class */ |
3319 | if(di->ac_chg.enabled) { | 3612 | if (di->ac_chg.enabled) { |
3320 | ret = power_supply_register(di->dev, &di->ac_chg.psy); | 3613 | ret = power_supply_register(di->dev, &di->ac_chg.psy); |
3321 | if (ret) { | 3614 | if (ret) { |
3322 | dev_err(di->dev, "failed to register AC charger\n"); | 3615 | dev_err(di->dev, "failed to register AC charger\n"); |
@@ -3325,7 +3618,7 @@ static int ab8500_charger_probe(struct platform_device *pdev) | |||
3325 | } | 3618 | } |
3326 | 3619 | ||
3327 | /* Register USB charger class */ | 3620 | /* Register USB charger class */ |
3328 | if(di->usb_chg.enabled) { | 3621 | if (di->usb_chg.enabled) { |
3329 | ret = power_supply_register(di->dev, &di->usb_chg.psy); | 3622 | ret = power_supply_register(di->dev, &di->usb_chg.psy); |
3330 | if (ret) { | 3623 | if (ret) { |
3331 | dev_err(di->dev, "failed to register USB charger\n"); | 3624 | dev_err(di->dev, "failed to register USB charger\n"); |
@@ -3385,14 +3678,16 @@ static int ab8500_charger_probe(struct platform_device *pdev) | |||
3385 | ch_stat = ab8500_charger_detect_chargers(di, false); | 3678 | ch_stat = ab8500_charger_detect_chargers(di, false); |
3386 | 3679 | ||
3387 | if ((ch_stat & AC_PW_CONN) == AC_PW_CONN) { | 3680 | if ((ch_stat & AC_PW_CONN) == AC_PW_CONN) { |
3388 | queue_delayed_work(di->charger_wq, | 3681 | if (is_ab8500(di->parent)) |
3389 | &di->ac_charger_attached_work, | 3682 | queue_delayed_work(di->charger_wq, |
3390 | HZ); | 3683 | &di->ac_charger_attached_work, |
3684 | HZ); | ||
3391 | } | 3685 | } |
3392 | if ((ch_stat & USB_PW_CONN) == USB_PW_CONN) { | 3686 | if ((ch_stat & USB_PW_CONN) == USB_PW_CONN) { |
3393 | queue_delayed_work(di->charger_wq, | 3687 | if (is_ab8500(di->parent)) |
3394 | &di->usb_charger_attached_work, | 3688 | queue_delayed_work(di->charger_wq, |
3395 | HZ); | 3689 | &di->usb_charger_attached_work, |
3690 | HZ); | ||
3396 | } | 3691 | } |
3397 | 3692 | ||
3398 | mutex_unlock(&di->charger_attached_mutex); | 3693 | mutex_unlock(&di->charger_attached_mutex); |
@@ -3410,10 +3705,10 @@ free_irq: | |||
3410 | put_usb_phy: | 3705 | put_usb_phy: |
3411 | usb_put_phy(di->usb_phy); | 3706 | usb_put_phy(di->usb_phy); |
3412 | free_usb: | 3707 | free_usb: |
3413 | if(di->usb_chg.enabled) | 3708 | if (di->usb_chg.enabled) |
3414 | power_supply_unregister(&di->usb_chg.psy); | 3709 | power_supply_unregister(&di->usb_chg.psy); |
3415 | free_ac: | 3710 | free_ac: |
3416 | if(di->ac_chg.enabled) | 3711 | if (di->ac_chg.enabled) |
3417 | power_supply_unregister(&di->ac_chg.psy); | 3712 | power_supply_unregister(&di->ac_chg.psy); |
3418 | free_charger_wq: | 3713 | free_charger_wq: |
3419 | destroy_workqueue(di->charger_wq); | 3714 | destroy_workqueue(di->charger_wq); |
diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c index 25dae4c4b0ef..1601d27ce5d4 100644 --- a/drivers/power/ab8500_fg.c +++ b/drivers/power/ab8500_fg.c | |||
@@ -36,7 +36,7 @@ | |||
36 | 36 | ||
37 | #define MILLI_TO_MICRO 1000 | 37 | #define MILLI_TO_MICRO 1000 |
38 | #define FG_LSB_IN_MA 1627 | 38 | #define FG_LSB_IN_MA 1627 |
39 | #define QLSB_NANO_AMP_HOURS_X10 1129 | 39 | #define QLSB_NANO_AMP_HOURS_X10 1071 |
40 | #define INS_CURR_TIMEOUT (3 * HZ) | 40 | #define INS_CURR_TIMEOUT (3 * HZ) |
41 | 41 | ||
42 | #define SEC_TO_SAMPLE(S) (S * 4) | 42 | #define SEC_TO_SAMPLE(S) (S * 4) |
@@ -672,11 +672,11 @@ int ab8500_fg_inst_curr_finalize(struct ab8500_fg *di, int *res) | |||
672 | /* | 672 | /* |
673 | * Convert to unit value in mA | 673 | * Convert to unit value in mA |
674 | * Full scale input voltage is | 674 | * Full scale input voltage is |
675 | * 66.660mV => LSB = 66.660mV/(4096*res) = 1.627mA | 675 | * 63.160mV => LSB = 63.160mV/(4096*res) = 1.542mA |
676 | * Given a 250ms conversion cycle time the LSB corresponds | 676 | * Given a 250ms conversion cycle time the LSB corresponds |
677 | * to 112.9 nAh. Convert to current by dividing by the conversion | 677 | * to 107.1 nAh. Convert to current by dividing by the conversion |
678 | * time in hours (250ms = 1 / (3600 * 4)h) | 678 | * time in hours (250ms = 1 / (3600 * 4)h) |
679 | * 112.9nAh assumes 10mOhm, but fg_res is in 0.1mOhm | 679 | * 107.1nAh assumes 10mOhm, but fg_res is in 0.1mOhm |
680 | */ | 680 | */ |
681 | val = (val * QLSB_NANO_AMP_HOURS_X10 * 36 * 4) / | 681 | val = (val * QLSB_NANO_AMP_HOURS_X10 * 36 * 4) / |
682 | (1000 * di->bm->fg_res); | 682 | (1000 * di->bm->fg_res); |
@@ -1354,9 +1354,6 @@ static void ab8500_fg_check_capacity_limits(struct ab8500_fg *di, bool init) | |||
1354 | * algorithm says. | 1354 | * algorithm says. |
1355 | */ | 1355 | */ |
1356 | di->bat_cap.prev_percent = 1; | 1356 | di->bat_cap.prev_percent = 1; |
1357 | di->bat_cap.permille = 1; | ||
1358 | di->bat_cap.prev_mah = 1; | ||
1359 | di->bat_cap.mah = 1; | ||
1360 | percent = 1; | 1357 | percent = 1; |
1361 | 1358 | ||
1362 | changed = true; | 1359 | changed = true; |
@@ -1683,7 +1680,6 @@ static void ab8500_fg_algorithm_discharging(struct ab8500_fg *di) | |||
1683 | break; | 1680 | break; |
1684 | 1681 | ||
1685 | case AB8500_FG_DISCHARGE_WAKEUP: | 1682 | case AB8500_FG_DISCHARGE_WAKEUP: |
1686 | ab8500_fg_coulomb_counter(di, true); | ||
1687 | ab8500_fg_calc_cap_discharge_voltage(di, true); | 1683 | ab8500_fg_calc_cap_discharge_voltage(di, true); |
1688 | 1684 | ||
1689 | di->fg_samples = SEC_TO_SAMPLE( | 1685 | di->fg_samples = SEC_TO_SAMPLE( |
@@ -1768,9 +1764,10 @@ static void ab8500_fg_algorithm(struct ab8500_fg *di) | |||
1768 | ab8500_fg_algorithm_discharging(di); | 1764 | ab8500_fg_algorithm_discharging(di); |
1769 | } | 1765 | } |
1770 | 1766 | ||
1771 | dev_dbg(di->dev, "[FG_DATA] %d %d %d %d %d %d %d %d %d " | 1767 | dev_dbg(di->dev, "[FG_DATA] %d %d %d %d %d %d %d %d %d %d " |
1772 | "%d %d %d %d %d %d %d\n", | 1768 | "%d %d %d %d %d %d %d\n", |
1773 | di->bat_cap.max_mah_design, | 1769 | di->bat_cap.max_mah_design, |
1770 | di->bat_cap.max_mah, | ||
1774 | di->bat_cap.mah, | 1771 | di->bat_cap.mah, |
1775 | di->bat_cap.permille, | 1772 | di->bat_cap.permille, |
1776 | di->bat_cap.level, | 1773 | di->bat_cap.level, |
@@ -1982,7 +1979,7 @@ static void ab8500_fg_instant_work(struct work_struct *work) | |||
1982 | } | 1979 | } |
1983 | 1980 | ||
1984 | /** | 1981 | /** |
1985 | * ab8500_fg_cc_data_end_handler() - isr to get battery avg current. | 1982 | * ab8500_fg_cc_data_end_handler() - end of data conversion isr. |
1986 | * @irq: interrupt number | 1983 | * @irq: interrupt number |
1987 | * @_di: pointer to the ab8500_fg structure | 1984 | * @_di: pointer to the ab8500_fg structure |
1988 | * | 1985 | * |
@@ -2002,7 +1999,7 @@ static irqreturn_t ab8500_fg_cc_data_end_handler(int irq, void *_di) | |||
2002 | } | 1999 | } |
2003 | 2000 | ||
2004 | /** | 2001 | /** |
2005 | * ab8500_fg_cc_convend_handler() - isr to get battery avg current. | 2002 | * ab8500_fg_cc_int_calib_handler () - end of calibration isr. |
2006 | * @irq: interrupt number | 2003 | * @irq: interrupt number |
2007 | * @_di: pointer to the ab8500_fg structure | 2004 | * @_di: pointer to the ab8500_fg structure |
2008 | * | 2005 | * |
@@ -2153,9 +2150,7 @@ static int ab8500_fg_get_property(struct power_supply *psy, | |||
2153 | val->intval = di->bat_cap.prev_mah; | 2150 | val->intval = di->bat_cap.prev_mah; |
2154 | break; | 2151 | break; |
2155 | case POWER_SUPPLY_PROP_CAPACITY: | 2152 | case POWER_SUPPLY_PROP_CAPACITY: |
2156 | if (di->bm->capacity_scaling) | 2153 | if (di->flags.batt_unknown && !di->bm->chg_unknown_bat && |
2157 | val->intval = di->bat_cap.cap_scale.scaled_cap; | ||
2158 | else if (di->flags.batt_unknown && !di->bm->chg_unknown_bat && | ||
2159 | di->flags.batt_id_received) | 2154 | di->flags.batt_id_received) |
2160 | val->intval = 100; | 2155 | val->intval = 100; |
2161 | else | 2156 | else |
@@ -2344,6 +2339,50 @@ static int ab8500_fg_init_hw_registers(struct ab8500_fg *di) | |||
2344 | dev_err(di->dev, "BattOk init write failed.\n"); | 2339 | dev_err(di->dev, "BattOk init write failed.\n"); |
2345 | goto out; | 2340 | goto out; |
2346 | } | 2341 | } |
2342 | |||
2343 | if (((is_ab8505(di->parent) || is_ab9540(di->parent)) && | ||
2344 | abx500_get_chip_id(di->dev) >= AB8500_CUT2P0) | ||
2345 | || is_ab8540(di->parent)) { | ||
2346 | ret = abx500_set_register_interruptible(di->dev, AB8500_RTC, | ||
2347 | AB8505_RTC_PCUT_MAX_TIME_REG, di->bm->fg_params->pcut_max_time); | ||
2348 | |||
2349 | if (ret) { | ||
2350 | dev_err(di->dev, "%s write failed AB8505_RTC_PCUT_MAX_TIME_REG\n", __func__); | ||
2351 | goto out; | ||
2352 | }; | ||
2353 | |||
2354 | ret = abx500_set_register_interruptible(di->dev, AB8500_RTC, | ||
2355 | AB8505_RTC_PCUT_FLAG_TIME_REG, di->bm->fg_params->pcut_flag_time); | ||
2356 | |||
2357 | if (ret) { | ||
2358 | dev_err(di->dev, "%s write failed AB8505_RTC_PCUT_FLAG_TIME_REG\n", __func__); | ||
2359 | goto out; | ||
2360 | }; | ||
2361 | |||
2362 | ret = abx500_set_register_interruptible(di->dev, AB8500_RTC, | ||
2363 | AB8505_RTC_PCUT_RESTART_REG, di->bm->fg_params->pcut_max_restart); | ||
2364 | |||
2365 | if (ret) { | ||
2366 | dev_err(di->dev, "%s write failed AB8505_RTC_PCUT_RESTART_REG\n", __func__); | ||
2367 | goto out; | ||
2368 | }; | ||
2369 | |||
2370 | ret = abx500_set_register_interruptible(di->dev, AB8500_RTC, | ||
2371 | AB8505_RTC_PCUT_DEBOUNCE_REG, di->bm->fg_params->pcut_debounce_time); | ||
2372 | |||
2373 | if (ret) { | ||
2374 | dev_err(di->dev, "%s write failed AB8505_RTC_PCUT_DEBOUNCE_REG\n", __func__); | ||
2375 | goto out; | ||
2376 | }; | ||
2377 | |||
2378 | ret = abx500_set_register_interruptible(di->dev, AB8500_RTC, | ||
2379 | AB8505_RTC_PCUT_CTL_STATUS_REG, di->bm->fg_params->pcut_enable); | ||
2380 | |||
2381 | if (ret) { | ||
2382 | dev_err(di->dev, "%s write failed AB8505_RTC_PCUT_CTL_STATUS_REG\n", __func__); | ||
2383 | goto out; | ||
2384 | }; | ||
2385 | } | ||
2347 | out: | 2386 | out: |
2348 | return ret; | 2387 | return ret; |
2349 | } | 2388 | } |
@@ -2546,6 +2585,428 @@ static int ab8500_fg_sysfs_init(struct ab8500_fg *di) | |||
2546 | 2585 | ||
2547 | return ret; | 2586 | return ret; |
2548 | } | 2587 | } |
2588 | |||
2589 | static ssize_t ab8505_powercut_flagtime_read(struct device *dev, | ||
2590 | struct device_attribute *attr, | ||
2591 | char *buf) | ||
2592 | { | ||
2593 | int ret; | ||
2594 | u8 reg_value; | ||
2595 | struct power_supply *psy = dev_get_drvdata(dev); | ||
2596 | struct ab8500_fg *di; | ||
2597 | |||
2598 | di = to_ab8500_fg_device_info(psy); | ||
2599 | |||
2600 | ret = abx500_get_register_interruptible(di->dev, AB8500_RTC, | ||
2601 | AB8505_RTC_PCUT_FLAG_TIME_REG, ®_value); | ||
2602 | |||
2603 | if (ret < 0) { | ||
2604 | dev_err(dev, "Failed to read AB8505_RTC_PCUT_FLAG_TIME_REG\n"); | ||
2605 | goto fail; | ||
2606 | } | ||
2607 | |||
2608 | return scnprintf(buf, PAGE_SIZE, "%d\n", (reg_value & 0x7F)); | ||
2609 | |||
2610 | fail: | ||
2611 | return ret; | ||
2612 | } | ||
2613 | |||
2614 | static ssize_t ab8505_powercut_flagtime_write(struct device *dev, | ||
2615 | struct device_attribute *attr, | ||
2616 | const char *buf, size_t count) | ||
2617 | { | ||
2618 | int ret; | ||
2619 | long unsigned reg_value; | ||
2620 | struct power_supply *psy = dev_get_drvdata(dev); | ||
2621 | struct ab8500_fg *di; | ||
2622 | |||
2623 | di = to_ab8500_fg_device_info(psy); | ||
2624 | |||
2625 | reg_value = simple_strtoul(buf, NULL, 10); | ||
2626 | |||
2627 | if (reg_value > 0x7F) { | ||
2628 | dev_err(dev, "Incorrect parameter, echo 0 (1.98s) - 127 (15.625ms) for flagtime\n"); | ||
2629 | goto fail; | ||
2630 | } | ||
2631 | |||
2632 | ret = abx500_set_register_interruptible(di->dev, AB8500_RTC, | ||
2633 | AB8505_RTC_PCUT_FLAG_TIME_REG, (u8)reg_value); | ||
2634 | |||
2635 | if (ret < 0) | ||
2636 | dev_err(dev, "Failed to set AB8505_RTC_PCUT_FLAG_TIME_REG\n"); | ||
2637 | |||
2638 | fail: | ||
2639 | return count; | ||
2640 | } | ||
2641 | |||
2642 | static ssize_t ab8505_powercut_maxtime_read(struct device *dev, | ||
2643 | struct device_attribute *attr, | ||
2644 | char *buf) | ||
2645 | { | ||
2646 | int ret; | ||
2647 | u8 reg_value; | ||
2648 | struct power_supply *psy = dev_get_drvdata(dev); | ||
2649 | struct ab8500_fg *di; | ||
2650 | |||
2651 | di = to_ab8500_fg_device_info(psy); | ||
2652 | |||
2653 | ret = abx500_get_register_interruptible(di->dev, AB8500_RTC, | ||
2654 | AB8505_RTC_PCUT_MAX_TIME_REG, ®_value); | ||
2655 | |||
2656 | if (ret < 0) { | ||
2657 | dev_err(dev, "Failed to read AB8505_RTC_PCUT_MAX_TIME_REG\n"); | ||
2658 | goto fail; | ||
2659 | } | ||
2660 | |||
2661 | return scnprintf(buf, PAGE_SIZE, "%d\n", (reg_value & 0x7F)); | ||
2662 | |||
2663 | fail: | ||
2664 | return ret; | ||
2665 | |||
2666 | } | ||
2667 | |||
2668 | static ssize_t ab8505_powercut_maxtime_write(struct device *dev, | ||
2669 | struct device_attribute *attr, | ||
2670 | const char *buf, size_t count) | ||
2671 | { | ||
2672 | int ret; | ||
2673 | int reg_value; | ||
2674 | struct power_supply *psy = dev_get_drvdata(dev); | ||
2675 | struct ab8500_fg *di; | ||
2676 | |||
2677 | di = to_ab8500_fg_device_info(psy); | ||
2678 | |||
2679 | reg_value = simple_strtoul(buf, NULL, 10); | ||
2680 | if (reg_value > 0x7F) { | ||
2681 | dev_err(dev, "Incorrect parameter, echo 0 (0.0s) - 127 (1.98s) for maxtime\n"); | ||
2682 | goto fail; | ||
2683 | } | ||
2684 | |||
2685 | ret = abx500_set_register_interruptible(di->dev, AB8500_RTC, | ||
2686 | AB8505_RTC_PCUT_MAX_TIME_REG, (u8)reg_value); | ||
2687 | |||
2688 | if (ret < 0) | ||
2689 | dev_err(dev, "Failed to set AB8505_RTC_PCUT_MAX_TIME_REG\n"); | ||
2690 | |||
2691 | fail: | ||
2692 | return count; | ||
2693 | } | ||
2694 | |||
2695 | static ssize_t ab8505_powercut_restart_read(struct device *dev, | ||
2696 | struct device_attribute *attr, | ||
2697 | char *buf) | ||
2698 | { | ||
2699 | int ret; | ||
2700 | u8 reg_value; | ||
2701 | struct power_supply *psy = dev_get_drvdata(dev); | ||
2702 | struct ab8500_fg *di; | ||
2703 | |||
2704 | di = to_ab8500_fg_device_info(psy); | ||
2705 | |||
2706 | ret = abx500_get_register_interruptible(di->dev, AB8500_RTC, | ||
2707 | AB8505_RTC_PCUT_RESTART_REG, ®_value); | ||
2708 | |||
2709 | if (ret < 0) { | ||
2710 | dev_err(dev, "Failed to read AB8505_RTC_PCUT_RESTART_REG\n"); | ||
2711 | goto fail; | ||
2712 | } | ||
2713 | |||
2714 | return scnprintf(buf, PAGE_SIZE, "%d\n", (reg_value & 0xF)); | ||
2715 | |||
2716 | fail: | ||
2717 | return ret; | ||
2718 | } | ||
2719 | |||
2720 | static ssize_t ab8505_powercut_restart_write(struct device *dev, | ||
2721 | struct device_attribute *attr, | ||
2722 | const char *buf, size_t count) | ||
2723 | { | ||
2724 | int ret; | ||
2725 | int reg_value; | ||
2726 | struct power_supply *psy = dev_get_drvdata(dev); | ||
2727 | struct ab8500_fg *di; | ||
2728 | |||
2729 | di = to_ab8500_fg_device_info(psy); | ||
2730 | |||
2731 | reg_value = simple_strtoul(buf, NULL, 10); | ||
2732 | if (reg_value > 0xF) { | ||
2733 | dev_err(dev, "Incorrect parameter, echo 0 - 15 for number of restart\n"); | ||
2734 | goto fail; | ||
2735 | } | ||
2736 | |||
2737 | ret = abx500_set_register_interruptible(di->dev, AB8500_RTC, | ||
2738 | AB8505_RTC_PCUT_RESTART_REG, (u8)reg_value); | ||
2739 | |||
2740 | if (ret < 0) | ||
2741 | dev_err(dev, "Failed to set AB8505_RTC_PCUT_RESTART_REG\n"); | ||
2742 | |||
2743 | fail: | ||
2744 | return count; | ||
2745 | |||
2746 | } | ||
2747 | |||
2748 | static ssize_t ab8505_powercut_timer_read(struct device *dev, | ||
2749 | struct device_attribute *attr, | ||
2750 | char *buf) | ||
2751 | { | ||
2752 | int ret; | ||
2753 | u8 reg_value; | ||
2754 | struct power_supply *psy = dev_get_drvdata(dev); | ||
2755 | struct ab8500_fg *di; | ||
2756 | |||
2757 | di = to_ab8500_fg_device_info(psy); | ||
2758 | |||
2759 | ret = abx500_get_register_interruptible(di->dev, AB8500_RTC, | ||
2760 | AB8505_RTC_PCUT_TIME_REG, ®_value); | ||
2761 | |||
2762 | if (ret < 0) { | ||
2763 | dev_err(dev, "Failed to read AB8505_RTC_PCUT_TIME_REG\n"); | ||
2764 | goto fail; | ||
2765 | } | ||
2766 | |||
2767 | return scnprintf(buf, PAGE_SIZE, "%d\n", (reg_value & 0x7F)); | ||
2768 | |||
2769 | fail: | ||
2770 | return ret; | ||
2771 | } | ||
2772 | |||
2773 | static ssize_t ab8505_powercut_restart_counter_read(struct device *dev, | ||
2774 | struct device_attribute *attr, | ||
2775 | char *buf) | ||
2776 | { | ||
2777 | int ret; | ||
2778 | u8 reg_value; | ||
2779 | struct power_supply *psy = dev_get_drvdata(dev); | ||
2780 | struct ab8500_fg *di; | ||
2781 | |||
2782 | di = to_ab8500_fg_device_info(psy); | ||
2783 | |||
2784 | ret = abx500_get_register_interruptible(di->dev, AB8500_RTC, | ||
2785 | AB8505_RTC_PCUT_RESTART_REG, ®_value); | ||
2786 | |||
2787 | if (ret < 0) { | ||
2788 | dev_err(dev, "Failed to read AB8505_RTC_PCUT_RESTART_REG\n"); | ||
2789 | goto fail; | ||
2790 | } | ||
2791 | |||
2792 | return scnprintf(buf, PAGE_SIZE, "%d\n", (reg_value & 0xF0) >> 4); | ||
2793 | |||
2794 | fail: | ||
2795 | return ret; | ||
2796 | } | ||
2797 | |||
2798 | static ssize_t ab8505_powercut_read(struct device *dev, | ||
2799 | struct device_attribute *attr, | ||
2800 | char *buf) | ||
2801 | { | ||
2802 | int ret; | ||
2803 | u8 reg_value; | ||
2804 | struct power_supply *psy = dev_get_drvdata(dev); | ||
2805 | struct ab8500_fg *di; | ||
2806 | |||
2807 | di = to_ab8500_fg_device_info(psy); | ||
2808 | |||
2809 | ret = abx500_get_register_interruptible(di->dev, AB8500_RTC, | ||
2810 | AB8505_RTC_PCUT_CTL_STATUS_REG, ®_value); | ||
2811 | |||
2812 | if (ret < 0) | ||
2813 | goto fail; | ||
2814 | |||
2815 | return scnprintf(buf, PAGE_SIZE, "%d\n", (reg_value & 0x1)); | ||
2816 | |||
2817 | fail: | ||
2818 | return ret; | ||
2819 | } | ||
2820 | |||
2821 | static ssize_t ab8505_powercut_write(struct device *dev, | ||
2822 | struct device_attribute *attr, | ||
2823 | const char *buf, size_t count) | ||
2824 | { | ||
2825 | int ret; | ||
2826 | int reg_value; | ||
2827 | struct power_supply *psy = dev_get_drvdata(dev); | ||
2828 | struct ab8500_fg *di; | ||
2829 | |||
2830 | di = to_ab8500_fg_device_info(psy); | ||
2831 | |||
2832 | reg_value = simple_strtoul(buf, NULL, 10); | ||
2833 | if (reg_value > 0x1) { | ||
2834 | dev_err(dev, "Incorrect parameter, echo 0/1 to disable/enable Pcut feature\n"); | ||
2835 | goto fail; | ||
2836 | } | ||
2837 | |||
2838 | ret = abx500_set_register_interruptible(di->dev, AB8500_RTC, | ||
2839 | AB8505_RTC_PCUT_CTL_STATUS_REG, (u8)reg_value); | ||
2840 | |||
2841 | if (ret < 0) | ||
2842 | dev_err(dev, "Failed to set AB8505_RTC_PCUT_CTL_STATUS_REG\n"); | ||
2843 | |||
2844 | fail: | ||
2845 | return count; | ||
2846 | } | ||
2847 | |||
2848 | static ssize_t ab8505_powercut_flag_read(struct device *dev, | ||
2849 | struct device_attribute *attr, | ||
2850 | char *buf) | ||
2851 | { | ||
2852 | |||
2853 | int ret; | ||
2854 | u8 reg_value; | ||
2855 | struct power_supply *psy = dev_get_drvdata(dev); | ||
2856 | struct ab8500_fg *di; | ||
2857 | |||
2858 | di = to_ab8500_fg_device_info(psy); | ||
2859 | |||
2860 | ret = abx500_get_register_interruptible(di->dev, AB8500_RTC, | ||
2861 | AB8505_RTC_PCUT_CTL_STATUS_REG, ®_value); | ||
2862 | |||
2863 | if (ret < 0) { | ||
2864 | dev_err(dev, "Failed to read AB8505_RTC_PCUT_CTL_STATUS_REG\n"); | ||
2865 | goto fail; | ||
2866 | } | ||
2867 | |||
2868 | return scnprintf(buf, PAGE_SIZE, "%d\n", ((reg_value & 0x10) >> 4)); | ||
2869 | |||
2870 | fail: | ||
2871 | return ret; | ||
2872 | } | ||
2873 | |||
2874 | static ssize_t ab8505_powercut_debounce_read(struct device *dev, | ||
2875 | struct device_attribute *attr, | ||
2876 | char *buf) | ||
2877 | { | ||
2878 | int ret; | ||
2879 | u8 reg_value; | ||
2880 | struct power_supply *psy = dev_get_drvdata(dev); | ||
2881 | struct ab8500_fg *di; | ||
2882 | |||
2883 | di = to_ab8500_fg_device_info(psy); | ||
2884 | |||
2885 | ret = abx500_get_register_interruptible(di->dev, AB8500_RTC, | ||
2886 | AB8505_RTC_PCUT_DEBOUNCE_REG, ®_value); | ||
2887 | |||
2888 | if (ret < 0) { | ||
2889 | dev_err(dev, "Failed to read AB8505_RTC_PCUT_DEBOUNCE_REG\n"); | ||
2890 | goto fail; | ||
2891 | } | ||
2892 | |||
2893 | return scnprintf(buf, PAGE_SIZE, "%d\n", (reg_value & 0x7)); | ||
2894 | |||
2895 | fail: | ||
2896 | return ret; | ||
2897 | } | ||
2898 | |||
2899 | static ssize_t ab8505_powercut_debounce_write(struct device *dev, | ||
2900 | struct device_attribute *attr, | ||
2901 | const char *buf, size_t count) | ||
2902 | { | ||
2903 | int ret; | ||
2904 | int reg_value; | ||
2905 | struct power_supply *psy = dev_get_drvdata(dev); | ||
2906 | struct ab8500_fg *di; | ||
2907 | |||
2908 | di = to_ab8500_fg_device_info(psy); | ||
2909 | |||
2910 | reg_value = simple_strtoul(buf, NULL, 10); | ||
2911 | if (reg_value > 0x7) { | ||
2912 | dev_err(dev, "Incorrect parameter, echo 0 to 7 for debounce setting\n"); | ||
2913 | goto fail; | ||
2914 | } | ||
2915 | |||
2916 | ret = abx500_set_register_interruptible(di->dev, AB8500_RTC, | ||
2917 | AB8505_RTC_PCUT_DEBOUNCE_REG, (u8)reg_value); | ||
2918 | |||
2919 | if (ret < 0) | ||
2920 | dev_err(dev, "Failed to set AB8505_RTC_PCUT_DEBOUNCE_REG\n"); | ||
2921 | |||
2922 | fail: | ||
2923 | return count; | ||
2924 | } | ||
2925 | |||
2926 | static ssize_t ab8505_powercut_enable_status_read(struct device *dev, | ||
2927 | struct device_attribute *attr, | ||
2928 | char *buf) | ||
2929 | { | ||
2930 | int ret; | ||
2931 | u8 reg_value; | ||
2932 | struct power_supply *psy = dev_get_drvdata(dev); | ||
2933 | struct ab8500_fg *di; | ||
2934 | |||
2935 | di = to_ab8500_fg_device_info(psy); | ||
2936 | |||
2937 | ret = abx500_get_register_interruptible(di->dev, AB8500_RTC, | ||
2938 | AB8505_RTC_PCUT_CTL_STATUS_REG, ®_value); | ||
2939 | |||
2940 | if (ret < 0) { | ||
2941 | dev_err(dev, "Failed to read AB8505_RTC_PCUT_CTL_STATUS_REG\n"); | ||
2942 | goto fail; | ||
2943 | } | ||
2944 | |||
2945 | return scnprintf(buf, PAGE_SIZE, "%d\n", ((reg_value & 0x20) >> 5)); | ||
2946 | |||
2947 | fail: | ||
2948 | return ret; | ||
2949 | } | ||
2950 | |||
2951 | static struct device_attribute ab8505_fg_sysfs_psy_attrs[] = { | ||
2952 | __ATTR(powercut_flagtime, (S_IRUGO | S_IWUSR | S_IWGRP), | ||
2953 | ab8505_powercut_flagtime_read, ab8505_powercut_flagtime_write), | ||
2954 | __ATTR(powercut_maxtime, (S_IRUGO | S_IWUSR | S_IWGRP), | ||
2955 | ab8505_powercut_maxtime_read, ab8505_powercut_maxtime_write), | ||
2956 | __ATTR(powercut_restart_max, (S_IRUGO | S_IWUSR | S_IWGRP), | ||
2957 | ab8505_powercut_restart_read, ab8505_powercut_restart_write), | ||
2958 | __ATTR(powercut_timer, S_IRUGO, ab8505_powercut_timer_read, NULL), | ||
2959 | __ATTR(powercut_restart_counter, S_IRUGO, | ||
2960 | ab8505_powercut_restart_counter_read, NULL), | ||
2961 | __ATTR(powercut_enable, (S_IRUGO | S_IWUSR | S_IWGRP), | ||
2962 | ab8505_powercut_read, ab8505_powercut_write), | ||
2963 | __ATTR(powercut_flag, S_IRUGO, ab8505_powercut_flag_read, NULL), | ||
2964 | __ATTR(powercut_debounce_time, (S_IRUGO | S_IWUSR | S_IWGRP), | ||
2965 | ab8505_powercut_debounce_read, ab8505_powercut_debounce_write), | ||
2966 | __ATTR(powercut_enable_status, S_IRUGO, | ||
2967 | ab8505_powercut_enable_status_read, NULL), | ||
2968 | }; | ||
2969 | |||
2970 | static int ab8500_fg_sysfs_psy_create_attrs(struct device *dev) | ||
2971 | { | ||
2972 | unsigned int i, j; | ||
2973 | struct power_supply *psy = dev_get_drvdata(dev); | ||
2974 | struct ab8500_fg *di; | ||
2975 | |||
2976 | di = to_ab8500_fg_device_info(psy); | ||
2977 | |||
2978 | if (((is_ab8505(di->parent) || is_ab9540(di->parent)) && | ||
2979 | abx500_get_chip_id(dev->parent) >= AB8500_CUT2P0) | ||
2980 | || is_ab8540(di->parent)) { | ||
2981 | for (j = 0; j < ARRAY_SIZE(ab8505_fg_sysfs_psy_attrs); j++) | ||
2982 | if (device_create_file(dev, &ab8505_fg_sysfs_psy_attrs[j])) | ||
2983 | goto sysfs_psy_create_attrs_failed_ab8505; | ||
2984 | } | ||
2985 | return 0; | ||
2986 | sysfs_psy_create_attrs_failed_ab8505: | ||
2987 | dev_err(dev, "Failed creating sysfs psy attrs for ab8505.\n"); | ||
2988 | while (j--) | ||
2989 | device_remove_file(dev, &ab8505_fg_sysfs_psy_attrs[i]); | ||
2990 | |||
2991 | return -EIO; | ||
2992 | } | ||
2993 | |||
2994 | static void ab8500_fg_sysfs_psy_remove_attrs(struct device *dev) | ||
2995 | { | ||
2996 | unsigned int i; | ||
2997 | struct power_supply *psy = dev_get_drvdata(dev); | ||
2998 | struct ab8500_fg *di; | ||
2999 | |||
3000 | di = to_ab8500_fg_device_info(psy); | ||
3001 | |||
3002 | if (((is_ab8505(di->parent) || is_ab9540(di->parent)) && | ||
3003 | abx500_get_chip_id(dev->parent) >= AB8500_CUT2P0) | ||
3004 | || is_ab8540(di->parent)) { | ||
3005 | for (i = 0; i < ARRAY_SIZE(ab8505_fg_sysfs_psy_attrs); i++) | ||
3006 | (void)device_remove_file(dev, &ab8505_fg_sysfs_psy_attrs[i]); | ||
3007 | } | ||
3008 | } | ||
3009 | |||
2549 | /* Exposure to the sysfs interface <<END>> */ | 3010 | /* Exposure to the sysfs interface <<END>> */ |
2550 | 3011 | ||
2551 | #if defined(CONFIG_PM) | 3012 | #if defined(CONFIG_PM) |
@@ -2607,6 +3068,7 @@ static int ab8500_fg_remove(struct platform_device *pdev) | |||
2607 | ab8500_fg_sysfs_exit(di); | 3068 | ab8500_fg_sysfs_exit(di); |
2608 | 3069 | ||
2609 | flush_scheduled_work(); | 3070 | flush_scheduled_work(); |
3071 | ab8500_fg_sysfs_psy_remove_attrs(di->fg_psy.dev); | ||
2610 | power_supply_unregister(&di->fg_psy); | 3072 | power_supply_unregister(&di->fg_psy); |
2611 | platform_set_drvdata(pdev, NULL); | 3073 | platform_set_drvdata(pdev, NULL); |
2612 | return ret; | 3074 | return ret; |
@@ -2772,6 +3234,13 @@ static int ab8500_fg_probe(struct platform_device *pdev) | |||
2772 | goto free_irq; | 3234 | goto free_irq; |
2773 | } | 3235 | } |
2774 | 3236 | ||
3237 | ret = ab8500_fg_sysfs_psy_create_attrs(di->fg_psy.dev); | ||
3238 | if (ret) { | ||
3239 | dev_err(di->dev, "failed to create FG psy\n"); | ||
3240 | ab8500_fg_sysfs_exit(di); | ||
3241 | goto free_irq; | ||
3242 | } | ||
3243 | |||
2775 | /* Calibrate the fg first time */ | 3244 | /* Calibrate the fg first time */ |
2776 | di->flags.calibrate = true; | 3245 | di->flags.calibrate = true; |
2777 | di->calib_state = AB8500_FG_CALIB_INIT; | 3246 | di->calib_state = AB8500_FG_CALIB_INIT; |
diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c index f043c0851a76..9863e423602c 100644 --- a/drivers/power/abx500_chargalg.c +++ b/drivers/power/abx500_chargalg.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) ST-Ericsson SA 2012 | 2 | * Copyright (C) ST-Ericsson SA 2012 |
3 | * Copyright (c) 2012 Sony Mobile Communications AB | ||
3 | * | 4 | * |
4 | * Charging algorithm driver for abx500 variants | 5 | * Charging algorithm driver for abx500 variants |
5 | * | 6 | * |
@@ -8,11 +9,13 @@ | |||
8 | * Johan Palsson <johan.palsson@stericsson.com> | 9 | * Johan Palsson <johan.palsson@stericsson.com> |
9 | * Karl Komierowski <karl.komierowski@stericsson.com> | 10 | * Karl Komierowski <karl.komierowski@stericsson.com> |
10 | * Arun R Murthy <arun.murthy@stericsson.com> | 11 | * Arun R Murthy <arun.murthy@stericsson.com> |
12 | * Author: Imre Sunyi <imre.sunyi@sonymobile.com> | ||
11 | */ | 13 | */ |
12 | 14 | ||
13 | #include <linux/init.h> | 15 | #include <linux/init.h> |
14 | #include <linux/module.h> | 16 | #include <linux/module.h> |
15 | #include <linux/device.h> | 17 | #include <linux/device.h> |
18 | #include <linux/hrtimer.h> | ||
16 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
17 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
18 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
@@ -24,8 +27,10 @@ | |||
24 | #include <linux/of.h> | 27 | #include <linux/of.h> |
25 | #include <linux/mfd/core.h> | 28 | #include <linux/mfd/core.h> |
26 | #include <linux/mfd/abx500.h> | 29 | #include <linux/mfd/abx500.h> |
30 | #include <linux/mfd/abx500/ab8500.h> | ||
27 | #include <linux/mfd/abx500/ux500_chargalg.h> | 31 | #include <linux/mfd/abx500/ux500_chargalg.h> |
28 | #include <linux/mfd/abx500/ab8500-bm.h> | 32 | #include <linux/mfd/abx500/ab8500-bm.h> |
33 | #include <linux/notifier.h> | ||
29 | 34 | ||
30 | /* Watchdog kick interval */ | 35 | /* Watchdog kick interval */ |
31 | #define CHG_WD_INTERVAL (6 * HZ) | 36 | #define CHG_WD_INTERVAL (6 * HZ) |
@@ -33,6 +38,18 @@ | |||
33 | /* End-of-charge criteria counter */ | 38 | /* End-of-charge criteria counter */ |
34 | #define EOC_COND_CNT 10 | 39 | #define EOC_COND_CNT 10 |
35 | 40 | ||
41 | /* One hour expressed in seconds */ | ||
42 | #define ONE_HOUR_IN_SECONDS 3600 | ||
43 | |||
44 | /* Five minutes expressed in seconds */ | ||
45 | #define FIVE_MINUTES_IN_SECONDS 300 | ||
46 | |||
47 | /* Plus margin for the low battery threshold */ | ||
48 | #define BAT_PLUS_MARGIN (100) | ||
49 | |||
50 | #define CHARGALG_CURR_STEP_LOW 0 | ||
51 | #define CHARGALG_CURR_STEP_HIGH 100 | ||
52 | |||
36 | #define to_abx500_chargalg_device_info(x) container_of((x), \ | 53 | #define to_abx500_chargalg_device_info(x) container_of((x), \ |
37 | struct abx500_chargalg, chargalg_psy); | 54 | struct abx500_chargalg, chargalg_psy); |
38 | 55 | ||
@@ -66,6 +83,11 @@ struct abx500_chargalg_suspension_status { | |||
66 | bool usb_suspended; | 83 | bool usb_suspended; |
67 | }; | 84 | }; |
68 | 85 | ||
86 | struct abx500_chargalg_current_step_status { | ||
87 | bool curr_step_change; | ||
88 | int curr_step; | ||
89 | }; | ||
90 | |||
69 | struct abx500_chargalg_battery_data { | 91 | struct abx500_chargalg_battery_data { |
70 | int temp; | 92 | int temp; |
71 | int volt; | 93 | int volt; |
@@ -82,6 +104,7 @@ enum abx500_chargalg_states { | |||
82 | STATE_HW_TEMP_PROTECT_INIT, | 104 | STATE_HW_TEMP_PROTECT_INIT, |
83 | STATE_HW_TEMP_PROTECT, | 105 | STATE_HW_TEMP_PROTECT, |
84 | STATE_NORMAL_INIT, | 106 | STATE_NORMAL_INIT, |
107 | STATE_USB_PP_PRE_CHARGE, | ||
85 | STATE_NORMAL, | 108 | STATE_NORMAL, |
86 | STATE_WAIT_FOR_RECHARGE_INIT, | 109 | STATE_WAIT_FOR_RECHARGE_INIT, |
87 | STATE_WAIT_FOR_RECHARGE, | 110 | STATE_WAIT_FOR_RECHARGE, |
@@ -113,6 +136,7 @@ static const char *states[] = { | |||
113 | "HW_TEMP_PROTECT_INIT", | 136 | "HW_TEMP_PROTECT_INIT", |
114 | "HW_TEMP_PROTECT", | 137 | "HW_TEMP_PROTECT", |
115 | "NORMAL_INIT", | 138 | "NORMAL_INIT", |
139 | "USB_PP_PRE_CHARGE", | ||
116 | "NORMAL", | 140 | "NORMAL", |
117 | "WAIT_FOR_RECHARGE_INIT", | 141 | "WAIT_FOR_RECHARGE_INIT", |
118 | "WAIT_FOR_RECHARGE", | 142 | "WAIT_FOR_RECHARGE", |
@@ -204,6 +228,8 @@ enum maxim_ret { | |||
204 | * @batt_data: data of the battery | 228 | * @batt_data: data of the battery |
205 | * @susp_status: current charger suspension status | 229 | * @susp_status: current charger suspension status |
206 | * @bm: Platform specific battery management information | 230 | * @bm: Platform specific battery management information |
231 | * @curr_status: Current step status for over-current protection | ||
232 | * @parent: pointer to the struct abx500 | ||
207 | * @chargalg_psy: structure that holds the battery properties exposed by | 233 | * @chargalg_psy: structure that holds the battery properties exposed by |
208 | * the charging algorithm | 234 | * the charging algorithm |
209 | * @events: structure for information about events triggered | 235 | * @events: structure for information about events triggered |
@@ -227,6 +253,8 @@ struct abx500_chargalg { | |||
227 | struct abx500_chargalg_charger_info chg_info; | 253 | struct abx500_chargalg_charger_info chg_info; |
228 | struct abx500_chargalg_battery_data batt_data; | 254 | struct abx500_chargalg_battery_data batt_data; |
229 | struct abx500_chargalg_suspension_status susp_status; | 255 | struct abx500_chargalg_suspension_status susp_status; |
256 | struct ab8500 *parent; | ||
257 | struct abx500_chargalg_current_step_status curr_status; | ||
230 | struct abx500_bm_data *bm; | 258 | struct abx500_bm_data *bm; |
231 | struct power_supply chargalg_psy; | 259 | struct power_supply chargalg_psy; |
232 | struct ux500_charger *ac_chg; | 260 | struct ux500_charger *ac_chg; |
@@ -236,51 +264,69 @@ struct abx500_chargalg { | |||
236 | struct delayed_work chargalg_periodic_work; | 264 | struct delayed_work chargalg_periodic_work; |
237 | struct delayed_work chargalg_wd_work; | 265 | struct delayed_work chargalg_wd_work; |
238 | struct work_struct chargalg_work; | 266 | struct work_struct chargalg_work; |
239 | struct timer_list safety_timer; | 267 | struct hrtimer safety_timer; |
240 | struct timer_list maintenance_timer; | 268 | struct hrtimer maintenance_timer; |
241 | struct kobject chargalg_kobject; | 269 | struct kobject chargalg_kobject; |
242 | }; | 270 | }; |
243 | 271 | ||
272 | /*External charger prepare notifier*/ | ||
273 | BLOCKING_NOTIFIER_HEAD(charger_notifier_list); | ||
274 | |||
244 | /* Main battery properties */ | 275 | /* Main battery properties */ |
245 | static enum power_supply_property abx500_chargalg_props[] = { | 276 | static enum power_supply_property abx500_chargalg_props[] = { |
246 | POWER_SUPPLY_PROP_STATUS, | 277 | POWER_SUPPLY_PROP_STATUS, |
247 | POWER_SUPPLY_PROP_HEALTH, | 278 | POWER_SUPPLY_PROP_HEALTH, |
248 | }; | 279 | }; |
249 | 280 | ||
281 | struct abx500_chargalg_sysfs_entry { | ||
282 | struct attribute attr; | ||
283 | ssize_t (*show)(struct abx500_chargalg *, char *); | ||
284 | ssize_t (*store)(struct abx500_chargalg *, const char *, size_t); | ||
285 | }; | ||
286 | |||
250 | /** | 287 | /** |
251 | * abx500_chargalg_safety_timer_expired() - Expiration of the safety timer | 288 | * abx500_chargalg_safety_timer_expired() - Expiration of the safety timer |
252 | * @data: pointer to the abx500_chargalg structure | 289 | * @timer: pointer to the hrtimer structure |
253 | * | 290 | * |
254 | * This function gets called when the safety timer for the charger | 291 | * This function gets called when the safety timer for the charger |
255 | * expires | 292 | * expires |
256 | */ | 293 | */ |
257 | static void abx500_chargalg_safety_timer_expired(unsigned long data) | 294 | static enum hrtimer_restart |
295 | abx500_chargalg_safety_timer_expired(struct hrtimer *timer) | ||
258 | { | 296 | { |
259 | struct abx500_chargalg *di = (struct abx500_chargalg *) data; | 297 | struct abx500_chargalg *di = container_of(timer, struct abx500_chargalg, |
298 | safety_timer); | ||
260 | dev_err(di->dev, "Safety timer expired\n"); | 299 | dev_err(di->dev, "Safety timer expired\n"); |
261 | di->events.safety_timer_expired = true; | 300 | di->events.safety_timer_expired = true; |
262 | 301 | ||
263 | /* Trigger execution of the algorithm instantly */ | 302 | /* Trigger execution of the algorithm instantly */ |
264 | queue_work(di->chargalg_wq, &di->chargalg_work); | 303 | queue_work(di->chargalg_wq, &di->chargalg_work); |
304 | |||
305 | return HRTIMER_NORESTART; | ||
265 | } | 306 | } |
266 | 307 | ||
267 | /** | 308 | /** |
268 | * abx500_chargalg_maintenance_timer_expired() - Expiration of | 309 | * abx500_chargalg_maintenance_timer_expired() - Expiration of |
269 | * the maintenance timer | 310 | * the maintenance timer |
270 | * @i: pointer to the abx500_chargalg structure | 311 | * @timer: pointer to the timer structure |
271 | * | 312 | * |
272 | * This function gets called when the maintenence timer | 313 | * This function gets called when the maintenence timer |
273 | * expires | 314 | * expires |
274 | */ | 315 | */ |
275 | static void abx500_chargalg_maintenance_timer_expired(unsigned long data) | 316 | static enum hrtimer_restart |
317 | abx500_chargalg_maintenance_timer_expired(struct hrtimer *timer) | ||
276 | { | 318 | { |
277 | 319 | ||
278 | struct abx500_chargalg *di = (struct abx500_chargalg *) data; | 320 | struct abx500_chargalg *di = container_of(timer, struct abx500_chargalg, |
321 | maintenance_timer); | ||
322 | |||
279 | dev_dbg(di->dev, "Maintenance timer expired\n"); | 323 | dev_dbg(di->dev, "Maintenance timer expired\n"); |
280 | di->events.maintenance_timer_expired = true; | 324 | di->events.maintenance_timer_expired = true; |
281 | 325 | ||
282 | /* Trigger execution of the algorithm instantly */ | 326 | /* Trigger execution of the algorithm instantly */ |
283 | queue_work(di->chargalg_wq, &di->chargalg_work); | 327 | queue_work(di->chargalg_wq, &di->chargalg_work); |
328 | |||
329 | return HRTIMER_NORESTART; | ||
284 | } | 330 | } |
285 | 331 | ||
286 | /** | 332 | /** |
@@ -303,6 +349,30 @@ static void abx500_chargalg_state_to(struct abx500_chargalg *di, | |||
303 | di->charge_state = state; | 349 | di->charge_state = state; |
304 | } | 350 | } |
305 | 351 | ||
352 | static int abx500_chargalg_check_charger_enable(struct abx500_chargalg *di) | ||
353 | { | ||
354 | switch (di->charge_state) { | ||
355 | case STATE_NORMAL: | ||
356 | case STATE_MAINTENANCE_A: | ||
357 | case STATE_MAINTENANCE_B: | ||
358 | break; | ||
359 | default: | ||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | if (di->chg_info.charger_type & USB_CHG) { | ||
364 | return di->usb_chg->ops.check_enable(di->usb_chg, | ||
365 | di->bm->bat_type[di->bm->batt_id].normal_vol_lvl, | ||
366 | di->bm->bat_type[di->bm->batt_id].normal_cur_lvl); | ||
367 | } else if ((di->chg_info.charger_type & AC_CHG) && | ||
368 | !(di->ac_chg->external)) { | ||
369 | return di->ac_chg->ops.check_enable(di->ac_chg, | ||
370 | di->bm->bat_type[di->bm->batt_id].normal_vol_lvl, | ||
371 | di->bm->bat_type[di->bm->batt_id].normal_cur_lvl); | ||
372 | } | ||
373 | return 0; | ||
374 | } | ||
375 | |||
306 | /** | 376 | /** |
307 | * abx500_chargalg_check_charger_connection() - Check charger connection change | 377 | * abx500_chargalg_check_charger_connection() - Check charger connection change |
308 | * @di: pointer to the abx500_chargalg structure | 378 | * @di: pointer to the abx500_chargalg structure |
@@ -348,6 +418,22 @@ static int abx500_chargalg_check_charger_connection(struct abx500_chargalg *di) | |||
348 | } | 418 | } |
349 | 419 | ||
350 | /** | 420 | /** |
421 | * abx500_chargalg_check_current_step_status() - Check charging current | ||
422 | * step status. | ||
423 | * @di: pointer to the abx500_chargalg structure | ||
424 | * | ||
425 | * This function will check if there is a change in the charging current step | ||
426 | * and change charge state accordingly. | ||
427 | */ | ||
428 | static void abx500_chargalg_check_current_step_status | ||
429 | (struct abx500_chargalg *di) | ||
430 | { | ||
431 | if (di->curr_status.curr_step_change) | ||
432 | abx500_chargalg_state_to(di, STATE_NORMAL_INIT); | ||
433 | di->curr_status.curr_step_change = false; | ||
434 | } | ||
435 | |||
436 | /** | ||
351 | * abx500_chargalg_start_safety_timer() - Start charging safety timer | 437 | * abx500_chargalg_start_safety_timer() - Start charging safety timer |
352 | * @di: pointer to the abx500_chargalg structure | 438 | * @di: pointer to the abx500_chargalg structure |
353 | * | 439 | * |
@@ -356,19 +442,16 @@ static int abx500_chargalg_check_charger_connection(struct abx500_chargalg *di) | |||
356 | */ | 442 | */ |
357 | static void abx500_chargalg_start_safety_timer(struct abx500_chargalg *di) | 443 | static void abx500_chargalg_start_safety_timer(struct abx500_chargalg *di) |
358 | { | 444 | { |
359 | unsigned long timer_expiration = 0; | 445 | /* Charger-dependent expiration time in hours*/ |
446 | int timer_expiration = 0; | ||
360 | 447 | ||
361 | switch (di->chg_info.charger_type) { | 448 | switch (di->chg_info.charger_type) { |
362 | case AC_CHG: | 449 | case AC_CHG: |
363 | timer_expiration = | 450 | timer_expiration = di->bm->main_safety_tmr_h; |
364 | round_jiffies(jiffies + | ||
365 | (di->bm->main_safety_tmr_h * 3600 * HZ)); | ||
366 | break; | 451 | break; |
367 | 452 | ||
368 | case USB_CHG: | 453 | case USB_CHG: |
369 | timer_expiration = | 454 | timer_expiration = di->bm->usb_safety_tmr_h; |
370 | round_jiffies(jiffies + | ||
371 | (di->bm->usb_safety_tmr_h * 3600 * HZ)); | ||
372 | break; | 455 | break; |
373 | 456 | ||
374 | default: | 457 | default: |
@@ -377,11 +460,10 @@ static void abx500_chargalg_start_safety_timer(struct abx500_chargalg *di) | |||
377 | } | 460 | } |
378 | 461 | ||
379 | di->events.safety_timer_expired = false; | 462 | di->events.safety_timer_expired = false; |
380 | di->safety_timer.expires = timer_expiration; | 463 | hrtimer_set_expires_range(&di->safety_timer, |
381 | if (!timer_pending(&di->safety_timer)) | 464 | ktime_set(timer_expiration * ONE_HOUR_IN_SECONDS, 0), |
382 | add_timer(&di->safety_timer); | 465 | ktime_set(FIVE_MINUTES_IN_SECONDS, 0)); |
383 | else | 466 | hrtimer_start_expires(&di->safety_timer, HRTIMER_MODE_REL); |
384 | mod_timer(&di->safety_timer, timer_expiration); | ||
385 | } | 467 | } |
386 | 468 | ||
387 | /** | 469 | /** |
@@ -392,8 +474,8 @@ static void abx500_chargalg_start_safety_timer(struct abx500_chargalg *di) | |||
392 | */ | 474 | */ |
393 | static void abx500_chargalg_stop_safety_timer(struct abx500_chargalg *di) | 475 | static void abx500_chargalg_stop_safety_timer(struct abx500_chargalg *di) |
394 | { | 476 | { |
395 | di->events.safety_timer_expired = false; | 477 | if (hrtimer_try_to_cancel(&di->safety_timer) >= 0) |
396 | del_timer(&di->safety_timer); | 478 | di->events.safety_timer_expired = false; |
397 | } | 479 | } |
398 | 480 | ||
399 | /** | 481 | /** |
@@ -408,17 +490,11 @@ static void abx500_chargalg_stop_safety_timer(struct abx500_chargalg *di) | |||
408 | static void abx500_chargalg_start_maintenance_timer(struct abx500_chargalg *di, | 490 | static void abx500_chargalg_start_maintenance_timer(struct abx500_chargalg *di, |
409 | int duration) | 491 | int duration) |
410 | { | 492 | { |
411 | unsigned long timer_expiration; | 493 | hrtimer_set_expires_range(&di->maintenance_timer, |
412 | 494 | ktime_set(duration * ONE_HOUR_IN_SECONDS, 0), | |
413 | /* Convert from hours to jiffies */ | 495 | ktime_set(FIVE_MINUTES_IN_SECONDS, 0)); |
414 | timer_expiration = round_jiffies(jiffies + (duration * 3600 * HZ)); | ||
415 | |||
416 | di->events.maintenance_timer_expired = false; | 496 | di->events.maintenance_timer_expired = false; |
417 | di->maintenance_timer.expires = timer_expiration; | 497 | hrtimer_start_expires(&di->maintenance_timer, HRTIMER_MODE_REL); |
418 | if (!timer_pending(&di->maintenance_timer)) | ||
419 | add_timer(&di->maintenance_timer); | ||
420 | else | ||
421 | mod_timer(&di->maintenance_timer, timer_expiration); | ||
422 | } | 498 | } |
423 | 499 | ||
424 | /** | 500 | /** |
@@ -430,8 +506,8 @@ static void abx500_chargalg_start_maintenance_timer(struct abx500_chargalg *di, | |||
430 | */ | 506 | */ |
431 | static void abx500_chargalg_stop_maintenance_timer(struct abx500_chargalg *di) | 507 | static void abx500_chargalg_stop_maintenance_timer(struct abx500_chargalg *di) |
432 | { | 508 | { |
433 | di->events.maintenance_timer_expired = false; | 509 | if (hrtimer_try_to_cancel(&di->maintenance_timer) >= 0) |
434 | del_timer(&di->maintenance_timer); | 510 | di->events.maintenance_timer_expired = false; |
435 | } | 511 | } |
436 | 512 | ||
437 | /** | 513 | /** |
@@ -477,6 +553,8 @@ static int abx500_chargalg_kick_watchdog(struct abx500_chargalg *di) | |||
477 | static int abx500_chargalg_ac_en(struct abx500_chargalg *di, int enable, | 553 | static int abx500_chargalg_ac_en(struct abx500_chargalg *di, int enable, |
478 | int vset, int iset) | 554 | int vset, int iset) |
479 | { | 555 | { |
556 | static int abx500_chargalg_ex_ac_enable_toggle; | ||
557 | |||
480 | if (!di->ac_chg || !di->ac_chg->ops.enable) | 558 | if (!di->ac_chg || !di->ac_chg->ops.enable) |
481 | return -ENXIO; | 559 | return -ENXIO; |
482 | 560 | ||
@@ -489,6 +567,14 @@ static int abx500_chargalg_ac_en(struct abx500_chargalg *di, int enable, | |||
489 | di->chg_info.ac_iset = iset; | 567 | di->chg_info.ac_iset = iset; |
490 | di->chg_info.ac_vset = vset; | 568 | di->chg_info.ac_vset = vset; |
491 | 569 | ||
570 | /* Enable external charger */ | ||
571 | if (enable && di->ac_chg->external && | ||
572 | !abx500_chargalg_ex_ac_enable_toggle) { | ||
573 | blocking_notifier_call_chain(&charger_notifier_list, | ||
574 | 0, di->dev); | ||
575 | abx500_chargalg_ex_ac_enable_toggle++; | ||
576 | } | ||
577 | |||
492 | return di->ac_chg->ops.enable(di->ac_chg, enable, vset, iset); | 578 | return di->ac_chg->ops.enable(di->ac_chg, enable, vset, iset); |
493 | } | 579 | } |
494 | 580 | ||
@@ -520,6 +606,37 @@ static int abx500_chargalg_usb_en(struct abx500_chargalg *di, int enable, | |||
520 | return di->usb_chg->ops.enable(di->usb_chg, enable, vset, iset); | 606 | return di->usb_chg->ops.enable(di->usb_chg, enable, vset, iset); |
521 | } | 607 | } |
522 | 608 | ||
609 | /** | ||
610 | * ab8540_chargalg_usb_pp_en() - Enable/ disable USB power path | ||
611 | * @di: pointer to the abx500_chargalg structure | ||
612 | * @enable: power path enable/disable | ||
613 | * | ||
614 | * The USB power path will be enable/ disable | ||
615 | */ | ||
616 | static int ab8540_chargalg_usb_pp_en(struct abx500_chargalg *di, bool enable) | ||
617 | { | ||
618 | if (!di->usb_chg || !di->usb_chg->ops.pp_enable) | ||
619 | return -ENXIO; | ||
620 | |||
621 | return di->usb_chg->ops.pp_enable(di->usb_chg, enable); | ||
622 | } | ||
623 | |||
624 | /** | ||
625 | * ab8540_chargalg_usb_pre_chg_en() - Enable/ disable USB pre-charge | ||
626 | * @di: pointer to the abx500_chargalg structure | ||
627 | * @enable: USB pre-charge enable/disable | ||
628 | * | ||
629 | * The USB USB pre-charge will be enable/ disable | ||
630 | */ | ||
631 | static int ab8540_chargalg_usb_pre_chg_en(struct abx500_chargalg *di, | ||
632 | bool enable) | ||
633 | { | ||
634 | if (!di->usb_chg || !di->usb_chg->ops.pre_chg_enable) | ||
635 | return -ENXIO; | ||
636 | |||
637 | return di->usb_chg->ops.pre_chg_enable(di->usb_chg, enable); | ||
638 | } | ||
639 | |||
523 | /** | 640 | /** |
524 | * abx500_chargalg_update_chg_curr() - Update charger current | 641 | * abx500_chargalg_update_chg_curr() - Update charger current |
525 | * @di: pointer to the abx500_chargalg structure | 642 | * @di: pointer to the abx500_chargalg structure |
@@ -613,8 +730,6 @@ static void abx500_chargalg_hold_charging(struct abx500_chargalg *di) | |||
613 | static void abx500_chargalg_start_charging(struct abx500_chargalg *di, | 730 | static void abx500_chargalg_start_charging(struct abx500_chargalg *di, |
614 | int vset, int iset) | 731 | int vset, int iset) |
615 | { | 732 | { |
616 | bool start_chargalg_wd = true; | ||
617 | |||
618 | switch (di->chg_info.charger_type) { | 733 | switch (di->chg_info.charger_type) { |
619 | case AC_CHG: | 734 | case AC_CHG: |
620 | dev_dbg(di->dev, | 735 | dev_dbg(di->dev, |
@@ -632,12 +747,8 @@ static void abx500_chargalg_start_charging(struct abx500_chargalg *di, | |||
632 | 747 | ||
633 | default: | 748 | default: |
634 | dev_err(di->dev, "Unknown charger to charge from\n"); | 749 | dev_err(di->dev, "Unknown charger to charge from\n"); |
635 | start_chargalg_wd = false; | ||
636 | break; | 750 | break; |
637 | } | 751 | } |
638 | |||
639 | if (start_chargalg_wd && !delayed_work_pending(&di->chargalg_wd_work)) | ||
640 | queue_delayed_work(di->chargalg_wq, &di->chargalg_wd_work, 0); | ||
641 | } | 752 | } |
642 | 753 | ||
643 | /** | 754 | /** |
@@ -725,6 +836,9 @@ static void abx500_chargalg_end_of_charge(struct abx500_chargalg *di) | |||
725 | di->batt_data.avg_curr > 0) { | 836 | di->batt_data.avg_curr > 0) { |
726 | if (++di->eoc_cnt >= EOC_COND_CNT) { | 837 | if (++di->eoc_cnt >= EOC_COND_CNT) { |
727 | di->eoc_cnt = 0; | 838 | di->eoc_cnt = 0; |
839 | if ((di->chg_info.charger_type & USB_CHG) && | ||
840 | (di->usb_chg->power_path)) | ||
841 | ab8540_chargalg_usb_pp_en(di, true); | ||
728 | di->charge_status = POWER_SUPPLY_STATUS_FULL; | 842 | di->charge_status = POWER_SUPPLY_STATUS_FULL; |
729 | di->maintenance_chg = true; | 843 | di->maintenance_chg = true; |
730 | dev_dbg(di->dev, "EOC reached!\n"); | 844 | dev_dbg(di->dev, "EOC reached!\n"); |
@@ -1217,6 +1331,8 @@ static void abx500_chargalg_external_power_changed(struct power_supply *psy) | |||
1217 | static void abx500_chargalg_algorithm(struct abx500_chargalg *di) | 1331 | static void abx500_chargalg_algorithm(struct abx500_chargalg *di) |
1218 | { | 1332 | { |
1219 | int charger_status; | 1333 | int charger_status; |
1334 | int ret; | ||
1335 | int curr_step_lvl; | ||
1220 | 1336 | ||
1221 | /* Collect data from all power_supply class devices */ | 1337 | /* Collect data from all power_supply class devices */ |
1222 | class_for_each_device(power_supply_class, NULL, | 1338 | class_for_each_device(power_supply_class, NULL, |
@@ -1227,6 +1343,15 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di) | |||
1227 | abx500_chargalg_check_charger_voltage(di); | 1343 | abx500_chargalg_check_charger_voltage(di); |
1228 | 1344 | ||
1229 | charger_status = abx500_chargalg_check_charger_connection(di); | 1345 | charger_status = abx500_chargalg_check_charger_connection(di); |
1346 | abx500_chargalg_check_current_step_status(di); | ||
1347 | |||
1348 | if (is_ab8500(di->parent)) { | ||
1349 | ret = abx500_chargalg_check_charger_enable(di); | ||
1350 | if (ret < 0) | ||
1351 | dev_err(di->dev, "Checking charger is enabled error" | ||
1352 | ": Returned Value %d\n", ret); | ||
1353 | } | ||
1354 | |||
1230 | /* | 1355 | /* |
1231 | * First check if we have a charger connected. | 1356 | * First check if we have a charger connected. |
1232 | * Also we don't allow charging of unknown batteries if configured | 1357 | * Also we don't allow charging of unknown batteries if configured |
@@ -1416,9 +1541,34 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di) | |||
1416 | break; | 1541 | break; |
1417 | 1542 | ||
1418 | case STATE_NORMAL_INIT: | 1543 | case STATE_NORMAL_INIT: |
1419 | abx500_chargalg_start_charging(di, | 1544 | if ((di->chg_info.charger_type & USB_CHG) && |
1420 | di->bm->bat_type[di->bm->batt_id].normal_vol_lvl, | 1545 | di->usb_chg->power_path) { |
1421 | di->bm->bat_type[di->bm->batt_id].normal_cur_lvl); | 1546 | if (di->batt_data.volt > |
1547 | (di->bm->fg_params->lowbat_threshold + | ||
1548 | BAT_PLUS_MARGIN)) { | ||
1549 | ab8540_chargalg_usb_pre_chg_en(di, false); | ||
1550 | ab8540_chargalg_usb_pp_en(di, false); | ||
1551 | } else { | ||
1552 | ab8540_chargalg_usb_pp_en(di, true); | ||
1553 | ab8540_chargalg_usb_pre_chg_en(di, true); | ||
1554 | abx500_chargalg_state_to(di, | ||
1555 | STATE_USB_PP_PRE_CHARGE); | ||
1556 | break; | ||
1557 | } | ||
1558 | } | ||
1559 | |||
1560 | if (di->curr_status.curr_step == CHARGALG_CURR_STEP_LOW) | ||
1561 | abx500_chargalg_stop_charging(di); | ||
1562 | else { | ||
1563 | curr_step_lvl = di->bm->bat_type[ | ||
1564 | di->bm->batt_id].normal_cur_lvl | ||
1565 | * di->curr_status.curr_step | ||
1566 | / CHARGALG_CURR_STEP_HIGH; | ||
1567 | abx500_chargalg_start_charging(di, | ||
1568 | di->bm->bat_type[di->bm->batt_id] | ||
1569 | .normal_vol_lvl, curr_step_lvl); | ||
1570 | } | ||
1571 | |||
1422 | abx500_chargalg_state_to(di, STATE_NORMAL); | 1572 | abx500_chargalg_state_to(di, STATE_NORMAL); |
1423 | abx500_chargalg_start_safety_timer(di); | 1573 | abx500_chargalg_start_safety_timer(di); |
1424 | abx500_chargalg_stop_maintenance_timer(di); | 1574 | abx500_chargalg_stop_maintenance_timer(di); |
@@ -1430,6 +1580,13 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di) | |||
1430 | 1580 | ||
1431 | break; | 1581 | break; |
1432 | 1582 | ||
1583 | case STATE_USB_PP_PRE_CHARGE: | ||
1584 | if (di->batt_data.volt > | ||
1585 | (di->bm->fg_params->lowbat_threshold + | ||
1586 | BAT_PLUS_MARGIN)) | ||
1587 | abx500_chargalg_state_to(di, STATE_NORMAL_INIT); | ||
1588 | break; | ||
1589 | |||
1433 | case STATE_NORMAL: | 1590 | case STATE_NORMAL: |
1434 | handle_maxim_chg_curr(di); | 1591 | handle_maxim_chg_curr(di); |
1435 | if (di->charge_status == POWER_SUPPLY_STATUS_FULL && | 1592 | if (di->charge_status == POWER_SUPPLY_STATUS_FULL && |
@@ -1653,99 +1810,134 @@ static int abx500_chargalg_get_property(struct power_supply *psy, | |||
1653 | 1810 | ||
1654 | /* Exposure to the sysfs interface */ | 1811 | /* Exposure to the sysfs interface */ |
1655 | 1812 | ||
1656 | /** | 1813 | static ssize_t abx500_chargalg_curr_step_show(struct abx500_chargalg *di, |
1657 | * abx500_chargalg_sysfs_show() - sysfs show operations | 1814 | char *buf) |
1658 | * @kobj: pointer to the struct kobject | ||
1659 | * @attr: pointer to the struct attribute | ||
1660 | * @buf: buffer that holds the parameter to send to userspace | ||
1661 | * | ||
1662 | * Returns a buffer to be displayed in user space | ||
1663 | */ | ||
1664 | static ssize_t abx500_chargalg_sysfs_show(struct kobject *kobj, | ||
1665 | struct attribute *attr, char *buf) | ||
1666 | { | 1815 | { |
1667 | struct abx500_chargalg *di = container_of(kobj, | 1816 | return sprintf(buf, "%d\n", di->curr_status.curr_step); |
1668 | struct abx500_chargalg, chargalg_kobject); | 1817 | } |
1818 | |||
1819 | static ssize_t abx500_chargalg_curr_step_store(struct abx500_chargalg *di, | ||
1820 | const char *buf, size_t length) | ||
1821 | { | ||
1822 | long int param; | ||
1823 | int ret; | ||
1824 | |||
1825 | ret = kstrtol(buf, 10, ¶m); | ||
1826 | if (ret < 0) | ||
1827 | return ret; | ||
1828 | |||
1829 | di->curr_status.curr_step = param; | ||
1830 | if (di->curr_status.curr_step >= CHARGALG_CURR_STEP_LOW && | ||
1831 | di->curr_status.curr_step <= CHARGALG_CURR_STEP_HIGH) { | ||
1832 | di->curr_status.curr_step_change = true; | ||
1833 | queue_work(di->chargalg_wq, &di->chargalg_work); | ||
1834 | } else | ||
1835 | dev_info(di->dev, "Wrong current step\n" | ||
1836 | "Enter 0. Disable AC/USB Charging\n" | ||
1837 | "1--100. Set AC/USB charging current step\n" | ||
1838 | "100. Enable AC/USB Charging\n"); | ||
1839 | |||
1840 | return strlen(buf); | ||
1841 | } | ||
1842 | |||
1669 | 1843 | ||
1844 | static ssize_t abx500_chargalg_en_show(struct abx500_chargalg *di, | ||
1845 | char *buf) | ||
1846 | { | ||
1670 | return sprintf(buf, "%d\n", | 1847 | return sprintf(buf, "%d\n", |
1671 | di->susp_status.ac_suspended && | 1848 | di->susp_status.ac_suspended && |
1672 | di->susp_status.usb_suspended); | 1849 | di->susp_status.usb_suspended); |
1673 | } | 1850 | } |
1674 | 1851 | ||
1675 | /** | 1852 | static ssize_t abx500_chargalg_en_store(struct abx500_chargalg *di, |
1676 | * abx500_chargalg_sysfs_charger() - sysfs store operations | 1853 | const char *buf, size_t length) |
1677 | * @kobj: pointer to the struct kobject | ||
1678 | * @attr: pointer to the struct attribute | ||
1679 | * @buf: buffer that holds the parameter passed from userspace | ||
1680 | * @length: length of the parameter passed | ||
1681 | * | ||
1682 | * Returns length of the buffer(input taken from user space) on success | ||
1683 | * else error code on failure | ||
1684 | * The operation to be performed on passing the parameters from the user space. | ||
1685 | */ | ||
1686 | static ssize_t abx500_chargalg_sysfs_charger(struct kobject *kobj, | ||
1687 | struct attribute *attr, const char *buf, size_t length) | ||
1688 | { | 1854 | { |
1689 | struct abx500_chargalg *di = container_of(kobj, | ||
1690 | struct abx500_chargalg, chargalg_kobject); | ||
1691 | long int param; | 1855 | long int param; |
1692 | int ac_usb; | 1856 | int ac_usb; |
1693 | int ret; | 1857 | int ret; |
1694 | char entry = *attr->name; | ||
1695 | 1858 | ||
1696 | switch (entry) { | 1859 | ret = kstrtol(buf, 10, ¶m); |
1697 | case 'c': | 1860 | if (ret < 0) |
1698 | ret = strict_strtol(buf, 10, ¶m); | 1861 | return ret; |
1699 | if (ret < 0) | 1862 | |
1700 | return ret; | 1863 | ac_usb = param; |
1701 | 1864 | switch (ac_usb) { | |
1702 | ac_usb = param; | 1865 | case 0: |
1703 | switch (ac_usb) { | 1866 | /* Disable charging */ |
1704 | case 0: | 1867 | di->susp_status.ac_suspended = true; |
1705 | /* Disable charging */ | 1868 | di->susp_status.usb_suspended = true; |
1706 | di->susp_status.ac_suspended = true; | 1869 | di->susp_status.suspended_change = true; |
1707 | di->susp_status.usb_suspended = true; | 1870 | /* Trigger a state change */ |
1708 | di->susp_status.suspended_change = true; | 1871 | queue_work(di->chargalg_wq, |
1709 | /* Trigger a state change */ | 1872 | &di->chargalg_work); |
1710 | queue_work(di->chargalg_wq, | 1873 | break; |
1711 | &di->chargalg_work); | 1874 | case 1: |
1712 | break; | 1875 | /* Enable AC Charging */ |
1713 | case 1: | 1876 | di->susp_status.ac_suspended = false; |
1714 | /* Enable AC Charging */ | 1877 | di->susp_status.suspended_change = true; |
1715 | di->susp_status.ac_suspended = false; | 1878 | /* Trigger a state change */ |
1716 | di->susp_status.suspended_change = true; | 1879 | queue_work(di->chargalg_wq, |
1717 | /* Trigger a state change */ | 1880 | &di->chargalg_work); |
1718 | queue_work(di->chargalg_wq, | 1881 | break; |
1719 | &di->chargalg_work); | 1882 | case 2: |
1720 | break; | 1883 | /* Enable USB charging */ |
1721 | case 2: | 1884 | di->susp_status.usb_suspended = false; |
1722 | /* Enable USB charging */ | 1885 | di->susp_status.suspended_change = true; |
1723 | di->susp_status.usb_suspended = false; | 1886 | /* Trigger a state change */ |
1724 | di->susp_status.suspended_change = true; | 1887 | queue_work(di->chargalg_wq, |
1725 | /* Trigger a state change */ | 1888 | &di->chargalg_work); |
1726 | queue_work(di->chargalg_wq, | ||
1727 | &di->chargalg_work); | ||
1728 | break; | ||
1729 | default: | ||
1730 | dev_info(di->dev, "Wrong input\n" | ||
1731 | "Enter 0. Disable AC/USB Charging\n" | ||
1732 | "1. Enable AC charging\n" | ||
1733 | "2. Enable USB Charging\n"); | ||
1734 | }; | ||
1735 | break; | 1889 | break; |
1890 | default: | ||
1891 | dev_info(di->dev, "Wrong input\n" | ||
1892 | "Enter 0. Disable AC/USB Charging\n" | ||
1893 | "1. Enable AC charging\n" | ||
1894 | "2. Enable USB Charging\n"); | ||
1736 | }; | 1895 | }; |
1737 | return strlen(buf); | 1896 | return strlen(buf); |
1738 | } | 1897 | } |
1739 | 1898 | ||
1740 | static struct attribute abx500_chargalg_en_charger = \ | 1899 | static struct abx500_chargalg_sysfs_entry abx500_chargalg_en_charger = |
1900 | __ATTR(chargalg, 0644, abx500_chargalg_en_show, | ||
1901 | abx500_chargalg_en_store); | ||
1902 | |||
1903 | static struct abx500_chargalg_sysfs_entry abx500_chargalg_curr_step = | ||
1904 | __ATTR(chargalg_curr_step, 0644, abx500_chargalg_curr_step_show, | ||
1905 | abx500_chargalg_curr_step_store); | ||
1906 | |||
1907 | static ssize_t abx500_chargalg_sysfs_show(struct kobject *kobj, | ||
1908 | struct attribute *attr, char *buf) | ||
1741 | { | 1909 | { |
1742 | .name = "chargalg", | 1910 | struct abx500_chargalg_sysfs_entry *entry = container_of(attr, |
1743 | .mode = S_IRUGO | S_IWUSR, | 1911 | struct abx500_chargalg_sysfs_entry, attr); |
1744 | }; | 1912 | |
1913 | struct abx500_chargalg *di = container_of(kobj, | ||
1914 | struct abx500_chargalg, chargalg_kobject); | ||
1915 | |||
1916 | if (!entry->show) | ||
1917 | return -EIO; | ||
1918 | |||
1919 | return entry->show(di, buf); | ||
1920 | } | ||
1921 | |||
1922 | static ssize_t abx500_chargalg_sysfs_charger(struct kobject *kobj, | ||
1923 | struct attribute *attr, const char *buf, size_t length) | ||
1924 | { | ||
1925 | struct abx500_chargalg_sysfs_entry *entry = container_of(attr, | ||
1926 | struct abx500_chargalg_sysfs_entry, attr); | ||
1927 | |||
1928 | struct abx500_chargalg *di = container_of(kobj, | ||
1929 | struct abx500_chargalg, chargalg_kobject); | ||
1930 | |||
1931 | if (!entry->store) | ||
1932 | return -EIO; | ||
1933 | |||
1934 | return entry->store(di, buf, length); | ||
1935 | } | ||
1745 | 1936 | ||
1746 | static struct attribute *abx500_chargalg_chg[] = { | 1937 | static struct attribute *abx500_chargalg_chg[] = { |
1747 | &abx500_chargalg_en_charger, | 1938 | &abx500_chargalg_en_charger.attr, |
1748 | NULL | 1939 | &abx500_chargalg_curr_step.attr, |
1940 | NULL, | ||
1749 | }; | 1941 | }; |
1750 | 1942 | ||
1751 | static const struct sysfs_ops abx500_chargalg_sysfs_ops = { | 1943 | static const struct sysfs_ops abx500_chargalg_sysfs_ops = { |
@@ -1832,10 +2024,16 @@ static int abx500_chargalg_remove(struct platform_device *pdev) | |||
1832 | /* sysfs interface to enable/disbale charging from user space */ | 2024 | /* sysfs interface to enable/disbale charging from user space */ |
1833 | abx500_chargalg_sysfs_exit(di); | 2025 | abx500_chargalg_sysfs_exit(di); |
1834 | 2026 | ||
2027 | hrtimer_cancel(&di->safety_timer); | ||
2028 | hrtimer_cancel(&di->maintenance_timer); | ||
2029 | |||
2030 | cancel_delayed_work_sync(&di->chargalg_periodic_work); | ||
2031 | cancel_delayed_work_sync(&di->chargalg_wd_work); | ||
2032 | cancel_work_sync(&di->chargalg_work); | ||
2033 | |||
1835 | /* Delete the work queue */ | 2034 | /* Delete the work queue */ |
1836 | destroy_workqueue(di->chargalg_wq); | 2035 | destroy_workqueue(di->chargalg_wq); |
1837 | 2036 | ||
1838 | flush_scheduled_work(); | ||
1839 | power_supply_unregister(&di->chargalg_psy); | 2037 | power_supply_unregister(&di->chargalg_psy); |
1840 | platform_set_drvdata(pdev, NULL); | 2038 | platform_set_drvdata(pdev, NULL); |
1841 | 2039 | ||
@@ -1873,8 +2071,9 @@ static int abx500_chargalg_probe(struct platform_device *pdev) | |||
1873 | } | 2071 | } |
1874 | } | 2072 | } |
1875 | 2073 | ||
1876 | /* get device struct */ | 2074 | /* get device struct and parent */ |
1877 | di->dev = &pdev->dev; | 2075 | di->dev = &pdev->dev; |
2076 | di->parent = dev_get_drvdata(pdev->dev.parent); | ||
1878 | 2077 | ||
1879 | /* chargalg supply */ | 2078 | /* chargalg supply */ |
1880 | di->chargalg_psy.name = "abx500_chargalg"; | 2079 | di->chargalg_psy.name = "abx500_chargalg"; |
@@ -1888,15 +2087,13 @@ static int abx500_chargalg_probe(struct platform_device *pdev) | |||
1888 | abx500_chargalg_external_power_changed; | 2087 | abx500_chargalg_external_power_changed; |
1889 | 2088 | ||
1890 | /* Initilialize safety timer */ | 2089 | /* Initilialize safety timer */ |
1891 | init_timer(&di->safety_timer); | 2090 | hrtimer_init(&di->safety_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS); |
1892 | di->safety_timer.function = abx500_chargalg_safety_timer_expired; | 2091 | di->safety_timer.function = abx500_chargalg_safety_timer_expired; |
1893 | di->safety_timer.data = (unsigned long) di; | ||
1894 | 2092 | ||
1895 | /* Initilialize maintenance timer */ | 2093 | /* Initilialize maintenance timer */ |
1896 | init_timer(&di->maintenance_timer); | 2094 | hrtimer_init(&di->maintenance_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS); |
1897 | di->maintenance_timer.function = | 2095 | di->maintenance_timer.function = |
1898 | abx500_chargalg_maintenance_timer_expired; | 2096 | abx500_chargalg_maintenance_timer_expired; |
1899 | di->maintenance_timer.data = (unsigned long) di; | ||
1900 | 2097 | ||
1901 | /* Create a work queue for the chargalg */ | 2098 | /* Create a work queue for the chargalg */ |
1902 | di->chargalg_wq = | 2099 | di->chargalg_wq = |
@@ -1933,6 +2130,7 @@ static int abx500_chargalg_probe(struct platform_device *pdev) | |||
1933 | dev_err(di->dev, "failed to create sysfs entry\n"); | 2130 | dev_err(di->dev, "failed to create sysfs entry\n"); |
1934 | goto free_psy; | 2131 | goto free_psy; |
1935 | } | 2132 | } |
2133 | di->curr_status.curr_step = CHARGALG_CURR_STEP_HIGH; | ||
1936 | 2134 | ||
1937 | /* Run the charging algorithm */ | 2135 | /* Run the charging algorithm */ |
1938 | queue_delayed_work(di->chargalg_wq, &di->chargalg_periodic_work, 0); | 2136 | queue_delayed_work(di->chargalg_wq, &di->chargalg_periodic_work, 0); |
@@ -1964,18 +2162,7 @@ static struct platform_driver abx500_chargalg_driver = { | |||
1964 | }, | 2162 | }, |
1965 | }; | 2163 | }; |
1966 | 2164 | ||
1967 | static int __init abx500_chargalg_init(void) | 2165 | module_platform_driver(abx500_chargalg_driver); |
1968 | { | ||
1969 | return platform_driver_register(&abx500_chargalg_driver); | ||
1970 | } | ||
1971 | |||
1972 | static void __exit abx500_chargalg_exit(void) | ||
1973 | { | ||
1974 | platform_driver_unregister(&abx500_chargalg_driver); | ||
1975 | } | ||
1976 | |||
1977 | module_init(abx500_chargalg_init); | ||
1978 | module_exit(abx500_chargalg_exit); | ||
1979 | 2166 | ||
1980 | MODULE_LICENSE("GPL v2"); | 2167 | MODULE_LICENSE("GPL v2"); |
1981 | MODULE_AUTHOR("Johan Palsson, Karl Komierowski"); | 2168 | MODULE_AUTHOR("Johan Palsson, Karl Komierowski"); |
diff --git a/drivers/power/pm2301_charger.c b/drivers/power/pm2301_charger.c index ed48d75bb786..618c46d25a3b 100644 --- a/drivers/power/pm2301_charger.c +++ b/drivers/power/pm2301_charger.c | |||
@@ -16,24 +16,24 @@ | |||
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
18 | #include <linux/power_supply.h> | 18 | #include <linux/power_supply.h> |
19 | #include <linux/completion.h> | ||
20 | #include <linux/regulator/consumer.h> | 19 | #include <linux/regulator/consumer.h> |
21 | #include <linux/err.h> | 20 | #include <linux/err.h> |
22 | #include <linux/i2c.h> | 21 | #include <linux/i2c.h> |
23 | #include <linux/workqueue.h> | 22 | #include <linux/workqueue.h> |
24 | #include <linux/kobject.h> | ||
25 | #include <linux/mfd/abx500.h> | ||
26 | #include <linux/mfd/abx500/ab8500.h> | 23 | #include <linux/mfd/abx500/ab8500.h> |
27 | #include <linux/mfd/abx500/ab8500-bm.h> | 24 | #include <linux/mfd/abx500/ab8500-bm.h> |
28 | #include <linux/mfd/abx500/ab8500-gpadc.h> | ||
29 | #include <linux/mfd/abx500/ux500_chargalg.h> | 25 | #include <linux/mfd/abx500/ux500_chargalg.h> |
30 | #include <linux/pm2301_charger.h> | 26 | #include <linux/pm2301_charger.h> |
31 | #include <linux/gpio.h> | 27 | #include <linux/gpio.h> |
28 | #include <linux/pm_runtime.h> | ||
32 | 29 | ||
33 | #include "pm2301_charger.h" | 30 | #include "pm2301_charger.h" |
34 | 31 | ||
35 | #define to_pm2xxx_charger_ac_device_info(x) container_of((x), \ | 32 | #define to_pm2xxx_charger_ac_device_info(x) container_of((x), \ |
36 | struct pm2xxx_charger, ac_chg) | 33 | struct pm2xxx_charger, ac_chg) |
34 | #define SLEEP_MIN 50 | ||
35 | #define SLEEP_MAX 100 | ||
36 | #define PM2XXX_AUTOSUSPEND_DELAY 500 | ||
37 | 37 | ||
38 | static int pm2xxx_interrupt_registers[] = { | 38 | static int pm2xxx_interrupt_registers[] = { |
39 | PM2XXX_REG_INT1, | 39 | PM2XXX_REG_INT1, |
@@ -113,33 +113,24 @@ static const struct i2c_device_id pm2xxx_ident[] = { | |||
113 | 113 | ||
114 | static void set_lpn_pin(struct pm2xxx_charger *pm2) | 114 | static void set_lpn_pin(struct pm2xxx_charger *pm2) |
115 | { | 115 | { |
116 | if (pm2->ac.charger_connected) | 116 | if (!pm2->ac.charger_connected && gpio_is_valid(pm2->lpn_pin)) { |
117 | return; | 117 | gpio_set_value(pm2->lpn_pin, 1); |
118 | gpio_set_value(pm2->lpn_pin, 1); | 118 | usleep_range(SLEEP_MIN, SLEEP_MAX); |
119 | 119 | } | |
120 | return; | ||
121 | } | 120 | } |
122 | 121 | ||
123 | static void clear_lpn_pin(struct pm2xxx_charger *pm2) | 122 | static void clear_lpn_pin(struct pm2xxx_charger *pm2) |
124 | { | 123 | { |
125 | if (pm2->ac.charger_connected) | 124 | if (!pm2->ac.charger_connected && gpio_is_valid(pm2->lpn_pin)) |
126 | return; | 125 | gpio_set_value(pm2->lpn_pin, 0); |
127 | gpio_set_value(pm2->lpn_pin, 0); | ||
128 | |||
129 | return; | ||
130 | } | 126 | } |
131 | 127 | ||
132 | static int pm2xxx_reg_read(struct pm2xxx_charger *pm2, int reg, u8 *val) | 128 | static int pm2xxx_reg_read(struct pm2xxx_charger *pm2, int reg, u8 *val) |
133 | { | 129 | { |
134 | int ret; | 130 | int ret; |
135 | /* | 131 | |
136 | * When AC adaptor is unplugged, the host | 132 | /* wake up the device */ |
137 | * must put LPN high to be able to | 133 | pm_runtime_get_sync(pm2->dev); |
138 | * communicate by I2C with PM2301 | ||
139 | * and receive I2C "acknowledge" from PM2301. | ||
140 | */ | ||
141 | mutex_lock(&pm2->lock); | ||
142 | set_lpn_pin(pm2); | ||
143 | 134 | ||
144 | ret = i2c_smbus_read_i2c_block_data(pm2->config.pm2xxx_i2c, reg, | 135 | ret = i2c_smbus_read_i2c_block_data(pm2->config.pm2xxx_i2c, reg, |
145 | 1, val); | 136 | 1, val); |
@@ -147,8 +138,8 @@ static int pm2xxx_reg_read(struct pm2xxx_charger *pm2, int reg, u8 *val) | |||
147 | dev_err(pm2->dev, "Error reading register at 0x%x\n", reg); | 138 | dev_err(pm2->dev, "Error reading register at 0x%x\n", reg); |
148 | else | 139 | else |
149 | ret = 0; | 140 | ret = 0; |
150 | clear_lpn_pin(pm2); | 141 | |
151 | mutex_unlock(&pm2->lock); | 142 | pm_runtime_put_sync(pm2->dev); |
152 | 143 | ||
153 | return ret; | 144 | return ret; |
154 | } | 145 | } |
@@ -156,14 +147,9 @@ static int pm2xxx_reg_read(struct pm2xxx_charger *pm2, int reg, u8 *val) | |||
156 | static int pm2xxx_reg_write(struct pm2xxx_charger *pm2, int reg, u8 val) | 147 | static int pm2xxx_reg_write(struct pm2xxx_charger *pm2, int reg, u8 val) |
157 | { | 148 | { |
158 | int ret; | 149 | int ret; |
159 | /* | 150 | |
160 | * When AC adaptor is unplugged, the host | 151 | /* wake up the device */ |
161 | * must put LPN high to be able to | 152 | pm_runtime_get_sync(pm2->dev); |
162 | * communicate by I2C with PM2301 | ||
163 | * and receive I2C "acknowledge" from PM2301. | ||
164 | */ | ||
165 | mutex_lock(&pm2->lock); | ||
166 | set_lpn_pin(pm2); | ||
167 | 153 | ||
168 | ret = i2c_smbus_write_i2c_block_data(pm2->config.pm2xxx_i2c, reg, | 154 | ret = i2c_smbus_write_i2c_block_data(pm2->config.pm2xxx_i2c, reg, |
169 | 1, &val); | 155 | 1, &val); |
@@ -171,8 +157,8 @@ static int pm2xxx_reg_write(struct pm2xxx_charger *pm2, int reg, u8 val) | |||
171 | dev_err(pm2->dev, "Error writing register at 0x%x\n", reg); | 157 | dev_err(pm2->dev, "Error writing register at 0x%x\n", reg); |
172 | else | 158 | else |
173 | ret = 0; | 159 | ret = 0; |
174 | clear_lpn_pin(pm2); | 160 | |
175 | mutex_unlock(&pm2->lock); | 161 | pm_runtime_put_sync(pm2->dev); |
176 | 162 | ||
177 | return ret; | 163 | return ret; |
178 | } | 164 | } |
@@ -192,11 +178,22 @@ static int pm2xxx_charging_disable_mngt(struct pm2xxx_charger *pm2) | |||
192 | { | 178 | { |
193 | int ret; | 179 | int ret; |
194 | 180 | ||
181 | /* Disable SW EOC ctrl */ | ||
182 | ret = pm2xxx_reg_write(pm2, PM2XXX_SW_CTRL_REG, PM2XXX_SWCTRL_HW); | ||
183 | if (ret < 0) { | ||
184 | dev_err(pm2->dev, "%s pm2xxx write failed\n", __func__); | ||
185 | return ret; | ||
186 | } | ||
187 | |||
195 | /* Disable charging */ | 188 | /* Disable charging */ |
196 | ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG2, | 189 | ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG2, |
197 | (PM2XXX_CH_AUTO_RESUME_DIS | PM2XXX_CHARGER_DIS)); | 190 | (PM2XXX_CH_AUTO_RESUME_DIS | PM2XXX_CHARGER_DIS)); |
191 | if (ret < 0) { | ||
192 | dev_err(pm2->dev, "%s pm2xxx write failed\n", __func__); | ||
193 | return ret; | ||
194 | } | ||
198 | 195 | ||
199 | return ret; | 196 | return 0; |
200 | } | 197 | } |
201 | 198 | ||
202 | static int pm2xxx_charger_batt_therm_mngt(struct pm2xxx_charger *pm2, int val) | 199 | static int pm2xxx_charger_batt_therm_mngt(struct pm2xxx_charger *pm2, int val) |
@@ -216,21 +213,14 @@ int pm2xxx_charger_die_therm_mngt(struct pm2xxx_charger *pm2, int val) | |||
216 | 213 | ||
217 | static int pm2xxx_charger_ovv_mngt(struct pm2xxx_charger *pm2, int val) | 214 | static int pm2xxx_charger_ovv_mngt(struct pm2xxx_charger *pm2, int val) |
218 | { | 215 | { |
219 | int ret = 0; | 216 | dev_err(pm2->dev, "Overvoltage detected\n"); |
217 | pm2->flags.ovv = true; | ||
218 | power_supply_changed(&pm2->ac_chg.psy); | ||
220 | 219 | ||
221 | pm2->failure_input_ovv++; | 220 | /* Schedule a new HW failure check */ |
222 | if (pm2->failure_input_ovv < 4) { | 221 | queue_delayed_work(pm2->charger_wq, &pm2->check_hw_failure_work, 0); |
223 | ret = pm2xxx_charging_enable_mngt(pm2); | ||
224 | goto out; | ||
225 | } else { | ||
226 | pm2->failure_input_ovv = 0; | ||
227 | dev_err(pm2->dev, "Overvoltage detected\n"); | ||
228 | pm2->flags.ovv = true; | ||
229 | power_supply_changed(&pm2->ac_chg.psy); | ||
230 | } | ||
231 | 222 | ||
232 | out: | 223 | return 0; |
233 | return ret; | ||
234 | } | 224 | } |
235 | 225 | ||
236 | static int pm2xxx_charger_wd_exp_mngt(struct pm2xxx_charger *pm2, int val) | 226 | static int pm2xxx_charger_wd_exp_mngt(struct pm2xxx_charger *pm2, int val) |
@@ -245,13 +235,29 @@ static int pm2xxx_charger_wd_exp_mngt(struct pm2xxx_charger *pm2, int val) | |||
245 | 235 | ||
246 | static int pm2xxx_charger_vbat_lsig_mngt(struct pm2xxx_charger *pm2, int val) | 236 | static int pm2xxx_charger_vbat_lsig_mngt(struct pm2xxx_charger *pm2, int val) |
247 | { | 237 | { |
238 | int ret; | ||
239 | |||
248 | switch (val) { | 240 | switch (val) { |
249 | case PM2XXX_INT1_ITVBATLOWR: | 241 | case PM2XXX_INT1_ITVBATLOWR: |
250 | dev_dbg(pm2->dev, "VBAT grows above VBAT_LOW level\n"); | 242 | dev_dbg(pm2->dev, "VBAT grows above VBAT_LOW level\n"); |
243 | /* Enable SW EOC ctrl */ | ||
244 | ret = pm2xxx_reg_write(pm2, PM2XXX_SW_CTRL_REG, | ||
245 | PM2XXX_SWCTRL_SW); | ||
246 | if (ret < 0) { | ||
247 | dev_err(pm2->dev, "%s pm2xxx write failed\n", __func__); | ||
248 | return ret; | ||
249 | } | ||
251 | break; | 250 | break; |
252 | 251 | ||
253 | case PM2XXX_INT1_ITVBATLOWF: | 252 | case PM2XXX_INT1_ITVBATLOWF: |
254 | dev_dbg(pm2->dev, "VBAT drops below VBAT_LOW level\n"); | 253 | dev_dbg(pm2->dev, "VBAT drops below VBAT_LOW level\n"); |
254 | /* Disable SW EOC ctrl */ | ||
255 | ret = pm2xxx_reg_write(pm2, PM2XXX_SW_CTRL_REG, | ||
256 | PM2XXX_SWCTRL_HW); | ||
257 | if (ret < 0) { | ||
258 | dev_err(pm2->dev, "%s pm2xxx write failed\n", __func__); | ||
259 | return ret; | ||
260 | } | ||
255 | break; | 261 | break; |
256 | 262 | ||
257 | default: | 263 | default: |
@@ -322,16 +328,27 @@ static int pm2_int_reg0(void *pm2_data, int val) | |||
322 | struct pm2xxx_charger *pm2 = pm2_data; | 328 | struct pm2xxx_charger *pm2 = pm2_data; |
323 | int ret = 0; | 329 | int ret = 0; |
324 | 330 | ||
325 | if (val & (PM2XXX_INT1_ITVBATLOWR | PM2XXX_INT1_ITVBATLOWF)) { | 331 | if (val & PM2XXX_INT1_ITVBATLOWR) { |
326 | ret = pm2xxx_charger_vbat_lsig_mngt(pm2, val & | 332 | ret = pm2xxx_charger_vbat_lsig_mngt(pm2, |
327 | (PM2XXX_INT1_ITVBATLOWR | PM2XXX_INT1_ITVBATLOWF)); | 333 | PM2XXX_INT1_ITVBATLOWR); |
334 | if (ret < 0) | ||
335 | goto out; | ||
336 | } | ||
337 | |||
338 | if (val & PM2XXX_INT1_ITVBATLOWF) { | ||
339 | ret = pm2xxx_charger_vbat_lsig_mngt(pm2, | ||
340 | PM2XXX_INT1_ITVBATLOWF); | ||
341 | if (ret < 0) | ||
342 | goto out; | ||
328 | } | 343 | } |
329 | 344 | ||
330 | if (val & PM2XXX_INT1_ITVBATDISCONNECT) { | 345 | if (val & PM2XXX_INT1_ITVBATDISCONNECT) { |
331 | ret = pm2xxx_charger_bat_disc_mngt(pm2, | 346 | ret = pm2xxx_charger_bat_disc_mngt(pm2, |
332 | PM2XXX_INT1_ITVBATDISCONNECT); | 347 | PM2XXX_INT1_ITVBATDISCONNECT); |
348 | if (ret < 0) | ||
349 | goto out; | ||
333 | } | 350 | } |
334 | 351 | out: | |
335 | return ret; | 352 | return ret; |
336 | } | 353 | } |
337 | 354 | ||
@@ -447,7 +464,6 @@ static int pm2_int_reg5(void *pm2_data, int val) | |||
447 | struct pm2xxx_charger *pm2 = pm2_data; | 464 | struct pm2xxx_charger *pm2 = pm2_data; |
448 | int ret = 0; | 465 | int ret = 0; |
449 | 466 | ||
450 | |||
451 | if (val & (PM2XXX_INT6_ITVPWR2DROP | PM2XXX_INT6_ITVPWR1DROP)) { | 467 | if (val & (PM2XXX_INT6_ITVPWR2DROP | PM2XXX_INT6_ITVPWR1DROP)) { |
452 | dev_dbg(pm2->dev, "VMPWR drop to VBAT level\n"); | 468 | dev_dbg(pm2->dev, "VMPWR drop to VBAT level\n"); |
453 | } | 469 | } |
@@ -468,14 +484,22 @@ static irqreturn_t pm2xxx_irq_int(int irq, void *data) | |||
468 | struct pm2xxx_interrupts *interrupt = pm2->pm2_int; | 484 | struct pm2xxx_interrupts *interrupt = pm2->pm2_int; |
469 | int i; | 485 | int i; |
470 | 486 | ||
471 | for (i = 0; i < PM2XXX_NUM_INT_REG; i++) { | 487 | /* wake up the device */ |
472 | pm2xxx_reg_read(pm2, | 488 | pm_runtime_get_sync(pm2->dev); |
489 | |||
490 | do { | ||
491 | for (i = 0; i < PM2XXX_NUM_INT_REG; i++) { | ||
492 | pm2xxx_reg_read(pm2, | ||
473 | pm2xxx_interrupt_registers[i], | 493 | pm2xxx_interrupt_registers[i], |
474 | &(interrupt->reg[i])); | 494 | &(interrupt->reg[i])); |
475 | 495 | ||
476 | if (interrupt->reg[i] > 0) | 496 | if (interrupt->reg[i] > 0) |
477 | interrupt->handler[i](pm2, interrupt->reg[i]); | 497 | interrupt->handler[i](pm2, interrupt->reg[i]); |
478 | } | 498 | } |
499 | } while (gpio_get_value(pm2->pdata->gpio_irq_number) == 0); | ||
500 | |||
501 | pm_runtime_mark_last_busy(pm2->dev); | ||
502 | pm_runtime_put_autosuspend(pm2->dev); | ||
479 | 503 | ||
480 | return IRQ_HANDLED; | 504 | return IRQ_HANDLED; |
481 | } | 505 | } |
@@ -592,6 +616,8 @@ static int pm2xxx_charger_ac_get_property(struct power_supply *psy, | |||
592 | val->intval = POWER_SUPPLY_HEALTH_DEAD; | 616 | val->intval = POWER_SUPPLY_HEALTH_DEAD; |
593 | else if (pm2->flags.main_thermal_prot) | 617 | else if (pm2->flags.main_thermal_prot) |
594 | val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; | 618 | val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; |
619 | else if (pm2->flags.ovv) | ||
620 | val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE; | ||
595 | else | 621 | else |
596 | val->intval = POWER_SUPPLY_HEALTH_GOOD; | 622 | val->intval = POWER_SUPPLY_HEALTH_GOOD; |
597 | break; | 623 | break; |
@@ -674,10 +700,6 @@ static int pm2xxx_charging_init(struct pm2xxx_charger *pm2) | |||
674 | ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_LOW_LEV_COMP_REG, | 700 | ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_LOW_LEV_COMP_REG, |
675 | PM2XXX_VBAT_LOW_MONITORING_ENA); | 701 | PM2XXX_VBAT_LOW_MONITORING_ENA); |
676 | 702 | ||
677 | /* Disable LED */ | ||
678 | ret = pm2xxx_reg_write(pm2, PM2XXX_LED_CTRL_REG, | ||
679 | PM2XXX_LED_SELECT_DIS); | ||
680 | |||
681 | return ret; | 703 | return ret; |
682 | } | 704 | } |
683 | 705 | ||
@@ -822,10 +844,54 @@ static void pm2xxx_charger_ac_work(struct work_struct *work) | |||
822 | sysfs_notify(&pm2->ac_chg.psy.dev->kobj, NULL, "present"); | 844 | sysfs_notify(&pm2->ac_chg.psy.dev->kobj, NULL, "present"); |
823 | }; | 845 | }; |
824 | 846 | ||
847 | static void pm2xxx_charger_check_hw_failure_work(struct work_struct *work) | ||
848 | { | ||
849 | u8 reg_value; | ||
850 | |||
851 | struct pm2xxx_charger *pm2 = container_of(work, | ||
852 | struct pm2xxx_charger, check_hw_failure_work.work); | ||
853 | |||
854 | if (pm2->flags.ovv) { | ||
855 | pm2xxx_reg_read(pm2, PM2XXX_SRCE_REG_INT4, ®_value); | ||
856 | |||
857 | if (!(reg_value & (PM2XXX_INT4_S_ITVPWR1OVV | | ||
858 | PM2XXX_INT4_S_ITVPWR2OVV))) { | ||
859 | pm2->flags.ovv = false; | ||
860 | power_supply_changed(&pm2->ac_chg.psy); | ||
861 | } | ||
862 | } | ||
863 | |||
864 | /* If we still have a failure, schedule a new check */ | ||
865 | if (pm2->flags.ovv) { | ||
866 | queue_delayed_work(pm2->charger_wq, | ||
867 | &pm2->check_hw_failure_work, round_jiffies(HZ)); | ||
868 | } | ||
869 | } | ||
870 | |||
825 | static void pm2xxx_charger_check_main_thermal_prot_work( | 871 | static void pm2xxx_charger_check_main_thermal_prot_work( |
826 | struct work_struct *work) | 872 | struct work_struct *work) |
827 | { | 873 | { |
828 | }; | 874 | int ret; |
875 | u8 val; | ||
876 | |||
877 | struct pm2xxx_charger *pm2 = container_of(work, struct pm2xxx_charger, | ||
878 | check_main_thermal_prot_work); | ||
879 | |||
880 | /* Check if die temp warning is still active */ | ||
881 | ret = pm2xxx_reg_read(pm2, PM2XXX_SRCE_REG_INT5, &val); | ||
882 | if (ret < 0) { | ||
883 | dev_err(pm2->dev, "%s pm2xxx read failed\n", __func__); | ||
884 | return; | ||
885 | } | ||
886 | if (val & (PM2XXX_INT5_S_ITTHERMALWARNINGRISE | ||
887 | | PM2XXX_INT5_S_ITTHERMALSHUTDOWNRISE)) | ||
888 | pm2->flags.main_thermal_prot = true; | ||
889 | else if (val & (PM2XXX_INT5_S_ITTHERMALWARNINGFALL | ||
890 | | PM2XXX_INT5_S_ITTHERMALSHUTDOWNFALL)) | ||
891 | pm2->flags.main_thermal_prot = false; | ||
892 | |||
893 | power_supply_changed(&pm2->ac_chg.psy); | ||
894 | } | ||
829 | 895 | ||
830 | static struct pm2xxx_interrupts pm2xxx_int = { | 896 | static struct pm2xxx_interrupts pm2xxx_int = { |
831 | .handler[0] = pm2_int_reg0, | 897 | .handler[0] = pm2_int_reg0, |
@@ -842,22 +908,92 @@ static struct pm2xxx_irq pm2xxx_charger_irq[] = { | |||
842 | 908 | ||
843 | static int pm2xxx_wall_charger_resume(struct i2c_client *i2c_client) | 909 | static int pm2xxx_wall_charger_resume(struct i2c_client *i2c_client) |
844 | { | 910 | { |
911 | struct pm2xxx_charger *pm2; | ||
912 | |||
913 | pm2 = (struct pm2xxx_charger *)i2c_get_clientdata(i2c_client); | ||
914 | set_lpn_pin(pm2); | ||
915 | |||
916 | /* If we still have a HW failure, schedule a new check */ | ||
917 | if (pm2->flags.ovv) | ||
918 | queue_delayed_work(pm2->charger_wq, | ||
919 | &pm2->check_hw_failure_work, 0); | ||
920 | |||
845 | return 0; | 921 | return 0; |
846 | } | 922 | } |
847 | 923 | ||
848 | static int pm2xxx_wall_charger_suspend(struct i2c_client *i2c_client, | 924 | static int pm2xxx_wall_charger_suspend(struct i2c_client *i2c_client, |
849 | pm_message_t state) | 925 | pm_message_t state) |
850 | { | 926 | { |
927 | struct pm2xxx_charger *pm2; | ||
928 | |||
929 | pm2 = (struct pm2xxx_charger *)i2c_get_clientdata(i2c_client); | ||
930 | clear_lpn_pin(pm2); | ||
931 | |||
932 | /* Cancel any pending HW failure check */ | ||
933 | if (delayed_work_pending(&pm2->check_hw_failure_work)) | ||
934 | cancel_delayed_work(&pm2->check_hw_failure_work); | ||
935 | |||
936 | flush_work(&pm2->ac_work); | ||
937 | flush_work(&pm2->check_main_thermal_prot_work); | ||
938 | |||
851 | return 0; | 939 | return 0; |
852 | } | 940 | } |
853 | 941 | ||
854 | static int __devinit pm2xxx_wall_charger_probe(struct i2c_client *i2c_client, | 942 | #ifdef CONFIG_PM |
943 | static int pm2xxx_runtime_suspend(struct device *dev) | ||
944 | { | ||
945 | struct i2c_client *pm2xxx_i2c_client = to_i2c_client(dev); | ||
946 | struct pm2xxx_charger *pm2; | ||
947 | int ret = 0; | ||
948 | |||
949 | pm2 = (struct pm2xxx_charger *)i2c_get_clientdata(pm2xxx_i2c_client); | ||
950 | if (!pm2) { | ||
951 | dev_err(pm2->dev, "no pm2xxx_charger data supplied\n"); | ||
952 | ret = -EINVAL; | ||
953 | return ret; | ||
954 | } | ||
955 | |||
956 | clear_lpn_pin(pm2); | ||
957 | |||
958 | return ret; | ||
959 | } | ||
960 | |||
961 | static int pm2xxx_runtime_resume(struct device *dev) | ||
962 | { | ||
963 | struct i2c_client *pm2xxx_i2c_client = to_i2c_client(dev); | ||
964 | struct pm2xxx_charger *pm2; | ||
965 | int ret = 0; | ||
966 | |||
967 | pm2 = (struct pm2xxx_charger *)i2c_get_clientdata(pm2xxx_i2c_client); | ||
968 | if (!pm2) { | ||
969 | dev_err(pm2->dev, "no pm2xxx_charger data supplied\n"); | ||
970 | ret = -EINVAL; | ||
971 | return ret; | ||
972 | } | ||
973 | |||
974 | if (gpio_is_valid(pm2->lpn_pin) && gpio_get_value(pm2->lpn_pin) == 0) | ||
975 | set_lpn_pin(pm2); | ||
976 | |||
977 | return ret; | ||
978 | } | ||
979 | |||
980 | static const struct dev_pm_ops pm2xxx_pm_ops = { | ||
981 | .runtime_suspend = pm2xxx_runtime_suspend, | ||
982 | .runtime_resume = pm2xxx_runtime_resume, | ||
983 | }; | ||
984 | #define PM2XXX_PM_OPS (&pm2xxx_pm_ops) | ||
985 | #else | ||
986 | #define PM2XXX_PM_OPS NULL | ||
987 | #endif | ||
988 | |||
989 | static int pm2xxx_wall_charger_probe(struct i2c_client *i2c_client, | ||
855 | const struct i2c_device_id *id) | 990 | const struct i2c_device_id *id) |
856 | { | 991 | { |
857 | struct pm2xxx_platform_data *pl_data = i2c_client->dev.platform_data; | 992 | struct pm2xxx_platform_data *pl_data = i2c_client->dev.platform_data; |
858 | struct pm2xxx_charger *pm2; | 993 | struct pm2xxx_charger *pm2; |
859 | int ret = 0; | 994 | int ret = 0; |
860 | u8 val; | 995 | u8 val; |
996 | int i; | ||
861 | 997 | ||
862 | pm2 = kzalloc(sizeof(struct pm2xxx_charger), GFP_KERNEL); | 998 | pm2 = kzalloc(sizeof(struct pm2xxx_charger), GFP_KERNEL); |
863 | if (!pm2) { | 999 | if (!pm2) { |
@@ -867,7 +1003,6 @@ static int __devinit pm2xxx_wall_charger_probe(struct i2c_client *i2c_client, | |||
867 | 1003 | ||
868 | /* get parent data */ | 1004 | /* get parent data */ |
869 | pm2->dev = &i2c_client->dev; | 1005 | pm2->dev = &i2c_client->dev; |
870 | pm2->gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | ||
871 | 1006 | ||
872 | pm2->pm2_int = &pm2xxx_int; | 1007 | pm2->pm2_int = &pm2xxx_int; |
873 | 1008 | ||
@@ -889,14 +1024,6 @@ static int __devinit pm2xxx_wall_charger_probe(struct i2c_client *i2c_client, | |||
889 | 1024 | ||
890 | pm2->bat = pl_data->battery; | 1025 | pm2->bat = pl_data->battery; |
891 | 1026 | ||
892 | /*get lpn GPIO from platform data*/ | ||
893 | if (!pm2->pdata->lpn_gpio) { | ||
894 | dev_err(pm2->dev, "no lpn gpio data supplied\n"); | ||
895 | ret = -EINVAL; | ||
896 | goto free_device_info; | ||
897 | } | ||
898 | pm2->lpn_pin = pm2->pdata->lpn_gpio; | ||
899 | |||
900 | if (!i2c_check_functionality(i2c_client->adapter, | 1027 | if (!i2c_check_functionality(i2c_client->adapter, |
901 | I2C_FUNC_SMBUS_BYTE_DATA | | 1028 | I2C_FUNC_SMBUS_BYTE_DATA | |
902 | I2C_FUNC_SMBUS_READ_WORD_DATA)) { | 1029 | I2C_FUNC_SMBUS_READ_WORD_DATA)) { |
@@ -945,6 +1072,10 @@ static int __devinit pm2xxx_wall_charger_probe(struct i2c_client *i2c_client, | |||
945 | INIT_WORK(&pm2->check_main_thermal_prot_work, | 1072 | INIT_WORK(&pm2->check_main_thermal_prot_work, |
946 | pm2xxx_charger_check_main_thermal_prot_work); | 1073 | pm2xxx_charger_check_main_thermal_prot_work); |
947 | 1074 | ||
1075 | /* Init work for HW failure check */ | ||
1076 | INIT_DEFERRABLE_WORK(&pm2->check_hw_failure_work, | ||
1077 | pm2xxx_charger_check_hw_failure_work); | ||
1078 | |||
948 | /* | 1079 | /* |
949 | * VDD ADC supply needs to be enabled from this driver when there | 1080 | * VDD ADC supply needs to be enabled from this driver when there |
950 | * is a charger connected to avoid erroneous BTEMP_HIGH/LOW | 1081 | * is a charger connected to avoid erroneous BTEMP_HIGH/LOW |
@@ -965,40 +1096,72 @@ static int __devinit pm2xxx_wall_charger_probe(struct i2c_client *i2c_client, | |||
965 | } | 1096 | } |
966 | 1097 | ||
967 | /* Register interrupts */ | 1098 | /* Register interrupts */ |
968 | ret = request_threaded_irq(pm2->pdata->irq_number, NULL, | 1099 | ret = request_threaded_irq(gpio_to_irq(pm2->pdata->gpio_irq_number), |
1100 | NULL, | ||
969 | pm2xxx_charger_irq[0].isr, | 1101 | pm2xxx_charger_irq[0].isr, |
970 | pm2->pdata->irq_type, | 1102 | pm2->pdata->irq_type, |
971 | pm2xxx_charger_irq[0].name, pm2); | 1103 | pm2xxx_charger_irq[0].name, pm2); |
972 | 1104 | ||
973 | if (ret != 0) { | 1105 | if (ret != 0) { |
974 | dev_err(pm2->dev, "failed to request %s IRQ %d: %d\n", | 1106 | dev_err(pm2->dev, "failed to request %s IRQ %d: %d\n", |
975 | pm2xxx_charger_irq[0].name, pm2->pdata->irq_number, ret); | 1107 | pm2xxx_charger_irq[0].name, |
1108 | gpio_to_irq(pm2->pdata->gpio_irq_number), ret); | ||
976 | goto unregister_pm2xxx_charger; | 1109 | goto unregister_pm2xxx_charger; |
977 | } | 1110 | } |
978 | 1111 | ||
979 | /*Initialize lock*/ | 1112 | ret = pm_runtime_set_active(pm2->dev); |
980 | mutex_init(&pm2->lock); | 1113 | if (ret) |
1114 | dev_err(pm2->dev, "set active Error\n"); | ||
981 | 1115 | ||
982 | /* | 1116 | pm_runtime_enable(pm2->dev); |
983 | * Charger detection mechanism requires pulling up the LPN pin | 1117 | pm_runtime_set_autosuspend_delay(pm2->dev, PM2XXX_AUTOSUSPEND_DELAY); |
984 | * while i2c communication if Charger is not connected | 1118 | pm_runtime_use_autosuspend(pm2->dev); |
985 | * LPN pin of PM2301 is GPIO60 of AB9540 | 1119 | pm_runtime_resume(pm2->dev); |
986 | */ | 1120 | |
987 | ret = gpio_request(pm2->lpn_pin, "pm2301_lpm_gpio"); | 1121 | /* pm interrupt can wake up system */ |
988 | if (ret < 0) { | 1122 | ret = enable_irq_wake(gpio_to_irq(pm2->pdata->gpio_irq_number)); |
989 | dev_err(pm2->dev, "pm2301_lpm_gpio request failed\n"); | 1123 | if (ret) { |
990 | goto unregister_pm2xxx_charger; | 1124 | dev_err(pm2->dev, "failed to set irq wake\n"); |
1125 | goto unregister_pm2xxx_interrupt; | ||
991 | } | 1126 | } |
992 | ret = gpio_direction_output(pm2->lpn_pin, 0); | 1127 | |
993 | if (ret < 0) { | 1128 | mutex_init(&pm2->lock); |
994 | dev_err(pm2->dev, "pm2301_lpm_gpio direction failed\n"); | 1129 | |
995 | goto free_gpio; | 1130 | if (gpio_is_valid(pm2->pdata->lpn_gpio)) { |
1131 | /* get lpn GPIO from platform data */ | ||
1132 | pm2->lpn_pin = pm2->pdata->lpn_gpio; | ||
1133 | |||
1134 | /* | ||
1135 | * Charger detection mechanism requires pulling up the LPN pin | ||
1136 | * while i2c communication if Charger is not connected | ||
1137 | * LPN pin of PM2301 is GPIO60 of AB9540 | ||
1138 | */ | ||
1139 | ret = gpio_request(pm2->lpn_pin, "pm2301_lpm_gpio"); | ||
1140 | |||
1141 | if (ret < 0) { | ||
1142 | dev_err(pm2->dev, "pm2301_lpm_gpio request failed\n"); | ||
1143 | goto disable_pm2_irq_wake; | ||
1144 | } | ||
1145 | ret = gpio_direction_output(pm2->lpn_pin, 0); | ||
1146 | if (ret < 0) { | ||
1147 | dev_err(pm2->dev, "pm2301_lpm_gpio direction failed\n"); | ||
1148 | goto free_gpio; | ||
1149 | } | ||
1150 | set_lpn_pin(pm2); | ||
996 | } | 1151 | } |
997 | 1152 | ||
1153 | /* read interrupt registers */ | ||
1154 | for (i = 0; i < PM2XXX_NUM_INT_REG; i++) | ||
1155 | pm2xxx_reg_read(pm2, | ||
1156 | pm2xxx_interrupt_registers[i], | ||
1157 | &val); | ||
1158 | |||
998 | ret = pm2xxx_charger_detection(pm2, &val); | 1159 | ret = pm2xxx_charger_detection(pm2, &val); |
999 | 1160 | ||
1000 | if ((ret == 0) && val) { | 1161 | if ((ret == 0) && val) { |
1001 | pm2->ac.charger_connected = 1; | 1162 | pm2->ac.charger_connected = 1; |
1163 | ab8500_override_turn_on_stat(~AB8500_POW_KEY_1_ON, | ||
1164 | AB8500_MAIN_CH_DET); | ||
1002 | pm2->ac_conn = true; | 1165 | pm2->ac_conn = true; |
1003 | power_supply_changed(&pm2->ac_chg.psy); | 1166 | power_supply_changed(&pm2->ac_chg.psy); |
1004 | sysfs_notify(&pm2->ac_chg.psy.dev->kobj, NULL, "present"); | 1167 | sysfs_notify(&pm2->ac_chg.psy.dev->kobj, NULL, "present"); |
@@ -1007,7 +1170,13 @@ static int __devinit pm2xxx_wall_charger_probe(struct i2c_client *i2c_client, | |||
1007 | return 0; | 1170 | return 0; |
1008 | 1171 | ||
1009 | free_gpio: | 1172 | free_gpio: |
1010 | gpio_free(pm2->lpn_pin); | 1173 | if (gpio_is_valid(pm2->lpn_pin)) |
1174 | gpio_free(pm2->lpn_pin); | ||
1175 | disable_pm2_irq_wake: | ||
1176 | disable_irq_wake(gpio_to_irq(pm2->pdata->gpio_irq_number)); | ||
1177 | unregister_pm2xxx_interrupt: | ||
1178 | /* disable interrupt */ | ||
1179 | free_irq(gpio_to_irq(pm2->pdata->gpio_irq_number), pm2); | ||
1011 | unregister_pm2xxx_charger: | 1180 | unregister_pm2xxx_charger: |
1012 | /* unregister power supply */ | 1181 | /* unregister power supply */ |
1013 | power_supply_unregister(&pm2->ac_chg.psy); | 1182 | power_supply_unregister(&pm2->ac_chg.psy); |
@@ -1018,18 +1187,24 @@ free_charger_wq: | |||
1018 | destroy_workqueue(pm2->charger_wq); | 1187 | destroy_workqueue(pm2->charger_wq); |
1019 | free_device_info: | 1188 | free_device_info: |
1020 | kfree(pm2); | 1189 | kfree(pm2); |
1190 | |||
1021 | return ret; | 1191 | return ret; |
1022 | } | 1192 | } |
1023 | 1193 | ||
1024 | static int __devexit pm2xxx_wall_charger_remove(struct i2c_client *i2c_client) | 1194 | static int pm2xxx_wall_charger_remove(struct i2c_client *i2c_client) |
1025 | { | 1195 | { |
1026 | struct pm2xxx_charger *pm2 = i2c_get_clientdata(i2c_client); | 1196 | struct pm2xxx_charger *pm2 = i2c_get_clientdata(i2c_client); |
1027 | 1197 | ||
1198 | /* Disable pm_runtime */ | ||
1199 | pm_runtime_disable(pm2->dev); | ||
1028 | /* Disable AC charging */ | 1200 | /* Disable AC charging */ |
1029 | pm2xxx_charger_ac_en(&pm2->ac_chg, false, 0, 0); | 1201 | pm2xxx_charger_ac_en(&pm2->ac_chg, false, 0, 0); |
1030 | 1202 | ||
1203 | /* Disable wake by pm interrupt */ | ||
1204 | disable_irq_wake(gpio_to_irq(pm2->pdata->gpio_irq_number)); | ||
1205 | |||
1031 | /* Disable interrupts */ | 1206 | /* Disable interrupts */ |
1032 | free_irq(pm2->pdata->irq_number, pm2); | 1207 | free_irq(gpio_to_irq(pm2->pdata->gpio_irq_number), pm2); |
1033 | 1208 | ||
1034 | /* Delete the work queue */ | 1209 | /* Delete the work queue */ |
1035 | destroy_workqueue(pm2->charger_wq); | 1210 | destroy_workqueue(pm2->charger_wq); |
@@ -1041,8 +1216,8 @@ static int __devexit pm2xxx_wall_charger_remove(struct i2c_client *i2c_client) | |||
1041 | 1216 | ||
1042 | power_supply_unregister(&pm2->ac_chg.psy); | 1217 | power_supply_unregister(&pm2->ac_chg.psy); |
1043 | 1218 | ||
1044 | /*Free GPIO60*/ | 1219 | if (gpio_is_valid(pm2->lpn_pin)) |
1045 | gpio_free(pm2->lpn_pin); | 1220 | gpio_free(pm2->lpn_pin); |
1046 | 1221 | ||
1047 | kfree(pm2); | 1222 | kfree(pm2); |
1048 | 1223 | ||
@@ -1058,12 +1233,13 @@ MODULE_DEVICE_TABLE(i2c, pm2xxx_id); | |||
1058 | 1233 | ||
1059 | static struct i2c_driver pm2xxx_charger_driver = { | 1234 | static struct i2c_driver pm2xxx_charger_driver = { |
1060 | .probe = pm2xxx_wall_charger_probe, | 1235 | .probe = pm2xxx_wall_charger_probe, |
1061 | .remove = __devexit_p(pm2xxx_wall_charger_remove), | 1236 | .remove = pm2xxx_wall_charger_remove, |
1062 | .suspend = pm2xxx_wall_charger_suspend, | 1237 | .suspend = pm2xxx_wall_charger_suspend, |
1063 | .resume = pm2xxx_wall_charger_resume, | 1238 | .resume = pm2xxx_wall_charger_resume, |
1064 | .driver = { | 1239 | .driver = { |
1065 | .name = "pm2xxx-wall_charger", | 1240 | .name = "pm2xxx-wall_charger", |
1066 | .owner = THIS_MODULE, | 1241 | .owner = THIS_MODULE, |
1242 | .pm = PM2XXX_PM_OPS, | ||
1067 | }, | 1243 | }, |
1068 | .id_table = pm2xxx_id, | 1244 | .id_table = pm2xxx_id, |
1069 | }; | 1245 | }; |
@@ -1078,11 +1254,10 @@ static void __exit pm2xxx_charger_exit(void) | |||
1078 | i2c_del_driver(&pm2xxx_charger_driver); | 1254 | i2c_del_driver(&pm2xxx_charger_driver); |
1079 | } | 1255 | } |
1080 | 1256 | ||
1081 | subsys_initcall_sync(pm2xxx_charger_init); | 1257 | device_initcall_sync(pm2xxx_charger_init); |
1082 | module_exit(pm2xxx_charger_exit); | 1258 | module_exit(pm2xxx_charger_exit); |
1083 | 1259 | ||
1084 | MODULE_LICENSE("GPL v2"); | 1260 | MODULE_LICENSE("GPL v2"); |
1085 | MODULE_AUTHOR("Rajkumar kasirajan, Olivier Launay"); | 1261 | MODULE_AUTHOR("Rajkumar kasirajan, Olivier Launay"); |
1086 | MODULE_ALIAS("platform:pm2xxx-charger"); | 1262 | MODULE_ALIAS("platform:pm2xxx-charger"); |
1087 | MODULE_DESCRIPTION("PM2xxx charger management driver"); | 1263 | MODULE_DESCRIPTION("PM2xxx charger management driver"); |
1088 | |||
diff --git a/drivers/power/pm2301_charger.h b/drivers/power/pm2301_charger.h index e6319cdbc94f..8ce3cc0195df 100644 --- a/drivers/power/pm2301_charger.h +++ b/drivers/power/pm2301_charger.h | |||
@@ -9,27 +9,6 @@ | |||
9 | #ifndef PM2301_CHARGER_H | 9 | #ifndef PM2301_CHARGER_H |
10 | #define PM2301_CHARGER_H | 10 | #define PM2301_CHARGER_H |
11 | 11 | ||
12 | #define MAIN_WDOG_ENA 0x01 | ||
13 | #define MAIN_WDOG_KICK 0x02 | ||
14 | #define MAIN_WDOG_DIS 0x00 | ||
15 | #define CHARG_WD_KICK 0x01 | ||
16 | #define MAIN_CH_ENA 0x01 | ||
17 | #define MAIN_CH_NO_OVERSHOOT_ENA_N 0x02 | ||
18 | #define MAIN_CH_DET 0x01 | ||
19 | #define MAIN_CH_CV_ON 0x04 | ||
20 | #define OTP_ENABLE_WD 0x01 | ||
21 | |||
22 | #define MAIN_CH_INPUT_CURR_SHIFT 4 | ||
23 | |||
24 | #define LED_INDICATOR_PWM_ENA 0x01 | ||
25 | #define LED_INDICATOR_PWM_DIS 0x00 | ||
26 | #define LED_IND_CUR_5MA 0x04 | ||
27 | #define LED_INDICATOR_PWM_DUTY_252_256 0xBF | ||
28 | |||
29 | /* HW failure constants */ | ||
30 | #define MAIN_CH_TH_PROT 0x02 | ||
31 | #define MAIN_CH_NOK 0x01 | ||
32 | |||
33 | /* Watchdog timeout constant */ | 12 | /* Watchdog timeout constant */ |
34 | #define WD_TIMER 0x30 /* 4min */ | 13 | #define WD_TIMER 0x30 /* 4min */ |
35 | #define WD_KICK_INTERVAL (30 * HZ) | 14 | #define WD_KICK_INTERVAL (30 * HZ) |
@@ -495,7 +474,6 @@ struct pm2xxx_charger { | |||
495 | int failure_input_ovv; | 474 | int failure_input_ovv; |
496 | unsigned int lpn_pin; | 475 | unsigned int lpn_pin; |
497 | struct pm2xxx_interrupts *pm2_int; | 476 | struct pm2xxx_interrupts *pm2_int; |
498 | struct ab8500_gpadc *gpadc; | ||
499 | struct regulator *regu; | 477 | struct regulator *regu; |
500 | struct pm2xxx_bm_data *bat; | 478 | struct pm2xxx_bm_data *bat; |
501 | struct mutex lock; | 479 | struct mutex lock; |
@@ -506,6 +484,7 @@ struct pm2xxx_charger { | |||
506 | struct delayed_work check_vbat_work; | 484 | struct delayed_work check_vbat_work; |
507 | struct work_struct ac_work; | 485 | struct work_struct ac_work; |
508 | struct work_struct check_main_thermal_prot_work; | 486 | struct work_struct check_main_thermal_prot_work; |
487 | struct delayed_work check_hw_failure_work; | ||
509 | struct ux500_charger ac_chg; | 488 | struct ux500_charger ac_chg; |
510 | struct pm2xxx_charger_event_flags flags; | 489 | struct pm2xxx_charger_event_flags flags; |
511 | }; | 490 | }; |