mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	There is no need to have the 'struct dentry *dev_state' variable static since new value always be assigned before use it. Signed-off-by: YueHaibing <yuehaibing@huawei.com> Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Cc: Borislav Petkov <bp@alien8.de> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: kernel-janitors@vger.kernel.org Link: http://lkml.kernel.org/r/1539340822-117563-1-git-send-email-yuehaibing@huawei.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
		
			
				
	
	
		
			181 lines
		
	
	
	
		
			4.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			181 lines
		
	
	
	
		
			4.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * Intel SOC Punit device state debug driver
 | 
						|
 * Punit controls power management for North Complex devices (Graphics
 | 
						|
 * blocks, Image Signal Processing, video processing, display, DSP etc.)
 | 
						|
 *
 | 
						|
 * Copyright (c) 2015, Intel Corporation.
 | 
						|
 *
 | 
						|
 * This program is free software; you can redistribute it and/or modify it
 | 
						|
 * under the terms and conditions of the GNU General Public License,
 | 
						|
 * version 2, as published by the Free Software Foundation.
 | 
						|
 *
 | 
						|
 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
						|
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
						|
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
						|
 * more details.
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
#include <linux/module.h>
 | 
						|
#include <linux/init.h>
 | 
						|
#include <linux/device.h>
 | 
						|
#include <linux/debugfs.h>
 | 
						|
#include <linux/seq_file.h>
 | 
						|
#include <linux/io.h>
 | 
						|
#include <asm/cpu_device_id.h>
 | 
						|
#include <asm/intel-family.h>
 | 
						|
#include <asm/iosf_mbi.h>
 | 
						|
 | 
						|
/* Subsystem config/status Video processor */
 | 
						|
#define VED_SS_PM0		0x32
 | 
						|
/* Subsystem config/status ISP (Image Signal Processor) */
 | 
						|
#define ISP_SS_PM0		0x39
 | 
						|
/* Subsystem config/status Input/output controller */
 | 
						|
#define MIO_SS_PM		0x3B
 | 
						|
/* Shift bits for getting status for video, isp and i/o */
 | 
						|
#define SSS_SHIFT		24
 | 
						|
 | 
						|
/* Power gate status reg */
 | 
						|
#define PWRGT_STATUS		0x61
 | 
						|
/* Shift bits for getting status for graphics rendering */
 | 
						|
#define RENDER_POS		0
 | 
						|
/* Shift bits for getting status for media control */
 | 
						|
#define MEDIA_POS		2
 | 
						|
/* Shift bits for getting status for Valley View/Baytrail display */
 | 
						|
#define VLV_DISPLAY_POS		6
 | 
						|
 | 
						|
/* Subsystem config/status display for Cherry Trail SOC */
 | 
						|
#define CHT_DSP_SSS		0x36
 | 
						|
/* Shift bits for getting status for display */
 | 
						|
#define CHT_DSP_SSS_POS		16
 | 
						|
 | 
						|
struct punit_device {
 | 
						|
	char *name;
 | 
						|
	int reg;
 | 
						|
	int sss_pos;
 | 
						|
};
 | 
						|
 | 
						|
static const struct punit_device punit_device_tng[] = {
 | 
						|
	{ "DISPLAY",	CHT_DSP_SSS,	SSS_SHIFT },
 | 
						|
	{ "VED",	VED_SS_PM0,	SSS_SHIFT },
 | 
						|
	{ "ISP",	ISP_SS_PM0,	SSS_SHIFT },
 | 
						|
	{ "MIO",	MIO_SS_PM,	SSS_SHIFT },
 | 
						|
	{ NULL }
 | 
						|
};
 | 
						|
 | 
						|
static const struct punit_device punit_device_byt[] = {
 | 
						|
	{ "GFX RENDER",	PWRGT_STATUS,	RENDER_POS },
 | 
						|
	{ "GFX MEDIA",	PWRGT_STATUS,	MEDIA_POS },
 | 
						|
	{ "DISPLAY",	PWRGT_STATUS,	VLV_DISPLAY_POS },
 | 
						|
	{ "VED",	VED_SS_PM0,	SSS_SHIFT },
 | 
						|
	{ "ISP",	ISP_SS_PM0,	SSS_SHIFT },
 | 
						|
	{ "MIO",	MIO_SS_PM,	SSS_SHIFT },
 | 
						|
	{ NULL }
 | 
						|
};
 | 
						|
 | 
						|
static const struct punit_device punit_device_cht[] = {
 | 
						|
	{ "GFX RENDER",	PWRGT_STATUS,	RENDER_POS },
 | 
						|
	{ "GFX MEDIA",	PWRGT_STATUS,	MEDIA_POS },
 | 
						|
	{ "DISPLAY",	CHT_DSP_SSS,	CHT_DSP_SSS_POS },
 | 
						|
	{ "VED",	VED_SS_PM0,	SSS_SHIFT },
 | 
						|
	{ "ISP",	ISP_SS_PM0,	SSS_SHIFT },
 | 
						|
	{ "MIO",	MIO_SS_PM,	SSS_SHIFT },
 | 
						|
	{ NULL }
 | 
						|
};
 | 
						|
 | 
						|
static const char * const dstates[] = {"D0", "D0i1", "D0i2", "D0i3"};
 | 
						|
 | 
						|
static int punit_dev_state_show(struct seq_file *seq_file, void *unused)
 | 
						|
{
 | 
						|
	u32 punit_pwr_status;
 | 
						|
	struct punit_device *punit_devp = seq_file->private;
 | 
						|
	int index;
 | 
						|
	int status;
 | 
						|
 | 
						|
	seq_puts(seq_file, "\n\nPUNIT NORTH COMPLEX DEVICES :\n");
 | 
						|
	while (punit_devp->name) {
 | 
						|
		status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
 | 
						|
				       punit_devp->reg, &punit_pwr_status);
 | 
						|
		if (status) {
 | 
						|
			seq_printf(seq_file, "%9s : Read Failed\n",
 | 
						|
				   punit_devp->name);
 | 
						|
		} else  {
 | 
						|
			index = (punit_pwr_status >> punit_devp->sss_pos) & 3;
 | 
						|
			seq_printf(seq_file, "%9s : %s\n", punit_devp->name,
 | 
						|
				   dstates[index]);
 | 
						|
		}
 | 
						|
		punit_devp++;
 | 
						|
	}
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
DEFINE_SHOW_ATTRIBUTE(punit_dev_state);
 | 
						|
 | 
						|
static struct dentry *punit_dbg_file;
 | 
						|
 | 
						|
static int punit_dbgfs_register(struct punit_device *punit_device)
 | 
						|
{
 | 
						|
	struct dentry *dev_state;
 | 
						|
 | 
						|
	punit_dbg_file = debugfs_create_dir("punit_atom", NULL);
 | 
						|
	if (!punit_dbg_file)
 | 
						|
		return -ENXIO;
 | 
						|
 | 
						|
	dev_state = debugfs_create_file("dev_power_state", 0444,
 | 
						|
					punit_dbg_file, punit_device,
 | 
						|
					&punit_dev_state_fops);
 | 
						|
	if (!dev_state) {
 | 
						|
		pr_err("punit_dev_state register failed\n");
 | 
						|
		debugfs_remove(punit_dbg_file);
 | 
						|
		return -ENXIO;
 | 
						|
	}
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
static void punit_dbgfs_unregister(void)
 | 
						|
{
 | 
						|
	debugfs_remove_recursive(punit_dbg_file);
 | 
						|
}
 | 
						|
 | 
						|
#define ICPU(model, drv_data) \
 | 
						|
	{ X86_VENDOR_INTEL, 6, model, X86_FEATURE_MWAIT,\
 | 
						|
	  (kernel_ulong_t)&drv_data }
 | 
						|
 | 
						|
static const struct x86_cpu_id intel_punit_cpu_ids[] = {
 | 
						|
	ICPU(INTEL_FAM6_ATOM_SILVERMONT, punit_device_byt),
 | 
						|
	ICPU(INTEL_FAM6_ATOM_SILVERMONT_MID,  punit_device_tng),
 | 
						|
	ICPU(INTEL_FAM6_ATOM_AIRMONT,	  punit_device_cht),
 | 
						|
	{}
 | 
						|
};
 | 
						|
 | 
						|
MODULE_DEVICE_TABLE(x86cpu, intel_punit_cpu_ids);
 | 
						|
 | 
						|
static int __init punit_atom_debug_init(void)
 | 
						|
{
 | 
						|
	const struct x86_cpu_id *id;
 | 
						|
	int ret;
 | 
						|
 | 
						|
	id = x86_match_cpu(intel_punit_cpu_ids);
 | 
						|
	if (!id)
 | 
						|
		return -ENODEV;
 | 
						|
 | 
						|
	ret = punit_dbgfs_register((struct punit_device *)id->driver_data);
 | 
						|
	if (ret < 0)
 | 
						|
		return ret;
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
static void __exit punit_atom_debug_exit(void)
 | 
						|
{
 | 
						|
	punit_dbgfs_unregister();
 | 
						|
}
 | 
						|
 | 
						|
module_init(punit_atom_debug_init);
 | 
						|
module_exit(punit_atom_debug_exit);
 | 
						|
 | 
						|
MODULE_AUTHOR("Kumar P, Mahesh <mahesh.kumar.p@intel.com>");
 | 
						|
MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
 | 
						|
MODULE_DESCRIPTION("Driver for Punit devices states debugging");
 | 
						|
MODULE_LICENSE("GPL v2");
 |