Commit | Line | Data |
---|---|---|
1dbae815 TL |
1 | /* |
2 | * linux/arch/arm/mach-omap2/mux.c | |
3 | * | |
2351872c | 4 | * OMAP2 and OMAP3 pin multiplexing configurations |
1dbae815 | 5 | * |
9330899e TL |
6 | * Copyright (C) 2004 - 2008 Texas Instruments Inc. |
7 | * Copyright (C) 2003 - 2008 Nokia Corporation | |
1dbae815 | 8 | * |
9330899e | 9 | * Written by Tony Lindgren |
1dbae815 TL |
10 | * |
11 | * This program is free software; you can redistribute it and/or modify | |
12 | * it under the terms of the GNU General Public License as published by | |
13 | * the Free Software Foundation; either version 2 of the License, or | |
14 | * (at your option) any later version. | |
15 | * | |
16 | * This program is distributed in the hope that it will be useful, | |
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 | * GNU General Public License for more details. | |
20 | * | |
21 | * You should have received a copy of the GNU General Public License | |
22 | * along with this program; if not, write to the Free Software | |
23 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
24 | * | |
25 | */ | |
1dbae815 TL |
26 | #include <linux/module.h> |
27 | #include <linux/init.h> | |
fced80c7 | 28 | #include <linux/io.h> |
1dbae815 | 29 | #include <linux/spinlock.h> |
15ac7afe | 30 | #include <linux/list.h> |
4b715efc TL |
31 | #include <linux/ctype.h> |
32 | #include <linux/debugfs.h> | |
33 | #include <linux/seq_file.h> | |
34 | #include <linux/uaccess.h> | |
1dbae815 | 35 | |
fced80c7 RK |
36 | #include <asm/system.h> |
37 | ||
ce491cf8 TL |
38 | #include <plat/control.h> |
39 | #include <plat/mux.h> | |
1dbae815 | 40 | |
15ac7afe | 41 | #include "mux.h" |
1dbae815 | 42 | |
92c9f501 MR |
43 | #define OMAP_MUX_BASE_OFFSET 0x30 /* Offset from CTRL_BASE */ |
44 | #define OMAP_MUX_BASE_SZ 0x5ca | |
45 | ||
15ac7afe TL |
46 | struct omap_mux_entry { |
47 | struct omap_mux mux; | |
48 | struct list_head node; | |
49 | }; | |
50 | ||
4b715efc | 51 | static unsigned long mux_phys; |
92c9f501 MR |
52 | static void __iomem *mux_base; |
53 | ||
d4bb72e5 | 54 | u16 omap_mux_read(u16 reg) |
92c9f501 MR |
55 | { |
56 | if (cpu_is_omap24xx()) | |
57 | return __raw_readb(mux_base + reg); | |
58 | else | |
59 | return __raw_readw(mux_base + reg); | |
60 | } | |
61 | ||
d4bb72e5 | 62 | void omap_mux_write(u16 val, u16 reg) |
92c9f501 MR |
63 | { |
64 | if (cpu_is_omap24xx()) | |
65 | __raw_writeb(val, mux_base + reg); | |
66 | else | |
67 | __raw_writew(val, mux_base + reg); | |
68 | } | |
7d7f665d | 69 | |
d4bb72e5 TL |
70 | void omap_mux_write_array(struct omap_board_mux *board_mux) |
71 | { | |
72 | while (board_mux->reg_offset != OMAP_MUX_TERMINATOR) { | |
73 | omap_mux_write(board_mux->value, board_mux->reg_offset); | |
74 | board_mux++; | |
75 | } | |
76 | } | |
77 | ||
088ef950 | 78 | #if defined(CONFIG_ARCH_OMAP2) && defined(CONFIG_OMAP_MUX) |
15ac7afe TL |
79 | |
80 | static struct omap_mux_cfg arch_mux_cfg; | |
81 | ||
1dbae815 TL |
82 | /* NOTE: See mux.h for the enumeration */ |
83 | ||
9330899e | 84 | static struct pin_config __initdata_or_module omap24xx_pins[] = { |
1dbae815 TL |
85 | /* |
86 | * description mux mux pull pull debug | |
87 | * offset mode ena type | |
88 | */ | |
89 | ||
90 | /* 24xx I2C */ | |
91 | MUX_CFG_24XX("M19_24XX_I2C1_SCL", 0x111, 0, 0, 0, 1) | |
92 | MUX_CFG_24XX("L15_24XX_I2C1_SDA", 0x112, 0, 0, 0, 1) | |
7bbb3cc5 | 93 | MUX_CFG_24XX("J15_24XX_I2C2_SCL", 0x113, 0, 0, 1, 1) |
1dbae815 TL |
94 | MUX_CFG_24XX("H19_24XX_I2C2_SDA", 0x114, 0, 0, 0, 1) |
95 | ||
96 | /* Menelaus interrupt */ | |
97 | MUX_CFG_24XX("W19_24XX_SYS_NIRQ", 0x12c, 0, 1, 1, 1) | |
98 | ||
8d7f9f50 TL |
99 | /* 24xx clocks */ |
100 | MUX_CFG_24XX("W14_24XX_SYS_CLKOUT", 0x137, 0, 1, 1, 1) | |
101 | ||
7bbb3cc5 | 102 | /* 24xx GPMC chipselects, wait pin monitoring */ |
7d34f3b3 TL |
103 | MUX_CFG_24XX("E2_GPMC_NCS2", 0x08e, 0, 1, 1, 1) |
104 | MUX_CFG_24XX("L2_GPMC_NCS7", 0x093, 0, 1, 1, 1) | |
3cbc9605 TL |
105 | MUX_CFG_24XX("L3_GPMC_WAIT0", 0x09a, 0, 1, 1, 1) |
106 | MUX_CFG_24XX("N7_GPMC_WAIT1", 0x09b, 0, 1, 1, 1) | |
107 | MUX_CFG_24XX("M1_GPMC_WAIT2", 0x09c, 0, 1, 1, 1) | |
108 | MUX_CFG_24XX("P1_GPMC_WAIT3", 0x09d, 0, 1, 1, 1) | |
109 | ||
8d7f9f50 TL |
110 | /* 24xx McBSP */ |
111 | MUX_CFG_24XX("Y15_24XX_MCBSP2_CLKX", 0x124, 1, 1, 0, 1) | |
112 | MUX_CFG_24XX("R14_24XX_MCBSP2_FSX", 0x125, 1, 1, 0, 1) | |
113 | MUX_CFG_24XX("W15_24XX_MCBSP2_DR", 0x126, 1, 1, 0, 1) | |
114 | MUX_CFG_24XX("V15_24XX_MCBSP2_DX", 0x127, 1, 1, 0, 1) | |
115 | ||
1dbae815 | 116 | /* 24xx GPIO */ |
7d34f3b3 TL |
117 | MUX_CFG_24XX("M21_242X_GPIO11", 0x0c9, 3, 1, 1, 1) |
118 | MUX_CFG_24XX("P21_242X_GPIO12", 0x0ca, 3, 0, 0, 1) | |
119 | MUX_CFG_24XX("AA10_242X_GPIO13", 0x0e5, 3, 0, 0, 1) | |
120 | MUX_CFG_24XX("AA6_242X_GPIO14", 0x0e6, 3, 0, 0, 1) | |
121 | MUX_CFG_24XX("AA4_242X_GPIO15", 0x0e7, 3, 0, 0, 1) | |
122 | MUX_CFG_24XX("Y11_242X_GPIO16", 0x0e8, 3, 0, 0, 1) | |
123 | MUX_CFG_24XX("AA12_242X_GPIO17", 0x0e9, 3, 0, 0, 1) | |
124 | MUX_CFG_24XX("AA8_242X_GPIO58", 0x0ea, 3, 0, 0, 1) | |
1dbae815 | 125 | MUX_CFG_24XX("Y20_24XX_GPIO60", 0x12c, 3, 0, 0, 1) |
7d34f3b3 | 126 | MUX_CFG_24XX("W4__24XX_GPIO74", 0x0f2, 3, 0, 0, 1) |
f7337a19 | 127 | MUX_CFG_24XX("N15_24XX_GPIO85", 0x103, 3, 0, 0, 1) |
1dbae815 | 128 | MUX_CFG_24XX("M15_24XX_GPIO92", 0x10a, 3, 0, 0, 1) |
f7337a19 TL |
129 | MUX_CFG_24XX("P20_24XX_GPIO93", 0x10b, 3, 0, 0, 1) |
130 | MUX_CFG_24XX("P18_24XX_GPIO95", 0x10d, 3, 0, 0, 1) | |
131 | MUX_CFG_24XX("M18_24XX_GPIO96", 0x10e, 3, 0, 0, 1) | |
132 | MUX_CFG_24XX("L14_24XX_GPIO97", 0x10f, 3, 0, 0, 1) | |
7d34f3b3 | 133 | MUX_CFG_24XX("J15_24XX_GPIO99", 0x113, 3, 1, 1, 1) |
8d7f9f50 | 134 | MUX_CFG_24XX("V14_24XX_GPIO117", 0x128, 3, 1, 0, 1) |
7bbb3cc5 | 135 | MUX_CFG_24XX("P14_24XX_GPIO125", 0x140, 3, 1, 1, 1) |
8d7f9f50 | 136 | |
5ac42153 TL |
137 | /* 242x DBG GPIO */ |
138 | MUX_CFG_24XX("V4_242X_GPIO49", 0xd3, 3, 0, 0, 1) | |
139 | MUX_CFG_24XX("W2_242X_GPIO50", 0xd4, 3, 0, 0, 1) | |
140 | MUX_CFG_24XX("U4_242X_GPIO51", 0xd5, 3, 0, 0, 1) | |
141 | MUX_CFG_24XX("V3_242X_GPIO52", 0xd6, 3, 0, 0, 1) | |
142 | MUX_CFG_24XX("V2_242X_GPIO53", 0xd7, 3, 0, 0, 1) | |
143 | MUX_CFG_24XX("V6_242X_GPIO53", 0xcf, 3, 0, 0, 1) | |
144 | MUX_CFG_24XX("T4_242X_GPIO54", 0xd8, 3, 0, 0, 1) | |
145 | MUX_CFG_24XX("Y4_242X_GPIO54", 0xd0, 3, 0, 0, 1) | |
146 | MUX_CFG_24XX("T3_242X_GPIO55", 0xd9, 3, 0, 0, 1) | |
147 | MUX_CFG_24XX("U2_242X_GPIO56", 0xda, 3, 0, 0, 1) | |
148 | ||
149 | /* 24xx external DMA requests */ | |
7d34f3b3 TL |
150 | MUX_CFG_24XX("AA10_242X_DMAREQ0", 0x0e5, 2, 0, 0, 1) |
151 | MUX_CFG_24XX("AA6_242X_DMAREQ1", 0x0e6, 2, 0, 0, 1) | |
152 | MUX_CFG_24XX("E4_242X_DMAREQ2", 0x074, 2, 0, 0, 1) | |
153 | MUX_CFG_24XX("G4_242X_DMAREQ3", 0x073, 2, 0, 0, 1) | |
154 | MUX_CFG_24XX("D3_242X_DMAREQ4", 0x072, 2, 0, 0, 1) | |
155 | MUX_CFG_24XX("E3_242X_DMAREQ5", 0x071, 2, 0, 0, 1) | |
5ac42153 | 156 | |
7d34f3b3 | 157 | /* UART3 */ |
8d7f9f50 TL |
158 | MUX_CFG_24XX("K15_24XX_UART3_TX", 0x118, 0, 0, 0, 1) |
159 | MUX_CFG_24XX("K14_24XX_UART3_RX", 0x119, 0, 0, 0, 1) | |
160 | ||
abc45e1d KP |
161 | /* MMC/SDIO */ |
162 | MUX_CFG_24XX("G19_24XX_MMC_CLKO", 0x0f3, 0, 0, 0, 1) | |
163 | MUX_CFG_24XX("H18_24XX_MMC_CMD", 0x0f4, 0, 0, 0, 1) | |
164 | MUX_CFG_24XX("F20_24XX_MMC_DAT0", 0x0f5, 0, 0, 0, 1) | |
165 | MUX_CFG_24XX("H14_24XX_MMC_DAT1", 0x0f6, 0, 0, 0, 1) | |
166 | MUX_CFG_24XX("E19_24XX_MMC_DAT2", 0x0f7, 0, 0, 0, 1) | |
167 | MUX_CFG_24XX("D19_24XX_MMC_DAT3", 0x0f8, 0, 0, 0, 1) | |
168 | MUX_CFG_24XX("F19_24XX_MMC_DAT_DIR0", 0x0f9, 0, 0, 0, 1) | |
169 | MUX_CFG_24XX("E20_24XX_MMC_DAT_DIR1", 0x0fa, 0, 0, 0, 1) | |
170 | MUX_CFG_24XX("F18_24XX_MMC_DAT_DIR2", 0x0fb, 0, 0, 0, 1) | |
171 | MUX_CFG_24XX("E18_24XX_MMC_DAT_DIR3", 0x0fc, 0, 0, 0, 1) | |
172 | MUX_CFG_24XX("G18_24XX_MMC_CMD_DIR", 0x0fd, 0, 0, 0, 1) | |
173 | MUX_CFG_24XX("H15_24XX_MMC_CLKI", 0x0fe, 0, 0, 0, 1) | |
174 | ||
7bbb3cc5 KP |
175 | /* Full speed USB */ |
176 | MUX_CFG_24XX("J20_24XX_USB0_PUEN", 0x11d, 0, 0, 0, 1) | |
177 | MUX_CFG_24XX("J19_24XX_USB0_VP", 0x11e, 0, 0, 0, 1) | |
178 | MUX_CFG_24XX("K20_24XX_USB0_VM", 0x11f, 0, 0, 0, 1) | |
179 | MUX_CFG_24XX("J18_24XX_USB0_RCV", 0x120, 0, 0, 0, 1) | |
180 | MUX_CFG_24XX("K19_24XX_USB0_TXEN", 0x121, 0, 0, 0, 1) | |
181 | MUX_CFG_24XX("J14_24XX_USB0_SE0", 0x122, 0, 0, 0, 1) | |
182 | MUX_CFG_24XX("K18_24XX_USB0_DAT", 0x123, 0, 0, 0, 1) | |
183 | ||
184 | MUX_CFG_24XX("N14_24XX_USB1_SE0", 0x0ed, 2, 0, 0, 1) | |
185 | MUX_CFG_24XX("W12_24XX_USB1_SE0", 0x0dd, 3, 0, 0, 1) | |
186 | MUX_CFG_24XX("P15_24XX_USB1_DAT", 0x0ee, 2, 0, 0, 1) | |
187 | MUX_CFG_24XX("R13_24XX_USB1_DAT", 0x0e0, 3, 0, 0, 1) | |
188 | MUX_CFG_24XX("W20_24XX_USB1_TXEN", 0x0ec, 2, 0, 0, 1) | |
189 | MUX_CFG_24XX("P13_24XX_USB1_TXEN", 0x0df, 3, 0, 0, 1) | |
190 | MUX_CFG_24XX("V19_24XX_USB1_RCV", 0x0eb, 2, 0, 0, 1) | |
191 | MUX_CFG_24XX("V12_24XX_USB1_RCV", 0x0de, 3, 0, 0, 1) | |
192 | ||
193 | MUX_CFG_24XX("AA10_24XX_USB2_SE0", 0x0e5, 2, 0, 0, 1) | |
194 | MUX_CFG_24XX("Y11_24XX_USB2_DAT", 0x0e8, 2, 0, 0, 1) | |
195 | MUX_CFG_24XX("AA12_24XX_USB2_TXEN", 0x0e9, 2, 0, 0, 1) | |
196 | MUX_CFG_24XX("AA6_24XX_USB2_RCV", 0x0e6, 2, 0, 0, 1) | |
197 | MUX_CFG_24XX("AA4_24XX_USB2_TLLSE0", 0x0e7, 2, 0, 0, 1) | |
198 | ||
8d7f9f50 TL |
199 | /* Keypad GPIO*/ |
200 | MUX_CFG_24XX("T19_24XX_KBR0", 0x106, 3, 1, 1, 1) | |
201 | MUX_CFG_24XX("R19_24XX_KBR1", 0x107, 3, 1, 1, 1) | |
202 | MUX_CFG_24XX("V18_24XX_KBR2", 0x139, 3, 1, 1, 1) | |
203 | MUX_CFG_24XX("M21_24XX_KBR3", 0xc9, 3, 1, 1, 1) | |
204 | MUX_CFG_24XX("E5__24XX_KBR4", 0x138, 3, 1, 1, 1) | |
205 | MUX_CFG_24XX("M18_24XX_KBR5", 0x10e, 3, 1, 1, 1) | |
206 | MUX_CFG_24XX("R20_24XX_KBC0", 0x108, 3, 0, 0, 1) | |
207 | MUX_CFG_24XX("M14_24XX_KBC1", 0x109, 3, 0, 0, 1) | |
208 | MUX_CFG_24XX("H19_24XX_KBC2", 0x114, 3, 0, 0, 1) | |
209 | MUX_CFG_24XX("V17_24XX_KBC3", 0x135, 3, 0, 0, 1) | |
210 | MUX_CFG_24XX("P21_24XX_KBC4", 0xca, 3, 0, 0, 1) | |
211 | MUX_CFG_24XX("L14_24XX_KBC5", 0x10f, 3, 0, 0, 1) | |
212 | MUX_CFG_24XX("N19_24XX_KBC6", 0x110, 3, 0, 0, 1) | |
213 | ||
214 | /* 24xx Menelaus Keypad GPIO */ | |
215 | MUX_CFG_24XX("B3__24XX_KBR5", 0x30, 3, 1, 1, 1) | |
216 | MUX_CFG_24XX("AA4_24XX_KBC2", 0xe7, 3, 0, 0, 1) | |
217 | MUX_CFG_24XX("B13_24XX_KBC6", 0x110, 3, 0, 0, 1) | |
1dbae815 | 218 | |
f7337a19 TL |
219 | /* 2430 USB */ |
220 | MUX_CFG_24XX("AD9_2430_USB0_PUEN", 0x133, 4, 0, 0, 1) | |
221 | MUX_CFG_24XX("Y11_2430_USB0_VP", 0x134, 4, 0, 0, 1) | |
222 | MUX_CFG_24XX("AD7_2430_USB0_VM", 0x135, 4, 0, 0, 1) | |
223 | MUX_CFG_24XX("AE7_2430_USB0_RCV", 0x136, 4, 0, 0, 1) | |
224 | MUX_CFG_24XX("AD4_2430_USB0_TXEN", 0x137, 4, 0, 0, 1) | |
225 | MUX_CFG_24XX("AF9_2430_USB0_SE0", 0x138, 4, 0, 0, 1) | |
226 | MUX_CFG_24XX("AE6_2430_USB0_DAT", 0x139, 4, 0, 0, 1) | |
227 | MUX_CFG_24XX("AD24_2430_USB1_SE0", 0x107, 2, 0, 0, 1) | |
228 | MUX_CFG_24XX("AB24_2430_USB1_RCV", 0x108, 2, 0, 0, 1) | |
229 | MUX_CFG_24XX("Y25_2430_USB1_TXEN", 0x109, 2, 0, 0, 1) | |
230 | MUX_CFG_24XX("AA26_2430_USB1_DAT", 0x10A, 2, 0, 0, 1) | |
231 | ||
232 | /* 2430 HS-USB */ | |
233 | MUX_CFG_24XX("AD9_2430_USB0HS_DATA3", 0x133, 0, 0, 0, 1) | |
234 | MUX_CFG_24XX("Y11_2430_USB0HS_DATA4", 0x134, 0, 0, 0, 1) | |
235 | MUX_CFG_24XX("AD7_2430_USB0HS_DATA5", 0x135, 0, 0, 0, 1) | |
236 | MUX_CFG_24XX("AE7_2430_USB0HS_DATA6", 0x136, 0, 0, 0, 1) | |
237 | MUX_CFG_24XX("AD4_2430_USB0HS_DATA2", 0x137, 0, 0, 0, 1) | |
238 | MUX_CFG_24XX("AF9_2430_USB0HS_DATA0", 0x138, 0, 0, 0, 1) | |
239 | MUX_CFG_24XX("AE6_2430_USB0HS_DATA1", 0x139, 0, 0, 0, 1) | |
240 | MUX_CFG_24XX("AE8_2430_USB0HS_CLK", 0x13A, 0, 0, 0, 1) | |
241 | MUX_CFG_24XX("AD8_2430_USB0HS_DIR", 0x13B, 0, 0, 0, 1) | |
242 | MUX_CFG_24XX("AE5_2430_USB0HS_STP", 0x13c, 0, 1, 1, 1) | |
243 | MUX_CFG_24XX("AE9_2430_USB0HS_NXT", 0x13D, 0, 0, 0, 1) | |
244 | MUX_CFG_24XX("AC7_2430_USB0HS_DATA7", 0x13E, 0, 0, 0, 1) | |
245 | ||
246 | /* 2430 McBSP */ | |
2619bc32 AK |
247 | MUX_CFG_24XX("AD6_2430_MCBSP_CLKS", 0x011E, 0, 0, 0, 1) |
248 | ||
249 | MUX_CFG_24XX("AB2_2430_MCBSP1_CLKR", 0x011A, 0, 0, 0, 1) | |
250 | MUX_CFG_24XX("AD5_2430_MCBSP1_FSR", 0x011B, 0, 0, 0, 1) | |
251 | MUX_CFG_24XX("AA1_2430_MCBSP1_DX", 0x011C, 0, 0, 0, 1) | |
252 | MUX_CFG_24XX("AF3_2430_MCBSP1_DR", 0x011D, 0, 0, 0, 1) | |
253 | MUX_CFG_24XX("AB3_2430_MCBSP1_FSX", 0x011F, 0, 0, 0, 1) | |
254 | MUX_CFG_24XX("Y9_2430_MCBSP1_CLKX", 0x0120, 0, 0, 0, 1) | |
255 | ||
f7337a19 TL |
256 | MUX_CFG_24XX("AC10_2430_MCBSP2_FSX", 0x012E, 1, 0, 0, 1) |
257 | MUX_CFG_24XX("AD16_2430_MCBSP2_CLX", 0x012F, 1, 0, 0, 1) | |
258 | MUX_CFG_24XX("AE13_2430_MCBSP2_DX", 0x0130, 1, 0, 0, 1) | |
259 | MUX_CFG_24XX("AD13_2430_MCBSP2_DR", 0x0131, 1, 0, 0, 1) | |
260 | MUX_CFG_24XX("AC10_2430_MCBSP2_FSX_OFF",0x012E, 0, 0, 0, 1) | |
261 | MUX_CFG_24XX("AD16_2430_MCBSP2_CLX_OFF",0x012F, 0, 0, 0, 1) | |
262 | MUX_CFG_24XX("AE13_2430_MCBSP2_DX_OFF", 0x0130, 0, 0, 0, 1) | |
263 | MUX_CFG_24XX("AD13_2430_MCBSP2_DR_OFF", 0x0131, 0, 0, 0, 1) | |
2619bc32 AK |
264 | |
265 | MUX_CFG_24XX("AC9_2430_MCBSP3_CLKX", 0x0103, 0, 0, 0, 1) | |
266 | MUX_CFG_24XX("AE4_2430_MCBSP3_FSX", 0x0104, 0, 0, 0, 1) | |
267 | MUX_CFG_24XX("AE2_2430_MCBSP3_DR", 0x0105, 0, 0, 0, 1) | |
268 | MUX_CFG_24XX("AF4_2430_MCBSP3_DX", 0x0106, 0, 0, 0, 1) | |
269 | ||
270 | MUX_CFG_24XX("N3_2430_MCBSP4_CLKX", 0x010B, 1, 0, 0, 1) | |
271 | MUX_CFG_24XX("AD23_2430_MCBSP4_DR", 0x010C, 1, 0, 0, 1) | |
272 | MUX_CFG_24XX("AB25_2430_MCBSP4_DX", 0x010D, 1, 0, 0, 1) | |
273 | MUX_CFG_24XX("AC25_2430_MCBSP4_FSX", 0x010E, 1, 0, 0, 1) | |
274 | ||
275 | MUX_CFG_24XX("AE16_2430_MCBSP5_CLKX", 0x00ED, 1, 0, 0, 1) | |
276 | MUX_CFG_24XX("AF12_2430_MCBSP5_FSX", 0x00ED, 1, 0, 0, 1) | |
277 | MUX_CFG_24XX("K7_2430_MCBSP5_DX", 0x00EF, 1, 0, 0, 1) | |
278 | MUX_CFG_24XX("M1_2430_MCBSP5_DR", 0x00F0, 1, 0, 0, 1) | |
279 | ||
280 | /* 2430 MCSPI1 */ | |
281 | MUX_CFG_24XX("Y18_2430_MCSPI1_CLK", 0x010F, 0, 0, 0, 1) | |
282 | MUX_CFG_24XX("AD15_2430_MCSPI1_SIMO", 0x0110, 0, 0, 0, 1) | |
283 | MUX_CFG_24XX("AE17_2430_MCSPI1_SOMI", 0x0111, 0, 0, 0, 1) | |
284 | MUX_CFG_24XX("U1_2430_MCSPI1_CS0", 0x0112, 0, 0, 0, 1) | |
285 | ||
286 | /* Touchscreen GPIO */ | |
287 | MUX_CFG_24XX("AF19_2430_GPIO_85", 0x0113, 3, 0, 0, 1) | |
288 | ||
1dbae815 TL |
289 | }; |
290 | ||
9330899e TL |
291 | #define OMAP24XX_PINS_SZ ARRAY_SIZE(omap24xx_pins) |
292 | ||
9330899e | 293 | #if defined(CONFIG_OMAP_MUX_DEBUG) || defined(CONFIG_OMAP_MUX_WARNINGS) |
15f45e6f | 294 | |
2351872c | 295 | static void __init_or_module omap2_cfg_debug(const struct pin_config *cfg, u16 reg) |
9330899e TL |
296 | { |
297 | u16 orig; | |
298 | u8 warn = 0, debug = 0; | |
299 | ||
92c9f501 | 300 | orig = omap_mux_read(cfg->mux_reg - OMAP_MUX_BASE_OFFSET); |
9330899e TL |
301 | |
302 | #ifdef CONFIG_OMAP_MUX_DEBUG | |
303 | debug = cfg->debug; | |
304 | #endif | |
305 | warn = (orig != reg); | |
306 | if (debug || warn) | |
307 | printk(KERN_WARNING | |
a58caad1 | 308 | "MUX: setup %s (0x%p): 0x%04x -> 0x%04x\n", |
44595982 PW |
309 | cfg->name, omap_ctrl_base_get() + cfg->mux_reg, |
310 | orig, reg); | |
9330899e TL |
311 | } |
312 | #else | |
313 | #define omap2_cfg_debug(x, y) do {} while (0) | |
314 | #endif | |
315 | ||
2619bc32 | 316 | static int __init_or_module omap24xx_cfg_reg(const struct pin_config *cfg) |
1dbae815 | 317 | { |
9330899e TL |
318 | static DEFINE_SPINLOCK(mux_spin_lock); |
319 | unsigned long flags; | |
225dfda1 | 320 | u8 reg = 0; |
225dfda1 | 321 | |
9330899e | 322 | spin_lock_irqsave(&mux_spin_lock, flags); |
225dfda1 TL |
323 | reg |= cfg->mask & 0x7; |
324 | if (cfg->pull_val) | |
2351872c | 325 | reg |= OMAP2_PULL_ENA; |
9330899e | 326 | if (cfg->pu_pd_val) |
2351872c | 327 | reg |= OMAP2_PULL_UP; |
9330899e | 328 | omap2_cfg_debug(cfg, reg); |
92c9f501 | 329 | omap_mux_write(reg, cfg->mux_reg - OMAP_MUX_BASE_OFFSET); |
9330899e | 330 | spin_unlock_irqrestore(&mux_spin_lock, flags); |
225dfda1 | 331 | |
1dbae815 TL |
332 | return 0; |
333 | } | |
7d7f665d TL |
334 | |
335 | int __init omap2_mux_init(void) | |
336 | { | |
92c9f501 MR |
337 | u32 mux_pbase; |
338 | ||
339 | if (cpu_is_omap2420()) | |
340 | mux_pbase = OMAP2420_CTRL_BASE + OMAP_MUX_BASE_OFFSET; | |
341 | else if (cpu_is_omap2430()) | |
342 | mux_pbase = OMAP243X_CTRL_BASE + OMAP_MUX_BASE_OFFSET; | |
15ac7afe TL |
343 | else |
344 | return -ENODEV; | |
92c9f501 MR |
345 | |
346 | mux_base = ioremap(mux_pbase, OMAP_MUX_BASE_SZ); | |
347 | if (!mux_base) { | |
348 | printk(KERN_ERR "mux: Could not ioremap\n"); | |
349 | return -ENODEV; | |
350 | } | |
351 | ||
7d7f665d TL |
352 | if (cpu_is_omap24xx()) { |
353 | arch_mux_cfg.pins = omap24xx_pins; | |
9330899e | 354 | arch_mux_cfg.size = OMAP24XX_PINS_SZ; |
7d7f665d | 355 | arch_mux_cfg.cfg_reg = omap24xx_cfg_reg; |
15f45e6f TL |
356 | |
357 | return omap_mux_register(&arch_mux_cfg); | |
7d7f665d | 358 | } |
7d7f665d | 359 | |
15f45e6f | 360 | return 0; |
7d7f665d | 361 | } |
1dbae815 | 362 | |
15f45e6f TL |
363 | #else |
364 | int __init omap2_mux_init(void) | |
365 | { | |
366 | return 0; | |
367 | } | |
15ac7afe TL |
368 | #endif /* CONFIG_OMAP_MUX */ |
369 | ||
370 | /*----------------------------------------------------------------------------*/ | |
371 | ||
a8eb7ca0 | 372 | #ifdef CONFIG_ARCH_OMAP3 |
15ac7afe TL |
373 | static LIST_HEAD(muxmodes); |
374 | static DEFINE_MUTEX(muxmode_mutex); | |
375 | ||
376 | #ifdef CONFIG_OMAP_MUX | |
377 | ||
378 | static char *omap_mux_options; | |
379 | ||
380 | int __init omap_mux_init_gpio(int gpio, int val) | |
381 | { | |
382 | struct omap_mux_entry *e; | |
383 | int found = 0; | |
384 | ||
385 | if (!gpio) | |
386 | return -EINVAL; | |
387 | ||
388 | list_for_each_entry(e, &muxmodes, node) { | |
389 | struct omap_mux *m = &e->mux; | |
390 | if (gpio == m->gpio) { | |
391 | u16 old_mode; | |
392 | u16 mux_mode; | |
393 | ||
394 | old_mode = omap_mux_read(m->reg_offset); | |
395 | mux_mode = val & ~(OMAP_MUX_NR_MODES - 1); | |
396 | mux_mode |= OMAP_MUX_MODE4; | |
397 | printk(KERN_DEBUG "mux: Setting signal " | |
398 | "%s.gpio%i 0x%04x -> 0x%04x\n", | |
399 | m->muxnames[0], gpio, old_mode, mux_mode); | |
400 | omap_mux_write(mux_mode, m->reg_offset); | |
401 | found++; | |
402 | } | |
403 | } | |
404 | ||
405 | if (found == 1) | |
406 | return 0; | |
407 | ||
408 | if (found > 1) { | |
409 | printk(KERN_ERR "mux: Multiple gpio paths for gpio%i\n", gpio); | |
410 | return -EINVAL; | |
411 | } | |
412 | ||
413 | printk(KERN_ERR "mux: Could not set gpio%i\n", gpio); | |
414 | ||
415 | return -ENODEV; | |
416 | } | |
417 | ||
418 | int __init omap_mux_init_signal(char *muxname, int val) | |
419 | { | |
420 | struct omap_mux_entry *e; | |
421 | char *m0_name = NULL, *mode_name = NULL; | |
422 | int found = 0; | |
423 | ||
424 | mode_name = strchr(muxname, '.'); | |
425 | if (mode_name) { | |
426 | *mode_name = '\0'; | |
427 | mode_name++; | |
428 | m0_name = muxname; | |
429 | } else { | |
430 | mode_name = muxname; | |
431 | } | |
432 | ||
433 | list_for_each_entry(e, &muxmodes, node) { | |
434 | struct omap_mux *m = &e->mux; | |
435 | char *m0_entry = m->muxnames[0]; | |
436 | int i; | |
437 | ||
438 | if (m0_name && strcmp(m0_name, m0_entry)) | |
439 | continue; | |
440 | ||
441 | for (i = 0; i < OMAP_MUX_NR_MODES; i++) { | |
442 | char *mode_cur = m->muxnames[i]; | |
443 | ||
444 | if (!mode_cur) | |
445 | continue; | |
446 | ||
447 | if (!strcmp(mode_name, mode_cur)) { | |
448 | u16 old_mode; | |
449 | u16 mux_mode; | |
450 | ||
451 | old_mode = omap_mux_read(m->reg_offset); | |
452 | mux_mode = val | i; | |
453 | printk(KERN_DEBUG "mux: Setting signal " | |
454 | "%s.%s 0x%04x -> 0x%04x\n", | |
455 | m0_entry, muxname, old_mode, mux_mode); | |
456 | omap_mux_write(mux_mode, m->reg_offset); | |
457 | found++; | |
458 | } | |
459 | } | |
460 | } | |
461 | ||
462 | if (found == 1) | |
463 | return 0; | |
464 | ||
465 | if (found > 1) { | |
466 | printk(KERN_ERR "mux: Multiple signal paths (%i) for %s\n", | |
467 | found, muxname); | |
468 | return -EINVAL; | |
469 | } | |
470 | ||
471 | printk(KERN_ERR "mux: Could not set signal %s\n", muxname); | |
472 | ||
473 | return -ENODEV; | |
474 | } | |
475 | ||
4b715efc TL |
476 | #ifdef CONFIG_DEBUG_FS |
477 | ||
478 | #define OMAP_MUX_MAX_NR_FLAGS 10 | |
479 | #define OMAP_MUX_TEST_FLAG(val, mask) \ | |
480 | if (((val) & (mask)) == (mask)) { \ | |
481 | i++; \ | |
482 | flags[i] = #mask; \ | |
483 | } | |
484 | ||
485 | /* REVISIT: Add checking for non-optimal mux settings */ | |
486 | static inline void omap_mux_decode(struct seq_file *s, u16 val) | |
487 | { | |
488 | char *flags[OMAP_MUX_MAX_NR_FLAGS]; | |
78737ae1 | 489 | char mode[sizeof("OMAP_MUX_MODE") + 1]; |
4b715efc TL |
490 | int i = -1; |
491 | ||
492 | sprintf(mode, "OMAP_MUX_MODE%d", val & 0x7); | |
493 | i++; | |
494 | flags[i] = mode; | |
495 | ||
496 | OMAP_MUX_TEST_FLAG(val, OMAP_PIN_OFF_WAKEUPENABLE); | |
497 | if (val & OMAP_OFF_EN) { | |
498 | if (!(val & OMAP_OFFOUT_EN)) { | |
499 | if (!(val & OMAP_OFF_PULL_UP)) { | |
500 | OMAP_MUX_TEST_FLAG(val, | |
501 | OMAP_PIN_OFF_INPUT_PULLDOWN); | |
502 | } else { | |
503 | OMAP_MUX_TEST_FLAG(val, | |
504 | OMAP_PIN_OFF_INPUT_PULLUP); | |
505 | } | |
506 | } else { | |
507 | if (!(val & OMAP_OFFOUT_VAL)) { | |
508 | OMAP_MUX_TEST_FLAG(val, | |
509 | OMAP_PIN_OFF_OUTPUT_LOW); | |
510 | } else { | |
511 | OMAP_MUX_TEST_FLAG(val, | |
512 | OMAP_PIN_OFF_OUTPUT_HIGH); | |
513 | } | |
514 | } | |
515 | } | |
516 | ||
517 | if (val & OMAP_INPUT_EN) { | |
518 | if (val & OMAP_PULL_ENA) { | |
519 | if (!(val & OMAP_PULL_UP)) { | |
520 | OMAP_MUX_TEST_FLAG(val, | |
521 | OMAP_PIN_INPUT_PULLDOWN); | |
522 | } else { | |
523 | OMAP_MUX_TEST_FLAG(val, OMAP_PIN_INPUT_PULLUP); | |
524 | } | |
525 | } else { | |
526 | OMAP_MUX_TEST_FLAG(val, OMAP_PIN_INPUT); | |
527 | } | |
528 | } else { | |
529 | i++; | |
530 | flags[i] = "OMAP_PIN_OUTPUT"; | |
531 | } | |
532 | ||
533 | do { | |
534 | seq_printf(s, "%s", flags[i]); | |
535 | if (i > 0) | |
536 | seq_printf(s, " | "); | |
537 | } while (i-- > 0); | |
538 | } | |
539 | ||
540 | #define OMAP_MUX_DEFNAME_LEN 16 | |
541 | ||
542 | static int omap_mux_dbg_board_show(struct seq_file *s, void *unused) | |
543 | { | |
544 | struct omap_mux_entry *e; | |
545 | ||
546 | list_for_each_entry(e, &muxmodes, node) { | |
547 | struct omap_mux *m = &e->mux; | |
548 | char m0_def[OMAP_MUX_DEFNAME_LEN]; | |
549 | char *m0_name = m->muxnames[0]; | |
550 | u16 val; | |
551 | int i, mode; | |
552 | ||
553 | if (!m0_name) | |
554 | continue; | |
555 | ||
78737ae1 | 556 | /* REVISIT: Needs to be updated if mode0 names get longer */ |
4b715efc TL |
557 | for (i = 0; i < OMAP_MUX_DEFNAME_LEN; i++) { |
558 | if (m0_name[i] == '\0') { | |
559 | m0_def[i] = m0_name[i]; | |
560 | break; | |
561 | } | |
562 | m0_def[i] = toupper(m0_name[i]); | |
563 | } | |
564 | val = omap_mux_read(m->reg_offset); | |
565 | mode = val & OMAP_MUX_MODE7; | |
566 | ||
567 | seq_printf(s, "OMAP%i_MUX(%s, ", | |
568 | cpu_is_omap34xx() ? 3 : 0, m0_def); | |
569 | omap_mux_decode(s, val); | |
570 | seq_printf(s, "),\n"); | |
571 | } | |
572 | ||
573 | return 0; | |
574 | } | |
575 | ||
576 | static int omap_mux_dbg_board_open(struct inode *inode, struct file *file) | |
577 | { | |
578 | return single_open(file, omap_mux_dbg_board_show, &inode->i_private); | |
579 | } | |
580 | ||
581 | static const struct file_operations omap_mux_dbg_board_fops = { | |
582 | .open = omap_mux_dbg_board_open, | |
583 | .read = seq_read, | |
584 | .llseek = seq_lseek, | |
585 | .release = single_release, | |
586 | }; | |
587 | ||
588 | static int omap_mux_dbg_signal_show(struct seq_file *s, void *unused) | |
589 | { | |
590 | struct omap_mux *m = s->private; | |
591 | const char *none = "NA"; | |
592 | u16 val; | |
593 | int mode; | |
594 | ||
595 | val = omap_mux_read(m->reg_offset); | |
596 | mode = val & OMAP_MUX_MODE7; | |
597 | ||
598 | seq_printf(s, "name: %s.%s (0x%08lx/0x%03x = 0x%04x), b %s, t %s\n", | |
599 | m->muxnames[0], m->muxnames[mode], | |
600 | mux_phys + m->reg_offset, m->reg_offset, val, | |
601 | m->balls[0] ? m->balls[0] : none, | |
602 | m->balls[1] ? m->balls[1] : none); | |
603 | seq_printf(s, "mode: "); | |
604 | omap_mux_decode(s, val); | |
605 | seq_printf(s, "\n"); | |
606 | seq_printf(s, "signals: %s | %s | %s | %s | %s | %s | %s | %s\n", | |
607 | m->muxnames[0] ? m->muxnames[0] : none, | |
608 | m->muxnames[1] ? m->muxnames[1] : none, | |
609 | m->muxnames[2] ? m->muxnames[2] : none, | |
610 | m->muxnames[3] ? m->muxnames[3] : none, | |
611 | m->muxnames[4] ? m->muxnames[4] : none, | |
612 | m->muxnames[5] ? m->muxnames[5] : none, | |
613 | m->muxnames[6] ? m->muxnames[6] : none, | |
614 | m->muxnames[7] ? m->muxnames[7] : none); | |
615 | ||
616 | return 0; | |
617 | } | |
618 | ||
619 | #define OMAP_MUX_MAX_ARG_CHAR 7 | |
620 | ||
621 | static ssize_t omap_mux_dbg_signal_write(struct file *file, | |
622 | const char __user *user_buf, | |
623 | size_t count, loff_t *ppos) | |
624 | { | |
625 | char buf[OMAP_MUX_MAX_ARG_CHAR]; | |
626 | struct seq_file *seqf; | |
627 | struct omap_mux *m; | |
628 | unsigned long val; | |
629 | int buf_size, ret; | |
630 | ||
631 | if (count > OMAP_MUX_MAX_ARG_CHAR) | |
632 | return -EINVAL; | |
633 | ||
634 | memset(buf, 0, sizeof(buf)); | |
635 | buf_size = min(count, sizeof(buf) - 1); | |
636 | ||
637 | if (copy_from_user(buf, user_buf, buf_size)) | |
638 | return -EFAULT; | |
639 | ||
640 | ret = strict_strtoul(buf, 0x10, &val); | |
641 | if (ret < 0) | |
642 | return ret; | |
643 | ||
644 | if (val > 0xffff) | |
645 | return -EINVAL; | |
646 | ||
647 | seqf = file->private_data; | |
648 | m = seqf->private; | |
649 | ||
650 | omap_mux_write((u16)val, m->reg_offset); | |
651 | *ppos += count; | |
652 | ||
653 | return count; | |
654 | } | |
655 | ||
656 | static int omap_mux_dbg_signal_open(struct inode *inode, struct file *file) | |
657 | { | |
658 | return single_open(file, omap_mux_dbg_signal_show, inode->i_private); | |
659 | } | |
660 | ||
661 | static const struct file_operations omap_mux_dbg_signal_fops = { | |
662 | .open = omap_mux_dbg_signal_open, | |
663 | .read = seq_read, | |
664 | .write = omap_mux_dbg_signal_write, | |
665 | .llseek = seq_lseek, | |
666 | .release = single_release, | |
667 | }; | |
668 | ||
669 | static struct dentry *mux_dbg_dir; | |
670 | ||
671 | static void __init omap_mux_dbg_init(void) | |
672 | { | |
673 | struct omap_mux_entry *e; | |
674 | ||
675 | mux_dbg_dir = debugfs_create_dir("omap_mux", NULL); | |
676 | if (!mux_dbg_dir) | |
677 | return; | |
678 | ||
679 | (void)debugfs_create_file("board", S_IRUGO, mux_dbg_dir, | |
680 | NULL, &omap_mux_dbg_board_fops); | |
681 | ||
682 | list_for_each_entry(e, &muxmodes, node) { | |
683 | struct omap_mux *m = &e->mux; | |
684 | ||
685 | (void)debugfs_create_file(m->muxnames[0], S_IWUGO, mux_dbg_dir, | |
686 | m, &omap_mux_dbg_signal_fops); | |
687 | } | |
688 | } | |
689 | ||
690 | #else | |
691 | static inline void omap_mux_dbg_init(void) | |
692 | { | |
693 | } | |
694 | #endif /* CONFIG_DEBUG_FS */ | |
695 | ||
15ac7afe TL |
696 | static void __init omap_mux_free_names(struct omap_mux *m) |
697 | { | |
698 | int i; | |
699 | ||
700 | for (i = 0; i < OMAP_MUX_NR_MODES; i++) | |
701 | kfree(m->muxnames[i]); | |
702 | ||
703 | #ifdef CONFIG_DEBUG_FS | |
704 | for (i = 0; i < OMAP_MUX_NR_SIDES; i++) | |
705 | kfree(m->balls[i]); | |
706 | #endif | |
707 | ||
708 | } | |
709 | ||
710 | /* Free all data except for GPIO pins unless CONFIG_DEBUG_FS is set */ | |
711 | static int __init omap_mux_late_init(void) | |
712 | { | |
713 | struct omap_mux_entry *e, *tmp; | |
714 | ||
715 | list_for_each_entry_safe(e, tmp, &muxmodes, node) { | |
716 | struct omap_mux *m = &e->mux; | |
717 | u16 mode = omap_mux_read(m->reg_offset); | |
718 | ||
719 | if (OMAP_MODE_GPIO(mode)) | |
720 | continue; | |
721 | ||
722 | #ifndef CONFIG_DEBUG_FS | |
723 | mutex_lock(&muxmode_mutex); | |
724 | list_del(&e->node); | |
725 | mutex_unlock(&muxmode_mutex); | |
726 | omap_mux_free_names(m); | |
727 | kfree(m); | |
1dbae815 | 728 | #endif |
15ac7afe TL |
729 | |
730 | } | |
731 | ||
4b715efc TL |
732 | omap_mux_dbg_init(); |
733 | ||
15ac7afe TL |
734 | return 0; |
735 | } | |
736 | late_initcall(omap_mux_late_init); | |
737 | ||
738 | static void __init omap_mux_package_fixup(struct omap_mux *p, | |
739 | struct omap_mux *superset) | |
740 | { | |
741 | while (p->reg_offset != OMAP_MUX_TERMINATOR) { | |
742 | struct omap_mux *s = superset; | |
743 | int found = 0; | |
744 | ||
745 | while (s->reg_offset != OMAP_MUX_TERMINATOR) { | |
746 | if (s->reg_offset == p->reg_offset) { | |
747 | *s = *p; | |
748 | found++; | |
749 | break; | |
750 | } | |
751 | s++; | |
752 | } | |
753 | if (!found) | |
754 | printk(KERN_ERR "mux: Unknown entry offset 0x%x\n", | |
755 | p->reg_offset); | |
756 | p++; | |
757 | } | |
758 | } | |
759 | ||
760 | #ifdef CONFIG_DEBUG_FS | |
761 | ||
762 | static void __init omap_mux_package_init_balls(struct omap_ball *b, | |
763 | struct omap_mux *superset) | |
764 | { | |
765 | while (b->reg_offset != OMAP_MUX_TERMINATOR) { | |
766 | struct omap_mux *s = superset; | |
767 | int found = 0; | |
768 | ||
769 | while (s->reg_offset != OMAP_MUX_TERMINATOR) { | |
770 | if (s->reg_offset == b->reg_offset) { | |
771 | s->balls[0] = b->balls[0]; | |
772 | s->balls[1] = b->balls[1]; | |
773 | found++; | |
774 | break; | |
775 | } | |
776 | s++; | |
777 | } | |
778 | if (!found) | |
779 | printk(KERN_ERR "mux: Unknown ball offset 0x%x\n", | |
780 | b->reg_offset); | |
781 | b++; | |
782 | } | |
783 | } | |
784 | ||
785 | #else /* CONFIG_DEBUG_FS */ | |
786 | ||
787 | static inline void omap_mux_package_init_balls(struct omap_ball *b, | |
788 | struct omap_mux *superset) | |
789 | { | |
790 | } | |
791 | ||
792 | #endif /* CONFIG_DEBUG_FS */ | |
793 | ||
794 | static int __init omap_mux_setup(char *options) | |
795 | { | |
796 | if (!options) | |
797 | return 0; | |
798 | ||
799 | omap_mux_options = options; | |
800 | ||
801 | return 1; | |
802 | } | |
803 | __setup("omap_mux=", omap_mux_setup); | |
804 | ||
805 | /* | |
806 | * Note that the omap_mux=some.signal1=0x1234,some.signal2=0x1234 | |
807 | * cmdline options only override the bootloader values. | |
808 | * During development, please enable CONFIG_DEBUG_FS, and use the | |
809 | * signal specific entries under debugfs. | |
810 | */ | |
811 | static void __init omap_mux_set_cmdline_signals(void) | |
812 | { | |
813 | char *options, *next_opt, *token; | |
814 | ||
815 | if (!omap_mux_options) | |
816 | return; | |
817 | ||
818 | options = kmalloc(strlen(omap_mux_options) + 1, GFP_KERNEL); | |
819 | if (!options) | |
820 | return; | |
821 | ||
822 | strcpy(options, omap_mux_options); | |
823 | next_opt = options; | |
824 | ||
825 | while ((token = strsep(&next_opt, ",")) != NULL) { | |
826 | char *keyval, *name; | |
827 | unsigned long val; | |
828 | ||
829 | keyval = token; | |
830 | name = strsep(&keyval, "="); | |
831 | if (name) { | |
832 | int res; | |
833 | ||
834 | res = strict_strtoul(keyval, 0x10, &val); | |
835 | if (res < 0) | |
836 | continue; | |
837 | ||
838 | omap_mux_init_signal(name, (u16)val); | |
839 | } | |
840 | } | |
841 | ||
842 | kfree(options); | |
843 | } | |
844 | ||
15ac7afe TL |
845 | static int __init omap_mux_copy_names(struct omap_mux *src, |
846 | struct omap_mux *dst) | |
847 | { | |
848 | int i; | |
849 | ||
850 | for (i = 0; i < OMAP_MUX_NR_MODES; i++) { | |
851 | if (src->muxnames[i]) { | |
852 | dst->muxnames[i] = | |
853 | kmalloc(strlen(src->muxnames[i]) + 1, | |
854 | GFP_KERNEL); | |
855 | if (!dst->muxnames[i]) | |
856 | goto free; | |
857 | strcpy(dst->muxnames[i], src->muxnames[i]); | |
858 | } | |
859 | } | |
860 | ||
861 | #ifdef CONFIG_DEBUG_FS | |
862 | for (i = 0; i < OMAP_MUX_NR_SIDES; i++) { | |
863 | if (src->balls[i]) { | |
864 | dst->balls[i] = | |
865 | kmalloc(strlen(src->balls[i]) + 1, | |
866 | GFP_KERNEL); | |
867 | if (!dst->balls[i]) | |
868 | goto free; | |
869 | strcpy(dst->balls[i], src->balls[i]); | |
870 | } | |
871 | } | |
872 | #endif | |
873 | ||
874 | return 0; | |
875 | ||
876 | free: | |
877 | omap_mux_free_names(dst); | |
878 | return -ENOMEM; | |
879 | ||
880 | } | |
881 | ||
882 | #endif /* CONFIG_OMAP_MUX */ | |
883 | ||
884 | static u16 omap_mux_get_by_gpio(int gpio) | |
885 | { | |
886 | struct omap_mux_entry *e; | |
887 | u16 offset = OMAP_MUX_TERMINATOR; | |
888 | ||
889 | list_for_each_entry(e, &muxmodes, node) { | |
890 | struct omap_mux *m = &e->mux; | |
891 | if (m->gpio == gpio) { | |
892 | offset = m->reg_offset; | |
893 | break; | |
894 | } | |
895 | } | |
896 | ||
897 | return offset; | |
898 | } | |
899 | ||
900 | /* Needed for dynamic muxing of GPIO pins for off-idle */ | |
901 | u16 omap_mux_get_gpio(int gpio) | |
902 | { | |
903 | u16 offset; | |
904 | ||
905 | offset = omap_mux_get_by_gpio(gpio); | |
906 | if (offset == OMAP_MUX_TERMINATOR) { | |
907 | printk(KERN_ERR "mux: Could not get gpio%i\n", gpio); | |
908 | return offset; | |
909 | } | |
910 | ||
911 | return omap_mux_read(offset); | |
912 | } | |
913 | ||
914 | /* Needed for dynamic muxing of GPIO pins for off-idle */ | |
915 | void omap_mux_set_gpio(u16 val, int gpio) | |
916 | { | |
917 | u16 offset; | |
918 | ||
919 | offset = omap_mux_get_by_gpio(gpio); | |
920 | if (offset == OMAP_MUX_TERMINATOR) { | |
921 | printk(KERN_ERR "mux: Could not set gpio%i\n", gpio); | |
922 | return; | |
923 | } | |
924 | ||
925 | omap_mux_write(val, offset); | |
926 | } | |
927 | ||
928 | static struct omap_mux * __init omap_mux_list_add(struct omap_mux *src) | |
929 | { | |
930 | struct omap_mux_entry *entry; | |
931 | struct omap_mux *m; | |
932 | ||
933 | entry = kzalloc(sizeof(struct omap_mux_entry), GFP_KERNEL); | |
934 | if (!entry) | |
935 | return NULL; | |
936 | ||
937 | m = &entry->mux; | |
938 | memcpy(m, src, sizeof(struct omap_mux_entry)); | |
939 | ||
940 | #ifdef CONFIG_OMAP_MUX | |
941 | if (omap_mux_copy_names(src, m)) { | |
942 | kfree(entry); | |
943 | return NULL; | |
944 | } | |
945 | #endif | |
946 | ||
947 | mutex_lock(&muxmode_mutex); | |
948 | list_add_tail(&entry->node, &muxmodes); | |
949 | mutex_unlock(&muxmode_mutex); | |
950 | ||
951 | return m; | |
952 | } | |
953 | ||
954 | /* | |
955 | * Note if CONFIG_OMAP_MUX is not selected, we will only initialize | |
956 | * the GPIO to mux offset mapping that is needed for dynamic muxing | |
957 | * of GPIO pins for off-idle. | |
958 | */ | |
959 | static void __init omap_mux_init_list(struct omap_mux *superset) | |
960 | { | |
961 | while (superset->reg_offset != OMAP_MUX_TERMINATOR) { | |
962 | struct omap_mux *entry; | |
963 | ||
b72c7d54 RL |
964 | #ifdef CONFIG_OMAP_MUX |
965 | if (!superset->muxnames || !superset->muxnames[0]) { | |
15ac7afe TL |
966 | superset++; |
967 | continue; | |
968 | } | |
b72c7d54 RL |
969 | #else |
970 | /* Skip pins that are not muxed as GPIO by bootloader */ | |
971 | if (!OMAP_MODE_GPIO(omap_mux_read(superset->reg_offset))) { | |
9ecef433 TL |
972 | superset++; |
973 | continue; | |
974 | } | |
975 | #endif | |
976 | ||
15ac7afe TL |
977 | entry = omap_mux_list_add(superset); |
978 | if (!entry) { | |
979 | printk(KERN_ERR "mux: Could not add entry\n"); | |
980 | return; | |
981 | } | |
982 | superset++; | |
983 | } | |
984 | } | |
985 | ||
321cfc85 TL |
986 | #ifdef CONFIG_OMAP_MUX |
987 | ||
988 | static void omap_mux_init_package(struct omap_mux *superset, | |
989 | struct omap_mux *package_subset, | |
990 | struct omap_ball *package_balls) | |
991 | { | |
992 | if (package_subset) | |
993 | omap_mux_package_fixup(package_subset, superset); | |
994 | if (package_balls) | |
995 | omap_mux_package_init_balls(package_balls, superset); | |
996 | } | |
997 | ||
998 | static void omap_mux_init_signals(struct omap_board_mux *board_mux) | |
999 | { | |
1000 | omap_mux_set_cmdline_signals(); | |
1001 | omap_mux_write_array(board_mux); | |
1002 | } | |
1003 | ||
1004 | #else | |
1005 | ||
1006 | static void omap_mux_init_package(struct omap_mux *superset, | |
1007 | struct omap_mux *package_subset, | |
1008 | struct omap_ball *package_balls) | |
1009 | { | |
1010 | } | |
1011 | ||
1012 | static void omap_mux_init_signals(struct omap_board_mux *board_mux) | |
1013 | { | |
1014 | } | |
1015 | ||
1016 | #endif | |
1017 | ||
15ac7afe TL |
1018 | int __init omap_mux_init(u32 mux_pbase, u32 mux_size, |
1019 | struct omap_mux *superset, | |
1020 | struct omap_mux *package_subset, | |
1021 | struct omap_board_mux *board_mux, | |
1022 | struct omap_ball *package_balls) | |
1023 | { | |
1024 | if (mux_base) | |
1025 | return -EBUSY; | |
1026 | ||
4b715efc | 1027 | mux_phys = mux_pbase; |
15ac7afe TL |
1028 | mux_base = ioremap(mux_pbase, mux_size); |
1029 | if (!mux_base) { | |
1030 | printk(KERN_ERR "mux: Could not ioremap\n"); | |
1031 | return -ENODEV; | |
1032 | } | |
1033 | ||
321cfc85 | 1034 | omap_mux_init_package(superset, package_subset, package_balls); |
15ac7afe | 1035 | omap_mux_init_list(superset); |
321cfc85 | 1036 | omap_mux_init_signals(board_mux); |
2cb0c54f | 1037 | |
15ac7afe TL |
1038 | return 0; |
1039 | } | |
1040 | ||
a8eb7ca0 | 1041 | #endif /* CONFIG_ARCH_OMAP3 */ |
15f45e6f | 1042 |