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