1 /* 2 * (C) Copyright 2017 Rockchip Electronics Co., Ltd 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <asm/io.h> 8 #include <common.h> 9 #include <boot_rkimg.h> 10 #include <console.h> 11 #include <dm.h> 12 #include <errno.h> 13 #include <key.h> 14 #include <led.h> 15 #include <rtc.h> 16 #include <pwm.h> 17 #include <asm/arch/rockchip_smccc.h> 18 #include <asm/suspend.h> 19 #include <linux/input.h> 20 #include <power/charge_display.h> 21 #include <power/charge_animation.h> 22 #include <power/rockchip_pm.h> 23 #include <power/fuel_gauge.h> 24 #include <power/pmic.h> 25 #include <power/rk8xx_pmic.h> 26 #include <power/regulator.h> 27 #include <video_rockchip.h> 28 #ifdef CONFIG_IRQ 29 #include <irq-generic.h> 30 #include <rk_timer_irq.h> 31 #endif 32 33 DECLARE_GLOBAL_DATA_PTR; 34 35 #define IMAGE_RESET_IDX -1 36 #define IMAGE_SOC_100_IDX(n) ((n) - 2) 37 #define IMAGE_LOWPOWER_IDX(n) ((n) - 1) 38 #define SYSTEM_SUSPEND_DELAY_MS 5000 39 #define FUEL_GAUGE_POLL_MS 1000 40 41 #define LED_CHARGING_NAME "battery_charging" 42 #define LED_CHARGING_FULL_NAME "battery_full" 43 44 struct charge_image { 45 const char *name; 46 int soc; 47 int period; /* ms */ 48 }; 49 50 struct charge_animation_priv { 51 struct udevice *pmic; 52 struct udevice *fg; 53 struct udevice *rtc; 54 #ifdef CONFIG_LED 55 struct udevice *led_charging; 56 struct udevice *led_full; 57 #endif 58 const struct charge_image *image; 59 int image_num; 60 61 int auto_wakeup_key_state; 62 ulong auto_screen_off_timeout; /* ms */ 63 ulong suspend_delay_timeout; /* ms */ 64 }; 65 66 /* 67 * IF you want to use your own charge images, please: 68 * 69 * 1. Update the following 'image[]' to point to your own images; 70 * 2. You must set the failed image as last one and soc = -1 !!! 71 */ 72 static const struct charge_image image[] = { 73 { .name = "battery_0.bmp", .soc = 5, .period = 600 }, 74 { .name = "battery_1.bmp", .soc = 20, .period = 600 }, 75 { .name = "battery_2.bmp", .soc = 40, .period = 600 }, 76 { .name = "battery_3.bmp", .soc = 60, .period = 600 }, 77 { .name = "battery_4.bmp", .soc = 80, .period = 600 }, 78 { .name = "battery_5.bmp", .soc = 100, .period = 600 }, 79 { .name = "battery_fail.bmp", .soc = -1, .period = 1000 }, 80 }; 81 82 static int charge_animation_ofdata_to_platdata(struct udevice *dev) 83 { 84 struct charge_animation_pdata *pdata = dev_get_platdata(dev); 85 86 /* charge mode */ 87 pdata->uboot_charge = 88 dev_read_u32_default(dev, "rockchip,uboot-charge-on", 0); 89 pdata->android_charge = 90 dev_read_u32_default(dev, "rockchip,android-charge-on", 0); 91 92 pdata->exit_charge_level = 93 dev_read_u32_default(dev, "rockchip,uboot-exit-charge-level", 0); 94 pdata->exit_charge_voltage = 95 dev_read_u32_default(dev, "rockchip,uboot-exit-charge-voltage", 0); 96 97 pdata->low_power_voltage = 98 dev_read_u32_default(dev, "rockchip,uboot-low-power-voltage", 0); 99 100 pdata->screen_on_voltage = 101 dev_read_u32_default(dev, "rockchip,screen-on-voltage", 0); 102 pdata->system_suspend = 103 dev_read_u32_default(dev, "rockchip,system-suspend", 0); 104 105 pdata->auto_wakeup_interval = 106 dev_read_u32_default(dev, "rockchip,auto-wakeup-interval", 0); 107 pdata->auto_wakeup_screen_invert = 108 dev_read_u32_default(dev, "rockchip,auto-wakeup-screen-invert", 0); 109 110 pdata->auto_off_screen_interval = 111 dev_read_u32_default(dev, "rockchip,auto-off-screen-interval", 15); 112 113 if (pdata->screen_on_voltage > pdata->exit_charge_voltage) 114 pdata->screen_on_voltage = pdata->exit_charge_voltage; 115 116 debug("mode: uboot=%d, android=%d; exit: soc=%d%%, voltage=%dmv;\n" 117 "lp_voltage=%d%%, screen_on=%dmv\n", 118 pdata->uboot_charge, pdata->android_charge, 119 pdata->exit_charge_level, pdata->exit_charge_voltage, 120 pdata->low_power_voltage, pdata->screen_on_voltage); 121 122 return 0; 123 } 124 125 static int check_key_press(struct udevice *dev) 126 { 127 struct charge_animation_pdata *pdata = dev_get_platdata(dev); 128 struct charge_animation_priv *priv = dev_get_priv(dev); 129 u32 state, rtc_state = 0; 130 131 #ifdef CONFIG_DM_RTC 132 if (priv->rtc) 133 rtc_state = rtc_alarm_trigger(priv->rtc); 134 #endif 135 if (rtc_state) { 136 printf("rtc alarm trigger...\n"); 137 return KEY_PRESS_LONG_DOWN; 138 } 139 140 state = key_read(KEY_POWER); 141 if (state < 0) 142 printf("read power key failed: %d\n", state); 143 else if (state == KEY_PRESS_DOWN) 144 printf("power key pressed...\n"); 145 else if (state == KEY_PRESS_LONG_DOWN) 146 printf("power key long pressed...\n"); 147 148 /* Fixup key state for following cases */ 149 if (pdata->auto_wakeup_interval) { 150 if (pdata->auto_wakeup_screen_invert) { 151 if (priv->auto_wakeup_key_state == KEY_PRESS_DOWN) { 152 /* Value is updated in timer interrupt */ 153 priv->auto_wakeup_key_state = KEY_PRESS_NONE; 154 state = KEY_PRESS_DOWN; 155 } 156 } 157 } else if (pdata->auto_off_screen_interval) { 158 if (priv->auto_screen_off_timeout && 159 get_timer(priv->auto_screen_off_timeout) > 160 pdata->auto_off_screen_interval * 1000) { /* 1000ms */ 161 state = KEY_PRESS_DOWN; 162 printf("Auto screen off\n"); 163 } 164 } 165 166 return state; 167 } 168 169 /* 170 * If not enable CONFIG_IRQ, cpu can't suspend to ATF or wfi, so that wakeup 171 * period timer is useless. 172 */ 173 #ifndef CONFIG_IRQ 174 static int system_suspend_enter(struct udevice *dev) 175 { 176 return 0; 177 } 178 179 static void autowakeup_timer_init(struct udevice *dev, uint32_t seconds) {} 180 static void autowakeup_timer_uninit(void) {} 181 182 #else 183 static int system_suspend_enter(struct udevice *dev) 184 { 185 struct charge_animation_pdata *pdata = dev_get_platdata(dev); 186 struct charge_animation_priv *priv = dev_get_priv(dev); 187 188 /* 189 * When cpu is in wfi and we try to give a long key press event without 190 * key release, cpu would wakeup and enter wfi again immediately. So 191 * here is the problem: cpu can only wakeup when long key released. 192 * 193 * Actually, we want cpu can detect long key event without key release, 194 * so we give a suspend delay timeout for cpu to detect this. 195 */ 196 if (priv->suspend_delay_timeout && 197 get_timer(priv->suspend_delay_timeout) <= SYSTEM_SUSPEND_DELAY_MS) 198 return 0; 199 200 if (pdata->system_suspend && IS_ENABLED(CONFIG_ARM_SMCCC)) { 201 printf("\nSystem suspend: "); 202 putc('0'); 203 regulators_enable_state_mem(false); 204 putc('1'); 205 local_irq_disable(); 206 putc('2'); 207 irqs_suspend(); 208 putc('3'); 209 device_suspend(); 210 putc('4'); 211 putc('\n'); 212 213 /* Trap into ATF for low power mode */ 214 cpu_suspend(0, psci_system_suspend); 215 216 putc('\n'); 217 putc('4'); 218 device_resume(); 219 putc('3'); 220 irqs_resume(); 221 putc('2'); 222 local_irq_enable(); 223 putc('1'); 224 putc('\n'); 225 } else { 226 printf("\nWfi\n"); 227 wfi(); 228 putc('1'); 229 } 230 231 priv->suspend_delay_timeout = get_timer(0); 232 233 /* 234 * We must wait for key release event finish, otherwise 235 * we may read key state too early. 236 */ 237 mdelay(300); 238 239 return 0; 240 } 241 242 static void timer_irq_handler(int irq, void *data) 243 { 244 struct udevice *dev = data; 245 struct charge_animation_priv *priv = dev_get_priv(dev); 246 static long long count; 247 248 writel(TIMER_CLR_INT, TIMER_BASE + TIMER_INTSTATUS); 249 250 priv->auto_wakeup_key_state = KEY_PRESS_DOWN; 251 printf("auto wakeup count: %lld\n", ++count); 252 } 253 254 static void autowakeup_timer_init(struct udevice *dev, uint32_t seconds) 255 { 256 uint64_t period = 24000000ULL * seconds; 257 258 /* Disable before conifg */ 259 writel(0, TIMER_BASE + TIMER_CTRL); 260 261 /* Config */ 262 writel((uint32_t)period, TIMER_BASE + TIMER_LOAD_COUNT0); 263 writel((uint32_t)(period >> 32), TIMER_BASE + TIMER_LOAD_COUNT1); 264 writel(TIMER_CLR_INT, TIMER_BASE + TIMER_INTSTATUS); 265 writel(TIMER_EN | TIMER_INT_EN, TIMER_BASE + TIMER_CTRL); 266 267 /* IRQ */ 268 irq_install_handler(TIMER_IRQ, timer_irq_handler, dev); 269 irq_handler_enable(TIMER_IRQ); 270 } 271 272 static void autowakeup_timer_uninit(void) 273 { 274 irq_free_handler(TIMER_IRQ); 275 } 276 #endif 277 278 #ifdef CONFIG_DRM_ROCKCHIP 279 static void charge_show_bmp(const char *name) 280 { 281 rockchip_show_bmp(name); 282 } 283 284 static void charge_show_logo(void) 285 { 286 rockchip_show_logo(); 287 } 288 #else 289 static void charge_show_bmp(const char *name) {} 290 static void charge_show_logo(void) {} 291 #endif 292 293 #ifdef CONFIG_LED 294 static int leds_update(struct udevice *dev, int soc) 295 { 296 struct charge_animation_priv *priv = dev_get_priv(dev); 297 static int old_soc = -1; 298 int ret, ledst; 299 300 if (old_soc == soc) 301 return 0; 302 303 old_soc = soc; 304 if (priv->led_charging) { 305 ledst = (soc < 100) ? LEDST_ON : LEDST_OFF; 306 ret = led_set_state(priv->led_charging, ledst); 307 if (ret) { 308 printf("set charging led %s failed, ret=%d\n", 309 (ledst == LEDST_ON) ? "ON" : "OFF", ret); 310 return ret; 311 } 312 } 313 314 if (priv->led_full) { 315 ledst = (soc == 100) ? LEDST_ON : LEDST_OFF; 316 ret = led_set_state(priv->led_full, ledst); 317 if (ret) { 318 printf("set charging full led %s failed, ret=%d\n", 319 ledst == LEDST_ON ? "ON" : "OFF", ret); 320 return ret; 321 } 322 } 323 324 return 0; 325 } 326 #else 327 static int leds_update(struct udevice *dev, int soc) { return 0; } 328 #endif 329 330 static int charge_extrem_low_power(struct udevice *dev) 331 { 332 struct charge_animation_pdata *pdata = dev_get_platdata(dev); 333 struct charge_animation_priv *priv = dev_get_priv(dev); 334 struct udevice *pmic = priv->pmic; 335 struct udevice *fg = priv->fg; 336 int voltage, soc, charging = 1; 337 static int timer_initialized; 338 int ret; 339 340 voltage = fuel_gauge_get_voltage(fg); 341 if (voltage < 0) 342 return -EINVAL; 343 344 while (voltage < pdata->low_power_voltage + 50) { 345 /* Check charger online */ 346 charging = fuel_gauge_get_chrg_online(fg); 347 if (charging <= 0) { 348 printf("%s: Not charging, online=%d. Shutdown...\n", 349 __func__, charging); 350 /* wait uart flush before shutdown */ 351 mdelay(5); 352 /* PMIC shutdown */ 353 pmic_shutdown(pmic); 354 355 printf("Cpu should never reach here, shutdown failed !\n"); 356 continue; 357 } 358 359 /* Enable auto wakeup */ 360 if (!timer_initialized) { 361 timer_initialized = 1; 362 autowakeup_timer_init(dev, 5); 363 } 364 365 /* 366 * Just for fuel gauge to update something important, 367 * including charge current, coulometer or other. 368 */ 369 soc = fuel_gauge_get_soc(fg); 370 if (soc < 0 || soc > 100) { 371 printf("get soc failed: %d\n", soc); 372 continue; 373 } 374 375 /* Update led */ 376 ret = leds_update(dev, soc); 377 if (ret) 378 printf("update led failed: %d\n", ret); 379 380 printf("Extrem low power, force charging... threshold=%dmv, now=%dmv\n", 381 pdata->low_power_voltage, voltage); 382 383 /* System suspend */ 384 system_suspend_enter(dev); 385 386 /* Update voltage */ 387 voltage = fuel_gauge_get_voltage(fg); 388 if (voltage < 0) { 389 printf("get voltage failed: %d\n", voltage); 390 continue; 391 } 392 } 393 394 autowakeup_timer_uninit(); 395 396 return 0; 397 } 398 399 static int charge_animation_show(struct udevice *dev) 400 { 401 struct charge_animation_pdata *pdata = dev_get_platdata(dev); 402 struct charge_animation_priv *priv = dev_get_priv(dev); 403 const struct charge_image *image = priv->image; 404 struct udevice *pmic = priv->pmic; 405 struct udevice *fg = priv->fg; 406 const char *preboot = env_get("preboot"); 407 int image_num = priv->image_num; 408 bool ever_lowpower_screen_off = false; 409 bool screen_on = true; 410 ulong show_start = 0, charge_start = 0, debug_start = 0; 411 ulong delta; 412 ulong ms = 0, sec = 0; 413 int start_idx = 0, show_idx = -1, old_show_idx = IMAGE_RESET_IDX; 414 int soc, voltage, current, key_state; 415 int i, charging = 1, ret; 416 int boot_mode; 417 int first_poll_fg = 1; 418 419 /* 420 * Check sequence: 421 * 422 * 1. Extrem low power charge? 423 * 2. Preboot cmd? 424 * 3. Valid boot mode? 425 * 4. U-Boot charge enabled by dts config? 426 * 5. Screen off before charge? 427 * 6. Enter charge ! 428 * 429 */ 430 if (!fuel_gauge_bat_is_exist(fg)) { 431 printf("Exit charge: battery is not exist\n"); 432 return 0; 433 } 434 435 /* Extrem low power charge */ 436 ret = charge_extrem_low_power(dev); 437 if (ret < 0) { 438 printf("extrem low power charge failed, ret=%d\n", ret); 439 return ret; 440 } 441 442 /* If there is preboot command, exit */ 443 if (preboot && !strstr(preboot, "dvfs")) { 444 printf("Exit charge: due to preboot cmd '%s'\n", preboot); 445 return 0; 446 } 447 448 /* Not valid charge mode, exit */ 449 #ifdef CONFIG_RKIMG_BOOTLOADER 450 boot_mode = rockchip_get_boot_mode(); 451 if ((boot_mode != BOOT_MODE_CHARGING) && 452 (boot_mode != BOOT_MODE_UNDEFINE)) { 453 printf("Exit charge: due to boot mode\n"); 454 return 0; 455 } 456 #endif 457 458 /* Not charger online, exit */ 459 charging = fuel_gauge_get_chrg_online(fg); 460 if (charging <= 0) { 461 printf("Exit charge: due to charger offline\n"); 462 return 0; 463 } 464 465 /* Enter android charge, set property for kernel */ 466 if (pdata->android_charge) { 467 env_update("bootargs", "androidboot.mode=charger"); 468 printf("Android charge mode\n"); 469 } 470 471 /* Not enable U-Boot charge, exit */ 472 if (!pdata->uboot_charge) { 473 printf("Exit charge: due to not enable uboot charge\n"); 474 return 0; 475 } 476 477 voltage = fuel_gauge_get_voltage(fg); 478 if (voltage < 0) { 479 printf("get voltage failed: %d\n", voltage); 480 return -EINVAL; 481 } 482 483 /* If low power, turn off screen */ 484 if (voltage <= pdata->screen_on_voltage + 50) { 485 screen_on = false; 486 ever_lowpower_screen_off = true; 487 charge_show_bmp(NULL); 488 } 489 490 /* Auto wakeup */ 491 if (pdata->auto_wakeup_interval) { 492 printf("Auto wakeup: %dS\n", pdata->auto_wakeup_interval); 493 autowakeup_timer_init(dev, pdata->auto_wakeup_interval); 494 } 495 496 /* Give a message warning when CONFIG_IRQ is not enabled */ 497 #ifdef CONFIG_IRQ 498 printf("Enter U-Boot charging mode\n"); 499 #else 500 printf("Enter U-Boot charging mode(without IRQ)\n"); 501 #endif 502 503 charge_start = get_timer(0); 504 delta = get_timer(0); 505 506 /* Charging ! */ 507 while (1) { 508 /* 509 * At the most time, fuel gauge is usually a i2c device, we 510 * should avoid read/write all the time. We had better set 511 * poll seconds to update fuel gauge info. 512 */ 513 if (!first_poll_fg && get_timer(delta) < FUEL_GAUGE_POLL_MS) 514 goto show_images; 515 516 delta = get_timer(0); 517 518 debug("step1 (%d)... \n", screen_on); 519 520 /* 521 * Most fuel gauge is I2C interface, it shouldn't be interrupted 522 * during transfer. The power key event depends on interrupt, so 523 * we should disable local irq when update fuel gauge. 524 */ 525 local_irq_disable(); 526 527 /* Step1: Is charging now ? */ 528 charging = fuel_gauge_get_chrg_online(fg); 529 if (charging <= 0) { 530 printf("Not charging, online=%d. Shutdown...\n", 531 charging); 532 533 /* wait uart flush before shutdown */ 534 mdelay(5); 535 536 /* PMIC shutdown */ 537 pmic_shutdown(pmic); 538 539 printf("Cpu should never reach here, shutdown failed !\n"); 540 continue; 541 } 542 543 debug("step2 (%d)... show_idx=%d\n", screen_on, show_idx); 544 545 /* Step2: get soc and voltage */ 546 soc = fuel_gauge_get_soc(fg); 547 if (soc < 0 || soc > 100) { 548 printf("get soc failed: %d\n", soc); 549 continue; 550 } 551 552 voltage = fuel_gauge_get_voltage(fg); 553 if (voltage < 0) { 554 printf("get voltage failed: %d\n", voltage); 555 continue; 556 } 557 558 current = fuel_gauge_get_current(fg); 559 if (current == -ENOSYS) { 560 printf("get current failed: %d\n", current); 561 continue; 562 } 563 564 first_poll_fg = 0; 565 local_irq_enable(); 566 567 show_images: 568 /* 569 * Just for debug, otherwise there will be nothing output which 570 * is not good to know what happen. 571 */ 572 if (!debug_start) 573 debug_start = get_timer(0); 574 if (get_timer(debug_start) > 20000) { 575 debug_start = get_timer(0); 576 printf("[%8ld]: soc=%d%%, vol=%dmv, c=%dma, " 577 "online=%d, screen_on=%d\n", 578 get_timer(0)/1000, soc, voltage, 579 current, charging, screen_on); 580 } 581 582 /* Update leds */ 583 ret = leds_update(dev, soc); 584 if (ret) 585 printf("update led failed: %d\n", ret); 586 587 /* 588 * If ever lowpower screen off, force screen_on=false, which 589 * means key event can't modify screen_on, only voltage higher 590 * then threshold can update screen_on=true; 591 */ 592 if (ever_lowpower_screen_off) 593 screen_on = false; 594 595 /* 596 * Auto turn on screen when voltage higher than Vol screen on. 597 * 'ever_lowpower_screen_off' means enter the while(1) loop with 598 * screen off. 599 */ 600 if ((ever_lowpower_screen_off) && 601 (voltage > pdata->screen_on_voltage)) { 602 ever_lowpower_screen_off = false; 603 screen_on = true; 604 show_idx = IMAGE_RESET_IDX; 605 } 606 607 /* 608 * IMAGE_RESET_IDX means show_idx show be update by start_idx. 609 * When short key pressed event trigged, we will set show_idx 610 * as IMAGE_RESET_IDX which updates images index from start_idx 611 * that calculate by current soc. 612 */ 613 if (show_idx == IMAGE_RESET_IDX) { 614 for (i = 0; i < IMAGE_SOC_100_IDX(image_num); i++) { 615 /* Find out which image we start to show */ 616 if ((soc >= image[i].soc) && 617 (soc < image[i + 1].soc)) { 618 start_idx = i; 619 break; 620 } 621 622 if (soc >= 100) { 623 start_idx = IMAGE_SOC_100_IDX(image_num); 624 break; 625 } 626 } 627 628 debug("%s: show_idx=%d, screen_on=%d\n", 629 __func__, show_idx, screen_on); 630 631 /* Mark start index and start time */ 632 show_idx = start_idx; 633 show_start = get_timer(0); 634 } 635 636 debug("step3 (%d)... show_idx=%d\n", screen_on, show_idx); 637 638 /* Step3: show images */ 639 if (screen_on) { 640 /* Don't call 'charge_show_bmp' unless image changed */ 641 if (old_show_idx != show_idx) { 642 old_show_idx = show_idx; 643 debug("SHOW: %s\n", image[show_idx].name); 644 charge_show_bmp(image[show_idx].name); 645 } 646 /* Re-calculate timeout to off screen */ 647 if (priv->auto_screen_off_timeout == 0) 648 priv->auto_screen_off_timeout = get_timer(0); 649 } else { 650 priv->auto_screen_off_timeout = 0; 651 system_suspend_enter(dev); 652 } 653 654 mdelay(5); 655 656 /* Every image shows period */ 657 if (get_timer(show_start) > image[show_idx].period) { 658 show_start = get_timer(0); 659 /* Update to next image */ 660 show_idx++; 661 if (show_idx > IMAGE_SOC_100_IDX(image_num)) 662 show_idx = IMAGE_RESET_IDX; 663 } 664 665 debug("step4 (%d)... \n", screen_on); 666 667 /* 668 * Step4: check key event. 669 * 670 * Short key event: turn on/off screen; 671 * Long key event: show logo and boot system or still charging. 672 */ 673 key_state = check_key_press(dev); 674 if (key_state == KEY_PRESS_DOWN) { 675 /* 676 * Clear current image index, and show image 677 * from start_idx 678 */ 679 old_show_idx = IMAGE_RESET_IDX; 680 show_idx = IMAGE_RESET_IDX; 681 682 /* 683 * Reverse the screen state 684 * 685 * If screen_on=false, means this short key pressed 686 * event turn on the screen and we need show images. 687 * 688 * If screen_on=true, means this short key pressed 689 * event turn off the screen and we never show images. 690 */ 691 if (screen_on) { 692 charge_show_bmp(NULL); /* Turn off screen */ 693 screen_on = false; 694 priv->suspend_delay_timeout = get_timer(0); 695 } else { 696 screen_on = true; 697 } 698 699 printf("screen %s\n", screen_on ? "on" : "off"); 700 } else if (key_state == KEY_PRESS_LONG_DOWN) { 701 /* Set screen_on=true anyway when key long pressed */ 702 if (!screen_on) 703 screen_on = true; 704 705 printf("screen %s\n", screen_on ? "on" : "off"); 706 707 /* Is able to boot now ? */ 708 if (soc < pdata->exit_charge_level) { 709 printf("soc=%d%%, threshold soc=%d%%\n", 710 soc, pdata->exit_charge_level); 711 printf("Low power, unable to boot, charging...\n"); 712 show_idx = IMAGE_LOWPOWER_IDX(image_num); 713 continue; 714 } 715 716 if (voltage < pdata->exit_charge_voltage) { 717 printf("voltage=%dmv, threshold voltage=%dmv\n", 718 voltage, pdata->exit_charge_voltage); 719 printf("Low power, unable to boot, charging...\n"); 720 show_idx = IMAGE_LOWPOWER_IDX(image_num); 721 continue; 722 } 723 724 /* Success exit charging */ 725 printf("Exit charge animation...\n"); 726 charge_show_logo(); 727 break; 728 } else { 729 /* Do nothing */ 730 } 731 732 debug("step5 (%d)... \n", screen_on); 733 734 /* Step5: Exit by ctrl+c */ 735 if (ctrlc()) { 736 if (voltage >= pdata->screen_on_voltage) 737 charge_show_logo(); 738 printf("Exit charge, due to ctrl+c\n"); 739 break; 740 } 741 } 742 743 if (pdata->auto_wakeup_interval) 744 autowakeup_timer_uninit(); 745 746 ms = get_timer(charge_start); 747 if (ms >= 1000) { 748 sec = ms / 1000; 749 ms = ms % 1000; 750 } 751 752 printf("charging time total: %lu.%lus, soc=%d%%, vol=%dmv\n", 753 sec, ms, soc, voltage); 754 755 return 0; 756 } 757 758 static const struct dm_charge_display_ops charge_animation_ops = { 759 .show = charge_animation_show, 760 }; 761 762 static int charge_animation_probe(struct udevice *dev) 763 { 764 struct charge_animation_priv *priv = dev_get_priv(dev); 765 int ret, soc; 766 767 /* Get PMIC: used for power off system */ 768 ret = uclass_get_device(UCLASS_PMIC, 0, &priv->pmic); 769 if (ret) { 770 if (ret == -ENODEV) 771 printf("Can't find PMIC\n"); 772 else 773 printf("Get UCLASS PMIC failed: %d\n", ret); 774 return ret; 775 } 776 777 /* Get fuel gauge: used for charging */ 778 ret = uclass_get_device(UCLASS_FG, 0, &priv->fg); 779 if (ret) { 780 if (ret == -ENODEV) 781 debug("Can't find FG\n"); 782 else 783 debug("Get UCLASS FG failed: %d\n", ret); 784 return ret; 785 } 786 787 /* Get rtc: used for power on */ 788 ret = uclass_get_device(UCLASS_RTC, 0, &priv->rtc); 789 if (ret) { 790 if (ret == -ENODEV) 791 debug("Can't find RTC\n"); 792 else 793 debug("Get UCLASS RTC failed: %d\n", ret); 794 } 795 796 /* Get PWRKEY: used for wakeup and turn off/on LCD */ 797 if (key_read(KEY_POWER) == KEY_NOT_EXIST) { 798 debug("Can't find power key\n"); 799 return -EINVAL; 800 } 801 802 /* Initialize charge current */ 803 soc = fuel_gauge_get_soc(priv->fg); 804 if (soc < 0 || soc > 100) { 805 debug("get soc failed: %d\n", soc); 806 return -EINVAL; 807 } 808 809 /* Get leds */ 810 #ifdef CONFIG_LED 811 ret = led_get_by_label(LED_CHARGING_NAME, &priv->led_charging); 812 if (!ret) 813 printf("Found Charging LED\n"); 814 ret = led_get_by_label(LED_CHARGING_FULL_NAME, &priv->led_full); 815 if (!ret) 816 printf("Found Charging-Full LED\n"); 817 #endif 818 819 /* Get charge images */ 820 priv->image = image; 821 priv->image_num = ARRAY_SIZE(image); 822 823 printf("Enable charge animation display\n"); 824 825 return 0; 826 } 827 828 static const struct udevice_id charge_animation_ids[] = { 829 { .compatible = "rockchip,uboot-charge" }, 830 { }, 831 }; 832 833 U_BOOT_DRIVER(charge_animation) = { 834 .name = "charge-animation", 835 .id = UCLASS_CHARGE_DISPLAY, 836 .probe = charge_animation_probe, 837 .of_match = charge_animation_ids, 838 .ops = &charge_animation_ops, 839 .ofdata_to_platdata = charge_animation_ofdata_to_platdata, 840 .platdata_auto_alloc_size = sizeof(struct charge_animation_pdata), 841 .priv_auto_alloc_size = sizeof(struct charge_animation_priv), 842 }; 843