]>
Commit | Line | Data |
---|---|---|
bc5833c4 JL |
1 | /* |
2 | * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. | |
3 | * | |
4 | * See file CREDITS for list of people who contributed to this | |
5 | * project. | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or | |
8 | * modify it under the terms of the GNU General Public License as | |
9 | * published by the Free Software Foundation; either version 2 of | |
10 | * the License, or (at your option) any later version. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
f5cdc117 | 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
bc5833c4 JL |
15 | * GNU General Public License for more details. |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with this program; if not, write to the Free Software | |
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
20 | * MA 02111-1307 USA | |
21 | */ | |
22 | ||
23 | #include <common.h> | |
24 | #include <asm/io.h> | |
25 | #include <asm/arch/imx-regs.h> | |
26 | #include <asm/arch/mx6x_pins.h> | |
27 | #include <asm/arch/iomux-v3.h> | |
3996a96c | 28 | #include <asm/arch/clock.h> |
bc5833c4 JL |
29 | #include <asm/errno.h> |
30 | #include <asm/gpio.h> | |
31 | #include <mmc.h> | |
32 | #include <fsl_esdhc.h> | |
2bf3359e | 33 | #include <micrel.h> |
2af81e27 JL |
34 | #include <miiphy.h> |
35 | #include <netdev.h> | |
bc5833c4 JL |
36 | DECLARE_GLOBAL_DATA_PTR; |
37 | ||
f5cdc117 WD |
38 | #define UART_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \ |
39 | PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \ | |
bc5833c4 JL |
40 | PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) |
41 | ||
f5cdc117 WD |
42 | #define USDHC_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \ |
43 | PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_LOW | \ | |
bc5833c4 JL |
44 | PAD_CTL_DSE_80ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) |
45 | ||
2af81e27 | 46 | #define ENET_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \ |
f5cdc117 | 47 | PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \ |
2af81e27 JL |
48 | PAD_CTL_DSE_40ohm | PAD_CTL_HYS) |
49 | ||
373a1d8c EN |
50 | #define SPI_PAD_CTRL (PAD_CTL_HYS | \ |
51 | PAD_CTL_PUS_100K_DOWN | PAD_CTL_SPEED_MED | \ | |
52 | PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST) | |
53 | ||
28fdbddc EN |
54 | #define BUTTON_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \ |
55 | PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \ | |
56 | PAD_CTL_DSE_40ohm | PAD_CTL_HYS) | |
57 | ||
bc5833c4 JL |
58 | int dram_init(void) |
59 | { | |
60 | gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE); | |
61 | ||
62 | return 0; | |
63 | } | |
64 | ||
8e7d7b6b TK |
65 | iomux_v3_cfg_t uart1_pads[] = { |
66 | MX6Q_PAD_SD3_DAT6__UART1_RXD | MUX_PAD_CTRL(UART_PAD_CTRL), | |
67 | MX6Q_PAD_SD3_DAT7__UART1_TXD | MUX_PAD_CTRL(UART_PAD_CTRL), | |
68 | }; | |
69 | ||
bc5833c4 JL |
70 | iomux_v3_cfg_t uart2_pads[] = { |
71 | MX6Q_PAD_EIM_D26__UART2_TXD | MUX_PAD_CTRL(UART_PAD_CTRL), | |
72 | MX6Q_PAD_EIM_D27__UART2_RXD | MUX_PAD_CTRL(UART_PAD_CTRL), | |
73 | }; | |
74 | ||
75 | iomux_v3_cfg_t usdhc3_pads[] = { | |
76 | MX6Q_PAD_SD3_CLK__USDHC3_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL), | |
77 | MX6Q_PAD_SD3_CMD__USDHC3_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL), | |
78 | MX6Q_PAD_SD3_DAT0__USDHC3_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL), | |
79 | MX6Q_PAD_SD3_DAT1__USDHC3_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL), | |
80 | MX6Q_PAD_SD3_DAT2__USDHC3_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL), | |
81 | MX6Q_PAD_SD3_DAT3__USDHC3_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL), | |
82 | MX6Q_PAD_SD3_DAT5__GPIO_7_0 | MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */ | |
83 | }; | |
84 | ||
85 | iomux_v3_cfg_t usdhc4_pads[] = { | |
86 | MX6Q_PAD_SD4_CLK__USDHC4_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL), | |
87 | MX6Q_PAD_SD4_CMD__USDHC4_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL), | |
88 | MX6Q_PAD_SD4_DAT0__USDHC4_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL), | |
89 | MX6Q_PAD_SD4_DAT1__USDHC4_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL), | |
90 | MX6Q_PAD_SD4_DAT2__USDHC4_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL), | |
91 | MX6Q_PAD_SD4_DAT3__USDHC4_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL), | |
92 | MX6Q_PAD_NANDF_D6__GPIO_2_6 | MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */ | |
93 | }; | |
94 | ||
2af81e27 JL |
95 | iomux_v3_cfg_t enet_pads1[] = { |
96 | MX6Q_PAD_ENET_MDIO__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
97 | MX6Q_PAD_ENET_MDC__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
98 | MX6Q_PAD_RGMII_TXC__ENET_RGMII_TXC | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
99 | MX6Q_PAD_RGMII_TD0__ENET_RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
100 | MX6Q_PAD_RGMII_TD1__ENET_RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
101 | MX6Q_PAD_RGMII_TD2__ENET_RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
102 | MX6Q_PAD_RGMII_TD3__ENET_RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
103 | MX6Q_PAD_RGMII_TX_CTL__RGMII_TX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
104 | MX6Q_PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
105 | /* pin 35 - 1 (PHY_AD2) on reset */ | |
106 | MX6Q_PAD_RGMII_RXC__GPIO_6_30 | MUX_PAD_CTRL(NO_PAD_CTRL), | |
107 | /* pin 32 - 1 - (MODE0) all */ | |
108 | MX6Q_PAD_RGMII_RD0__GPIO_6_25 | MUX_PAD_CTRL(NO_PAD_CTRL), | |
109 | /* pin 31 - 1 - (MODE1) all */ | |
110 | MX6Q_PAD_RGMII_RD1__GPIO_6_27 | MUX_PAD_CTRL(NO_PAD_CTRL), | |
111 | /* pin 28 - 1 - (MODE2) all */ | |
112 | MX6Q_PAD_RGMII_RD2__GPIO_6_28 | MUX_PAD_CTRL(NO_PAD_CTRL), | |
113 | /* pin 27 - 1 - (MODE3) all */ | |
114 | MX6Q_PAD_RGMII_RD3__GPIO_6_29 | MUX_PAD_CTRL(NO_PAD_CTRL), | |
115 | /* pin 33 - 1 - (CLK125_EN) 125Mhz clockout enabled */ | |
116 | MX6Q_PAD_RGMII_RX_CTL__GPIO_6_24 | MUX_PAD_CTRL(NO_PAD_CTRL), | |
117 | /* pin 42 PHY nRST */ | |
118 | MX6Q_PAD_EIM_D23__GPIO_3_23 | MUX_PAD_CTRL(NO_PAD_CTRL), | |
119 | }; | |
120 | ||
121 | iomux_v3_cfg_t enet_pads2[] = { | |
122 | MX6Q_PAD_RGMII_RXC__ENET_RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
123 | MX6Q_PAD_RGMII_RD0__ENET_RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
124 | MX6Q_PAD_RGMII_RD1__ENET_RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
125 | MX6Q_PAD_RGMII_RD2__ENET_RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
126 | MX6Q_PAD_RGMII_RD3__ENET_RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
127 | MX6Q_PAD_RGMII_RX_CTL__RGMII_RX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
128 | }; | |
129 | ||
28fdbddc EN |
130 | /* Button assignments for J14 */ |
131 | static iomux_v3_cfg_t button_pads[] = { | |
132 | /* Menu */ | |
133 | MX6Q_PAD_NANDF_D1__GPIO_2_1 | MUX_PAD_CTRL(BUTTON_PAD_CTRL), | |
134 | /* Back */ | |
135 | MX6Q_PAD_NANDF_D2__GPIO_2_2 | MUX_PAD_CTRL(BUTTON_PAD_CTRL), | |
136 | /* Labelled Search (mapped to Power under Android) */ | |
137 | MX6Q_PAD_NANDF_D3__GPIO_2_3 | MUX_PAD_CTRL(BUTTON_PAD_CTRL), | |
138 | /* Home */ | |
139 | MX6Q_PAD_NANDF_D4__GPIO_2_4 | MUX_PAD_CTRL(BUTTON_PAD_CTRL), | |
140 | /* Volume Down */ | |
141 | MX6Q_PAD_GPIO_19__GPIO_4_5 | MUX_PAD_CTRL(BUTTON_PAD_CTRL), | |
142 | /* Volume Up */ | |
143 | MX6Q_PAD_GPIO_18__GPIO_7_13 | MUX_PAD_CTRL(BUTTON_PAD_CTRL), | |
144 | }; | |
145 | ||
2af81e27 JL |
146 | static void setup_iomux_enet(void) |
147 | { | |
148 | gpio_direction_output(87, 0); /* GPIO 3-23 */ | |
149 | gpio_direction_output(190, 1); /* GPIO 6-30 */ | |
150 | gpio_direction_output(185, 1); /* GPIO 6-25 */ | |
151 | gpio_direction_output(187, 1); /* GPIO 6-27 */ | |
152 | gpio_direction_output(188, 1); /* GPIO 6-28*/ | |
153 | gpio_direction_output(189, 1); /* GPIO 6-29 */ | |
154 | imx_iomux_v3_setup_multiple_pads(enet_pads1, ARRAY_SIZE(enet_pads1)); | |
155 | gpio_direction_output(184, 1); /* GPIO 6-24 */ | |
156 | ||
157 | /* Need delay 10ms according to KSZ9021 spec */ | |
158 | udelay(1000 * 10); | |
bdb9f760 | 159 | gpio_set_value(87, 1); /* GPIO 3-23 */ |
2af81e27 JL |
160 | |
161 | imx_iomux_v3_setup_multiple_pads(enet_pads2, ARRAY_SIZE(enet_pads2)); | |
162 | } | |
163 | ||
2ea73e9e WG |
164 | iomux_v3_cfg_t usb_pads[] = { |
165 | MX6Q_PAD_GPIO_17__GPIO_7_12 | MUX_PAD_CTRL(NO_PAD_CTRL), | |
166 | }; | |
167 | ||
bc5833c4 JL |
168 | static void setup_iomux_uart(void) |
169 | { | |
8e7d7b6b | 170 | imx_iomux_v3_setup_multiple_pads(uart1_pads, ARRAY_SIZE(uart1_pads)); |
bc5833c4 JL |
171 | imx_iomux_v3_setup_multiple_pads(uart2_pads, ARRAY_SIZE(uart2_pads)); |
172 | } | |
173 | ||
2ea73e9e WG |
174 | #ifdef CONFIG_USB_EHCI_MX6 |
175 | int board_ehci_hcd_init(int port) | |
176 | { | |
177 | imx_iomux_v3_setup_multiple_pads(usb_pads, ARRAY_SIZE(usb_pads)); | |
178 | ||
179 | /* Reset USB hub */ | |
180 | gpio_direction_output(GPIO_NUMBER(7, 12), 0); | |
181 | mdelay(2); | |
182 | gpio_set_value(GPIO_NUMBER(7, 12), 1); | |
183 | ||
184 | return 0; | |
185 | } | |
186 | #endif | |
187 | ||
bc5833c4 JL |
188 | #ifdef CONFIG_FSL_ESDHC |
189 | struct fsl_esdhc_cfg usdhc_cfg[2] = { | |
190 | {USDHC3_BASE_ADDR, 1}, | |
191 | {USDHC4_BASE_ADDR, 1}, | |
192 | }; | |
193 | ||
194 | int board_mmc_getcd(struct mmc *mmc) | |
195 | { | |
196 | struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv; | |
197 | int ret; | |
198 | ||
199 | if (cfg->esdhc_base == USDHC3_BASE_ADDR) { | |
f5cdc117 WD |
200 | gpio_direction_input(192); /*GPIO7_0*/ |
201 | ret = !gpio_get_value(192); | |
bc5833c4 | 202 | } else { |
f5cdc117 WD |
203 | gpio_direction_input(38); /*GPIO2_6*/ |
204 | ret = !gpio_get_value(38); | |
bc5833c4 JL |
205 | } |
206 | ||
207 | return ret; | |
208 | } | |
209 | ||
210 | int board_mmc_init(bd_t *bis) | |
211 | { | |
212 | s32 status = 0; | |
213 | u32 index = 0; | |
214 | ||
215 | for (index = 0; index < CONFIG_SYS_FSL_USDHC_NUM; ++index) { | |
f5cdc117 WD |
216 | switch (index) { |
217 | case 0: | |
218 | imx_iomux_v3_setup_multiple_pads( | |
219 | usdhc3_pads, ARRAY_SIZE(usdhc3_pads)); | |
220 | break; | |
221 | case 1: | |
222 | imx_iomux_v3_setup_multiple_pads( | |
223 | usdhc4_pads, ARRAY_SIZE(usdhc4_pads)); | |
224 | break; | |
225 | default: | |
226 | printf("Warning: you configured more USDHC controllers" | |
227 | "(%d) then supported by the board (%d)\n", | |
228 | index + 1, CONFIG_SYS_FSL_USDHC_NUM); | |
229 | return status; | |
230 | } | |
231 | ||
232 | status |= fsl_esdhc_initialize(bis, &usdhc_cfg[index]); | |
bc5833c4 JL |
233 | } |
234 | ||
235 | return status; | |
236 | } | |
237 | #endif | |
238 | ||
1c9ceff8 EN |
239 | u32 get_board_rev(void) |
240 | { | |
241 | return 0x63000 ; | |
242 | } | |
243 | ||
373a1d8c EN |
244 | #ifdef CONFIG_MXC_SPI |
245 | iomux_v3_cfg_t ecspi1_pads[] = { | |
246 | /* SS1 */ | |
247 | MX6Q_PAD_EIM_D19__GPIO_3_19 | MUX_PAD_CTRL(SPI_PAD_CTRL), | |
248 | MX6Q_PAD_EIM_D17__ECSPI1_MISO | MUX_PAD_CTRL(SPI_PAD_CTRL), | |
249 | MX6Q_PAD_EIM_D18__ECSPI1_MOSI | MUX_PAD_CTRL(SPI_PAD_CTRL), | |
250 | MX6Q_PAD_EIM_D16__ECSPI1_SCLK | MUX_PAD_CTRL(SPI_PAD_CTRL), | |
251 | }; | |
252 | ||
253 | void setup_spi(void) | |
254 | { | |
ba54b927 | 255 | gpio_direction_output(CONFIG_SF_DEFAULT_CS, 1); |
373a1d8c EN |
256 | imx_iomux_v3_setup_multiple_pads(ecspi1_pads, |
257 | ARRAY_SIZE(ecspi1_pads)); | |
258 | } | |
259 | #endif | |
260 | ||
2bf3359e | 261 | int board_phy_config(struct phy_device *phydev) |
2af81e27 | 262 | { |
2af81e27 | 263 | /* min rx data delay */ |
2bf3359e TK |
264 | ksz9021_phy_extended_write(phydev, |
265 | MII_KSZ9021_EXT_RGMII_RX_DATA_SKEW, 0x0); | |
266 | /* min tx data delay */ | |
267 | ksz9021_phy_extended_write(phydev, | |
268 | MII_KSZ9021_EXT_RGMII_TX_DATA_SKEW, 0x0); | |
269 | /* max rx/tx clock delay, min rx/tx control */ | |
270 | ksz9021_phy_extended_write(phydev, | |
271 | MII_KSZ9021_EXT_RGMII_CLOCK_SKEW, 0xf0f0); | |
272 | if (phydev->drv->config) | |
273 | phydev->drv->config(phydev); | |
f5cdc117 | 274 | |
2af81e27 JL |
275 | return 0; |
276 | } | |
277 | ||
278 | int board_eth_init(bd_t *bis) | |
279 | { | |
2af81e27 JL |
280 | int ret; |
281 | ||
282 | setup_iomux_enet(); | |
283 | ||
284 | ret = cpu_eth_init(bis); | |
2bf3359e | 285 | if (ret) |
2af81e27 | 286 | printf("FEC MXC: %s:failed\n", __func__); |
2af81e27 JL |
287 | |
288 | return 0; | |
289 | } | |
290 | ||
28fdbddc EN |
291 | static void setup_buttons(void) |
292 | { | |
293 | imx_iomux_v3_setup_multiple_pads(button_pads, | |
294 | ARRAY_SIZE(button_pads)); | |
295 | } | |
296 | ||
3996a96c EN |
297 | #ifdef CONFIG_CMD_SATA |
298 | ||
299 | int setup_sata(void) | |
300 | { | |
301 | struct iomuxc_base_regs *const iomuxc_regs | |
302 | = (struct iomuxc_base_regs *) IOMUXC_BASE_ADDR; | |
303 | int ret = enable_sata_clock(); | |
304 | if (ret) | |
305 | return ret; | |
306 | ||
307 | clrsetbits_le32(&iomuxc_regs->gpr[13], | |
308 | IOMUXC_GPR13_SATA_MASK, | |
309 | IOMUXC_GPR13_SATA_PHY_8_RXEQ_3P0DB | |
310 | |IOMUXC_GPR13_SATA_PHY_7_SATA2M | |
311 | |IOMUXC_GPR13_SATA_SPEED_3G | |
312 | |(3<<IOMUXC_GPR13_SATA_PHY_6_SHIFT) | |
313 | |IOMUXC_GPR13_SATA_SATA_PHY_5_SS_DISABLED | |
314 | |IOMUXC_GPR13_SATA_SATA_PHY_4_ATTEN_9_16 | |
315 | |IOMUXC_GPR13_SATA_PHY_3_TXBOOST_0P00_DB | |
316 | |IOMUXC_GPR13_SATA_PHY_2_TX_1P104V | |
317 | |IOMUXC_GPR13_SATA_PHY_1_SLOW); | |
318 | ||
319 | return 0; | |
320 | } | |
321 | #endif | |
322 | ||
bc5833c4 JL |
323 | int board_early_init_f(void) |
324 | { | |
28fdbddc EN |
325 | setup_iomux_uart(); |
326 | setup_buttons(); | |
bc5833c4 | 327 | |
28fdbddc | 328 | return 0; |
bc5833c4 JL |
329 | } |
330 | ||
331 | int board_init(void) | |
332 | { | |
333 | /* address of boot parameters */ | |
334 | gd->bd->bi_boot_params = PHYS_SDRAM + 0x100; | |
335 | ||
d928a8f3 EN |
336 | #ifdef CONFIG_MXC_SPI |
337 | setup_spi(); | |
338 | #endif | |
339 | ||
3996a96c EN |
340 | #ifdef CONFIG_CMD_SATA |
341 | setup_sata(); | |
342 | #endif | |
343 | ||
bc5833c4 JL |
344 | return 0; |
345 | } | |
346 | ||
347 | int checkboard(void) | |
348 | { | |
349 | puts("Board: MX6Q-Sabre Lite\n"); | |
350 | ||
351 | return 0; | |
352 | } | |
28fdbddc EN |
353 | |
354 | struct button_key { | |
355 | char const *name; | |
356 | unsigned gpnum; | |
357 | char ident; | |
358 | }; | |
359 | ||
360 | static struct button_key const buttons[] = { | |
361 | {"back", GPIO_NUMBER(2, 2), 'B'}, | |
362 | {"home", GPIO_NUMBER(2, 4), 'H'}, | |
363 | {"menu", GPIO_NUMBER(2, 1), 'M'}, | |
364 | {"search", GPIO_NUMBER(2, 3), 'S'}, | |
365 | {"volup", GPIO_NUMBER(7, 13), 'V'}, | |
366 | {"voldown", GPIO_NUMBER(4, 5), 'v'}, | |
367 | }; | |
368 | ||
369 | /* | |
370 | * generate a null-terminated string containing the buttons pressed | |
371 | * returns number of keys pressed | |
372 | */ | |
373 | static int read_keys(char *buf) | |
374 | { | |
375 | int i, numpressed = 0; | |
376 | for (i = 0; i < ARRAY_SIZE(buttons); i++) { | |
377 | if (!gpio_get_value(buttons[i].gpnum)) | |
378 | buf[numpressed++] = buttons[i].ident; | |
379 | } | |
380 | buf[numpressed] = '\0'; | |
381 | return numpressed; | |
382 | } | |
383 | ||
384 | static int do_kbd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) | |
385 | { | |
386 | char envvalue[ARRAY_SIZE(buttons)+1]; | |
387 | int numpressed = read_keys(envvalue); | |
388 | setenv("keybd", envvalue); | |
389 | return numpressed == 0; | |
390 | } | |
391 | ||
392 | U_BOOT_CMD( | |
393 | kbd, 1, 1, do_kbd, | |
394 | "Tests for keypresses, sets 'keybd' environment variable", | |
395 | "Returns 0 (true) to shell if key is pressed." | |
396 | ); | |
397 | ||
398 | #ifdef CONFIG_PREBOOT | |
399 | static char const kbd_magic_prefix[] = "key_magic"; | |
400 | static char const kbd_command_prefix[] = "key_cmd"; | |
401 | ||
402 | static void preboot_keys(void) | |
403 | { | |
404 | int numpressed; | |
405 | char keypress[ARRAY_SIZE(buttons)+1]; | |
406 | numpressed = read_keys(keypress); | |
407 | if (numpressed) { | |
408 | char *kbd_magic_keys = getenv("magic_keys"); | |
409 | char *suffix; | |
410 | /* | |
411 | * loop over all magic keys | |
412 | */ | |
413 | for (suffix = kbd_magic_keys; *suffix; ++suffix) { | |
414 | char *keys; | |
415 | char magic[sizeof(kbd_magic_prefix) + 1]; | |
416 | sprintf(magic, "%s%c", kbd_magic_prefix, *suffix); | |
417 | keys = getenv(magic); | |
418 | if (keys) { | |
419 | if (!strcmp(keys, keypress)) | |
420 | break; | |
421 | } | |
422 | } | |
423 | if (*suffix) { | |
424 | char cmd_name[sizeof(kbd_command_prefix) + 1]; | |
425 | char *cmd; | |
426 | sprintf(cmd_name, "%s%c", kbd_command_prefix, *suffix); | |
427 | cmd = getenv(cmd_name); | |
428 | if (cmd) { | |
429 | setenv("preboot", cmd); | |
430 | return; | |
431 | } | |
432 | } | |
433 | } | |
434 | } | |
435 | #endif | |
436 | ||
437 | int misc_init_r(void) | |
438 | { | |
439 | #ifdef CONFIG_PREBOOT | |
440 | preboot_keys(); | |
441 | #endif | |
442 | return 0; | |
443 | } |