diff options
author | Tony Lindgren <tony@atomide.com> | 2009-12-11 19:16:32 -0500 |
---|---|---|
committer | Tony Lindgren <tony@atomide.com> | 2009-12-11 19:16:32 -0500 |
commit | 15ac7afe515631ec36966b1cf632a87276536f57 (patch) | |
tree | 68fae5c0154ccf441468569c0d763b32c3b90f21 | |
parent | 92c9f5018997dbc5f5e91eae2400d78ada2760b0 (diff) |
omap: mux: Add new style pin multiplexing code for omap3
Initially only for 34xx. This code allows us to:
- Make the code more generic as the omap internal signal
names can stay the same across omap generations for some
devices
- Map mux registers to GPIO registers that is needed for
dynamic muxing of pins during off-idle
- Override bootloader mux values via kernel cmdline using
omap_mux=some.signa1=0x1234,some.signal2=0x1234
- View and set the mux registers via debugfs if
CONFIG_DEBUG_FS is enabled
Cc: Mike Rapoport <mike@compulab.co.il>
Cc: Benoit Cousson <b-cousson@ti.com>
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
-rw-r--r-- | Documentation/kernel-parameters.txt | 5 | ||||
-rw-r--r-- | arch/arm/mach-omap2/mux.c | 444 | ||||
-rw-r--r-- | arch/arm/mach-omap2/mux.h | 160 | ||||
-rw-r--r-- | arch/arm/plat-omap/mux.c | 8 |
4 files changed, 611 insertions, 6 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 777dc8a32df8..4f62fcbce108 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -1787,6 +1787,11 @@ and is between 256 and 4096 characters. It is defined in the file | |||
1787 | waiting for the ACK, so if this is set too high | 1787 | waiting for the ACK, so if this is set too high |
1788 | interrupts *may* be lost! | 1788 | interrupts *may* be lost! |
1789 | 1789 | ||
1790 | omap_mux= [OMAP] Override bootloader pin multiplexing. | ||
1791 | Format: <mux_mode0.mode_name=value>... | ||
1792 | For example, to override I2C bus2: | ||
1793 | omap_mux=i2c2_scl.i2c2_scl=0x100,i2c2_sda.i2c2_sda=0x100 | ||
1794 | |||
1790 | opl3= [HW,OSS] | 1795 | opl3= [HW,OSS] |
1791 | Format: <io> | 1796 | Format: <io> |
1792 | 1797 | ||
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c index 64250c504c64..b082b504de8b 100644 --- a/arch/arm/mach-omap2/mux.c +++ b/arch/arm/mach-omap2/mux.c | |||
@@ -27,18 +27,23 @@ | |||
27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
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 | 31 | ||
31 | #include <asm/system.h> | 32 | #include <asm/system.h> |
32 | 33 | ||
33 | #include <plat/control.h> | 34 | #include <plat/control.h> |
34 | #include <plat/mux.h> | 35 | #include <plat/mux.h> |
35 | 36 | ||
36 | #ifdef CONFIG_OMAP_MUX | 37 | #include "mux.h" |
37 | 38 | ||
38 | #define OMAP_MUX_BASE_OFFSET 0x30 /* Offset from CTRL_BASE */ | 39 | #define OMAP_MUX_BASE_OFFSET 0x30 /* Offset from CTRL_BASE */ |
39 | #define OMAP_MUX_BASE_SZ 0x5ca | 40 | #define OMAP_MUX_BASE_SZ 0x5ca |
40 | 41 | ||
41 | static struct omap_mux_cfg arch_mux_cfg; | 42 | struct omap_mux_entry { |
43 | struct omap_mux mux; | ||
44 | struct list_head node; | ||
45 | }; | ||
46 | |||
42 | static void __iomem *mux_base; | 47 | static void __iomem *mux_base; |
43 | 48 | ||
44 | static inline u16 omap_mux_read(u16 reg) | 49 | static inline u16 omap_mux_read(u16 reg) |
@@ -57,6 +62,10 @@ static inline void omap_mux_write(u16 val, u16 reg) | |||
57 | __raw_writew(val, mux_base + reg); | 62 | __raw_writew(val, mux_base + reg); |
58 | } | 63 | } |
59 | 64 | ||
65 | #ifdef CONFIG_OMAP_MUX | ||
66 | |||
67 | static struct omap_mux_cfg arch_mux_cfg; | ||
68 | |||
60 | /* NOTE: See mux.h for the enumeration */ | 69 | /* NOTE: See mux.h for the enumeration */ |
61 | 70 | ||
62 | #ifdef CONFIG_ARCH_OMAP24XX | 71 | #ifdef CONFIG_ARCH_OMAP24XX |
@@ -667,8 +676,8 @@ int __init omap2_mux_init(void) | |||
667 | mux_pbase = OMAP2420_CTRL_BASE + OMAP_MUX_BASE_OFFSET; | 676 | mux_pbase = OMAP2420_CTRL_BASE + OMAP_MUX_BASE_OFFSET; |
668 | else if (cpu_is_omap2430()) | 677 | else if (cpu_is_omap2430()) |
669 | mux_pbase = OMAP243X_CTRL_BASE + OMAP_MUX_BASE_OFFSET; | 678 | mux_pbase = OMAP243X_CTRL_BASE + OMAP_MUX_BASE_OFFSET; |
670 | else if (cpu_is_omap34xx()) | 679 | else |
671 | mux_pbase = OMAP343X_CTRL_BASE + OMAP_MUX_BASE_OFFSET; | 680 | return -ENODEV; |
672 | 681 | ||
673 | mux_base = ioremap(mux_pbase, OMAP_MUX_BASE_SZ); | 682 | mux_base = ioremap(mux_pbase, OMAP_MUX_BASE_SZ); |
674 | if (!mux_base) { | 683 | if (!mux_base) { |
@@ -689,4 +698,431 @@ int __init omap2_mux_init(void) | |||
689 | return omap_mux_register(&arch_mux_cfg); | 698 | return omap_mux_register(&arch_mux_cfg); |
690 | } | 699 | } |
691 | 700 | ||
701 | #endif /* CONFIG_OMAP_MUX */ | ||
702 | |||
703 | /*----------------------------------------------------------------------------*/ | ||
704 | |||
705 | #ifdef CONFIG_ARCH_OMAP34XX | ||
706 | |||
707 | static LIST_HEAD(muxmodes); | ||
708 | static DEFINE_MUTEX(muxmode_mutex); | ||
709 | |||
710 | #ifdef CONFIG_OMAP_MUX | ||
711 | |||
712 | static char *omap_mux_options; | ||
713 | |||
714 | int __init omap_mux_init_gpio(int gpio, int val) | ||
715 | { | ||
716 | struct omap_mux_entry *e; | ||
717 | int found = 0; | ||
718 | |||
719 | if (!gpio) | ||
720 | return -EINVAL; | ||
721 | |||
722 | list_for_each_entry(e, &muxmodes, node) { | ||
723 | struct omap_mux *m = &e->mux; | ||
724 | if (gpio == m->gpio) { | ||
725 | u16 old_mode; | ||
726 | u16 mux_mode; | ||
727 | |||
728 | old_mode = omap_mux_read(m->reg_offset); | ||
729 | mux_mode = val & ~(OMAP_MUX_NR_MODES - 1); | ||
730 | mux_mode |= OMAP_MUX_MODE4; | ||
731 | printk(KERN_DEBUG "mux: Setting signal " | ||
732 | "%s.gpio%i 0x%04x -> 0x%04x\n", | ||
733 | m->muxnames[0], gpio, old_mode, mux_mode); | ||
734 | omap_mux_write(mux_mode, m->reg_offset); | ||
735 | found++; | ||
736 | } | ||
737 | } | ||
738 | |||
739 | if (found == 1) | ||
740 | return 0; | ||
741 | |||
742 | if (found > 1) { | ||
743 | printk(KERN_ERR "mux: Multiple gpio paths for gpio%i\n", gpio); | ||
744 | return -EINVAL; | ||
745 | } | ||
746 | |||
747 | printk(KERN_ERR "mux: Could not set gpio%i\n", gpio); | ||
748 | |||
749 | return -ENODEV; | ||
750 | } | ||
751 | |||
752 | int __init omap_mux_init_signal(char *muxname, int val) | ||
753 | { | ||
754 | struct omap_mux_entry *e; | ||
755 | char *m0_name = NULL, *mode_name = NULL; | ||
756 | int found = 0; | ||
757 | |||
758 | mode_name = strchr(muxname, '.'); | ||
759 | if (mode_name) { | ||
760 | *mode_name = '\0'; | ||
761 | mode_name++; | ||
762 | m0_name = muxname; | ||
763 | } else { | ||
764 | mode_name = muxname; | ||
765 | } | ||
766 | |||
767 | list_for_each_entry(e, &muxmodes, node) { | ||
768 | struct omap_mux *m = &e->mux; | ||
769 | char *m0_entry = m->muxnames[0]; | ||
770 | int i; | ||
771 | |||
772 | if (m0_name && strcmp(m0_name, m0_entry)) | ||
773 | continue; | ||
774 | |||
775 | for (i = 0; i < OMAP_MUX_NR_MODES; i++) { | ||
776 | char *mode_cur = m->muxnames[i]; | ||
777 | |||
778 | if (!mode_cur) | ||
779 | continue; | ||
780 | |||
781 | if (!strcmp(mode_name, mode_cur)) { | ||
782 | u16 old_mode; | ||
783 | u16 mux_mode; | ||
784 | |||
785 | old_mode = omap_mux_read(m->reg_offset); | ||
786 | mux_mode = val | i; | ||
787 | printk(KERN_DEBUG "mux: Setting signal " | ||
788 | "%s.%s 0x%04x -> 0x%04x\n", | ||
789 | m0_entry, muxname, old_mode, mux_mode); | ||
790 | omap_mux_write(mux_mode, m->reg_offset); | ||
791 | found++; | ||
792 | } | ||
793 | } | ||
794 | } | ||
795 | |||
796 | if (found == 1) | ||
797 | return 0; | ||
798 | |||
799 | if (found > 1) { | ||
800 | printk(KERN_ERR "mux: Multiple signal paths (%i) for %s\n", | ||
801 | found, muxname); | ||
802 | return -EINVAL; | ||
803 | } | ||
804 | |||
805 | printk(KERN_ERR "mux: Could not set signal %s\n", muxname); | ||
806 | |||
807 | return -ENODEV; | ||
808 | } | ||
809 | |||
810 | static void __init omap_mux_free_names(struct omap_mux *m) | ||
811 | { | ||
812 | int i; | ||
813 | |||
814 | for (i = 0; i < OMAP_MUX_NR_MODES; i++) | ||
815 | kfree(m->muxnames[i]); | ||
816 | |||
817 | #ifdef CONFIG_DEBUG_FS | ||
818 | for (i = 0; i < OMAP_MUX_NR_SIDES; i++) | ||
819 | kfree(m->balls[i]); | ||
820 | #endif | ||
821 | |||
822 | } | ||
823 | |||
824 | /* Free all data except for GPIO pins unless CONFIG_DEBUG_FS is set */ | ||
825 | static int __init omap_mux_late_init(void) | ||
826 | { | ||
827 | struct omap_mux_entry *e, *tmp; | ||
828 | |||
829 | list_for_each_entry_safe(e, tmp, &muxmodes, node) { | ||
830 | struct omap_mux *m = &e->mux; | ||
831 | u16 mode = omap_mux_read(m->reg_offset); | ||
832 | |||
833 | if (OMAP_MODE_GPIO(mode)) | ||
834 | continue; | ||
835 | |||
836 | #ifndef CONFIG_DEBUG_FS | ||
837 | mutex_lock(&muxmode_mutex); | ||
838 | list_del(&e->node); | ||
839 | mutex_unlock(&muxmode_mutex); | ||
840 | omap_mux_free_names(m); | ||
841 | kfree(m); | ||
692 | #endif | 842 | #endif |
843 | |||
844 | } | ||
845 | |||
846 | return 0; | ||
847 | } | ||
848 | late_initcall(omap_mux_late_init); | ||
849 | |||
850 | static void __init omap_mux_package_fixup(struct omap_mux *p, | ||
851 | struct omap_mux *superset) | ||
852 | { | ||
853 | while (p->reg_offset != OMAP_MUX_TERMINATOR) { | ||
854 | struct omap_mux *s = superset; | ||
855 | int found = 0; | ||
856 | |||
857 | while (s->reg_offset != OMAP_MUX_TERMINATOR) { | ||
858 | if (s->reg_offset == p->reg_offset) { | ||
859 | *s = *p; | ||
860 | found++; | ||
861 | break; | ||
862 | } | ||
863 | s++; | ||
864 | } | ||
865 | if (!found) | ||
866 | printk(KERN_ERR "mux: Unknown entry offset 0x%x\n", | ||
867 | p->reg_offset); | ||
868 | p++; | ||
869 | } | ||
870 | } | ||
871 | |||
872 | #ifdef CONFIG_DEBUG_FS | ||
873 | |||
874 | static void __init omap_mux_package_init_balls(struct omap_ball *b, | ||
875 | struct omap_mux *superset) | ||
876 | { | ||
877 | while (b->reg_offset != OMAP_MUX_TERMINATOR) { | ||
878 | struct omap_mux *s = superset; | ||
879 | int found = 0; | ||
880 | |||
881 | while (s->reg_offset != OMAP_MUX_TERMINATOR) { | ||
882 | if (s->reg_offset == b->reg_offset) { | ||
883 | s->balls[0] = b->balls[0]; | ||
884 | s->balls[1] = b->balls[1]; | ||
885 | found++; | ||
886 | break; | ||
887 | } | ||
888 | s++; | ||
889 | } | ||
890 | if (!found) | ||
891 | printk(KERN_ERR "mux: Unknown ball offset 0x%x\n", | ||
892 | b->reg_offset); | ||
893 | b++; | ||
894 | } | ||
895 | } | ||
896 | |||
897 | #else /* CONFIG_DEBUG_FS */ | ||
898 | |||
899 | static inline void omap_mux_package_init_balls(struct omap_ball *b, | ||
900 | struct omap_mux *superset) | ||
901 | { | ||
902 | } | ||
903 | |||
904 | #endif /* CONFIG_DEBUG_FS */ | ||
905 | |||
906 | static int __init omap_mux_setup(char *options) | ||
907 | { | ||
908 | if (!options) | ||
909 | return 0; | ||
910 | |||
911 | omap_mux_options = options; | ||
912 | |||
913 | return 1; | ||
914 | } | ||
915 | __setup("omap_mux=", omap_mux_setup); | ||
916 | |||
917 | /* | ||
918 | * Note that the omap_mux=some.signal1=0x1234,some.signal2=0x1234 | ||
919 | * cmdline options only override the bootloader values. | ||
920 | * During development, please enable CONFIG_DEBUG_FS, and use the | ||
921 | * signal specific entries under debugfs. | ||
922 | */ | ||
923 | static void __init omap_mux_set_cmdline_signals(void) | ||
924 | { | ||
925 | char *options, *next_opt, *token; | ||
926 | |||
927 | if (!omap_mux_options) | ||
928 | return; | ||
929 | |||
930 | options = kmalloc(strlen(omap_mux_options) + 1, GFP_KERNEL); | ||
931 | if (!options) | ||
932 | return; | ||
933 | |||
934 | strcpy(options, omap_mux_options); | ||
935 | next_opt = options; | ||
936 | |||
937 | while ((token = strsep(&next_opt, ",")) != NULL) { | ||
938 | char *keyval, *name; | ||
939 | unsigned long val; | ||
940 | |||
941 | keyval = token; | ||
942 | name = strsep(&keyval, "="); | ||
943 | if (name) { | ||
944 | int res; | ||
945 | |||
946 | res = strict_strtoul(keyval, 0x10, &val); | ||
947 | if (res < 0) | ||
948 | continue; | ||
949 | |||
950 | omap_mux_init_signal(name, (u16)val); | ||
951 | } | ||
952 | } | ||
953 | |||
954 | kfree(options); | ||
955 | } | ||
956 | |||
957 | static void __init omap_mux_set_board_signals(struct omap_board_mux *board_mux) | ||
958 | { | ||
959 | while (board_mux->reg_offset != OMAP_MUX_TERMINATOR) { | ||
960 | omap_mux_write(board_mux->value, board_mux->reg_offset); | ||
961 | board_mux++; | ||
962 | } | ||
963 | } | ||
964 | |||
965 | static int __init omap_mux_copy_names(struct omap_mux *src, | ||
966 | struct omap_mux *dst) | ||
967 | { | ||
968 | int i; | ||
969 | |||
970 | for (i = 0; i < OMAP_MUX_NR_MODES; i++) { | ||
971 | if (src->muxnames[i]) { | ||
972 | dst->muxnames[i] = | ||
973 | kmalloc(strlen(src->muxnames[i]) + 1, | ||
974 | GFP_KERNEL); | ||
975 | if (!dst->muxnames[i]) | ||
976 | goto free; | ||
977 | strcpy(dst->muxnames[i], src->muxnames[i]); | ||
978 | } | ||
979 | } | ||
980 | |||
981 | #ifdef CONFIG_DEBUG_FS | ||
982 | for (i = 0; i < OMAP_MUX_NR_SIDES; i++) { | ||
983 | if (src->balls[i]) { | ||
984 | dst->balls[i] = | ||
985 | kmalloc(strlen(src->balls[i]) + 1, | ||
986 | GFP_KERNEL); | ||
987 | if (!dst->balls[i]) | ||
988 | goto free; | ||
989 | strcpy(dst->balls[i], src->balls[i]); | ||
990 | } | ||
991 | } | ||
992 | #endif | ||
993 | |||
994 | return 0; | ||
995 | |||
996 | free: | ||
997 | omap_mux_free_names(dst); | ||
998 | return -ENOMEM; | ||
999 | |||
1000 | } | ||
1001 | |||
1002 | #endif /* CONFIG_OMAP_MUX */ | ||
1003 | |||
1004 | static u16 omap_mux_get_by_gpio(int gpio) | ||
1005 | { | ||
1006 | struct omap_mux_entry *e; | ||
1007 | u16 offset = OMAP_MUX_TERMINATOR; | ||
1008 | |||
1009 | list_for_each_entry(e, &muxmodes, node) { | ||
1010 | struct omap_mux *m = &e->mux; | ||
1011 | if (m->gpio == gpio) { | ||
1012 | offset = m->reg_offset; | ||
1013 | break; | ||
1014 | } | ||
1015 | } | ||
1016 | |||
1017 | return offset; | ||
1018 | } | ||
1019 | |||
1020 | /* Needed for dynamic muxing of GPIO pins for off-idle */ | ||
1021 | u16 omap_mux_get_gpio(int gpio) | ||
1022 | { | ||
1023 | u16 offset; | ||
1024 | |||
1025 | offset = omap_mux_get_by_gpio(gpio); | ||
1026 | if (offset == OMAP_MUX_TERMINATOR) { | ||
1027 | printk(KERN_ERR "mux: Could not get gpio%i\n", gpio); | ||
1028 | return offset; | ||
1029 | } | ||
1030 | |||
1031 | return omap_mux_read(offset); | ||
1032 | } | ||
1033 | |||
1034 | /* Needed for dynamic muxing of GPIO pins for off-idle */ | ||
1035 | void omap_mux_set_gpio(u16 val, int gpio) | ||
1036 | { | ||
1037 | u16 offset; | ||
1038 | |||
1039 | offset = omap_mux_get_by_gpio(gpio); | ||
1040 | if (offset == OMAP_MUX_TERMINATOR) { | ||
1041 | printk(KERN_ERR "mux: Could not set gpio%i\n", gpio); | ||
1042 | return; | ||
1043 | } | ||
1044 | |||
1045 | omap_mux_write(val, offset); | ||
1046 | } | ||
1047 | |||
1048 | static struct omap_mux * __init omap_mux_list_add(struct omap_mux *src) | ||
1049 | { | ||
1050 | struct omap_mux_entry *entry; | ||
1051 | struct omap_mux *m; | ||
1052 | |||
1053 | entry = kzalloc(sizeof(struct omap_mux_entry), GFP_KERNEL); | ||
1054 | if (!entry) | ||
1055 | return NULL; | ||
1056 | |||
1057 | m = &entry->mux; | ||
1058 | memcpy(m, src, sizeof(struct omap_mux_entry)); | ||
1059 | |||
1060 | #ifdef CONFIG_OMAP_MUX | ||
1061 | if (omap_mux_copy_names(src, m)) { | ||
1062 | kfree(entry); | ||
1063 | return NULL; | ||
1064 | } | ||
1065 | #endif | ||
1066 | |||
1067 | mutex_lock(&muxmode_mutex); | ||
1068 | list_add_tail(&entry->node, &muxmodes); | ||
1069 | mutex_unlock(&muxmode_mutex); | ||
1070 | |||
1071 | return m; | ||
1072 | } | ||
1073 | |||
1074 | /* | ||
1075 | * Note if CONFIG_OMAP_MUX is not selected, we will only initialize | ||
1076 | * the GPIO to mux offset mapping that is needed for dynamic muxing | ||
1077 | * of GPIO pins for off-idle. | ||
1078 | */ | ||
1079 | static void __init omap_mux_init_list(struct omap_mux *superset) | ||
1080 | { | ||
1081 | while (superset->reg_offset != OMAP_MUX_TERMINATOR) { | ||
1082 | struct omap_mux *entry; | ||
1083 | |||
1084 | #ifndef CONFIG_OMAP_MUX | ||
1085 | /* Skip pins that are not muxed as GPIO by bootloader */ | ||
1086 | if (!OMAP_MODE_GPIO(omap_mux_read(superset->reg_offset))) { | ||
1087 | superset++; | ||
1088 | continue; | ||
1089 | } | ||
1090 | #endif | ||
1091 | |||
1092 | entry = omap_mux_list_add(superset); | ||
1093 | if (!entry) { | ||
1094 | printk(KERN_ERR "mux: Could not add entry\n"); | ||
1095 | return; | ||
1096 | } | ||
1097 | superset++; | ||
1098 | } | ||
1099 | } | ||
1100 | |||
1101 | int __init omap_mux_init(u32 mux_pbase, u32 mux_size, | ||
1102 | struct omap_mux *superset, | ||
1103 | struct omap_mux *package_subset, | ||
1104 | struct omap_board_mux *board_mux, | ||
1105 | struct omap_ball *package_balls) | ||
1106 | { | ||
1107 | if (mux_base) | ||
1108 | return -EBUSY; | ||
1109 | |||
1110 | mux_base = ioremap(mux_pbase, mux_size); | ||
1111 | if (!mux_base) { | ||
1112 | printk(KERN_ERR "mux: Could not ioremap\n"); | ||
1113 | return -ENODEV; | ||
1114 | } | ||
1115 | |||
1116 | #ifdef CONFIG_OMAP_MUX | ||
1117 | omap_mux_package_fixup(package_subset, superset); | ||
1118 | omap_mux_package_init_balls(package_balls, superset); | ||
1119 | omap_mux_set_cmdline_signals(); | ||
1120 | omap_mux_set_board_signals(board_mux); | ||
1121 | #endif | ||
1122 | |||
1123 | omap_mux_init_list(superset); | ||
1124 | |||
1125 | return 0; | ||
1126 | } | ||
1127 | |||
1128 | #endif /* CONFIG_ARCH_OMAP34XX */ | ||
diff --git a/arch/arm/mach-omap2/mux.h b/arch/arm/mach-omap2/mux.h new file mode 100644 index 000000000000..bebe9cc60858 --- /dev/null +++ b/arch/arm/mach-omap2/mux.h | |||
@@ -0,0 +1,160 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2009 Nokia | ||
3 | * Copyright (C) 2009 Texas Instruments | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | */ | ||
9 | |||
10 | #define OMAP_MUX_TERMINATOR 0xffff | ||
11 | |||
12 | /* 34xx mux mode options for each pin. See TRM for options */ | ||
13 | #define OMAP_MUX_MODE0 0 | ||
14 | #define OMAP_MUX_MODE1 1 | ||
15 | #define OMAP_MUX_MODE2 2 | ||
16 | #define OMAP_MUX_MODE3 3 | ||
17 | #define OMAP_MUX_MODE4 4 | ||
18 | #define OMAP_MUX_MODE5 5 | ||
19 | #define OMAP_MUX_MODE6 6 | ||
20 | #define OMAP_MUX_MODE7 7 | ||
21 | |||
22 | /* 24xx/34xx mux bit defines */ | ||
23 | #define OMAP_PULL_ENA (1 << 3) | ||
24 | #define OMAP_PULL_UP (1 << 4) | ||
25 | #define OMAP_ALTELECTRICALSEL (1 << 5) | ||
26 | |||
27 | /* 34xx specific mux bit defines */ | ||
28 | #define OMAP_INPUT_EN (1 << 8) | ||
29 | #define OMAP_OFF_EN (1 << 9) | ||
30 | #define OMAP_OFFOUT_EN (1 << 10) | ||
31 | #define OMAP_OFFOUT_VAL (1 << 11) | ||
32 | #define OMAP_OFF_PULL_EN (1 << 12) | ||
33 | #define OMAP_OFF_PULL_UP (1 << 13) | ||
34 | #define OMAP_WAKEUP_EN (1 << 14) | ||
35 | |||
36 | /* Active pin states */ | ||
37 | #define OMAP_PIN_OUTPUT 0 | ||
38 | #define OMAP_PIN_INPUT OMAP_INPUT_EN | ||
39 | #define OMAP_PIN_INPUT_PULLUP (OMAP_PULL_ENA | OMAP_INPUT_EN \ | ||
40 | | OMAP_PULL_UP) | ||
41 | #define OMAP_PIN_INPUT_PULLDOWN (OMAP_PULL_ENA | OMAP_INPUT_EN) | ||
42 | |||
43 | /* Off mode states */ | ||
44 | #define OMAP_PIN_OFF_NONE 0 | ||
45 | #define OMAP_PIN_OFF_OUTPUT_HIGH (OMAP_OFF_EN | OMAP_OFFOUT_EN \ | ||
46 | | OMAP_OFFOUT_VAL) | ||
47 | #define OMAP_PIN_OFF_OUTPUT_LOW (OMAP_OFF_EN | OMAP_OFFOUT_EN) | ||
48 | #define OMAP_PIN_OFF_INPUT_PULLUP (OMAP_OFF_EN | OMAP_OFF_PULL_EN \ | ||
49 | | OMAP_OFF_PULL_UP) | ||
50 | #define OMAP_PIN_OFF_INPUT_PULLDOWN (OMAP_OFF_EN | OMAP_OFF_PULL_EN) | ||
51 | #define OMAP_PIN_OFF_WAKEUPENABLE OMAP_WAKEUP_EN | ||
52 | |||
53 | #define OMAP_MODE_GPIO(x) (((x) & OMAP_MUX_MODE7) == OMAP_MUX_MODE4) | ||
54 | |||
55 | /* Flags for omap_mux_init */ | ||
56 | #define OMAP_PACKAGE_MASK 0xffff | ||
57 | #define OMAP_PACKAGE_CUS 3 /* 423-pin 0.65 */ | ||
58 | #define OMAP_PACKAGE_CBB 2 /* 515-pin 0.40 0.50 */ | ||
59 | #define OMAP_PACKAGE_CBC 1 /* 515-pin 0.50 0.65 */ | ||
60 | |||
61 | |||
62 | #define OMAP_MUX_NR_MODES 8 /* Available modes */ | ||
63 | #define OMAP_MUX_NR_SIDES 2 /* Bottom & top */ | ||
64 | |||
65 | /** | ||
66 | * struct omap_mux - data for omap mux register offset and it's value | ||
67 | * @reg_offset: mux register offset from the mux base | ||
68 | * @gpio: GPIO number | ||
69 | * @muxnames: available signal modes for a ball | ||
70 | */ | ||
71 | struct omap_mux { | ||
72 | u16 reg_offset; | ||
73 | u16 gpio; | ||
74 | #ifdef CONFIG_OMAP_MUX | ||
75 | char *muxnames[OMAP_MUX_NR_MODES]; | ||
76 | #ifdef CONFIG_DEBUG_FS | ||
77 | char *balls[OMAP_MUX_NR_SIDES]; | ||
78 | #endif | ||
79 | #endif | ||
80 | }; | ||
81 | |||
82 | /** | ||
83 | * struct omap_ball - data for balls on omap package | ||
84 | * @reg_offset: mux register offset from the mux base | ||
85 | * @balls: available balls on the package | ||
86 | */ | ||
87 | struct omap_ball { | ||
88 | u16 reg_offset; | ||
89 | char *balls[OMAP_MUX_NR_SIDES]; | ||
90 | }; | ||
91 | |||
92 | /** | ||
93 | * struct omap_board_mux - data for initializing mux registers | ||
94 | * @reg_offset: mux register offset from the mux base | ||
95 | * @mux_value: desired mux value to set | ||
96 | */ | ||
97 | struct omap_board_mux { | ||
98 | u16 reg_offset; | ||
99 | u16 value; | ||
100 | }; | ||
101 | |||
102 | #if defined(CONFIG_OMAP_MUX) && defined(CONFIG_ARCH_OMAP34XX) | ||
103 | |||
104 | /** | ||
105 | * omap_mux_init_gpio - initialize a signal based on the GPIO number | ||
106 | * @gpio: GPIO number | ||
107 | * @val: Options for the mux register value | ||
108 | */ | ||
109 | int omap_mux_init_gpio(int gpio, int val); | ||
110 | |||
111 | /** | ||
112 | * omap_mux_init_signal - initialize a signal based on the signal name | ||
113 | * @muxname: Mux name in mode0_name.signal_name format | ||
114 | * @val: Options for the mux register value | ||
115 | */ | ||
116 | int omap_mux_init_signal(char *muxname, int val); | ||
117 | |||
118 | #else | ||
119 | |||
120 | static inline int omap_mux_init_gpio(int gpio, int val) | ||
121 | { | ||
122 | return 0; | ||
123 | } | ||
124 | static inline int omap_mux_init_signal(char *muxname, int val) | ||
125 | { | ||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | #endif | ||
130 | |||
131 | /** | ||
132 | * omap_mux_get_gpio() - get mux register value based on GPIO number | ||
133 | * @gpio: GPIO number | ||
134 | * | ||
135 | */ | ||
136 | u16 omap_mux_get_gpio(int gpio); | ||
137 | |||
138 | /** | ||
139 | * omap_mux_set_gpio() - set mux register value based on GPIO number | ||
140 | * @val: New mux register value | ||
141 | * @gpio: GPIO number | ||
142 | * | ||
143 | */ | ||
144 | void omap_mux_set_gpio(u16 val, int gpio); | ||
145 | |||
146 | /** | ||
147 | * omap3_mux_init() - initialize mux system with board specific set | ||
148 | * @board_mux: Board specific mux table | ||
149 | * @flags: OMAP package type used for the board | ||
150 | */ | ||
151 | int omap3_mux_init(struct omap_board_mux *board_mux, int flags); | ||
152 | |||
153 | /** | ||
154 | * omap_mux_init - private mux init function, do not call | ||
155 | */ | ||
156 | int omap_mux_init(u32 mux_pbase, u32 mux_size, | ||
157 | struct omap_mux *superset, | ||
158 | struct omap_mux *package_subset, | ||
159 | struct omap_board_mux *board_mux, | ||
160 | struct omap_ball *package_balls); | ||
diff --git a/arch/arm/plat-omap/mux.c b/arch/arm/plat-omap/mux.c index 05aebcad215b..06703635ace1 100644 --- a/arch/arm/plat-omap/mux.c +++ b/arch/arm/plat-omap/mux.c | |||
@@ -54,8 +54,12 @@ int __init_or_module omap_cfg_reg(const unsigned long index) | |||
54 | { | 54 | { |
55 | struct pin_config *reg; | 55 | struct pin_config *reg; |
56 | 56 | ||
57 | if (cpu_is_omap44xx()) | 57 | if (cpu_is_omap34xx() || cpu_is_omap44xx()) { |
58 | return 0; | 58 | printk(KERN_ERR "mux: Broken omap_cfg_reg(%lu) entry\n", |
59 | index); | ||
60 | WARN_ON(1); | ||
61 | return -EINVAL; | ||
62 | } | ||
59 | 63 | ||
60 | if (mux_cfg == NULL) { | 64 | if (mux_cfg == NULL) { |
61 | printk(KERN_ERR "Pin mux table not initialized\n"); | 65 | printk(KERN_ERR "Pin mux table not initialized\n"); |