Maemo patchset 20101501+0m5
[h-e-n] / drivers / misc / ssi / ssi_driver_debugfs.c
diff --git a/drivers/misc/ssi/ssi_driver_debugfs.c b/drivers/misc/ssi/ssi_driver_debugfs.c
new file mode 100644 (file)
index 0000000..4ae04bc
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * ssi_driver_debugfs.c
+ *
+ * Implements SSI debugfs.
+ *
+ * Copyright (C) 2007-2008 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Carlos Chinea <carlos.chinea@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+#include <linux/debugfs.h>
+#include "ssi_driver.h"
+
+#define SSI_DIR_NAME_SIZE      64
+
+static struct dentry *ssi_dir;
+
+static int ssi_debug_show(struct seq_file *m, void *p)
+{
+       struct ssi_dev *ssi_ctrl = m->private;
+
+       clk_enable(ssi_ctrl->ssi_clk);
+
+       seq_printf(m, "REVISION\t: 0x%08x\n",
+                               ssi_inl(ssi_ctrl->base, SSI_SYS_REVISION_REG));
+       seq_printf(m, "SYSCONFIG\t: 0x%08x\n",
+                               ssi_inl(ssi_ctrl->base, SSI_SYS_SYSCONFIG_REG));
+       seq_printf(m, "SYSSTATUS\t: 0x%08x\n",
+                               ssi_inl(ssi_ctrl->base, SSI_SYS_SYSSTATUS_REG));
+
+       clk_disable(ssi_ctrl->ssi_clk);
+       return 0;
+}
+
+static int ssi_debug_port_show(struct seq_file *m, void *p)
+{
+       struct ssi_port *ssi_port = m->private;
+       struct ssi_dev *ssi_ctrl = ssi_port->ssi_controller;
+       void __iomem *base = ssi_ctrl->base;
+       unsigned int port = ssi_port->port_number;
+       int ch;
+
+       clk_enable(ssi_ctrl->ssi_clk);
+
+       if (ssi_port->cawake_gpio >= 0)
+               seq_printf(m, "CAWAKE\t\t: %d\n", ssi_cawake(ssi_port));
+
+       seq_printf(m, "WAKE\t\t: 0x%08x\n",
+                                       ssi_inl(base, SSI_SYS_WAKE_REG(port)));
+       seq_printf(m, "MPU_ENABLE_IRQ%d\t: 0x%08x\n", ssi_port->n_irq,
+               ssi_inl(base, SSI_SYS_MPU_ENABLE_REG(port, ssi_port->n_irq)));
+       seq_printf(m, "MPU_STATUS_IRQ%d\t: 0x%08x\n", ssi_port->n_irq,
+               ssi_inl(base, SSI_SYS_MPU_STATUS_REG(port, ssi_port->n_irq)));
+       /* SST */
+       seq_printf(m, "\nSST\n===\n");
+       seq_printf(m, "MODE\t\t: 0x%08x\n",
+                                       ssi_inl(base, SSI_SST_MODE_REG(port)));
+       seq_printf(m, "FRAMESIZE\t: 0x%08x\n",
+                               ssi_inl(base, SSI_SST_FRAMESIZE_REG(port)));
+       seq_printf(m, "DIVISOR\t\t: 0x%08x\n",
+                               ssi_inl(base, SSI_SST_DIVISOR_REG(port)));
+       seq_printf(m, "CHANNELS\t: 0x%08x\n",
+                               ssi_inl(base, SSI_SST_CHANNELS_REG(port)));
+       seq_printf(m, "ARBMODE\t\t: 0x%08x\n",
+                               ssi_inl(base, SSI_SST_ARBMODE_REG(port)));
+       seq_printf(m, "TXSTATE\t\t: 0x%08x\n",
+                               ssi_inl(base, SSI_SST_TXSTATE_REG(port)));
+       seq_printf(m, "BUFSTATE\t: 0x%08x\n",
+                               ssi_inl(base, SSI_SST_BUFSTATE_REG(port)));
+       seq_printf(m, "BREAK\t\t: 0x%08x\n",
+                               ssi_inl(base, SSI_SST_BREAK_REG(port)));
+       for (ch = 0; ch < ssi_port->max_ch; ch++) {
+               seq_printf(m, "BUFFER_CH%d\t: 0x%08x\n", ch,
+                               ssi_inl(base, SSI_SST_BUFFER_CH_REG(port, ch)));
+       }
+       /* SSR */
+       seq_printf(m, "\nSSR\n===\n");
+       seq_printf(m, "MODE\t\t: 0x%08x\n",
+                                       ssi_inl(base, SSI_SSR_MODE_REG(port)));
+       seq_printf(m, "FRAMESIZE\t: 0x%08x\n",
+                               ssi_inl(base, SSI_SSR_FRAMESIZE_REG(port)));
+       seq_printf(m, "CHANNELS\t: 0x%08x\n",
+                               ssi_inl(base, SSI_SSR_CHANNELS_REG(port)));
+       seq_printf(m, "TIMEOUT\t\t: 0x%08x\n",
+                               ssi_inl(base, SSI_SSR_TIMEOUT_REG(port)));
+       seq_printf(m, "RXSTATE\t\t: 0x%08x\n",
+                               ssi_inl(base, SSI_SSR_RXSTATE_REG(port)));
+       seq_printf(m, "BUFSTATE\t: 0x%08x\n",
+                               ssi_inl(base, SSI_SSR_BUFSTATE_REG(port)));
+       seq_printf(m, "BREAK\t\t: 0x%08x\n",
+                               ssi_inl(base, SSI_SSR_BREAK_REG(port)));
+       seq_printf(m, "ERROR\t\t: 0x%08x\n",
+                               ssi_inl(base, SSI_SSR_ERROR_REG(port)));
+       seq_printf(m, "ERRORACK\t: 0x%08x\n",
+                               ssi_inl(base, SSI_SSR_ERRORACK_REG(port)));
+       for (ch = 0; ch < ssi_port->max_ch; ch++) {
+               seq_printf(m, "BUFFER_CH%d\t: 0x%08x\n", ch,
+                               ssi_inl(base, SSI_SSR_BUFFER_CH_REG(port, ch)));
+       }
+       clk_disable(ssi_ctrl->ssi_clk);
+       return 0;
+}
+
+static int ssi_debug_gdd_show(struct seq_file *m, void *p)
+{
+       struct ssi_dev *ssi_ctrl = m->private;
+       void __iomem *base = ssi_ctrl->base;
+       int lch;
+
+       clk_enable(ssi_ctrl->ssi_clk);
+
+       seq_printf(m, "GDD_MPU_STATUS\t: 0x%08x\n",
+                               ssi_inl(base, SSI_SYS_GDD_MPU_IRQ_STATUS_REG));
+       seq_printf(m, "GDD_MPU_ENABLE\t: 0x%08x\n\n",
+                               ssi_inl(base, SSI_SYS_GDD_MPU_IRQ_ENABLE_REG));
+
+       seq_printf(m, "HW_ID\t\t: 0x%08x\n", ssi_inl(base, SSI_GDD_HW_ID_REG));
+       seq_printf(m, "PPORT_ID\t: 0x%08x\n",
+                                       ssi_inl(base, SSI_GDD_PPORT_ID_REG));
+       seq_printf(m, "MPORT_ID\t: 0x%08x\n",
+                                       ssi_inl(base, SSI_GDD_MPORT_ID_REG));
+       seq_printf(m, "TEST\t\t: 0x%08x\n", ssi_inl(base, SSI_GDD_TEST_REG));
+       seq_printf(m, "GCR\t\t: 0x%08x\n", ssi_inl(base, SSI_GDD_GCR_REG));
+
+       for (lch = 0; lch < SSI_NUM_LCH; lch++) {
+               seq_printf(m, "\nGDD LCH %d\n=========\n", lch);
+               seq_printf(m, "CSDP\t\t: 0x%04x\n",
+                                       ssi_inw(base, SSI_GDD_CSDP_REG(lch)));
+               seq_printf(m, "CCR\t\t: 0x%04x\n",
+                                       ssi_inw(base, SSI_GDD_CCR_REG(lch)));
+               seq_printf(m, "CICR\t\t: 0x%04x\n",
+                                       ssi_inw(base, SSI_GDD_CICR_REG(lch)));
+               seq_printf(m, "CSR\t\t: 0x%04x\n",
+                                       ssi_inw(base, SSI_GDD_CSR_REG(lch)));
+               seq_printf(m, "CSSA\t\t: 0x%08x\n",
+                                       ssi_inl(base, SSI_GDD_CSSA_REG(lch)));
+               seq_printf(m, "CDSA\t\t: 0x%08x\n",
+                                       ssi_inl(base, SSI_GDD_CDSA_REG(lch)));
+               seq_printf(m, "CEN\t\t: 0x%04x\n",
+                                       ssi_inw(base, SSI_GDD_CEN_REG(lch)));
+               seq_printf(m, "CSAC\t\t: 0x%04x\n",
+                                       ssi_inw(base, SSI_GDD_CSAC_REG(lch)));
+               seq_printf(m, "CDAC\t\t: 0x%04x\n",
+                                       ssi_inw(base, SSI_GDD_CDAC_REG(lch)));
+               seq_printf(m, "CLNK_CTRL\t: 0x%04x\n",
+                               ssi_inw(base, SSI_GDD_CLNK_CTRL_REG(lch)));
+       }
+
+       clk_disable(ssi_ctrl->ssi_clk);
+       return 0;
+}
+
+static int ssi_regs_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, ssi_debug_show, inode->i_private);
+}
+
+static int ssi_port_regs_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, ssi_debug_port_show, inode->i_private);
+}
+
+static int ssi_gdd_regs_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, ssi_debug_gdd_show, inode->i_private);
+}
+
+static const struct file_operations ssi_regs_fops = {
+       .open           = ssi_regs_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static const struct file_operations ssi_port_regs_fops = {
+       .open           = ssi_port_regs_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static const struct file_operations ssi_gdd_regs_fops = {
+       .open           = ssi_gdd_regs_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+int __init ssi_debug_add_ctrl(struct ssi_dev *ssi_ctrl)
+{
+       struct platform_device *pdev = to_platform_device(ssi_ctrl->dev);
+       unsigned char dir_name[SSI_DIR_NAME_SIZE];
+       struct dentry *dir;
+       unsigned int port;
+
+       if (pdev->id < 0) {
+               ssi_ctrl->dir = debugfs_create_dir(pdev->name, ssi_dir);
+       } else {
+               snprintf(dir_name, sizeof(dir_name), "%s%d", pdev->name,
+                                                               pdev->id);
+               ssi_ctrl->dir = debugfs_create_dir(dir_name, ssi_dir);
+       }
+       if (IS_ERR(ssi_ctrl->dir))
+               return PTR_ERR(ssi_ctrl->dir);
+
+       debugfs_create_file("regs", S_IRUGO, ssi_ctrl->dir, ssi_ctrl,
+                                                               &ssi_regs_fops);
+
+       for (port = 0; port < ssi_ctrl->max_p; port++) {
+               snprintf(dir_name, sizeof(dir_name), "port%d", port + 1);
+               dir = debugfs_create_dir(dir_name, ssi_ctrl->dir);
+               if (IS_ERR(dir))
+                       goto rback;
+               debugfs_create_file("regs", S_IRUGO, dir,
+                               &ssi_ctrl->ssi_port[port], &ssi_port_regs_fops);
+       }
+
+       dir = debugfs_create_dir("gdd", ssi_ctrl->dir);
+       if (IS_ERR(dir))
+               goto rback;
+       debugfs_create_file("regs", S_IRUGO, dir, ssi_ctrl, &ssi_gdd_regs_fops);
+
+       return 0;
+rback:
+       debugfs_remove_recursive(ssi_ctrl->dir);
+       return PTR_ERR(dir);
+}
+
+void ssi_debug_remove_ctrl(struct ssi_dev *ssi_ctrl)
+{
+       debugfs_remove_recursive(ssi_ctrl->dir);
+}
+
+int __init ssi_debug_init(void)
+{
+       ssi_dir = debugfs_create_dir("ssi", NULL);
+       if (IS_ERR(ssi_dir))
+               return PTR_ERR(ssi_dir);
+
+       return 0;
+}
+
+void ssi_debug_exit(void)
+{
+       debugfs_remove_recursive(ssi_dir);
+}