|
@@ -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);
|