aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2009-12-11 19:16:32 -0500
committerTony Lindgren <tony@atomide.com>2009-12-11 19:16:32 -0500
commit4b715efccf9547c0d7fe864277526fee3d9b6bba (patch)
tree346705cf6fcb8a8259c7f77e2419ed6068eb60b3
parentca5742bdb58ebb74499731855dccf8f8a858b2e4 (diff)
omap: mux: Add debugfs support for new mux code
Add debugfs support for new mux code Signed-off-by: Tony Lindgren <tony@atomide.com>
-rw-r--r--arch/arm/mach-omap2/mux.c227
1 files changed, 227 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index b082b504de8b..d9684331e080 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -28,6 +28,10 @@
28#include <linux/io.h> 28#include <linux/io.h>
29#include <linux/spinlock.h> 29#include <linux/spinlock.h>
30#include <linux/list.h> 30#include <linux/list.h>
31#include <linux/ctype.h>
32#include <linux/debugfs.h>
33#include <linux/seq_file.h>
34#include <linux/uaccess.h>
31 35
32#include <asm/system.h> 36#include <asm/system.h>
33 37
@@ -44,6 +48,7 @@ struct omap_mux_entry {
44 struct list_head node; 48 struct list_head node;
45}; 49};
46 50
51static unsigned long mux_phys;
47static void __iomem *mux_base; 52static void __iomem *mux_base;
48 53
49static inline u16 omap_mux_read(u16 reg) 54static inline u16 omap_mux_read(u16 reg)
@@ -807,6 +812,225 @@ int __init omap_mux_init_signal(char *muxname, int val)
807 return -ENODEV; 812 return -ENODEV;
808} 813}
809 814
815#ifdef CONFIG_DEBUG_FS
816
817#define OMAP_MUX_MAX_NR_FLAGS 10
818#define OMAP_MUX_TEST_FLAG(val, mask) \
819 if (((val) & (mask)) == (mask)) { \
820 i++; \
821 flags[i] = #mask; \
822 }
823
824/* REVISIT: Add checking for non-optimal mux settings */
825static inline void omap_mux_decode(struct seq_file *s, u16 val)
826{
827 char *flags[OMAP_MUX_MAX_NR_FLAGS];
828 char mode[14];
829 int i = -1;
830
831 sprintf(mode, "OMAP_MUX_MODE%d", val & 0x7);
832 i++;
833 flags[i] = mode;
834
835 OMAP_MUX_TEST_FLAG(val, OMAP_PIN_OFF_WAKEUPENABLE);
836 if (val & OMAP_OFF_EN) {
837 if (!(val & OMAP_OFFOUT_EN)) {
838 if (!(val & OMAP_OFF_PULL_UP)) {
839 OMAP_MUX_TEST_FLAG(val,
840 OMAP_PIN_OFF_INPUT_PULLDOWN);
841 } else {
842 OMAP_MUX_TEST_FLAG(val,
843 OMAP_PIN_OFF_INPUT_PULLUP);
844 }
845 } else {
846 if (!(val & OMAP_OFFOUT_VAL)) {
847 OMAP_MUX_TEST_FLAG(val,
848 OMAP_PIN_OFF_OUTPUT_LOW);
849 } else {
850 OMAP_MUX_TEST_FLAG(val,
851 OMAP_PIN_OFF_OUTPUT_HIGH);
852 }
853 }
854 }
855
856 if (val & OMAP_INPUT_EN) {
857 if (val & OMAP_PULL_ENA) {
858 if (!(val & OMAP_PULL_UP)) {
859 OMAP_MUX_TEST_FLAG(val,
860 OMAP_PIN_INPUT_PULLDOWN);
861 } else {
862 OMAP_MUX_TEST_FLAG(val, OMAP_PIN_INPUT_PULLUP);
863 }
864 } else {
865 OMAP_MUX_TEST_FLAG(val, OMAP_PIN_INPUT);
866 }
867 } else {
868 i++;
869 flags[i] = "OMAP_PIN_OUTPUT";
870 }
871
872 do {
873 seq_printf(s, "%s", flags[i]);
874 if (i > 0)
875 seq_printf(s, " | ");
876 } while (i-- > 0);
877}
878
879#define OMAP_MUX_DEFNAME_LEN 16
880
881static int omap_mux_dbg_board_show(struct seq_file *s, void *unused)
882{
883 struct omap_mux_entry *e;
884
885 list_for_each_entry(e, &muxmodes, node) {
886 struct omap_mux *m = &e->mux;
887 char m0_def[OMAP_MUX_DEFNAME_LEN];
888 char *m0_name = m->muxnames[0];
889 u16 val;
890 int i, mode;
891
892 if (!m0_name)
893 continue;
894
895 for (i = 0; i < OMAP_MUX_DEFNAME_LEN; i++) {
896 if (m0_name[i] == '\0') {
897 m0_def[i] = m0_name[i];
898 break;
899 }
900 m0_def[i] = toupper(m0_name[i]);
901 }
902 val = omap_mux_read(m->reg_offset);
903 mode = val & OMAP_MUX_MODE7;
904
905 seq_printf(s, "OMAP%i_MUX(%s, ",
906 cpu_is_omap34xx() ? 3 : 0, m0_def);
907 omap_mux_decode(s, val);
908 seq_printf(s, "),\n");
909 }
910
911 return 0;
912}
913
914static int omap_mux_dbg_board_open(struct inode *inode, struct file *file)
915{
916 return single_open(file, omap_mux_dbg_board_show, &inode->i_private);
917}
918
919static const struct file_operations omap_mux_dbg_board_fops = {
920 .open = omap_mux_dbg_board_open,
921 .read = seq_read,
922 .llseek = seq_lseek,
923 .release = single_release,
924};
925
926static int omap_mux_dbg_signal_show(struct seq_file *s, void *unused)
927{
928 struct omap_mux *m = s->private;
929 const char *none = "NA";
930 u16 val;
931 int mode;
932
933 val = omap_mux_read(m->reg_offset);
934 mode = val & OMAP_MUX_MODE7;
935
936 seq_printf(s, "name: %s.%s (0x%08lx/0x%03x = 0x%04x), b %s, t %s\n",
937 m->muxnames[0], m->muxnames[mode],
938 mux_phys + m->reg_offset, m->reg_offset, val,
939 m->balls[0] ? m->balls[0] : none,
940 m->balls[1] ? m->balls[1] : none);
941 seq_printf(s, "mode: ");
942 omap_mux_decode(s, val);
943 seq_printf(s, "\n");
944 seq_printf(s, "signals: %s | %s | %s | %s | %s | %s | %s | %s\n",
945 m->muxnames[0] ? m->muxnames[0] : none,
946 m->muxnames[1] ? m->muxnames[1] : none,
947 m->muxnames[2] ? m->muxnames[2] : none,
948 m->muxnames[3] ? m->muxnames[3] : none,
949 m->muxnames[4] ? m->muxnames[4] : none,
950 m->muxnames[5] ? m->muxnames[5] : none,
951 m->muxnames[6] ? m->muxnames[6] : none,
952 m->muxnames[7] ? m->muxnames[7] : none);
953
954 return 0;
955}
956
957#define OMAP_MUX_MAX_ARG_CHAR 7
958
959static ssize_t omap_mux_dbg_signal_write(struct file *file,
960 const char __user *user_buf,
961 size_t count, loff_t *ppos)
962{
963 char buf[OMAP_MUX_MAX_ARG_CHAR];
964 struct seq_file *seqf;
965 struct omap_mux *m;
966 unsigned long val;
967 int buf_size, ret;
968
969 if (count > OMAP_MUX_MAX_ARG_CHAR)
970 return -EINVAL;
971
972 memset(buf, 0, sizeof(buf));
973 buf_size = min(count, sizeof(buf) - 1);
974
975 if (copy_from_user(buf, user_buf, buf_size))
976 return -EFAULT;
977
978 ret = strict_strtoul(buf, 0x10, &val);
979 if (ret < 0)
980 return ret;
981
982 if (val > 0xffff)
983 return -EINVAL;
984
985 seqf = file->private_data;
986 m = seqf->private;
987
988 omap_mux_write((u16)val, m->reg_offset);
989 *ppos += count;
990
991 return count;
992}
993
994static int omap_mux_dbg_signal_open(struct inode *inode, struct file *file)
995{
996 return single_open(file, omap_mux_dbg_signal_show, inode->i_private);
997}
998
999static const struct file_operations omap_mux_dbg_signal_fops = {
1000 .open = omap_mux_dbg_signal_open,
1001 .read = seq_read,
1002 .write = omap_mux_dbg_signal_write,
1003 .llseek = seq_lseek,
1004 .release = single_release,
1005};
1006
1007static struct dentry *mux_dbg_dir;
1008
1009static void __init omap_mux_dbg_init(void)
1010{
1011 struct omap_mux_entry *e;
1012
1013 mux_dbg_dir = debugfs_create_dir("omap_mux", NULL);
1014 if (!mux_dbg_dir)
1015 return;
1016
1017 (void)debugfs_create_file("board", S_IRUGO, mux_dbg_dir,
1018 NULL, &omap_mux_dbg_board_fops);
1019
1020 list_for_each_entry(e, &muxmodes, node) {
1021 struct omap_mux *m = &e->mux;
1022
1023 (void)debugfs_create_file(m->muxnames[0], S_IWUGO, mux_dbg_dir,
1024 m, &omap_mux_dbg_signal_fops);
1025 }
1026}
1027
1028#else
1029static inline void omap_mux_dbg_init(void)
1030{
1031}
1032#endif /* CONFIG_DEBUG_FS */
1033
810static void __init omap_mux_free_names(struct omap_mux *m) 1034static void __init omap_mux_free_names(struct omap_mux *m)
811{ 1035{
812 int i; 1036 int i;
@@ -843,6 +1067,8 @@ static int __init omap_mux_late_init(void)
843 1067
844 } 1068 }
845 1069
1070 omap_mux_dbg_init();
1071
846 return 0; 1072 return 0;
847} 1073}
848late_initcall(omap_mux_late_init); 1074late_initcall(omap_mux_late_init);
@@ -1107,6 +1333,7 @@ int __init omap_mux_init(u32 mux_pbase, u32 mux_size,
1107 if (mux_base) 1333 if (mux_base)
1108 return -EBUSY; 1334 return -EBUSY;
1109 1335
1336 mux_phys = mux_pbase;
1110 mux_base = ioremap(mux_pbase, mux_size); 1337 mux_base = ioremap(mux_pbase, mux_size);
1111 if (!mux_base) { 1338 if (!mux_base) {
1112 printk(KERN_ERR "mux: Could not ioremap\n"); 1339 printk(KERN_ERR "mux: Could not ioremap\n");