spl_boot.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /*
  2. * Freescale i.MX28 Boot setup
  3. *
  4. * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
  5. * on behalf of DENX Software Engineering GmbH
  6. *
  7. * See file CREDITS for list of people who contributed to this
  8. * project.
  9. *
  10. * This program is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU General Public License as
  12. * published by the Free Software Foundation; either version 2 of
  13. * the License, or (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  23. * MA 02111-1307 USA
  24. */
  25. #include <common.h>
  26. #include <config.h>
  27. #include <asm/io.h>
  28. #include <asm/arch/imx-regs.h>
  29. #include <asm/arch/sys_proto.h>
  30. #include <asm/gpio.h>
  31. #include "mxs_init.h"
  32. /*
  33. * This delay function is intended to be used only in early stage of boot, where
  34. * clock are not set up yet. The timer used here is reset on every boot and
  35. * takes a few seconds to roll. The boot doesn't take that long, so to keep the
  36. * code simple, it doesn't take rolling into consideration.
  37. */
  38. void early_delay(int delay)
  39. {
  40. struct mxs_digctl_regs *digctl_regs =
  41. (struct mxs_digctl_regs *)MXS_DIGCTL_BASE;
  42. uint32_t st = readl(&digctl_regs->hw_digctl_microseconds);
  43. st += delay;
  44. while (st > readl(&digctl_regs->hw_digctl_microseconds))
  45. ;
  46. }
  47. #define MUX_CONFIG_BOOTMODE_PAD (MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_NOPULL)
  48. static const iomux_cfg_t iomux_boot[] = {
  49. #if defined(CONFIG_MX23)
  50. MX23_PAD_LCD_D00__GPIO_1_0 | MUX_CONFIG_BOOTMODE_PAD,
  51. MX23_PAD_LCD_D01__GPIO_1_1 | MUX_CONFIG_BOOTMODE_PAD,
  52. MX23_PAD_LCD_D02__GPIO_1_2 | MUX_CONFIG_BOOTMODE_PAD,
  53. MX23_PAD_LCD_D03__GPIO_1_3 | MUX_CONFIG_BOOTMODE_PAD,
  54. MX23_PAD_LCD_D04__GPIO_1_4 | MUX_CONFIG_BOOTMODE_PAD,
  55. MX23_PAD_LCD_D05__GPIO_1_5 | MUX_CONFIG_BOOTMODE_PAD,
  56. #elif defined(CONFIG_MX28)
  57. MX28_PAD_LCD_D00__GPIO_1_0 | MUX_CONFIG_BOOTMODE_PAD,
  58. MX28_PAD_LCD_D01__GPIO_1_1 | MUX_CONFIG_BOOTMODE_PAD,
  59. MX28_PAD_LCD_D02__GPIO_1_2 | MUX_CONFIG_BOOTMODE_PAD,
  60. MX28_PAD_LCD_D03__GPIO_1_3 | MUX_CONFIG_BOOTMODE_PAD,
  61. MX28_PAD_LCD_D04__GPIO_1_4 | MUX_CONFIG_BOOTMODE_PAD,
  62. MX28_PAD_LCD_D05__GPIO_1_5 | MUX_CONFIG_BOOTMODE_PAD,
  63. #endif
  64. };
  65. static uint8_t mxs_get_bootmode_index(void)
  66. {
  67. uint8_t bootmode = 0;
  68. int i;
  69. uint8_t masked;
  70. /* Setup IOMUX of bootmode pads to GPIO */
  71. mxs_iomux_setup_multiple_pads(iomux_boot, ARRAY_SIZE(iomux_boot));
  72. #if defined(CONFIG_MX23)
  73. /* Setup bootmode pins as GPIO input */
  74. gpio_direction_input(MX23_PAD_LCD_D00__GPIO_1_0);
  75. gpio_direction_input(MX23_PAD_LCD_D01__GPIO_1_1);
  76. gpio_direction_input(MX23_PAD_LCD_D02__GPIO_1_2);
  77. gpio_direction_input(MX23_PAD_LCD_D03__GPIO_1_3);
  78. gpio_direction_input(MX23_PAD_LCD_D05__GPIO_1_5);
  79. /* Read bootmode pads */
  80. bootmode |= (gpio_get_value(MX23_PAD_LCD_D00__GPIO_1_0) ? 1 : 0) << 0;
  81. bootmode |= (gpio_get_value(MX23_PAD_LCD_D01__GPIO_1_1) ? 1 : 0) << 1;
  82. bootmode |= (gpio_get_value(MX23_PAD_LCD_D02__GPIO_1_2) ? 1 : 0) << 2;
  83. bootmode |= (gpio_get_value(MX23_PAD_LCD_D03__GPIO_1_3) ? 1 : 0) << 3;
  84. bootmode |= (gpio_get_value(MX23_PAD_LCD_D05__GPIO_1_5) ? 1 : 0) << 5;
  85. #elif defined(CONFIG_MX28)
  86. /* Setup bootmode pins as GPIO input */
  87. gpio_direction_input(MX28_PAD_LCD_D00__GPIO_1_0);
  88. gpio_direction_input(MX28_PAD_LCD_D01__GPIO_1_1);
  89. gpio_direction_input(MX28_PAD_LCD_D02__GPIO_1_2);
  90. gpio_direction_input(MX28_PAD_LCD_D03__GPIO_1_3);
  91. gpio_direction_input(MX28_PAD_LCD_D04__GPIO_1_4);
  92. gpio_direction_input(MX28_PAD_LCD_D05__GPIO_1_5);
  93. /* Read bootmode pads */
  94. bootmode |= (gpio_get_value(MX28_PAD_LCD_D00__GPIO_1_0) ? 1 : 0) << 0;
  95. bootmode |= (gpio_get_value(MX28_PAD_LCD_D01__GPIO_1_1) ? 1 : 0) << 1;
  96. bootmode |= (gpio_get_value(MX28_PAD_LCD_D02__GPIO_1_2) ? 1 : 0) << 2;
  97. bootmode |= (gpio_get_value(MX28_PAD_LCD_D03__GPIO_1_3) ? 1 : 0) << 3;
  98. bootmode |= (gpio_get_value(MX28_PAD_LCD_D04__GPIO_1_4) ? 1 : 0) << 4;
  99. bootmode |= (gpio_get_value(MX28_PAD_LCD_D05__GPIO_1_5) ? 1 : 0) << 5;
  100. #endif
  101. for (i = 0; i < ARRAY_SIZE(mxs_boot_modes); i++) {
  102. masked = bootmode & mxs_boot_modes[i].boot_mask;
  103. if (masked == mxs_boot_modes[i].boot_pads)
  104. break;
  105. }
  106. return i;
  107. }
  108. void mxs_common_spl_init(const iomux_cfg_t *iomux_setup,
  109. const unsigned int iomux_size)
  110. {
  111. struct mxs_spl_data *data = (struct mxs_spl_data *)
  112. ((CONFIG_SYS_TEXT_BASE - sizeof(struct mxs_spl_data)) & ~0xf);
  113. uint8_t bootmode = mxs_get_bootmode_index();
  114. mxs_iomux_setup_multiple_pads(iomux_setup, iomux_size);
  115. mxs_power_init();
  116. mxs_mem_init();
  117. data->mem_dram_size = mxs_mem_get_size();
  118. data->boot_mode_idx = bootmode;
  119. mxs_power_wait_pswitch();
  120. }
  121. /* Support aparatus */
  122. inline void board_init_f(unsigned long bootflag)
  123. {
  124. for (;;)
  125. ;
  126. }
  127. inline void board_init_r(gd_t *id, ulong dest_addr)
  128. {
  129. for (;;)
  130. ;
  131. }