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

dbx500-prcmu.c (3811B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) ST-Ericsson SA 2010
      4 *
      5 * Authors: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson
      6 *          Bengt Jonsson <bengt.g.jonsson@stericsson.com> for ST-Ericsson
      7 *
      8 * UX500 common part of Power domain regulators
      9 */
     10
     11#include <linux/kernel.h>
     12#include <linux/err.h>
     13#include <linux/regulator/driver.h>
     14#include <linux/debugfs.h>
     15#include <linux/seq_file.h>
     16#include <linux/slab.h>
     17#include <linux/module.h>
     18
     19#include "dbx500-prcmu.h"
     20
     21/*
     22 * power state reference count
     23 */
     24static int power_state_active_cnt; /* will initialize to zero */
     25static DEFINE_SPINLOCK(power_state_active_lock);
     26
     27void power_state_active_enable(void)
     28{
     29	unsigned long flags;
     30
     31	spin_lock_irqsave(&power_state_active_lock, flags);
     32	power_state_active_cnt++;
     33	spin_unlock_irqrestore(&power_state_active_lock, flags);
     34}
     35
     36int power_state_active_disable(void)
     37{
     38	int ret = 0;
     39	unsigned long flags;
     40
     41	spin_lock_irqsave(&power_state_active_lock, flags);
     42	if (power_state_active_cnt <= 0) {
     43		pr_err("power state: unbalanced enable/disable calls\n");
     44		ret = -EINVAL;
     45		goto out;
     46	}
     47
     48	power_state_active_cnt--;
     49out:
     50	spin_unlock_irqrestore(&power_state_active_lock, flags);
     51	return ret;
     52}
     53
     54#ifdef CONFIG_REGULATOR_DEBUG
     55
     56static int power_state_active_get(void)
     57{
     58	unsigned long flags;
     59	int cnt;
     60
     61	spin_lock_irqsave(&power_state_active_lock, flags);
     62	cnt = power_state_active_cnt;
     63	spin_unlock_irqrestore(&power_state_active_lock, flags);
     64
     65	return cnt;
     66}
     67
     68static struct ux500_regulator_debug {
     69	struct dentry *dir;
     70	struct dbx500_regulator_info *regulator_array;
     71	int num_regulators;
     72	u8 *state_before_suspend;
     73	u8 *state_after_suspend;
     74} rdebug;
     75
     76static int ux500_regulator_power_state_cnt_show(struct seq_file *s, void *p)
     77{
     78	/* print power state count */
     79	seq_printf(s, "ux500-regulator power state count: %i\n",
     80		   power_state_active_get());
     81
     82	return 0;
     83}
     84DEFINE_SHOW_ATTRIBUTE(ux500_regulator_power_state_cnt);
     85
     86static int ux500_regulator_status_show(struct seq_file *s, void *p)
     87{
     88	int i;
     89
     90	/* print dump header */
     91	seq_puts(s, "ux500-regulator status:\n");
     92	seq_printf(s, "%31s : %8s : %8s\n", "current", "before", "after");
     93
     94	for (i = 0; i < rdebug.num_regulators; i++) {
     95		struct dbx500_regulator_info *info;
     96		/* Access per-regulator data */
     97		info = &rdebug.regulator_array[i];
     98
     99		/* print status */
    100		seq_printf(s, "%20s : %8s : %8s : %8s\n",
    101			   info->desc.name,
    102			   info->is_enabled ? "enabled" : "disabled",
    103			   rdebug.state_before_suspend[i] ? "enabled" : "disabled",
    104			   rdebug.state_after_suspend[i] ? "enabled" : "disabled");
    105	}
    106
    107	return 0;
    108}
    109DEFINE_SHOW_ATTRIBUTE(ux500_regulator_status);
    110
    111int
    112ux500_regulator_debug_init(struct platform_device *pdev,
    113	struct dbx500_regulator_info *regulator_info,
    114	int num_regulators)
    115{
    116	/* create directory */
    117	rdebug.dir = debugfs_create_dir("ux500-regulator", NULL);
    118
    119	/* create "status" file */
    120	debugfs_create_file("status", 0444, rdebug.dir, &pdev->dev,
    121			    &ux500_regulator_status_fops);
    122
    123	/* create "power-state-count" file */
    124	debugfs_create_file("power-state-count", 0444, rdebug.dir,
    125			    &pdev->dev, &ux500_regulator_power_state_cnt_fops);
    126
    127	rdebug.regulator_array = regulator_info;
    128	rdebug.num_regulators = num_regulators;
    129
    130	rdebug.state_before_suspend = kzalloc(num_regulators, GFP_KERNEL);
    131	if (!rdebug.state_before_suspend)
    132		goto exit_destroy_power_state;
    133
    134	rdebug.state_after_suspend = kzalloc(num_regulators, GFP_KERNEL);
    135	if (!rdebug.state_after_suspend)
    136		goto exit_free;
    137
    138	return 0;
    139
    140exit_free:
    141	kfree(rdebug.state_before_suspend);
    142exit_destroy_power_state:
    143	debugfs_remove_recursive(rdebug.dir);
    144	return -ENOMEM;
    145}
    146
    147int ux500_regulator_debug_exit(void)
    148{
    149	debugfs_remove_recursive(rdebug.dir);
    150	kfree(rdebug.state_after_suspend);
    151	kfree(rdebug.state_before_suspend);
    152
    153	return 0;
    154}
    155#endif