]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/freescale/mx6qsabrelite/mx6qsabrelite.c
Unified codebase for TX28, TX48, TX51, TX53
[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 int dram_init(void)
59 {
60        gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
61
62        return 0;
63 }
64
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
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
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
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
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);
159         gpio_set_value(87, 1);  /* GPIO 3-23 */
160
161         imx_iomux_v3_setup_multiple_pads(enet_pads2, ARRAY_SIZE(enet_pads2));
162 }
163
164 iomux_v3_cfg_t usb_pads[] = {
165         MX6Q_PAD_GPIO_17__GPIO_7_12 | MUX_PAD_CTRL(NO_PAD_CTRL),
166 };
167
168 static void setup_iomux_uart(void)
169 {
170         imx_iomux_v3_setup_multiple_pads(uart1_pads, ARRAY_SIZE(uart1_pads));
171        imx_iomux_v3_setup_multiple_pads(uart2_pads, ARRAY_SIZE(uart2_pads));
172 }
173
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
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) {
200                gpio_direction_input(192); /*GPIO7_0*/
201                ret = !gpio_get_value(192);
202        } else {
203                gpio_direction_input(38); /*GPIO2_6*/
204                ret = !gpio_get_value(38);
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) {
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]);
233        }
234
235        return status;
236 }
237 #endif
238
239 u32 get_board_rev(void)
240 {
241         return 0x63000 ;
242 }
243
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 {
255         gpio_direction_output(CONFIG_SF_DEFAULT_CS, 1);
256         imx_iomux_v3_setup_multiple_pads(ecspi1_pads,
257                                          ARRAY_SIZE(ecspi1_pads));
258 }
259 #endif
260
261 int board_phy_config(struct phy_device *phydev)
262 {
263         /* min rx data delay */
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);
274
275         return 0;
276 }
277
278 int board_eth_init(bd_t *bis)
279 {
280         int ret;
281
282         setup_iomux_enet();
283
284         ret = cpu_eth_init(bis);
285         if (ret)
286                 printf("FEC MXC: %s:failed\n", __func__);
287
288         return 0;
289 }
290
291 static void setup_buttons(void)
292 {
293         imx_iomux_v3_setup_multiple_pads(button_pads,
294                                          ARRAY_SIZE(button_pads));
295 }
296
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
323 int board_early_init_f(void)
324 {
325         setup_iomux_uart();
326         setup_buttons();
327
328         return 0;
329 }
330
331 int board_init(void)
332 {
333        /* address of boot parameters */
334        gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
335
336 #ifdef CONFIG_MXC_SPI
337         setup_spi();
338 #endif
339
340 #ifdef CONFIG_CMD_SATA
341         setup_sata();
342 #endif
343
344        return 0;
345 }
346
347 int checkboard(void)
348 {
349        puts("Board: MX6Q-Sabre Lite\n");
350
351        return 0;
352 }
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 }