Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) ST-Ericsson SA 2010
0004  *
0005  * Authors: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson
0006  *          Bengt Jonsson <bengt.g.jonsson@stericsson.com> for ST-Ericsson
0007  *
0008  * UX500 common part of Power domain regulators
0009  */
0010 
0011 #include <linux/kernel.h>
0012 #include <linux/err.h>
0013 #include <linux/regulator/driver.h>
0014 #include <linux/debugfs.h>
0015 #include <linux/seq_file.h>
0016 #include <linux/slab.h>
0017 #include <linux/module.h>
0018 
0019 #include "dbx500-prcmu.h"
0020 
0021 /*
0022  * power state reference count
0023  */
0024 static int power_state_active_cnt; /* will initialize to zero */
0025 static DEFINE_SPINLOCK(power_state_active_lock);
0026 
0027 void power_state_active_enable(void)
0028 {
0029     unsigned long flags;
0030 
0031     spin_lock_irqsave(&power_state_active_lock, flags);
0032     power_state_active_cnt++;
0033     spin_unlock_irqrestore(&power_state_active_lock, flags);
0034 }
0035 
0036 int power_state_active_disable(void)
0037 {
0038     int ret = 0;
0039     unsigned long flags;
0040 
0041     spin_lock_irqsave(&power_state_active_lock, flags);
0042     if (power_state_active_cnt <= 0) {
0043         pr_err("power state: unbalanced enable/disable calls\n");
0044         ret = -EINVAL;
0045         goto out;
0046     }
0047 
0048     power_state_active_cnt--;
0049 out:
0050     spin_unlock_irqrestore(&power_state_active_lock, flags);
0051     return ret;
0052 }
0053 
0054 #ifdef CONFIG_REGULATOR_DEBUG
0055 
0056 static int power_state_active_get(void)
0057 {
0058     unsigned long flags;
0059     int cnt;
0060 
0061     spin_lock_irqsave(&power_state_active_lock, flags);
0062     cnt = power_state_active_cnt;
0063     spin_unlock_irqrestore(&power_state_active_lock, flags);
0064 
0065     return cnt;
0066 }
0067 
0068 static struct ux500_regulator_debug {
0069     struct dentry *dir;
0070     struct dbx500_regulator_info *regulator_array;
0071     int num_regulators;
0072     u8 *state_before_suspend;
0073     u8 *state_after_suspend;
0074 } rdebug;
0075 
0076 static int ux500_regulator_power_state_cnt_show(struct seq_file *s, void *p)
0077 {
0078     /* print power state count */
0079     seq_printf(s, "ux500-regulator power state count: %i\n",
0080            power_state_active_get());
0081 
0082     return 0;
0083 }
0084 DEFINE_SHOW_ATTRIBUTE(ux500_regulator_power_state_cnt);
0085 
0086 static int ux500_regulator_status_show(struct seq_file *s, void *p)
0087 {
0088     int i;
0089 
0090     /* print dump header */
0091     seq_puts(s, "ux500-regulator status:\n");
0092     seq_printf(s, "%31s : %8s : %8s\n", "current", "before", "after");
0093 
0094     for (i = 0; i < rdebug.num_regulators; i++) {
0095         struct dbx500_regulator_info *info;
0096         /* Access per-regulator data */
0097         info = &rdebug.regulator_array[i];
0098 
0099         /* print status */
0100         seq_printf(s, "%20s : %8s : %8s : %8s\n",
0101                info->desc.name,
0102                info->is_enabled ? "enabled" : "disabled",
0103                rdebug.state_before_suspend[i] ? "enabled" : "disabled",
0104                rdebug.state_after_suspend[i] ? "enabled" : "disabled");
0105     }
0106 
0107     return 0;
0108 }
0109 DEFINE_SHOW_ATTRIBUTE(ux500_regulator_status);
0110 
0111 int
0112 ux500_regulator_debug_init(struct platform_device *pdev,
0113     struct dbx500_regulator_info *regulator_info,
0114     int num_regulators)
0115 {
0116     /* create directory */
0117     rdebug.dir = debugfs_create_dir("ux500-regulator", NULL);
0118 
0119     /* create "status" file */
0120     debugfs_create_file("status", 0444, rdebug.dir, &pdev->dev,
0121                 &ux500_regulator_status_fops);
0122 
0123     /* create "power-state-count" file */
0124     debugfs_create_file("power-state-count", 0444, rdebug.dir,
0125                 &pdev->dev, &ux500_regulator_power_state_cnt_fops);
0126 
0127     rdebug.regulator_array = regulator_info;
0128     rdebug.num_regulators = num_regulators;
0129 
0130     rdebug.state_before_suspend = kzalloc(num_regulators, GFP_KERNEL);
0131     if (!rdebug.state_before_suspend)
0132         goto exit_destroy_power_state;
0133 
0134     rdebug.state_after_suspend = kzalloc(num_regulators, GFP_KERNEL);
0135     if (!rdebug.state_after_suspend)
0136         goto exit_free;
0137 
0138     return 0;
0139 
0140 exit_free:
0141     kfree(rdebug.state_before_suspend);
0142 exit_destroy_power_state:
0143     debugfs_remove_recursive(rdebug.dir);
0144     return -ENOMEM;
0145 }
0146 
0147 int ux500_regulator_debug_exit(void)
0148 {
0149     debugfs_remove_recursive(rdebug.dir);
0150     kfree(rdebug.state_after_suspend);
0151     kfree(rdebug.state_before_suspend);
0152 
0153     return 0;
0154 }
0155 #endif