Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d011411d authored by Feng Tang's avatar Feng Tang Committed by Greg Kroah-Hartman
Browse files

serial: pch_uart: add debugfs hook for register dump



This driver will be use as interfaces for multiple kinds of
devices like Bluetooth/GPS etc, this debug hook will make driver
debugging much easier.

Signed-off-by: default avatarFeng Tang <feng.tang@intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent d3bda529
Loading
Loading
Loading
Loading
+84 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
#include <linux/nmi.h>
#include <linux/delay.h>

#include <linux/debugfs.h>
#include <linux/dmaengine.h>
#include <linux/pch_dma.h>

@@ -144,6 +145,8 @@ enum {
#define PCH_UART_DLL		0x00
#define PCH_UART_DLM		0x01

#define PCH_UART_BRCSR		0x0E

#define PCH_UART_IID_RLS	(PCH_UART_IIR_REI)
#define PCH_UART_IID_RDR	(PCH_UART_IIR_RRI)
#define PCH_UART_IID_RDR_TO	(PCH_UART_IIR_RRI | PCH_UART_IIR_TOI)
@@ -243,6 +246,8 @@ struct eg20t_port {
	int				tx_dma_use;
	void				*rx_buf_virt;
	dma_addr_t			rx_buf_dma;

	struct dentry	*debugfs;
};

/**
@@ -292,6 +297,73 @@ static const int trigger_level_64[4] = { 1, 16, 32, 56 };
static const int trigger_level_16[4] = { 1, 4, 8, 14 };
static const int trigger_level_1[4] = { 1, 1, 1, 1 };

#ifdef CONFIG_DEBUG_FS

#define PCH_REGS_BUFSIZE	1024
static int pch_show_regs_open(struct inode *inode, struct file *file)
{
	file->private_data = inode->i_private;
	return 0;
}

static ssize_t port_show_regs(struct file *file, char __user *user_buf,
				size_t count, loff_t *ppos)
{
	struct eg20t_port *priv = file->private_data;
	char *buf;
	u32 len = 0;
	ssize_t ret;
	unsigned char lcr;

	buf = kzalloc(PCH_REGS_BUFSIZE, GFP_KERNEL);
	if (!buf)
		return 0;

	len += snprintf(buf + len, PCH_REGS_BUFSIZE - len,
			"PCH EG20T port[%d] regs:\n", priv->port.line);

	len += snprintf(buf + len, PCH_REGS_BUFSIZE - len,
			"=================================\n");
	len += snprintf(buf + len, PCH_REGS_BUFSIZE - len,
			"IER: \t0x%02x\n", ioread8(priv->membase + UART_IER));
	len += snprintf(buf + len, PCH_REGS_BUFSIZE - len,
			"IIR: \t0x%02x\n", ioread8(priv->membase + UART_IIR));
	len += snprintf(buf + len, PCH_REGS_BUFSIZE - len,
			"LCR: \t0x%02x\n", ioread8(priv->membase + UART_LCR));
	len += snprintf(buf + len, PCH_REGS_BUFSIZE - len,
			"MCR: \t0x%02x\n", ioread8(priv->membase + UART_MCR));
	len += snprintf(buf + len, PCH_REGS_BUFSIZE - len,
			"LSR: \t0x%02x\n", ioread8(priv->membase + UART_LSR));
	len += snprintf(buf + len, PCH_REGS_BUFSIZE - len,
			"MSR: \t0x%02x\n", ioread8(priv->membase + UART_MSR));
	len += snprintf(buf + len, PCH_REGS_BUFSIZE - len,
			"BRCSR: \t0x%02x\n",
			ioread8(priv->membase + PCH_UART_BRCSR));

	lcr = ioread8(priv->membase + UART_LCR);
	iowrite8(PCH_UART_LCR_DLAB, priv->membase + UART_LCR);
	len += snprintf(buf + len, PCH_REGS_BUFSIZE - len,
			"DLL: \t0x%02x\n", ioread8(priv->membase + UART_DLL));
	len += snprintf(buf + len, PCH_REGS_BUFSIZE - len,
			"DLM: \t0x%02x\n", ioread8(priv->membase + UART_DLM));
	iowrite8(lcr, priv->membase + UART_LCR);

	if (len > PCH_REGS_BUFSIZE)
		len = PCH_REGS_BUFSIZE;

	ret =  simple_read_from_buffer(user_buf, count, ppos, buf, len);
	kfree(buf);
	return ret;
}

static const struct file_operations port_regs_ops = {
	.owner		= THIS_MODULE,
	.open		= pch_show_regs_open,
	.read		= port_show_regs,
	.llseek		= default_llseek,
};
#endif	/* CONFIG_DEBUG_FS */

static void pch_uart_hal_request(struct pci_dev *pdev, int fifosize,
				 int base_baud)
{
@@ -1554,6 +1626,7 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
	int port_type;
	struct pch_uart_driver_data *board;
	const char *board_name;
	char name[32];	/* for debugfs file name */

	board = &drv_dat[id->driver_data];
	port_type = board->port_type;
@@ -1623,6 +1696,12 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
	if (ret < 0)
		goto init_port_hal_free;

#ifdef CONFIG_DEBUG_FS
	snprintf(name, sizeof(name), "uart%d_regs", board->line_no);
	priv->debugfs = debugfs_create_file(name, S_IFREG | S_IRUGO,
				NULL, priv, &port_regs_ops);
#endif

	return priv;

init_port_hal_free:
@@ -1639,6 +1718,11 @@ init_port_alloc_err:

static void pch_uart_exit_port(struct eg20t_port *priv)
{

#ifdef CONFIG_DEBUG_FS
	if (priv->debugfs)
		debugfs_remove(priv->debugfs);
#endif
	uart_remove_one_port(&pch_uart_driver, &priv->port);
	pci_set_drvdata(priv->pdev, NULL);
	free_page((unsigned long)priv->rxbuf.buf);