1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2002 by Heikki Hannikainen, Uwe Freese
11 * Revisions copyright (C) 2005 by Gerald Van Baren
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ****************************************************************************/
32 #include "mp3_playback.h"
34 #include "powermgmt.h"
35 #include "backlight.h"
42 #ifdef HAVE_LCD_BITMAP
46 #ifdef HAVE_REMOTE_LCD
47 #include "lcd-remote.h"
49 #if (CONFIG_PLATFORM & PLATFORM_HOSTED)
53 #if (defined(IAUDIO_X5) || defined(IAUDIO_M5) || defined(COWON_D2)) \
54 && !defined (SIMULATOR)
59 int last_sent_battery_level
= 100;
60 /* battery level (0-100%) */
61 int battery_percent
= -1;
62 void send_battery_level_event(void);
64 static bool sleeptimer_active
= false;
65 static long sleeptimer_endtick
;
66 /* Whether an active sleep timer should be restarted when a key is pressed */
67 static bool sleeptimer_key_restarts
= false;
68 /* The number of seconds the sleep timer was last set to */
69 static unsigned int sleeptimer_duration
= 0;
72 /* State of the charger input as seen by the power thread */
73 enum charger_input_state_type charger_input_state
;
74 /* Power inputs as seen by the power thread */
75 unsigned int power_thread_inputs
;
76 #if CONFIG_CHARGING >= CHARGING_MONITOR
77 /* Charging state (mode) as seen by the power thread */
78 enum charge_state_type charge_state
= DISCHARGING
;
80 #endif /* CONFIG_CHARGING */
82 static int shutdown_timeout
= 0;
84 void handle_auto_poweroff(void);
85 static int poweroff_timeout
= 0;
86 static long last_event_tick
= 0;
88 #if (CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE) == PERCENTAGE_MEASURE
89 int _battery_voltage(void) { return -1; }
91 const unsigned short percent_to_volt_discharge
[BATTERY_TYPES_COUNT
][11];
92 const unsigned short percent_to_volt_charge
[11];
94 #elif (CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE) == VOLTAGE_MEASURE
95 int _battery_level(void) { return -1; }
97 * Average battery voltage and charger voltage, filtered via a digital
98 * exponential filter (aka. exponential moving average, scaled):
99 * avgbat = y[n] = (N-1)/N*y[n-1] + x[n]. battery_millivolts = y[n] / N.
101 static unsigned int avgbat
;
102 /* filtered battery voltage, millivolts */
103 static unsigned int battery_millivolts
;
104 #elif (CONFIG_BATTERY_MEASURE == 0)
105 int _battery_voltage(void) { return -1; }
106 int _battery_level(void) { return -1; }
108 const unsigned short percent_to_volt_discharge
[BATTERY_TYPES_COUNT
][11];
109 const unsigned short percent_to_volt_charge
[11];
112 #if !(CONFIG_BATTERY_MEASURE & TIME_MEASURE)
113 static int powermgmt_est_runningtime_min
;
114 int _battery_time(void) { return powermgmt_est_runningtime_min
; }
117 /* default value, mAh */
118 static int battery_capacity
= BATTERY_CAPACITY_DEFAULT
;
120 #if BATTERY_TYPES_COUNT > 1
121 static int battery_type
= 0;
123 #define battery_type 0
126 /* Power history: power_history[0] is the newest sample */
127 unsigned short power_history
[POWER_HISTORY_LEN
] = {0};
129 #if CONFIG_CPU == JZ4732 /* FIXME! */ || (CONFIG_PLATFORM & PLATFORM_HOSTED)
130 static char power_stack
[DEFAULT_STACK_SIZE
+ POWERMGMT_DEBUG_STACK
];
132 static char power_stack
[DEFAULT_STACK_SIZE
/2 + POWERMGMT_DEBUG_STACK
];
134 static const char power_thread_name
[] = "power";
137 static int voltage_to_battery_level(int battery_millivolts
);
138 static void battery_status_update(void);
140 #ifdef CURRENT_NORMAL /*only used if we have run current*/
141 static int runcurrent(void);
144 void battery_read_info(int *voltage
, int *level
)
146 int millivolts
= _battery_voltage();
150 *voltage
= millivolts
;
153 percent
= voltage_to_battery_level(millivolts
);
155 percent
= _battery_level();
160 #if BATTERY_TYPES_COUNT > 1
161 void set_battery_type(int type
)
163 if (type
!= battery_type
) {
164 if ((unsigned)type
>= BATTERY_TYPES_COUNT
)
168 battery_status_update(); /* recalculate the battery status */
173 #ifdef BATTERY_CAPACITY_MIN
174 void set_battery_capacity(int capacity
)
176 if (capacity
> BATTERY_CAPACITY_MAX
)
177 capacity
= BATTERY_CAPACITY_MAX
;
178 if (capacity
< BATTERY_CAPACITY_MIN
)
179 capacity
= BATTERY_CAPACITY_MIN
;
181 battery_capacity
= capacity
;
183 battery_status_update(); /* recalculate the battery status */
187 int get_battery_capacity(void)
189 return battery_capacity
;
192 int battery_time(void)
194 #if ((CONFIG_BATTERY_MEASURE & TIME_MEASURE) == 0)
196 #ifndef CURRENT_NORMAL /* no estimation without current */
199 if (battery_capacity
<= 0) /* nor without capacity */
203 return _battery_time();
206 /* Returns battery level in percent */
207 int battery_level(void)
209 #ifdef HAVE_BATTERY_SWITCH
210 if ((power_input_status() & POWER_INPUT_BATTERY
) == 0)
213 return battery_percent
;
216 /* Tells if the battery level is safe for disk writes */
217 bool battery_level_safe(void)
219 #if defined(NO_LOW_BATTERY_SHUTDOWN)
221 #elif (CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE)
222 return (battery_percent
> 0);
223 #elif defined(HAVE_BATTERY_SWITCH)
224 /* Cannot rely upon the battery reading to be valid and the
225 * device could be powered externally. */
226 return input_millivolts() > battery_level_dangerous
[battery_type
];
228 return battery_millivolts
> battery_level_dangerous
[battery_type
];
232 /* look into the percent_to_volt_* table and get a realistic battery level */
233 static int voltage_to_percent(int voltage
, const short* table
)
235 if (voltage
<= table
[0]) {
238 else if (voltage
>= table
[10]) {
242 /* search nearest value */
245 while (i
< 10 && table
[i
+1] < voltage
)
248 /* interpolate linear between the smaller and greater value */
249 /* Tens digit, 10% per entry, ones digit: interpolated */
250 return i
*10 + (voltage
- table
[i
])*10 / (table
[i
+1] - table
[i
]);
254 /* update battery level and estimated runtime, called once per minute or
255 * when battery capacity / type settings are changed */
256 static int voltage_to_battery_level(int battery_millivolts
)
260 if (battery_millivolts
< 0)
263 #if CONFIG_CHARGING >= CHARGING_MONITOR
264 if (charging_state()) {
265 /* battery level is defined to be < 100% until charging is finished */
266 level
= voltage_to_percent(battery_millivolts
,
267 percent_to_volt_charge
);
272 #endif /* CONFIG_CHARGING >= CHARGING_MONITOR */
274 /* DISCHARGING or error state */
275 level
= voltage_to_percent(battery_millivolts
,
276 percent_to_volt_discharge
[battery_type
]);
282 static void battery_status_update(void)
284 int millivolt
= battery_voltage();
285 int level
= _battery_level();
288 level
= voltage_to_battery_level(millivolt
);
290 #ifdef CURRENT_NORMAL /*don't try to estimate run or charge
291 time without normal current defined*/
292 /* calculate estimated remaining running time */
293 #if CONFIG_CHARGING >= CHARGING_MONITOR
294 if (charging_state()) {
295 /* charging: remaining charging time */
296 powermgmt_est_runningtime_min
= (100 - level
)*battery_capacity
*60
297 / 100 / (CURRENT_MAX_CHG
- runcurrent());
302 /* discharging: remaining running time */
303 if (level
> 0 && (millivolt
> percent_to_volt_discharge
[battery_type
][0]
305 /* linear extrapolation */
306 powermgmt_est_runningtime_min
= (level
+ battery_percent
)*60
307 * battery_capacity
/ 200 / runcurrent();
309 if (0 > powermgmt_est_runningtime_min
) {
310 powermgmt_est_runningtime_min
= 0;
314 battery_percent
= level
;
315 send_battery_level_event();
318 #ifdef CURRENT_NORMAL /*check that we have a current defined in a config file*/
321 * Estimate how much current we are drawing just to run.
323 static int runcurrent(void)
325 int current
= CURRENT_NORMAL
;
329 #ifdef HAVE_USB_POWER
330 #if (CURRENT_USB < CURRENT_NORMAL)
337 current
= CURRENT_USB
;
340 #if defined(HAVE_BACKLIGHT)
341 if (backlight_get_current_timeout() == 0) /* LED always on */
342 current
+= CURRENT_BACKLIGHT
;
345 #if defined(HAVE_RECORDING) && defined(CURRENT_RECORD)
346 if (audio_status() & AUDIO_STATUS_RECORD
)
347 current
+= CURRENT_RECORD
;
350 #ifdef HAVE_SPDIF_POWER
352 current
+= CURRENT_SPDIF_OUT
;
355 #ifdef HAVE_REMOTE_LCD
357 current
+= CURRENT_REMOTE
;
360 #if defined(HAVE_ATA_POWER_OFF) && defined(CURRENT_ATA)
362 current
+= CURRENT_ATA
;
365 #endif /* BOOTLOADER */
370 #endif /* CURRENT_NORMAL */
372 /* Check to see whether or not we've received an alarm in the last second */
373 #ifdef HAVE_RTC_ALARM
374 static void power_thread_rtc_process(void)
376 if (rtc_check_alarm_flag())
377 rtc_enable_alarm(false);
381 /* switch off unit if battery level is too low for reliable operation */
382 bool query_force_shutdown(void)
384 #if defined(NO_LOW_BATTERY_SHUTDOWN)
386 #elif CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE
387 return battery_percent
== 0;
388 #elif defined(HAVE_BATTERY_SWITCH)
389 /* Cannot rely upon the battery reading to be valid and the
390 * device could be powered externally. */
391 return input_millivolts() < battery_level_shutoff
[battery_type
];
393 return battery_millivolts
< battery_level_shutoff
[battery_type
];
397 #if defined(HAVE_BATTERY_SWITCH) || defined(HAVE_RESET_BATTERY_FILTER)
399 * Reset the battery voltage filter to a new value and update the
402 void reset_battery_filter(int millivolts
)
404 avgbat
= millivolts
* BATT_AVE_SAMPLES
;
405 battery_millivolts
= millivolts
;
406 battery_status_update();
408 #endif /* HAVE_BATTERY_SWITCH */
410 /** Generic charging algorithms for common charging types **/
411 #if CONFIG_CHARGING == 0 || CONFIG_CHARGING == CHARGING_SIMPLE
412 static inline void powermgmt_init_target(void)
417 static inline void charging_algorithm_step(void)
422 static inline void charging_algorithm_close(void)
426 #elif CONFIG_CHARGING == CHARGING_MONITOR
428 * Monitor CHARGING/DISCHARGING state.
430 static inline void powermgmt_init_target(void)
435 static inline void charging_algorithm_step(void)
437 switch (charger_input_state
)
439 case CHARGER_PLUGGED
:
441 if (charging_state()) {
442 charge_state
= CHARGING
;
446 case CHARGER_UNPLUGGED
:
448 charge_state
= DISCHARGING
;
453 static inline void charging_algorithm_close(void)
457 #endif /* CONFIG_CHARGING == * */
460 /* Shortcut function calls - compatibility, simplicity. */
462 /* Returns true if any power input is capable of charging. */
463 bool charger_inserted(void)
465 return power_thread_inputs
& POWER_INPUT_CHARGER
;
468 /* Returns true if any power input is connected - charging-capable
470 bool power_input_present(void)
472 return power_thread_inputs
& POWER_INPUT
;
476 * Detect charger inserted. Return true if the state is transistional.
478 static inline bool detect_charger(unsigned int pwr
)
481 * Detect charger plugged/unplugged transitions. On a plugged or
482 * unplugged event, we return immediately, run once through the main
483 * loop (including the subroutines), and end up back here where we
484 * transition to the appropriate steady state charger on/off state.
486 if (pwr
& POWER_INPUT_CHARGER
) {
487 switch (charger_input_state
)
490 case CHARGER_UNPLUGGED
:
491 charger_input_state
= CHARGER_PLUGGED
;
494 case CHARGER_PLUGGED
:
495 queue_broadcast(SYS_CHARGER_CONNECTED
, 0);
496 last_sent_battery_level
= 0;
497 charger_input_state
= CHARGER
;
505 else { /* charger not inserted */
506 switch (charger_input_state
)
512 case CHARGER_UNPLUGGED
:
513 queue_broadcast(SYS_CHARGER_DISCONNECTED
, 0);
514 last_sent_battery_level
= 100;
515 charger_input_state
= NO_CHARGER
;
518 case CHARGER_PLUGGED
:
520 charger_input_state
= CHARGER_UNPLUGGED
;
525 /* Transitional state */
528 #endif /* CONFIG_CHARGING */
531 #if CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE
532 /* Returns filtered battery voltage [millivolts] */
533 int battery_voltage(void)
535 return battery_millivolts
;
538 static void average_init(void)
540 /* initialize the voltages for the exponential filter */
541 avgbat
= _battery_voltage() + 15;
543 #ifdef HAVE_DISK_STORAGE /* this adjustment is only needed for HD based */
544 /* The battery voltage is usually a little lower directly after
545 turning on, because the disk was used heavily. Raise it by 5% */
547 if (!charger_inserted()) /* only if charger not connected */
550 avgbat
+= (percent_to_volt_discharge
[battery_type
][6] -
551 percent_to_volt_discharge
[battery_type
][5]) / 2;
553 #endif /* HAVE_DISK_STORAGE */
555 avgbat
= avgbat
* BATT_AVE_SAMPLES
;
556 battery_millivolts
= power_history
[0] = avgbat
/ BATT_AVE_SAMPLES
;
559 static void average_step(void)
561 avgbat
+= _battery_voltage() - avgbat
/ BATT_AVE_SAMPLES
;
563 * battery_millivolts is the millivolt-scaled filtered battery value.
565 battery_millivolts
= avgbat
/ BATT_AVE_SAMPLES
;
568 static void average_step_low(void)
570 battery_millivolts
= (_battery_voltage() + battery_millivolts
+ 1) / 2;
571 avgbat
+= battery_millivolts
- avgbat
/ BATT_AVE_SAMPLES
;
574 static void init_battery_percent(void)
577 if (charger_inserted()) {
578 battery_percent
= voltage_to_percent(battery_millivolts
,
579 percent_to_volt_charge
);
584 battery_percent
= voltage_to_percent(battery_millivolts
,
585 percent_to_volt_discharge
[battery_type
]);
586 battery_percent
+= battery_percent
< 100;
591 static int power_hist_item(void)
593 return battery_millivolts
;
595 #define power_history_unit() battery_millivolts
598 int battery_voltage(void)
603 static void average_init(void) {}
604 static void average_step(void) {}
605 static void average_step_low(void) {}
606 static void init_battery_percent(void)
608 battery_percent
= _battery_level();
611 static int power_hist_item(void)
613 return battery_percent
;
617 static void collect_power_history(void)
619 /* rotate the power history */
620 memmove(&power_history
[1], &power_history
[0],
621 sizeof(power_history
) - sizeof(power_history
[0]));
622 power_history
[0] = power_hist_item();
626 * Monitor the presence of a charger and perform critical frequent steps
627 * such as running the battery voltage filter.
629 static inline void power_thread_step(void)
631 /* If the power off timeout expires, the main thread has failed
632 to shut down the system, and we need to force a power off */
633 if (shutdown_timeout
) {
634 shutdown_timeout
-= POWER_THREAD_STEP_TICKS
;
636 if (shutdown_timeout
<= 0)
640 #ifdef HAVE_RTC_ALARM
641 power_thread_rtc_process();
645 * Do a digital exponential filter. We don't sample the battery if
646 * the disk is spinning unless we are in USB mode (the disk will most
647 * likely always be spinning in USB mode) or charging.
649 if (!storage_disk_is_active() || usb_inserted()
650 #if CONFIG_CHARGING >= CHARGING_MONITOR
651 || charger_input_state
== CHARGER
655 /* update battery status every time an update is available */
656 battery_status_update();
658 else if (battery_percent
< 8) {
660 /* update battery status every time an update is available */
661 battery_status_update();
664 * If battery is low, observe voltage during disk activity.
665 * Shut down if voltage drops below shutoff level and we are not
666 * using NiMH or Alkaline batteries.
668 if (!shutdown_timeout
&& query_force_shutdown()) {
672 } /* power_thread_step */
674 static void power_thread(void)
676 long next_power_hist
;
678 /* Delay reading the first battery level */
680 while (_battery_voltage() > 4200) /* gives false readings initially */
687 /* Initialize power input status before calling other routines. */
688 power_thread_inputs
= power_input_status();
691 /* initialize voltage averaging (if available) */
693 /* get initial battery level value (in %) */
694 init_battery_percent();
695 /* get some initial data for the power curve */
696 collect_power_history();
697 /* call target specific init now */
698 powermgmt_init_target();
700 next_power_hist
= current_tick
+ HZ
*60;
705 unsigned int pwr
= power_input_status();
706 #ifdef HAVE_BATTERY_SWITCH
707 if ((pwr
^ power_thread_inputs
) & POWER_INPUT_BATTERY
) {
709 reset_battery_filter(_battery_voltage());
712 power_thread_inputs
= pwr
;
714 if (!detect_charger(pwr
))
715 #endif /* CONFIG_CHARGING */
718 sleep(POWER_THREAD_STEP_TICKS
);
720 /* Do common power tasks */
724 /* Perform target tasks */
725 charging_algorithm_step();
727 /* check if some idle or sleep timer wears off */
728 handle_auto_poweroff();
730 if (TIME_AFTER(current_tick
, next_power_hist
)) {
731 /* increment to ensure there is a record for every minute
732 * rather than go forward from the current tick */
733 next_power_hist
+= HZ
*60;
734 collect_power_history();
739 void powermgmt_init(void)
741 create_thread(power_thread
, power_stack
, sizeof(power_stack
), 0,
742 power_thread_name
IF_PRIO(, PRIORITY_SYSTEM
)
746 /* Various hardware housekeeping tasks relating to shutting down the player */
747 void shutdown_hw(void)
749 charging_algorithm_close();
752 if (battery_level_safe()) { /* do not save on critical battery */
753 #ifdef HAVE_LCD_BITMAP
757 /* Commit pending writes if needed. Even though we don't do write caching,
758 things like flash translation layers may need this to commit scattered
759 pages to there final locations. So far only used for iPod Nano 2G. */
760 #ifdef HAVE_STORAGE_FLUSH
764 if (storage_disk_is_active())
768 #if CONFIG_CODEC == SWCODEC
774 /* If HD is still active we try to wait for spindown, otherwise the
775 shutdown_timeout in power_thread_step will force a power off */
776 while (storage_disk_is_active())
779 #ifndef HAVE_LCD_COLOR
782 #ifdef HAVE_REMOTE_LCD
783 lcd_remote_set_contrast(0);
785 #ifdef HAVE_LCD_SHUTDOWN
789 /* Small delay to make sure all HW gets time to flush. Especially
790 eeprom chips are quite slow and might be still writing the last
796 void set_poweroff_timeout(int timeout
)
798 poweroff_timeout
= timeout
;
801 void reset_poweroff_timer(void)
803 last_event_tick
= current_tick
;
804 if (sleeptimer_active
&& sleeptimer_key_restarts
)
805 set_sleep_timer(sleeptimer_duration
);
808 void sys_poweroff(void)
811 logf("sys_poweroff()");
812 /* If the main thread fails to shut down the system, we will force a
813 power off after an 20 second timeout - 28 seconds if recording */
814 if (shutdown_timeout
== 0) {
815 #if (defined(IAUDIO_X5) || defined(IAUDIO_M5) || defined(COWON_D2)) && !defined(SIMULATOR)
816 pcf50606_reset_timeout(); /* Reset timer on first attempt only */
818 #ifdef HAVE_RECORDING
819 if (audio_status() & AUDIO_STATUS_RECORD
)
820 shutdown_timeout
+= HZ
*8;
823 /* The FTL alone may take half a minute to shut down cleanly. */
824 shutdown_timeout
+= HZ
*60;
826 shutdown_timeout
+= HZ
*20;
830 queue_broadcast(SYS_POWEROFF
, 0);
831 #endif /* BOOTLOADER */
834 void cancel_shutdown(void)
836 logf("cancel_shutdown()");
838 #if (defined(IAUDIO_X5) || defined(IAUDIO_M5) || defined(COWON_D2)) && !defined(SIMULATOR)
839 /* TODO: Move some things to target/ tree */
840 if (shutdown_timeout
)
841 pcf50606_reset_timeout();
844 shutdown_timeout
= 0;
847 /* Send system battery level update events on reaching certain significant
848 levels. This must be called after battery_percent has been updated. */
849 void send_battery_level_event(void)
851 static const int levels
[] = { 5, 15, 30, 50, 0 };
852 const int *level
= levels
;
856 if (battery_percent
<= *level
&& last_sent_battery_level
> *level
) {
857 last_sent_battery_level
= *level
;
858 queue_broadcast(SYS_BATTERY_UPDATE
, last_sent_battery_level
);
866 void set_sleep_timer(int seconds
)
869 sleeptimer_active
= true;
870 sleeptimer_endtick
= current_tick
+ seconds
* HZ
;
873 sleeptimer_active
= false;
874 sleeptimer_endtick
= 0;
876 sleeptimer_duration
= seconds
;
879 int get_sleep_timer(void)
881 if (sleeptimer_active
&& (sleeptimer_endtick
>= current_tick
))
882 return (sleeptimer_endtick
- current_tick
) / HZ
;
887 void set_keypress_restarts_sleep_timer(bool enable
)
889 sleeptimer_key_restarts
= enable
;
893 static void handle_sleep_timer(void)
895 if (!sleeptimer_active
)
898 /* Handle sleeptimer */
899 if (TIME_AFTER(current_tick
, sleeptimer_endtick
)) {
901 #if CONFIG_CHARGING && !defined(HAVE_POWEROFF_WHILE_CHARGING)
902 || charger_input_state
!= NO_CHARGER
905 DEBUGF("Sleep timer timeout. Stopping...\n");
908 backlight_off(); /* Nighty, nighty... */
911 DEBUGF("Sleep timer timeout. Shutting off...\n");
916 #endif /* BOOTLOADER */
919 * We shut off in the following cases:
920 * 1) The unit is idle, not playing music
921 * 2) The unit is playing music, but is paused
922 * 3) The battery level has reached shutdown limit
924 * We do not shut off in the following cases:
925 * 1) The USB is connected
926 * 2) The charger is connected
927 * 3) We are recording, or recording with pause
928 * 4) The radio is playing
930 void handle_auto_poweroff(void)
933 long timeout
= poweroff_timeout
*60*HZ
;
934 int audio_stat
= audio_status();
935 long tick
= current_tick
;
938 * Inhibit shutdown as long as the charger is plugged in. If it is
939 * unplugged, wait for a timeout period and then shut down.
941 if (audio_stat
== AUDIO_STATUS_PLAY
943 || charger_input_state
== CHARGER
946 last_event_tick
= current_tick
;
949 if (!shutdown_timeout
&& query_force_shutdown()) {
956 !(get_radio_status() & FMRADIO_PLAYING
) &&
960 (audio_stat
== (AUDIO_STATUS_PLAY
| AUDIO_STATUS_PAUSE
) &&
961 !sleeptimer_active
))) {
963 if (TIME_AFTER(tick
, last_event_tick
+ timeout
)
964 #if !(CONFIG_PLATFORM & PLATFORM_HOSTED)
965 && TIME_AFTER(tick
, storage_last_disk_activity() + timeout
)
971 handle_sleep_timer();