cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pm-debug.c (5137B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * OMAP Power Management debug routines
      4 *
      5 * Copyright (C) 2005 Texas Instruments, Inc.
      6 * Copyright (C) 2006-2008 Nokia Corporation
      7 *
      8 * Written by:
      9 * Richard Woodruff <r-woodruff2@ti.com>
     10 * Tony Lindgren
     11 * Juha Yrjola
     12 * Amit Kucheria <amit.kucheria@nokia.com>
     13 * Igor Stoppa <igor.stoppa@nokia.com>
     14 * Jouni Hogander
     15 *
     16 * Based on pm.c for omap2
     17 */
     18
     19#include <linux/kernel.h>
     20#include <linux/sched.h>
     21#include <linux/sched/clock.h>
     22#include <linux/clk.h>
     23#include <linux/err.h>
     24#include <linux/io.h>
     25#include <linux/module.h>
     26#include <linux/slab.h>
     27
     28#include "clock.h"
     29#include "powerdomain.h"
     30#include "clockdomain.h"
     31
     32#include "soc.h"
     33#include "cm2xxx_3xxx.h"
     34#include "prm2xxx_3xxx.h"
     35#include "pm.h"
     36
     37#ifdef CONFIG_DEBUG_FS
     38#include <linux/debugfs.h>
     39#include <linux/seq_file.h>
     40
     41static int pm_dbg_init_done;
     42
     43static int pm_dbg_init(void);
     44
     45static const char pwrdm_state_names[][PWRDM_MAX_PWRSTS] = {
     46	"OFF",
     47	"RET",
     48	"INA",
     49	"ON"
     50};
     51
     52void pm_dbg_update_time(struct powerdomain *pwrdm, int prev)
     53{
     54	s64 t;
     55
     56	if (!pm_dbg_init_done)
     57		return ;
     58
     59	/* Update timer for previous state */
     60	t = sched_clock();
     61
     62	pwrdm->state_timer[prev] += t - pwrdm->timer;
     63
     64	pwrdm->timer = t;
     65}
     66
     67static int clkdm_dbg_show_counter(struct clockdomain *clkdm, void *user)
     68{
     69	struct seq_file *s = (struct seq_file *)user;
     70
     71	if (strcmp(clkdm->name, "emu_clkdm") == 0 ||
     72		strcmp(clkdm->name, "wkup_clkdm") == 0 ||
     73		strncmp(clkdm->name, "dpll", 4) == 0)
     74		return 0;
     75
     76	seq_printf(s, "%s->%s (%d)\n", clkdm->name, clkdm->pwrdm.ptr->name,
     77		   clkdm->usecount);
     78
     79	return 0;
     80}
     81
     82static int pwrdm_dbg_show_counter(struct powerdomain *pwrdm, void *user)
     83{
     84	struct seq_file *s = (struct seq_file *)user;
     85	int i;
     86
     87	if (strcmp(pwrdm->name, "emu_pwrdm") == 0 ||
     88		strcmp(pwrdm->name, "wkup_pwrdm") == 0 ||
     89		strncmp(pwrdm->name, "dpll", 4) == 0)
     90		return 0;
     91
     92	if (pwrdm->state != pwrdm_read_pwrst(pwrdm))
     93		printk(KERN_ERR "pwrdm state mismatch(%s) %d != %d\n",
     94			pwrdm->name, pwrdm->state, pwrdm_read_pwrst(pwrdm));
     95
     96	seq_printf(s, "%s (%s)", pwrdm->name,
     97			pwrdm_state_names[pwrdm->state]);
     98	for (i = 0; i < PWRDM_MAX_PWRSTS; i++)
     99		seq_printf(s, ",%s:%d", pwrdm_state_names[i],
    100			pwrdm->state_counter[i]);
    101
    102	seq_printf(s, ",RET-LOGIC-OFF:%d", pwrdm->ret_logic_off_counter);
    103	for (i = 0; i < pwrdm->banks; i++)
    104		seq_printf(s, ",RET-MEMBANK%d-OFF:%d", i + 1,
    105				pwrdm->ret_mem_off_counter[i]);
    106
    107	seq_putc(s, '\n');
    108	return 0;
    109}
    110
    111static int pwrdm_dbg_show_timer(struct powerdomain *pwrdm, void *user)
    112{
    113	struct seq_file *s = (struct seq_file *)user;
    114	int i;
    115
    116	if (strcmp(pwrdm->name, "emu_pwrdm") == 0 ||
    117		strcmp(pwrdm->name, "wkup_pwrdm") == 0 ||
    118		strncmp(pwrdm->name, "dpll", 4) == 0)
    119		return 0;
    120
    121	pwrdm_state_switch(pwrdm);
    122
    123	seq_printf(s, "%s (%s)", pwrdm->name,
    124		pwrdm_state_names[pwrdm->state]);
    125
    126	for (i = 0; i < 4; i++)
    127		seq_printf(s, ",%s:%lld", pwrdm_state_names[i],
    128			pwrdm->state_timer[i]);
    129
    130	seq_putc(s, '\n');
    131	return 0;
    132}
    133
    134static int pm_dbg_counters_show(struct seq_file *s, void *unused)
    135{
    136	pwrdm_for_each(pwrdm_dbg_show_counter, s);
    137	clkdm_for_each(clkdm_dbg_show_counter, s);
    138
    139	return 0;
    140}
    141DEFINE_SHOW_ATTRIBUTE(pm_dbg_counters);
    142
    143static int pm_dbg_timers_show(struct seq_file *s, void *unused)
    144{
    145	pwrdm_for_each(pwrdm_dbg_show_timer, s);
    146	return 0;
    147}
    148DEFINE_SHOW_ATTRIBUTE(pm_dbg_timers);
    149
    150static int pwrdm_suspend_get(void *data, u64 *val)
    151{
    152	int ret = -EINVAL;
    153
    154	if (cpu_is_omap34xx())
    155		ret = omap3_pm_get_suspend_state((struct powerdomain *)data);
    156	*val = ret;
    157
    158	if (ret >= 0)
    159		return 0;
    160	return *val;
    161}
    162
    163static int pwrdm_suspend_set(void *data, u64 val)
    164{
    165	if (cpu_is_omap34xx())
    166		return omap3_pm_set_suspend_state(
    167			(struct powerdomain *)data, (int)val);
    168	return -EINVAL;
    169}
    170
    171DEFINE_DEBUGFS_ATTRIBUTE(pwrdm_suspend_fops, pwrdm_suspend_get,
    172			  pwrdm_suspend_set, "%llu\n");
    173
    174static int __init pwrdms_setup(struct powerdomain *pwrdm, void *dir)
    175{
    176	int i;
    177	s64 t;
    178	struct dentry *d;
    179
    180	t = sched_clock();
    181
    182	for (i = 0; i < 4; i++)
    183		pwrdm->state_timer[i] = 0;
    184
    185	pwrdm->timer = t;
    186
    187	if (strncmp(pwrdm->name, "dpll", 4) == 0)
    188		return 0;
    189
    190	d = debugfs_create_dir(pwrdm->name, (struct dentry *)dir);
    191	debugfs_create_file("suspend", S_IRUGO|S_IWUSR, d, pwrdm,
    192			    &pwrdm_suspend_fops);
    193
    194	return 0;
    195}
    196
    197static int option_get(void *data, u64 *val)
    198{
    199	u32 *option = data;
    200
    201	*val = *option;
    202
    203	return 0;
    204}
    205
    206static int option_set(void *data, u64 val)
    207{
    208	u32 *option = data;
    209
    210	*option = val;
    211
    212	if (option == &enable_off_mode) {
    213		if (cpu_is_omap34xx())
    214			omap3_pm_off_mode_enable(val);
    215	}
    216
    217	return 0;
    218}
    219
    220DEFINE_SIMPLE_ATTRIBUTE(pm_dbg_option_fops, option_get, option_set, "%llu\n");
    221
    222static int __init pm_dbg_init(void)
    223{
    224	struct dentry *d;
    225
    226	if (pm_dbg_init_done)
    227		return 0;
    228
    229	d = debugfs_create_dir("pm_debug", NULL);
    230
    231	debugfs_create_file("count", 0444, d, NULL, &pm_dbg_counters_fops);
    232	debugfs_create_file("time", 0444, d, NULL, &pm_dbg_timers_fops);
    233
    234	pwrdm_for_each(pwrdms_setup, (void *)d);
    235
    236	debugfs_create_file("enable_off_mode", S_IRUGO | S_IWUSR, d,
    237			    &enable_off_mode, &pm_dbg_option_fops);
    238	pm_dbg_init_done = 1;
    239
    240	return 0;
    241}
    242omap_arch_initcall(pm_dbg_init);
    243
    244#endif