diff options
| author | Anton Vorontsov <anton@enomsg.org> | 2013-03-18 22:02:58 -0400 |
|---|---|---|
| committer | Anton Vorontsov <anton@enomsg.org> | 2013-03-18 22:02:58 -0400 |
| commit | 441a499e5a5bf7b65ca557abd5ffc64b509dca65 (patch) | |
| tree | 4ea91d43d10521b466e8ea19db3b5e498e7c07fd | |
| parent | a937536b868b8369b98967929045f1df54234323 (diff) | |
| parent | b09f86dbfc20d9420dac43dba016cb65b582c983 (diff) | |
Merge branch 'for-mfd-and-power' of git://git.linaro.org/people/ljones/linux-3.0-ux500
From Lee Jones <lee.jones@linaro.org>:
"Please find the next instalment of the AB8500 Power drivers upgrade. A lot of
work has taken place on the internal development track, but little effort has
gone into mainlining it. There is a large backlog of patches which are in need
of forward-porting, then upstreaming. This patch-set aims to make a large dent
into them."
Conflicts:
drivers/mfd/ab8500-gpadc.c
| -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 | ||||
| -rw-r--r-- | include/linux/mfd/abx500.h | 21 | ||||
| -rw-r--r-- | include/linux/mfd/abx500/ab8500-bm.h | 60 | ||||
| -rw-r--r-- | include/linux/mfd/abx500/ab8500-gpadc.h | 74 | ||||
| -rw-r--r-- | include/linux/mfd/abx500/ab8500-sysctrl.h | 6 | ||||
| -rw-r--r-- | include/linux/mfd/abx500/ab8500.h | 3 | ||||
| -rw-r--r-- | include/linux/mfd/abx500/ux500_chargalg.h | 7 | ||||
| -rw-r--r-- | include/linux/pm2301_charger.h | 2 |
20 files changed, 4425 insertions, 916 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 | }; |
diff --git a/include/linux/mfd/abx500.h b/include/linux/mfd/abx500.h index 9ead60bc66b7..33b0253569a3 100644 --- a/include/linux/mfd/abx500.h +++ b/include/linux/mfd/abx500.h | |||
| @@ -89,6 +89,11 @@ struct abx500_fg; | |||
| 89 | * points. | 89 | * points. |
| 90 | * @maint_thres This is the threshold where we stop reporting | 90 | * @maint_thres This is the threshold where we stop reporting |
| 91 | * battery full while in maintenance, in per cent | 91 | * battery full while in maintenance, in per cent |
| 92 | * @pcut_enable: Enable power cut feature in ab8505 | ||
| 93 | * @pcut_max_time: Max time threshold | ||
| 94 | * @pcut_flag_time: Flagtime threshold | ||
| 95 | * @pcut_max_restart: Max number of restarts | ||
| 96 | * @pcut_debounce_time: Sets battery debounce time | ||
| 92 | */ | 97 | */ |
| 93 | struct abx500_fg_parameters { | 98 | struct abx500_fg_parameters { |
| 94 | int recovery_sleep_timer; | 99 | int recovery_sleep_timer; |
| @@ -106,6 +111,11 @@ struct abx500_fg_parameters { | |||
| 106 | int battok_raising_th_sel1; | 111 | int battok_raising_th_sel1; |
| 107 | int user_cap_limit; | 112 | int user_cap_limit; |
| 108 | int maint_thres; | 113 | int maint_thres; |
| 114 | bool pcut_enable; | ||
| 115 | u8 pcut_max_time; | ||
| 116 | u8 pcut_flag_time; | ||
| 117 | u8 pcut_max_restart; | ||
| 118 | u8 pcut_debounce_time; | ||
| 109 | }; | 119 | }; |
| 110 | 120 | ||
| 111 | /** | 121 | /** |
| @@ -236,7 +246,11 @@ struct abx500_bm_charger_parameters { | |||
| 236 | * @interval_not_charging charge alg cycle period time when not charging (sec) | 246 | * @interval_not_charging charge alg cycle period time when not charging (sec) |
| 237 | * @temp_hysteresis temperature hysteresis | 247 | * @temp_hysteresis temperature hysteresis |
| 238 | * @gnd_lift_resistance Battery ground to phone ground resistance (mOhm) | 248 | * @gnd_lift_resistance Battery ground to phone ground resistance (mOhm) |
| 239 | * @maxi: maximization parameters | 249 | * @n_chg_out_curr number of elements in array chg_output_curr |
| 250 | * @n_chg_in_curr number of elements in array chg_input_curr | ||
| 251 | * @chg_output_curr charger output current level map | ||
| 252 | * @chg_input_curr charger input current level map | ||
| 253 | * @maxi maximization parameters | ||
| 240 | * @cap_levels capacity in percent for the different capacity levels | 254 | * @cap_levels capacity in percent for the different capacity levels |
| 241 | * @bat_type table of supported battery types | 255 | * @bat_type table of supported battery types |
| 242 | * @chg_params charger parameters | 256 | * @chg_params charger parameters |
| @@ -257,6 +271,7 @@ struct abx500_bm_data { | |||
| 257 | bool autopower_cfg; | 271 | bool autopower_cfg; |
| 258 | bool ac_enabled; | 272 | bool ac_enabled; |
| 259 | bool usb_enabled; | 273 | bool usb_enabled; |
| 274 | bool usb_power_path; | ||
| 260 | bool no_maintenance; | 275 | bool no_maintenance; |
| 261 | bool capacity_scaling; | 276 | bool capacity_scaling; |
| 262 | bool chg_unknown_bat; | 277 | bool chg_unknown_bat; |
| @@ -270,6 +285,10 @@ struct abx500_bm_data { | |||
| 270 | int interval_not_charging; | 285 | int interval_not_charging; |
| 271 | int temp_hysteresis; | 286 | int temp_hysteresis; |
| 272 | int gnd_lift_resistance; | 287 | int gnd_lift_resistance; |
| 288 | int n_chg_out_curr; | ||
| 289 | int n_chg_in_curr; | ||
| 290 | int *chg_output_curr; | ||
| 291 | int *chg_input_curr; | ||
| 273 | const struct abx500_maxim_parameters *maxi; | 292 | const struct abx500_maxim_parameters *maxi; |
| 274 | const struct abx500_bm_capacity_levels *cap_levels; | 293 | const struct abx500_bm_capacity_levels *cap_levels; |
| 275 | struct abx500_battery_type *bat_type; | 294 | struct abx500_battery_type *bat_type; |
diff --git a/include/linux/mfd/abx500/ab8500-bm.h b/include/linux/mfd/abx500/ab8500-bm.h index 8d35bfe164c8..f5214dc651f9 100644 --- a/include/linux/mfd/abx500/ab8500-bm.h +++ b/include/linux/mfd/abx500/ab8500-bm.h | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | * Bank : 0x5 | 23 | * Bank : 0x5 |
| 24 | */ | 24 | */ |
| 25 | #define AB8500_USB_LINE_STAT_REG 0x80 | 25 | #define AB8500_USB_LINE_STAT_REG 0x80 |
| 26 | #define AB8500_USB_LINE_CTRL2_REG 0x82 | ||
| 26 | #define AB8500_USB_LINK1_STAT_REG 0x94 | 27 | #define AB8500_USB_LINK1_STAT_REG 0x94 |
| 27 | 28 | ||
| 28 | /* | 29 | /* |
| @@ -33,7 +34,7 @@ | |||
| 33 | #define AB8500_CH_STATUS2_REG 0x01 | 34 | #define AB8500_CH_STATUS2_REG 0x01 |
| 34 | #define AB8500_CH_USBCH_STAT1_REG 0x02 | 35 | #define AB8500_CH_USBCH_STAT1_REG 0x02 |
| 35 | #define AB8500_CH_USBCH_STAT2_REG 0x03 | 36 | #define AB8500_CH_USBCH_STAT2_REG 0x03 |
| 36 | #define AB8500_CH_FSM_STAT_REG 0x04 | 37 | #define AB8540_CH_USBCH_STAT3_REG 0x04 |
| 37 | #define AB8500_CH_STAT_REG 0x05 | 38 | #define AB8500_CH_STAT_REG 0x05 |
| 38 | 39 | ||
| 39 | /* | 40 | /* |
| @@ -69,6 +70,8 @@ | |||
| 69 | #define AB8500_USBCH_CTRL1_REG 0xC0 | 70 | #define AB8500_USBCH_CTRL1_REG 0xC0 |
| 70 | #define AB8500_USBCH_CTRL2_REG 0xC1 | 71 | #define AB8500_USBCH_CTRL2_REG 0xC1 |
| 71 | #define AB8500_USBCH_IPT_CRNTLVL_REG 0xC2 | 72 | #define AB8500_USBCH_IPT_CRNTLVL_REG 0xC2 |
| 73 | #define AB8540_USB_PP_MODE_REG 0xC5 | ||
| 74 | #define AB8540_USB_PP_CHR_REG 0xC6 | ||
| 72 | 75 | ||
| 73 | /* | 76 | /* |
| 74 | * Gas Gauge register offsets | 77 | * Gas Gauge register offsets |
| @@ -105,6 +108,7 @@ | |||
| 105 | #define AB8500_RTC_BACKUP_CHG_REG 0x0C | 108 | #define AB8500_RTC_BACKUP_CHG_REG 0x0C |
| 106 | #define AB8500_RTC_CC_CONF_REG 0x01 | 109 | #define AB8500_RTC_CC_CONF_REG 0x01 |
| 107 | #define AB8500_RTC_CTRL_REG 0x0B | 110 | #define AB8500_RTC_CTRL_REG 0x0B |
| 111 | #define AB8500_RTC_CTRL1_REG 0x11 | ||
| 108 | 112 | ||
| 109 | /* | 113 | /* |
| 110 | * OTP register offsets | 114 | * OTP register offsets |
| @@ -154,6 +158,7 @@ | |||
| 154 | #define CH_OP_CUR_LVL_1P4 0x0D | 158 | #define CH_OP_CUR_LVL_1P4 0x0D |
| 155 | #define CH_OP_CUR_LVL_1P5 0x0E | 159 | #define CH_OP_CUR_LVL_1P5 0x0E |
| 156 | #define CH_OP_CUR_LVL_1P6 0x0F | 160 | #define CH_OP_CUR_LVL_1P6 0x0F |
| 161 | #define CH_OP_CUR_LVL_2P 0x3F | ||
| 157 | 162 | ||
| 158 | /* BTEMP High thermal limits */ | 163 | /* BTEMP High thermal limits */ |
| 159 | #define BTEMP_HIGH_TH_57_0 0x00 | 164 | #define BTEMP_HIGH_TH_57_0 0x00 |
| @@ -179,10 +184,25 @@ | |||
| 179 | #define BUP_ICH_SEL_300UA 0x08 | 184 | #define BUP_ICH_SEL_300UA 0x08 |
| 180 | #define BUP_ICH_SEL_700UA 0x0C | 185 | #define BUP_ICH_SEL_700UA 0x0C |
| 181 | 186 | ||
| 182 | #define BUP_VCH_SEL_2P5V 0x00 | 187 | enum bup_vch_sel { |
| 183 | #define BUP_VCH_SEL_2P6V 0x01 | 188 | BUP_VCH_SEL_2P5V, |
| 184 | #define BUP_VCH_SEL_2P8V 0x02 | 189 | BUP_VCH_SEL_2P6V, |
| 185 | #define BUP_VCH_SEL_3P1V 0x03 | 190 | BUP_VCH_SEL_2P8V, |
| 191 | BUP_VCH_SEL_3P1V, | ||
| 192 | /* | ||
| 193 | * Note that the following 5 values 2.7v, 2.9v, 3.0v, 3.2v, 3.3v | ||
| 194 | * are only available on ab8540. You can't choose these 5 | ||
| 195 | * voltage on ab8500/ab8505/ab9540. | ||
| 196 | */ | ||
| 197 | BUP_VCH_SEL_2P7V, | ||
| 198 | BUP_VCH_SEL_2P9V, | ||
| 199 | BUP_VCH_SEL_3P0V, | ||
| 200 | BUP_VCH_SEL_3P2V, | ||
| 201 | BUP_VCH_SEL_3P3V, | ||
| 202 | }; | ||
| 203 | |||
| 204 | #define BUP_VCH_RANGE 0x02 | ||
| 205 | #define VBUP33_VRTCN 0x01 | ||
| 186 | 206 | ||
| 187 | /* Battery OVV constants */ | 207 | /* Battery OVV constants */ |
| 188 | #define BATT_OVV_ENA 0x02 | 208 | #define BATT_OVV_ENA 0x02 |
| @@ -228,6 +248,8 @@ | |||
| 228 | #define BAT_CTRL_20U_ENA 0x02 | 248 | #define BAT_CTRL_20U_ENA 0x02 |
| 229 | #define BAT_CTRL_18U_ENA 0x01 | 249 | #define BAT_CTRL_18U_ENA 0x01 |
| 230 | #define BAT_CTRL_16U_ENA 0x02 | 250 | #define BAT_CTRL_16U_ENA 0x02 |
| 251 | #define BAT_CTRL_60U_ENA 0x01 | ||
| 252 | #define BAT_CTRL_120U_ENA 0x02 | ||
| 231 | #define BAT_CTRL_CMP_ENA 0x04 | 253 | #define BAT_CTRL_CMP_ENA 0x04 |
| 232 | #define FORCE_BAT_CTRL_CMP_HIGH 0x08 | 254 | #define FORCE_BAT_CTRL_CMP_HIGH 0x08 |
| 233 | #define BAT_CTRL_PULL_UP_ENA 0x10 | 255 | #define BAT_CTRL_PULL_UP_ENA 0x10 |
| @@ -235,6 +257,24 @@ | |||
| 235 | /* Battery type */ | 257 | /* Battery type */ |
| 236 | #define BATTERY_UNKNOWN 00 | 258 | #define BATTERY_UNKNOWN 00 |
| 237 | 259 | ||
| 260 | /* Registers for pcut feature in ab8505 and ab9540 */ | ||
| 261 | #define AB8505_RTC_PCUT_CTL_STATUS_REG 0x12 | ||
| 262 | #define AB8505_RTC_PCUT_TIME_REG 0x13 | ||
| 263 | #define AB8505_RTC_PCUT_MAX_TIME_REG 0x14 | ||
| 264 | #define AB8505_RTC_PCUT_FLAG_TIME_REG 0x15 | ||
| 265 | #define AB8505_RTC_PCUT_RESTART_REG 0x16 | ||
| 266 | #define AB8505_RTC_PCUT_DEBOUNCE_REG 0x17 | ||
| 267 | |||
| 268 | /* USB Power Path constants for ab8540 */ | ||
| 269 | #define BUS_VSYS_VOL_SELECT_MASK 0x06 | ||
| 270 | #define BUS_VSYS_VOL_SELECT_3P6V 0x00 | ||
| 271 | #define BUS_VSYS_VOL_SELECT_3P325V 0x02 | ||
| 272 | #define BUS_VSYS_VOL_SELECT_3P9V 0x04 | ||
| 273 | #define BUS_VSYS_VOL_SELECT_4P3V 0x06 | ||
| 274 | #define BUS_POWER_PATH_MODE_ENA 0x01 | ||
| 275 | #define BUS_PP_PRECHG_CURRENT_MASK 0x0E | ||
| 276 | #define BUS_POWER_PATH_PRECHG_ENA 0x01 | ||
| 277 | |||
| 238 | /** | 278 | /** |
| 239 | * struct res_to_temp - defines one point in a temp to res curve. To | 279 | * struct res_to_temp - defines one point in a temp to res curve. To |
| 240 | * be used in battery packs that combines the identification resistor with a | 280 | * be used in battery packs that combines the identification resistor with a |
| @@ -283,6 +323,11 @@ struct ab8500_fg; | |||
| 283 | * points. | 323 | * points. |
| 284 | * @maint_thres This is the threshold where we stop reporting | 324 | * @maint_thres This is the threshold where we stop reporting |
| 285 | * battery full while in maintenance, in per cent | 325 | * battery full while in maintenance, in per cent |
| 326 | * @pcut_enable: Enable power cut feature in ab8505 | ||
| 327 | * @pcut_max_time: Max time threshold | ||
| 328 | * @pcut_flag_time: Flagtime threshold | ||
| 329 | * @pcut_max_restart: Max number of restarts | ||
| 330 | * @pcut_debunce_time: Sets battery debounce time | ||
| 286 | */ | 331 | */ |
| 287 | struct ab8500_fg_parameters { | 332 | struct ab8500_fg_parameters { |
| 288 | int recovery_sleep_timer; | 333 | int recovery_sleep_timer; |
| @@ -299,6 +344,11 @@ struct ab8500_fg_parameters { | |||
| 299 | int battok_raising_th_sel1; | 344 | int battok_raising_th_sel1; |
| 300 | int user_cap_limit; | 345 | int user_cap_limit; |
| 301 | int maint_thres; | 346 | int maint_thres; |
| 347 | bool pcut_enable; | ||
| 348 | u8 pcut_max_time; | ||
| 349 | u8 pcut_flag_time; | ||
| 350 | u8 pcut_max_restart; | ||
| 351 | u8 pcut_debunce_time; | ||
| 302 | }; | 352 | }; |
| 303 | 353 | ||
| 304 | /** | 354 | /** |
diff --git a/include/linux/mfd/abx500/ab8500-gpadc.h b/include/linux/mfd/abx500/ab8500-gpadc.h index 252966769d93..49ded001049b 100644 --- a/include/linux/mfd/abx500/ab8500-gpadc.h +++ b/include/linux/mfd/abx500/ab8500-gpadc.h | |||
| @@ -4,32 +4,72 @@ | |||
| 4 | * | 4 | * |
| 5 | * Author: Arun R Murthy <arun.murthy@stericsson.com> | 5 | * Author: Arun R Murthy <arun.murthy@stericsson.com> |
| 6 | * Author: Daniel Willerud <daniel.willerud@stericsson.com> | 6 | * Author: Daniel Willerud <daniel.willerud@stericsson.com> |
| 7 | * Author: M'boumba Cedric Madianga <cedric.madianga@stericsson.com> | ||
| 7 | */ | 8 | */ |
| 8 | 9 | ||
| 9 | #ifndef _AB8500_GPADC_H | 10 | #ifndef _AB8500_GPADC_H |
| 10 | #define _AB8500_GPADC_H | 11 | #define _AB8500_GPADC_H |
| 11 | 12 | ||
| 12 | /* GPADC source: From datasheet(ADCSwSel[4:0] in GPADCCtrl2) */ | 13 | /* GPADC source: From datasheet(ADCSwSel[4:0] in GPADCCtrl2 |
| 13 | #define BAT_CTRL 0x01 | 14 | * and ADCHwSel[4:0] in GPADCCtrl3 ) */ |
| 14 | #define BTEMP_BALL 0x02 | 15 | #define BAT_CTRL 0x01 |
| 15 | #define MAIN_CHARGER_V 0x03 | 16 | #define BTEMP_BALL 0x02 |
| 16 | #define ACC_DETECT1 0x04 | 17 | #define MAIN_CHARGER_V 0x03 |
| 17 | #define ACC_DETECT2 0x05 | 18 | #define ACC_DETECT1 0x04 |
| 18 | #define ADC_AUX1 0x06 | 19 | #define ACC_DETECT2 0x05 |
| 19 | #define ADC_AUX2 0x07 | 20 | #define ADC_AUX1 0x06 |
| 20 | #define MAIN_BAT_V 0x08 | 21 | #define ADC_AUX2 0x07 |
| 21 | #define VBUS_V 0x09 | 22 | #define MAIN_BAT_V 0x08 |
| 22 | #define MAIN_CHARGER_C 0x0A | 23 | #define VBUS_V 0x09 |
| 23 | #define USB_CHARGER_C 0x0B | 24 | #define MAIN_CHARGER_C 0x0A |
| 24 | #define BK_BAT_V 0x0C | 25 | #define USB_CHARGER_C 0x0B |
| 25 | #define DIE_TEMP 0x0D | 26 | #define BK_BAT_V 0x0C |
| 27 | #define DIE_TEMP 0x0D | ||
| 28 | #define USB_ID 0x0E | ||
| 29 | #define XTAL_TEMP 0x12 | ||
| 30 | #define VBAT_TRUE_MEAS 0x13 | ||
| 31 | #define BAT_CTRL_AND_IBAT 0x1C | ||
| 32 | #define VBAT_MEAS_AND_IBAT 0x1D | ||
| 33 | #define VBAT_TRUE_MEAS_AND_IBAT 0x1E | ||
| 34 | #define BAT_TEMP_AND_IBAT 0x1F | ||
| 35 | |||
| 36 | /* Virtual channel used only for ibat convertion to ampere | ||
| 37 | * Battery current conversion (ibat) cannot be requested as a single conversion | ||
| 38 | * but it is always in combination with other input requests | ||
| 39 | */ | ||
| 40 | #define IBAT_VIRTUAL_CHANNEL 0xFF | ||
| 41 | |||
| 42 | #define SAMPLE_1 1 | ||
| 43 | #define SAMPLE_4 4 | ||
| 44 | #define SAMPLE_8 8 | ||
| 45 | #define SAMPLE_16 16 | ||
| 46 | #define RISING_EDGE 0 | ||
| 47 | #define FALLING_EDGE 1 | ||
| 48 | |||
| 49 | /* Arbitrary ADC conversion type constants */ | ||
| 50 | #define ADC_SW 0 | ||
| 51 | #define ADC_HW 1 | ||
| 26 | 52 | ||
| 27 | struct ab8500_gpadc; | 53 | struct ab8500_gpadc; |
| 28 | 54 | ||
| 29 | struct ab8500_gpadc *ab8500_gpadc_get(char *name); | 55 | struct ab8500_gpadc *ab8500_gpadc_get(char *name); |
| 30 | int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 channel); | 56 | int ab8500_gpadc_sw_hw_convert(struct ab8500_gpadc *gpadc, u8 channel, |
| 31 | int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel); | 57 | u8 avg_sample, u8 trig_edge, u8 trig_timer, u8 conv_type); |
| 58 | static inline int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 channel) | ||
| 59 | { | ||
| 60 | return ab8500_gpadc_sw_hw_convert(gpadc, channel, | ||
| 61 | SAMPLE_16, 0, 0, ADC_SW); | ||
| 62 | } | ||
| 63 | |||
| 64 | int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel, | ||
| 65 | u8 avg_sample, u8 trig_edge, u8 trig_timer, u8 conv_type); | ||
| 66 | int ab8500_gpadc_double_read_raw(struct ab8500_gpadc *gpadc, u8 channel, | ||
| 67 | u8 avg_sample, u8 trig_edge, u8 trig_timer, u8 conv_type, | ||
| 68 | int *ibat); | ||
| 32 | int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc, | 69 | int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc, |
| 33 | u8 channel, int ad_value); | 70 | u8 channel, int ad_value); |
| 71 | void ab8540_gpadc_get_otp(struct ab8500_gpadc *gpadc, | ||
| 72 | u16 *vmain_l, u16 *vmain_h, u16 *btemp_l, u16 *btemp_h, | ||
| 73 | u16 *vbat_l, u16 *vbat_h, u16 *ibat_l, u16 *ibat_h); | ||
| 34 | 74 | ||
| 35 | #endif /* _AB8500_GPADC_H */ | 75 | #endif /* _AB8500_GPADC_H */ |
diff --git a/include/linux/mfd/abx500/ab8500-sysctrl.h b/include/linux/mfd/abx500/ab8500-sysctrl.h index ebf12e793db9..990bc93f46e1 100644 --- a/include/linux/mfd/abx500/ab8500-sysctrl.h +++ b/include/linux/mfd/abx500/ab8500-sysctrl.h | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | 12 | ||
| 13 | int ab8500_sysctrl_read(u16 reg, u8 *value); | 13 | int ab8500_sysctrl_read(u16 reg, u8 *value); |
| 14 | int ab8500_sysctrl_write(u16 reg, u8 mask, u8 value); | 14 | int ab8500_sysctrl_write(u16 reg, u8 mask, u8 value); |
| 15 | void ab8500_restart(char mode, const char *cmd); | ||
| 15 | 16 | ||
| 16 | #else | 17 | #else |
| 17 | 18 | ||
| @@ -40,6 +41,7 @@ static inline int ab8500_sysctrl_clear(u16 reg, u8 bits) | |||
| 40 | /* Configuration data for SysClkReq1RfClkBuf - SysClkReq8RfClkBuf */ | 41 | /* Configuration data for SysClkReq1RfClkBuf - SysClkReq8RfClkBuf */ |
| 41 | struct ab8500_sysctrl_platform_data { | 42 | struct ab8500_sysctrl_platform_data { |
| 42 | u8 initial_req_buf_config[8]; | 43 | u8 initial_req_buf_config[8]; |
| 44 | u16 (*reboot_reason_code)(const char *cmd); | ||
| 43 | }; | 45 | }; |
| 44 | 46 | ||
| 45 | /* Registers */ | 47 | /* Registers */ |
| @@ -299,4 +301,8 @@ struct ab8500_sysctrl_platform_data { | |||
| 299 | #define AB9540_SYSCLK12BUF4VALID_SYSCLK12BUF4VALID_MASK 0xFF | 301 | #define AB9540_SYSCLK12BUF4VALID_SYSCLK12BUF4VALID_MASK 0xFF |
| 300 | #define AB9540_SYSCLK12BUF4VALID_SYSCLK12BUF4VALID_SHIFT 0 | 302 | #define AB9540_SYSCLK12BUF4VALID_SYSCLK12BUF4VALID_SHIFT 0 |
| 301 | 303 | ||
| 304 | #define AB8500_ENABLE_WD 0x1 | ||
| 305 | #define AB8500_KICK_WD 0x2 | ||
| 306 | #define AB8500_WD_RESTART_ON_EXPIRE 0x10 | ||
| 307 | |||
| 302 | #endif /* __AB8500_SYSCTRL_H */ | 308 | #endif /* __AB8500_SYSCTRL_H */ |
diff --git a/include/linux/mfd/abx500/ab8500.h b/include/linux/mfd/abx500/ab8500.h index 9db0bda446a0..b5780fd40fe4 100644 --- a/include/linux/mfd/abx500/ab8500.h +++ b/include/linux/mfd/abx500/ab8500.h | |||
| @@ -362,6 +362,7 @@ struct ab8500 { | |||
| 362 | u8 *oldmask; | 362 | u8 *oldmask; |
| 363 | int mask_size; | 363 | int mask_size; |
| 364 | const int *irq_reg_offset; | 364 | const int *irq_reg_offset; |
| 365 | int it_latchhier_num; | ||
| 365 | }; | 366 | }; |
| 366 | 367 | ||
| 367 | struct regulator_reg_init; | 368 | struct regulator_reg_init; |
| @@ -512,6 +513,8 @@ static inline int is_ab9540_2p0_or_earlier(struct ab8500 *ab) | |||
| 512 | return (is_ab9540(ab) && (ab->chip_id < AB8500_CUT2P0)); | 513 | return (is_ab9540(ab) && (ab->chip_id < AB8500_CUT2P0)); |
| 513 | } | 514 | } |
| 514 | 515 | ||
| 516 | void ab8500_override_turn_on_stat(u8 mask, u8 set); | ||
| 517 | |||
| 515 | #ifdef CONFIG_AB8500_DEBUG | 518 | #ifdef CONFIG_AB8500_DEBUG |
| 516 | void ab8500_dump_all_banks(struct device *dev); | 519 | void ab8500_dump_all_banks(struct device *dev); |
| 517 | void ab8500_debug_register_interrupt(int line); | 520 | void ab8500_debug_register_interrupt(int line); |
diff --git a/include/linux/mfd/abx500/ux500_chargalg.h b/include/linux/mfd/abx500/ux500_chargalg.h index d43ac0f35526..234c99143bf7 100644 --- a/include/linux/mfd/abx500/ux500_chargalg.h +++ b/include/linux/mfd/abx500/ux500_chargalg.h | |||
| @@ -17,8 +17,11 @@ struct ux500_charger; | |||
| 17 | 17 | ||
| 18 | struct ux500_charger_ops { | 18 | struct ux500_charger_ops { |
| 19 | int (*enable) (struct ux500_charger *, int, int, int); | 19 | int (*enable) (struct ux500_charger *, int, int, int); |
| 20 | int (*check_enable) (struct ux500_charger *, int, int); | ||
| 20 | int (*kick_wd) (struct ux500_charger *); | 21 | int (*kick_wd) (struct ux500_charger *); |
| 21 | int (*update_curr) (struct ux500_charger *, int); | 22 | int (*update_curr) (struct ux500_charger *, int); |
| 23 | int (*pp_enable) (struct ux500_charger *, bool); | ||
| 24 | int (*pre_chg_enable) (struct ux500_charger *, bool); | ||
| 22 | }; | 25 | }; |
| 23 | 26 | ||
| 24 | /** | 27 | /** |
| @@ -29,6 +32,7 @@ struct ux500_charger_ops { | |||
| 29 | * @max_out_curr maximum output charger current in mA | 32 | * @max_out_curr maximum output charger current in mA |
| 30 | * @enabled indicates if this charger is used or not | 33 | * @enabled indicates if this charger is used or not |
| 31 | * @external external charger unit (pm2xxx) | 34 | * @external external charger unit (pm2xxx) |
| 35 | * @power_path USB power path support | ||
| 32 | */ | 36 | */ |
| 33 | struct ux500_charger { | 37 | struct ux500_charger { |
| 34 | struct power_supply psy; | 38 | struct power_supply psy; |
| @@ -38,6 +42,9 @@ struct ux500_charger { | |||
| 38 | int wdt_refresh; | 42 | int wdt_refresh; |
| 39 | bool enabled; | 43 | bool enabled; |
| 40 | bool external; | 44 | bool external; |
| 45 | bool power_path; | ||
| 41 | }; | 46 | }; |
| 42 | 47 | ||
| 48 | extern struct blocking_notifier_head charger_notifier_list; | ||
| 49 | |||
| 43 | #endif | 50 | #endif |
diff --git a/include/linux/pm2301_charger.h b/include/linux/pm2301_charger.h index fc3f026922ae..85c16defe11a 100644 --- a/include/linux/pm2301_charger.h +++ b/include/linux/pm2301_charger.h | |||
| @@ -48,7 +48,7 @@ struct pm2xxx_charger_platform_data { | |||
| 48 | size_t num_supplicants; | 48 | size_t num_supplicants; |
| 49 | int i2c_bus; | 49 | int i2c_bus; |
| 50 | const char *label; | 50 | const char *label; |
| 51 | int irq_number; | 51 | int gpio_irq_number; |
| 52 | unsigned int lpn_gpio; | 52 | unsigned int lpn_gpio; |
| 53 | int irq_type; | 53 | int irq_type; |
| 54 | }; | 54 | }; |
