/** * _omap_device_deactivate - decrease device readiness * @od: struct omap_device * * @ignore_lat: decrease to latency target (0) or full inactivity (1)? * * Decrease readiness of omap_device @od (thus increasing device * wakeup latency, but conserving power). If @ignore_lat is * IGNORE_WAKEUP_LAT, make the omap_device fully inactive. Otherwise, * if @ignore_lat is USE_WAKEUP_LAT, and the device's maximum wakeup * latency is less than the requested maximum wakeup latency, step * forwards in the omap_device_pm_latency table to ensure the device's * maximum wakeup latency is less than or equal to the requested * maximum wakeup latency. Returns 0. */ static int _omap_device_deactivate(struct omap_device *od, u8 ignore_lat) { struct timespec a, b, c; pr_debug("omap_device: %s: deactivating\n", od->pdev.name); while (od->pm_lat_level < od->pm_lats_cnt) { struct omap_device_pm_latency *odpl; unsigned long long deact_lat = 0; odpl = od->pm_lats + od->pm_lat_level; if (!ignore_lat && ((od->dev_wakeup_lat + odpl->activate_lat) > od->_dev_wakeup_lat_limit)) break; read_persistent_clock(&a); /* XXX check return code */ odpl->deactivate_func(od); read_persistent_clock(&b); c = timespec_sub(b, a); deact_lat = timespec_to_ns(&c); pr_debug("omap_device: %s: pm_lat %d: deactivate: elapsed time " "%llu nsec\n", od->pdev.name, od->pm_lat_level, deact_lat); if (deact_lat > odpl->deactivate_lat) { odpl->deactivate_lat_worst = deact_lat; if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) { odpl->deactivate_lat = deact_lat; pr_warning("omap_device: %s.%d: new worst case " "deactivate latency %d: %llu\n", od->pdev.name, od->pdev.id, od->pm_lat_level, deact_lat); } else pr_warning("omap_device: %s.%d: deactivate " "latency %d higher than exptected. " "(%llu > %d)\n", od->pdev.name, od->pdev.id, od->pm_lat_level, deact_lat, odpl->deactivate_lat); } od->dev_wakeup_lat += odpl->activate_lat; od->pm_lat_level++; } return 0; }
/** * _omap_device_activate - increase device readiness * @od: struct omap_device * * @ignore_lat: increase to latency target (0) or full readiness (1)? * * Increase readiness of omap_device @od (thus decreasing device * wakeup latency, but consuming more power). If @ignore_lat is * IGNORE_WAKEUP_LAT, make the omap_device fully active. Otherwise, * if @ignore_lat is USE_WAKEUP_LAT, and the device's maximum wakeup * latency is greater than the requested maximum wakeup latency, step * backwards in the omap_device_pm_latency table to ensure the * device's maximum wakeup latency is less than or equal to the * requested maximum wakeup latency. Returns 0. */ static int _omap_device_activate(struct omap_device *od, u8 ignore_lat) { struct timespec a, b, c; dev_dbg(&od->pdev->dev, "omap_device: activating\n"); while (od->pm_lat_level > 0) { struct omap_device_pm_latency *odpl; unsigned long long act_lat = 0; od->pm_lat_level--; odpl = od->pm_lats + od->pm_lat_level; if (!ignore_lat && (od->dev_wakeup_lat <= od->_dev_wakeup_lat_limit)) break; read_persistent_clock(&a); /* XXX check return code */ odpl->activate_func(od); read_persistent_clock(&b); c = timespec_sub(b, a); act_lat = timespec_to_ns(&c); dev_dbg(&od->pdev->dev, "omap_device: pm_lat %d: activate: elapsed time " "%llu nsec\n", od->pm_lat_level, act_lat); if (act_lat > odpl->activate_lat) { odpl->activate_lat_worst = act_lat; if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) { odpl->activate_lat = act_lat; dev_dbg(&od->pdev->dev, "new worst case activate latency " "%d: %llu\n", od->pm_lat_level, act_lat); } else dev_warn(&od->pdev->dev, "activate latency %d " "higher than exptected. (%llu > %d)\n", od->pm_lat_level, act_lat, odpl->activate_lat); } od->dev_wakeup_lat -= odpl->activate_lat; } return 0; }
static void tick_periodic(int cpu) { if (tick_do_timer_cpu == cpu) { write_seqlock(&xtime_lock); /* Keep track of the next tick event */ tick_next_period = ktime_add(tick_next_period, tick_period); #ifdef UNDER_HYPERVISOR { /* Compensate slow timer tick under hypervisor */ static __kernel_time_t rt_sec; static unsigned short rt_jiffies_sec = HZ; static unsigned short rt_ticks_sec = HZ; static unsigned short rt_jiffies = 0; static unsigned short rt_ticks = 0; static unsigned short rt_count = 1; // static unsigned short rt_log[11] = {0}; unsigned long tick = rt_jiffies_sec * ++rt_ticks / rt_ticks_sec - rt_jiffies; if (rt_jiffies + tick > rt_jiffies_sec + (HZ/4) ) tick = (rt_jiffies + tick > rt_jiffies_sec + HZ) ? 0 : 1; rt_jiffies += tick; do_timer(tick); if (0 == --rt_count) { static int first = 2; struct timespec ts; read_persistent_clock(&ts); if (rt_sec != ts.tv_sec) { /* rt_log[++rt_log[0]] = rt_ticks; if (rt_log[0] == 10) { rt_log[0] = 0; printk(KERN_ERR "tick_count : %d %d %d %d %d %d %d %d %d %d\n", rt_log[1], rt_log[2], rt_log[3], rt_log[4], rt_log[5], rt_log[6], rt_log[7], rt_log[8], rt_log[9], rt_log[10]); } */ if (!first) { rt_jiffies_sec = HZ + rt_jiffies_sec - rt_jiffies; rt_ticks_sec = rt_ticks ; } else { first--; } rt_sec = ts.tv_sec; rt_ticks = rt_jiffies = 0; } rt_count = (!first && rt_ticks_sec > rt_ticks + 3) ? (rt_ticks_sec - rt_ticks) >> 2 : 1; } } #else do_timer(1); #endif /* End of UNDER_HYPERVISOR */ write_sequnlock(&xtime_lock); }
static int suspend_time_debug_show(struct seq_file *s, void *data) { int bin; seq_printf(s, "time (secs) count\n"); seq_printf(s, "------------------\n"); //LGE_CHANGES [Start] #if 1 for (bin = 0; bin < 33; bin++) { #else for (bin = 0; bin < 32; bin++) { #endif //LGE_CNANGES if (time_in_suspend_bins[bin] == 0) continue; seq_printf(s, "%4d - %4d %4u\n", bin ? 1 << (bin - 1) : 0, 1 << bin, time_in_suspend_bins[bin]); } return 0; } static int suspend_time_debug_open(struct inode *inode, struct file *file) { return single_open(file, suspend_time_debug_show, NULL); } static const struct file_operations suspend_time_debug_fops = { .open = suspend_time_debug_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; static int __init suspend_time_debug_init(void) { struct dentry *d; d = debugfs_create_file("suspend_time", 0755, NULL, NULL, &suspend_time_debug_fops); if (!d) { pr_err("Failed to create suspend_time debug file\n"); return -ENOMEM; } return 0; } late_initcall(suspend_time_debug_init); #endif static int suspend_time_syscore_suspend(void) { read_persistent_clock(&suspend_time_before); return 0; }
static void sleep_history_syscore_resume(void) { struct timespec ts; /* snapshot the current time at suspend */ read_persistent_clock(&ts); if (ts.tv_sec == 0 && ts.tv_nsec == 0) return; sleep_history_marker(SLEEP_HISTORY_SUSPEND_PERSISTCLOCK_EXIT, &ts, NULL); }
static void suspend_time_syscore_resume(void) { struct timespec after; read_persistent_clock(&after); after = timespec_sub(after, suspend_time_before); time_in_suspend_bins[fls(after.tv_sec)]++; pr_info("Suspended for %lu.%03lu seconds\n", after.tv_sec, after.tv_nsec / NSEC_PER_MSEC); }
static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id) { struct gpio_button_data *bdata = dev_id; struct gpio_keys_button *button = bdata->button; BUG_ON(irq != bdata->irq); read_persistent_clock(&button->goog.ts); if (bdata->timer_debounce && !from_suspend_active(button)) mod_timer(&bdata->timer, jiffies + msecs_to_jiffies(bdata->timer_debounce)); else schedule_work(&bdata->work); return IRQ_HANDLED; }
/* Same for RTC */ int sysctl_lasat_rtc(ctl_table *table, int *name, int nlen, void *oldval, size_t *oldlenp, void *newval, size_t newlen) { int r; rtctmp = read_persistent_clock(); if (rtctmp < 0) rtctmp = 0; r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen); if (r < 0) return r; if (newval && newlen) rtc_mips_set_mmss(rtctmp); return r; }
/* proc function to read/write RealTime Clock */ int proc_dolasatrtc(ctl_table *table, int write, struct file *filp, void *buffer, size_t *lenp, loff_t *ppos) { int r; if (!write) { rtctmp = read_persistent_clock(); /* check for time < 0 and set to 0 */ if (rtctmp < 0) rtctmp = 0; } r = proc_dointvec(table, write, filp, buffer, lenp, ppos); if (r) return r; if (write) rtc_mips_set_mmss(rtctmp); return 0; }
/* proc function to read/write RealTime Clock */ int proc_dolasatrtc(ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos) { struct timespec ts; int r; if (!write) { read_persistent_clock(&ts); rtctmp = ts.tv_sec; /* check for time < 0 and set to 0 */ if (rtctmp < 0) rtctmp = 0; } r = proc_dointvec(table, write, buffer, lenp, ppos); if (r) return r; if (write) rtc_mips_set_mmss(rtctmp); return 0; }
void __init time_init(void) { /* FIXME: xtime&wall_to_monotonic are set in timekeeping_init. */ read_persistent_clock(&xtime); set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec); #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT printk("Calibrating CPU frequency "); platform_calibrate_ccount(); printk("%d.%02d MHz\n", (int)ccount_per_jiffy/(1000000/HZ), (int)(ccount_per_jiffy/(10000/HZ))%100); #endif ccount_clocksource.mult = clocksource_hz2mult(CCOUNT_PER_JIFFY * HZ, ccount_clocksource.shift); clocksource_register(&ccount_clocksource); /* Initialize the linux timer interrupt. */ setup_irq(LINUX_TIMER_INT, &timer_irqaction); set_linux_timer(get_ccount() + CCOUNT_PER_JIFFY); }
static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata, gpio_key_caller_t caller) { struct gpio_keys_button *button = bdata->button; struct input_dev *input = bdata->input; struct timespec ts, ts_delta; unsigned int type = button->type ?: EV_KEY; int state = (gpio_get_value_cansleep(button->gpio) ? 1 : 0) ^ button->active_low; if (button->goog.prev_state == state && caller == GPIO_KEYS_WORK && from_suspend_active(button) && !button->goog.synth_sent) { state = !state; button->goog.synth_sent = 1; } if (caller == GPIO_KEYS_WORK) { read_persistent_clock(&ts); ts_delta = timespec_sub(ts, button->goog.ts); dev_dbg(&input->dev, "Camera button time isr to input handling :%Ld ns\n", timespec_to_ns(&ts_delta)); } if (type == EV_ABS) { if (state) input_event(input, type, button->code, button->value); } else { input_event(input, type, button->code, !!state); } input_sync(input); button->goog.prev_state = state; dev_info(&input->dev, "Camera button caller:::%d %s %s\n", caller, ((state) ? "pressed" : "released"), ((button->goog.synth_sent) ? "synthesized" : "polled")); }
static int suspend_time_syscore_suspend(void) { read_persistent_clock(&suspend_time_before); return 0; }