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