summaryrefslogtreecommitdiff
path: root/arch/arm/mach-ux500/pm/cpuidle_dbg.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-ux500/pm/cpuidle_dbg.c')
-rw-r--r--arch/arm/mach-ux500/pm/cpuidle_dbg.c950
1 files changed, 0 insertions, 950 deletions
diff --git a/arch/arm/mach-ux500/pm/cpuidle_dbg.c b/arch/arm/mach-ux500/pm/cpuidle_dbg.c
deleted file mode 100644
index 344d7b8a0ed..00000000000
--- a/arch/arm/mach-ux500/pm/cpuidle_dbg.c
+++ /dev/null
@@ -1,950 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010-2011
- *
- * License Terms: GNU General Public License v2
- * Author: Rickard Andersson <rickard.andersson@stericsson.com>,
- * Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson
- */
-
-#include <linux/slab.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-#include <linux/workqueue.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/uaccess.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <linux/gpio/nomadik.h>
-#include <linux/amba/serial.h>
-
-#include <asm/hardware/gic.h>
-
-#include "cpuidle.h"
-#include "pm.h"
-#include "timer.h"
-
-#define APE_ON_TIMER_INTERVAL 5 /* Seconds */
-
-#define UART_RX_GPIO_PIN_MASK (1 << (CONFIG_UX500_CONSOLE_UART_GPIO_PIN % 32))
-
-#define UART011_MIS_RTIS (1 << 6) /* receive timeout interrupt status */
-#define UART011_MIS_RXIS (1 << 4) /* receive interrupt status */
-#define UART011_MIS 0x40 /* Masked interrupt status register */
-
-enum latency_type {
- LATENCY_ENTER = 0,
- LATENCY_EXIT,
- LATENCY_WAKE,
- NUM_LATENCY,
-};
-
-struct state_history_state {
- u32 counter;
- ktime_t time;
- u32 hit_rate;
- u32 state_ok;
- u32 state_error;
- u32 prcmu_int;
- u32 pending_int;
-
- u32 latency_count[NUM_LATENCY];
- ktime_t latency_sum[NUM_LATENCY];
- ktime_t latency_min[NUM_LATENCY];
- ktime_t latency_max[NUM_LATENCY];
-};
-
-struct state_history {
- ktime_t start;
- u32 state;
- u32 exit_counter;
- ktime_t measure_begin;
- int ape_blocked;
- int time_blocked;
- int both_blocked;
- int gov_blocked;
- struct state_history_state *states;
-};
-static DEFINE_PER_CPU(struct state_history, *state_history);
-
-static struct delayed_work cpuidle_work;
-static u32 dbg_console_enable = 1;
-static void __iomem *uart_base;
-static struct clk *uart_clk;
-
-/* Blocks ApSleep and ApDeepSleep */
-static bool force_APE_on;
-static bool reset_timer;
-static int deepest_allowed_state = CONFIG_U8500_CPUIDLE_DEEPEST_STATE;
-static u32 measure_latency;
-static bool wake_latency;
-static int verbose;
-
-static bool apidle_both_blocked;
-static bool apidle_ape_blocked;
-static bool apidle_time_blocked;
-static bool apidle_gov_blocked;
-
-static struct cstate *cstates;
-static int cstates_len;
-static DEFINE_SPINLOCK(dbg_lock);
-
-bool ux500_ci_dbg_force_ape_on(void)
-{
- clk_enable(uart_clk);
- if (readw(uart_base + UART01x_FR) & UART01x_FR_BUSY) {
- clk_disable(uart_clk);
- return true;
- }
- clk_disable(uart_clk);
-
- return force_APE_on;
-}
-
-int ux500_ci_dbg_deepest_state(void)
-{
- return deepest_allowed_state;
-}
-
-void ux500_ci_dbg_console_handle_ape_suspend(void)
-{
- if (!dbg_console_enable)
- return;
-
- irq_set_irq_wake(GPIO_TO_IRQ(CONFIG_UX500_CONSOLE_UART_GPIO_PIN), 1);
- irq_set_irq_type(GPIO_TO_IRQ(CONFIG_UX500_CONSOLE_UART_GPIO_PIN),
- IRQ_TYPE_EDGE_BOTH);
-}
-
-void ux500_ci_dbg_console_handle_ape_resume(void)
-{
- unsigned long flags;
- u32 WKS_reg_value;
-
- if (!dbg_console_enable)
- return;
-
- WKS_reg_value = ux500_pm_gpio_read_wake_up_status(0);
-
- if (WKS_reg_value & UART_RX_GPIO_PIN_MASK) {
- spin_lock_irqsave(&dbg_lock, flags);
- reset_timer = true;
- spin_unlock_irqrestore(&dbg_lock, flags);
- }
- irq_set_irq_wake(GPIO_TO_IRQ(CONFIG_UX500_CONSOLE_UART_GPIO_PIN), 0);
-
-}
-
-void ux500_ci_dbg_console_check_uart(void)
-{
- unsigned long flags;
- u32 status;
-
- if (!dbg_console_enable)
- return;
-
- clk_enable(uart_clk);
- spin_lock_irqsave(&dbg_lock, flags);
- status = readw(uart_base + UART011_MIS);
-
- if (status & (UART011_MIS_RTIS | UART011_MIS_RXIS))
- reset_timer = true;
-
- spin_unlock_irqrestore(&dbg_lock, flags);
- clk_disable(uart_clk);
-}
-
-void ux500_ci_dbg_console(void)
-{
- unsigned long flags;
-
- if (!dbg_console_enable)
- return;
-
- spin_lock_irqsave(&dbg_lock, flags);
- if (reset_timer) {
- reset_timer = false;
- spin_unlock_irqrestore(&dbg_lock, flags);
-
- cancel_delayed_work(&cpuidle_work);
- force_APE_on = true;
- schedule_delayed_work(&cpuidle_work,
- msecs_to_jiffies(APE_ON_TIMER_INTERVAL *
- 1000));
- } else {
- spin_unlock_irqrestore(&dbg_lock, flags);
- }
-}
-
-static void dbg_cpuidle_work_function(struct work_struct *work)
-{
- force_APE_on = false;
-}
-
-static void store_latency(struct state_history *sh,
- int ctarget,
- enum latency_type type,
- ktime_t d,
- bool lock)
-{
- unsigned long flags = 0;
-
- if (lock)
- spin_lock_irqsave(&dbg_lock, flags);
-
- sh->states[ctarget].latency_count[type]++;
-
- sh->states[ctarget].latency_sum[type] =
- ktime_add(sh->states[ctarget].latency_sum[type], d);
-
- if (ktime_to_us(d) > ktime_to_us(sh->states[ctarget].latency_max[type]))
- sh->states[ctarget].latency_max[type] = d;
-
- if (ktime_to_us(d) < ktime_to_us(sh->states[ctarget].latency_min[type]))
- sh->states[ctarget].latency_min[type] = d;
-
- if (lock)
- spin_unlock_irqrestore(&dbg_lock, flags);
-}
-
-void ux500_ci_dbg_exit_latency(int ctarget, ktime_t now, ktime_t exit,
- ktime_t enter)
-{
- struct state_history *sh;
- bool hit = true;
- enum prcmu_idle_stat prcmu_status;
- unsigned int d;
-
- if (!verbose)
- return;
-
- sh = per_cpu(state_history, smp_processor_id());
-
- sh->exit_counter++;
-
- d = ktime_to_us(ktime_sub(now, enter));
-
- if ((ctarget + 1) < deepest_allowed_state)
- hit = d < cstates[ctarget + 1].threshold;
- if (d < cstates[ctarget].threshold)
- hit = false;
-
- if (hit)
- sh->states[ctarget].hit_rate++;
-
- if (cstates[ctarget].state < CI_IDLE)
- return;
-
- prcmu_status = ux500_pm_prcmu_idle_stat();
-
- switch (prcmu_status) {
-
- case DEEP_SLEEP_OK:
- if (cstates[ctarget].state == CI_DEEP_SLEEP)
- sh->states[ctarget].state_ok++;
- break;
- case SLEEP_OK:
- if (cstates[ctarget].state == CI_SLEEP)
- sh->states[ctarget].state_ok++;
- break;
- case IDLE_OK:
- if (cstates[ctarget].state == CI_IDLE)
- sh->states[ctarget].state_ok++;
- break;
- case DEEPIDLE_OK:
- if (cstates[ctarget].state == CI_DEEP_IDLE)
- sh->states[ctarget].state_ok++;
- break;
- case PRCMU2ARMPENDINGIT_ER:
- sh->states[ctarget].prcmu_int++;
- break;
- case ARMPENDINGIT_ER:
- sh->states[ctarget].pending_int++;
- break;
- default:
- pr_info("cpuidle: unknown prcmu exit code: 0x%x state: %d\n",
- prcmu_status, cstates[ctarget].state);
- sh->states[ctarget].state_error++;
- break;
- }
-
- if (!measure_latency)
- return;
-
- store_latency(sh,
- ctarget,
- LATENCY_EXIT,
- ktime_sub(now, exit),
- true);
-}
-
-void ux500_ci_dbg_wake_latency(int ctarget, int sleep_time)
-{
- struct state_history *sh;
- ktime_t l;
- ktime_t zero_time;
-
- if (!wake_latency || cstates[ctarget].state < CI_IDLE)
- return;
-
- l = zero_time = ktime_set(0, 0);
- sh = per_cpu(state_history, smp_processor_id());
-
- if (cstates[ctarget].state >= CI_SLEEP)
- l = u8500_rtc_exit_latency_get();
-
- if (cstates[ctarget].state == CI_IDLE) {
- ktime_t d = ktime_set(0, sleep_time * 1000);
- ktime_t now = ktime_get();
-
- d = ktime_add(d, sh->start);
- if (ktime_to_us(now) > ktime_to_us(d))
- l = ktime_sub(now, d);
- else
- l = zero_time;
- }
-
- if (!ktime_equal(zero_time, l))
- store_latency(sh,
- ctarget,
- LATENCY_WAKE,
- l,
- true);
-}
-
-static void state_record_time(struct state_history *sh, int ctarget,
- ktime_t now, ktime_t start, bool latency)
-{
- ktime_t dtime;
-
- dtime = ktime_sub(now, sh->start);
- sh->states[sh->state].time = ktime_add(sh->states[sh->state].time,
- dtime);
-
- sh->start = now;
- sh->state = ctarget;
-
- if (latency && cstates[ctarget].state != CI_RUNNING && measure_latency)
- store_latency(sh,
- ctarget,
- LATENCY_ENTER,
- ktime_sub(now, start),
- false);
-
- sh->states[sh->state].counter++;
-}
-
-void ux500_ci_dbg_register_reason(int idx, bool power_state_req,
- u32 time, u32 max_depth)
-{
- if (cstates[idx].state == CI_IDLE && verbose) {
- apidle_ape_blocked = power_state_req;
- apidle_time_blocked = time < cstates[idx + 1].threshold;
- apidle_both_blocked = power_state_req && apidle_time_blocked;
- apidle_gov_blocked = cstates[max_depth].state == CI_IDLE;
- }
-}
-
-void ux500_ci_dbg_log(int ctarget, ktime_t enter_time)
-{
- int i;
- ktime_t now;
- unsigned long flags;
- struct state_history *sh;
- struct state_history *sh_other;
- int this_cpu;
-
- this_cpu = smp_processor_id();
-
- now = ktime_get();
-
- sh = per_cpu(state_history, this_cpu);
-
- spin_lock_irqsave(&dbg_lock, flags);
-
- if (cstates[ctarget].state == CI_IDLE && verbose) {
- if (apidle_both_blocked)
- sh->both_blocked++;
- if (apidle_ape_blocked)
- sh->ape_blocked++;
- if (apidle_time_blocked)
- sh->time_blocked++;
- if (apidle_gov_blocked)
- sh->gov_blocked++;
- }
-
- /*
- * Check if current state is just a repeat of
- * the state we're already in, then just quit.
- */
- if (ctarget == sh->state)
- goto done;
-
- state_record_time(sh, ctarget, now, enter_time, true);
-
- /*
- * Update other cpus, (this_cpu = A, other cpus = B) if:
- * - A = running and B != WFI | running: Set B to WFI
- * - A = WFI and then B must be running: No changes
- * - A = !WFI && !RUNNING and then B must be WFI: B sets to A
- */
-
- if (sh->state == CI_WFI)
- goto done;
-
- for_each_possible_cpu(i) {
-
- if (this_cpu == i)
- continue;
-
- sh_other = per_cpu(state_history, i);
-
- /* Same state, continue */
- if (sh_other->state == sh->state)
- continue;
-
- if (cstates[ctarget].state == CI_RUNNING &&
- cstates[sh_other->state].state != CI_WFI) {
- state_record_time(sh_other, CI_WFI, now,
- enter_time, false);
- continue;
- }
- /*
- * This cpu is something else than running or wfi, both must be
- * in the same state.
- */
- state_record_time(sh_other, ctarget, now, enter_time, true);
- }
-done:
- spin_unlock_irqrestore(&dbg_lock, flags);
-}
-
-static void state_history_reset(void)
-{
- unsigned long flags;
- unsigned int cpu;
- int i, j;
- struct state_history *sh;
-
- spin_lock_irqsave(&dbg_lock, flags);
-
- for_each_possible_cpu(cpu) {
- sh = per_cpu(state_history, cpu);
- for (i = 0; i < cstates_len; i++) {
- sh->states[i].counter = 0;
- sh->states[i].hit_rate = 0;
- sh->states[i].state_ok = 0;
- sh->states[i].state_error = 0;
- sh->states[i].prcmu_int = 0;
- sh->states[i].pending_int = 0;
-
- sh->states[i].time = ktime_set(0, 0);
-
- for (j = 0; j < NUM_LATENCY; j++) {
- sh->states[i].latency_count[j] = 0;
- sh->states[i].latency_min[j] = ktime_set(0,
- 10000000);
- sh->states[i].latency_max[j] = ktime_set(0, 0);
- sh->states[i].latency_sum[j] = ktime_set(0, 0);
- }
- }
-
- sh->start = ktime_get();
- sh->measure_begin = sh->start;
- /* Don't touch sh->state, since that is where we are now */
-
- sh->exit_counter = 0;
- sh->ape_blocked = 0;
- sh->time_blocked = 0;
- sh->both_blocked = 0;
- sh->gov_blocked = 0;
- }
- spin_unlock_irqrestore(&dbg_lock, flags);
-}
-
-static int get_val(const char __user *user_buf,
- size_t count, int min, int max)
-{
- long unsigned val;
- int err;
-
- err = kstrtoul_from_user(user_buf, count, 0, &val);
-
- if (err)
- return err;
-
- if (val > max)
- val = max;
- if (val < min)
- val = min;
-
- return val;
-}
-
-static ssize_t set_deepest_state(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- int val;
-
- val = get_val(user_buf, count, CI_WFI, cstates_len - 1);
-
- if (val < 0)
- return val;
-
- deepest_allowed_state = val;
-
- pr_debug("cpuidle: changed deepest allowed sleep state to %d.\n",
- deepest_allowed_state);
-
- return count;
-}
-
-static int deepest_state_print(struct seq_file *s, void *p)
-{
- seq_printf(s, "Deepest allowed sleep state is %d\n",
- deepest_allowed_state);
-
- return 0;
-}
-
-static ssize_t stats_write(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- state_history_reset();
- return count;
-}
-
-static int wake_latency_read(struct seq_file *s, void *p)
-{
- seq_printf(s, "wake latency measurements is %s\n",
- wake_latency ? "on" : "off");
- return 0;
-}
-
-static ssize_t wake_latency_write(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- int val = get_val(user_buf, count, 0, 1);
- if (val < 0)
- return val;
-
- wake_latency = val;
- ux500_rtcrtt_measure_latency(wake_latency);
- return count;
-}
-
-static int verbose_read(struct seq_file *s, void *p)
-{
- seq_printf(s, "verbose debug is %s\n", verbose ? "on" : "off");
- return 0;
-}
-
-static ssize_t verbose_write(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- int val = get_val(user_buf, count, 0, 1);
- if (val < 0)
- return val;
-
- verbose = val;
- state_history_reset();
-
- return count;
-}
-
-static void stats_disp_one(struct seq_file *s, struct state_history *sh,
- s64 total_us, int i)
-{
- int j;
- s64 avg[NUM_LATENCY];
- s64 t_us;
- s64 perc;
- ktime_t init_time, zero_time;
-
- init_time = ktime_set(0, 10000000);
- zero_time = ktime_set(0, 0);
-
- memset(&avg, 0, sizeof(s64) * NUM_LATENCY);
-
- for (j = 0; j < NUM_LATENCY; j++)
- avg[j] = ktime_to_us(sh->states[i].latency_sum[j]);
-
- t_us = ktime_to_us(sh->states[i].time);
- perc = ktime_to_us(sh->states[i].time);
- do_div(t_us, 1000); /* to ms */
- do_div(total_us, 100);
- if (total_us)
- do_div(perc, total_us);
-
- for (j = 0; j < NUM_LATENCY; j++) {
- if (sh->states[i].latency_count[j])
- do_div(avg[j], sh->states[i].latency_count[j]);
- }
-
- seq_printf(s, "\n%d - %s: %u",
- i, cstates[i].desc,
- sh->states[i].counter);
-
- if (sh->states[i].counter == 0)
- return;
-
- if (i > CI_WFI && verbose)
- seq_printf(s, " (%u prcmu_int:%u int:%u err:%u)",
- sh->states[i].state_ok,
- sh->states[i].prcmu_int,
- sh->states[i].pending_int,
- sh->states[i].state_error);
-
- seq_printf(s, " in %d ms %d%%",
- (u32) t_us, (u32)perc);
-
- if (cstates[i].state == CI_IDLE && verbose)
- seq_printf(s, ", reg:%d time:%d both:%d gov:%d",
- sh->ape_blocked, sh->time_blocked,
- sh->both_blocked, sh->gov_blocked);
-
- if (sh->states[i].counter && verbose)
- seq_printf(s, ", hit rate: %u%% ",
- 100 * sh->states[i].hit_rate /
- sh->states[i].counter);
-
- if (i == CI_RUNNING || !(measure_latency || wake_latency))
- return;
-
- for (j = 0; j < NUM_LATENCY; j++) {
- bool show = false;
- if (!ktime_equal(sh->states[i].latency_min[j], init_time)) {
- seq_printf(s, "\n\t\t\t\t");
- switch (j) {
- case LATENCY_ENTER:
- if (measure_latency) {
- seq_printf(s, "enter: ");
- show = true;
- }
- break;
- case LATENCY_EXIT:
- if (measure_latency) {
- seq_printf(s, "exit: ");
- show = true;
- }
- break;
- case LATENCY_WAKE:
- if (wake_latency) {
- seq_printf(s, "wake: ");
- show = true;
- }
- break;
- default:
- seq_printf(s, "unknown!: ");
- break;
- }
-
- if (!show)
- continue;
-
- if (ktime_equal(sh->states[i].latency_min[j],
- zero_time))
- seq_printf(s, "min < 30");
- else
- seq_printf(s, "min %lld",
- ktime_to_us(sh->states[i].latency_min[j]));
-
- seq_printf(s, " avg %lld max %lld us, count: %d",
- avg[j],
- ktime_to_us(sh->states[i].latency_max[j]),
- sh->states[i].latency_count[j]);
- }
- }
-}
-
-static int stats_print(struct seq_file *s, void *p)
-{
- int cpu;
- int i;
- unsigned long flags;
- struct state_history *sh;
- ktime_t total, wall;
- s64 total_us, total_s;
-
- for_each_online_cpu(cpu) {
- sh = per_cpu(state_history, cpu);
- spin_lock_irqsave(&dbg_lock, flags);
- seq_printf(s, "\nCPU%d\n", cpu);
-
- total = ktime_set(0, 0);
-
- for (i = 0; i < cstates_len; i++)
- total = ktime_add(total, sh->states[i].time);
-
- wall = ktime_sub(ktime_get(), sh->measure_begin);
-
- total_us = ktime_to_us(wall);
- total_s = ktime_to_ms(wall);
-
- do_div(total_s, 1000);
-
- if (verbose) {
- if (total_s)
- seq_printf(s,
- "wake ups per s: %u.%u \n",
- sh->exit_counter / (int) total_s,
- (10 * sh->exit_counter / (int) total_s) -
- 10 * (sh->exit_counter / (int) total_s));
-
- seq_printf(s,
- "\ndelta accounted vs wall clock: %lld us\n",
- ktime_to_us(ktime_sub(wall, total)));
- }
-
- for (i = 0; i < cstates_len; i++)
- stats_disp_one(s, sh, total_us, i);
-
- seq_printf(s, "\n");
- spin_unlock_irqrestore(&dbg_lock, flags);
- }
- seq_printf(s, "\n");
- return 0;
-}
-
-
-static int ap_family_show(struct seq_file *s, void *iter)
-{
- int i;
- u32 count = 0;
- unsigned long flags;
- struct state_history *sh;
-
- sh = per_cpu(state_history, 0);
- spin_lock_irqsave(&dbg_lock, flags);
-
- for (i = 0 ; i < cstates_len; i++) {
- if (cstates[i].state == (enum ci_pwrst)s->private)
- count += sh->states[i].counter;
- }
-
- seq_printf(s, "%u\n", count);
- spin_unlock_irqrestore(&dbg_lock, flags);
-
- return 0;
-}
-
-static int deepest_state_open_file(struct inode *inode, struct file *file)
-{
- return single_open(file, deepest_state_print, inode->i_private);
-}
-
-static int verbose_open_file(struct inode *inode, struct file *file)
-{
- return single_open(file, verbose_read, inode->i_private);
-}
-
-static int stats_open_file(struct inode *inode, struct file *file)
-{
- return single_open(file, stats_print, inode->i_private);
-}
-
-static int ap_family_open(struct inode *inode,
- struct file *file)
-{
- return single_open(file, ap_family_show, inode->i_private);
-}
-
-static int wake_latency_open(struct inode *inode,
- struct file *file)
-{
- return single_open(file, wake_latency_read, inode->i_private);
-}
-
-static const struct file_operations deepest_state_fops = {
- .open = deepest_state_open_file,
- .write = set_deepest_state,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
-
-static const struct file_operations verbose_state_fops = {
- .open = verbose_open_file,
- .write = verbose_write,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
-
-static const struct file_operations stats_fops = {
- .open = stats_open_file,
- .write = stats_write,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
-
-static const struct file_operations ap_family_fops = {
- .open = ap_family_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
-
-static const struct file_operations wake_latency_fops = {
- .open = wake_latency_open,
- .write = wake_latency_write,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
-
-static struct dentry *cpuidle_dir;
-
-static void __init setup_debugfs(void)
-{
- cpuidle_dir = debugfs_create_dir("cpuidle", NULL);
- if (IS_ERR_OR_NULL(cpuidle_dir))
- goto fail;
-
- if (IS_ERR_OR_NULL(debugfs_create_file("deepest_state",
- S_IWUGO | S_IRUGO, cpuidle_dir,
- NULL, &deepest_state_fops)))
- goto fail;
-
- if (IS_ERR_OR_NULL(debugfs_create_file("verbose",
- S_IWUGO | S_IRUGO, cpuidle_dir,
- NULL, &verbose_state_fops)))
- goto fail;
-
- if (IS_ERR_OR_NULL(debugfs_create_file("stats",
- S_IRUGO, cpuidle_dir, NULL,
- &stats_fops)))
- goto fail;
-
- if (IS_ERR_OR_NULL(debugfs_create_bool("dbg_console_enable",
- S_IWUGO | S_IRUGO, cpuidle_dir,
- &dbg_console_enable)))
- goto fail;
-
- if (IS_ERR_OR_NULL(debugfs_create_bool("measure_latency",
- S_IWUGO | S_IRUGO, cpuidle_dir,
- &measure_latency)))
- goto fail;
-
-
- if (IS_ERR_OR_NULL(debugfs_create_file("wake_latency",
- S_IWUGO | S_IRUGO, cpuidle_dir,
- NULL,
- &wake_latency_fops)))
- goto fail;
-
- if (IS_ERR_OR_NULL(debugfs_create_file("ap_idle", S_IRUGO,
- cpuidle_dir,
- (void *)CI_IDLE,
- &ap_family_fops)))
- goto fail;
-
- if (IS_ERR_OR_NULL(debugfs_create_file("ap_sleep", S_IRUGO,
- cpuidle_dir,
- (void *)CI_SLEEP,
- &ap_family_fops)))
- goto fail;
-
- if (IS_ERR_OR_NULL(debugfs_create_file("ap_deepidle", S_IRUGO,
- cpuidle_dir,
- (void *)CI_DEEP_IDLE,
- &ap_family_fops)))
- goto fail;
-
- if (IS_ERR_OR_NULL(debugfs_create_file("ap_deepsleep", S_IRUGO,
- cpuidle_dir,
- (void *)CI_DEEP_SLEEP,
- &ap_family_fops)))
- goto fail;
-
- return;
-fail:
- debugfs_remove_recursive(cpuidle_dir);
-}
-
-#define __UART_BASE(soc, x) soc##_UART##x##_BASE
-#define UART_BASE(soc, x) __UART_BASE(soc, x)
-
-void __init ux500_ci_dbg_init(void)
-{
- static const char clkname[] __initconst
- = "uart" __stringify(CONFIG_UX500_DEBUG_UART);
- unsigned long baseaddr;
- int cpu;
-
- struct state_history *sh;
-
- cstates = ux500_ci_get_cstates(&cstates_len);
-
- if (deepest_allowed_state > cstates_len)
- deepest_allowed_state = cstates_len;
-
- for_each_possible_cpu(cpu) {
- per_cpu(state_history, cpu) = kzalloc(sizeof(struct state_history),
- GFP_KERNEL);
- sh = per_cpu(state_history, cpu);
- sh->states = kzalloc(sizeof(struct state_history_state)
- * cstates_len,
- GFP_KERNEL);
- }
-
- state_history_reset();
-
- for_each_possible_cpu(cpu) {
- sh = per_cpu(state_history, cpu);
- /* Only first CPU used during boot */
- if (cpu == 0)
- sh->state = CI_RUNNING;
- else
- sh->state = CI_WFI;
- }
-
- setup_debugfs();
-
- /* Uart debug init */
-
- if (cpu_is_u8500())
- baseaddr = UART_BASE(U8500, CONFIG_UX500_DEBUG_UART);
- else if (cpu_is_u5500())
- baseaddr = UART_BASE(U5500, CONFIG_UX500_DEBUG_UART);
- else
- ux500_unknown_soc();
-
- uart_base = ioremap(baseaddr, SZ_4K);
- BUG_ON(!uart_base);
-
- uart_clk = clk_get_sys(clkname, NULL);
- BUG_ON(IS_ERR(uart_clk));
-
- INIT_DELAYED_WORK_DEFERRABLE(&cpuidle_work, dbg_cpuidle_work_function);
-
-}
-
-void ux500_ci_dbg_remove(void)
-{
- int cpu;
- struct state_history *sh;
-
- debugfs_remove_recursive(cpuidle_dir);
-
- for_each_possible_cpu(cpu) {
- sh = per_cpu(state_history, cpu);
- kfree(sh->states);
- kfree(sh);
- }
-
- iounmap(uart_base);
-}