1 /* 2 * Freescale i.MX23/i.MX28 common code 3 * 4 * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> 5 * on behalf of DENX Software Engineering GmbH 6 * 7 * Based on code from LTIB: 8 * Copyright (C) 2010 Freescale Semiconductor, Inc. 9 * 10 * See file CREDITS for list of people who contributed to this 11 * project. 12 * 13 * This program is free software; you can redistribute it and/or 14 * modify it under the terms of the GNU General Public License as 15 * published by the Free Software Foundation; either version 2 of 16 * the License, or (at your option) any later version. 17 * 18 * This program is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 * GNU General Public License for more details. 22 * 23 * You should have received a copy of the GNU General Public License 24 * along with this program; if not, write to the Free Software 25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 26 * MA 02111-1307 USA 27 */ 28 29 #include <common.h> 30 #include <asm/errno.h> 31 #include <asm/io.h> 32 #include <asm/arch/clock.h> 33 #include <asm/arch/dma.h> 34 #include <asm/arch/gpio.h> 35 #include <asm/arch/iomux.h> 36 #include <asm/arch/imx-regs.h> 37 #include <asm/arch/sys_proto.h> 38 #include <linux/compiler.h> 39 40 DECLARE_GLOBAL_DATA_PTR; 41 42 /* 1 second delay should be plenty of time for block reset. */ 43 #define RESET_MAX_TIMEOUT 1000000 44 45 #define MXS_BLOCK_SFTRST (1 << 31) 46 #define MXS_BLOCK_CLKGATE (1 << 30) 47 48 /* Lowlevel init isn't used on i.MX28, so just have a dummy here */ 49 inline void lowlevel_init(void) {} 50 51 void reset_cpu(ulong ignored) __attribute__((noreturn)); 52 53 void reset_cpu(ulong ignored) 54 { 55 struct mxs_rtc_regs *rtc_regs = 56 (struct mxs_rtc_regs *)MXS_RTC_BASE; 57 struct mxs_lcdif_regs *lcdif_regs = 58 (struct mxs_lcdif_regs *)MXS_LCDIF_BASE; 59 60 /* 61 * Shut down the LCD controller as it interferes with BootROM boot mode 62 * pads sampling. 63 */ 64 writel(LCDIF_CTRL_RUN, &lcdif_regs->hw_lcdif_ctrl_clr); 65 66 /* Wait 1 uS before doing the actual watchdog reset */ 67 writel(1, &rtc_regs->hw_rtc_watchdog); 68 writel(RTC_CTRL_WATCHDOGEN, &rtc_regs->hw_rtc_ctrl_set); 69 70 /* Endless loop, reset will exit from here */ 71 for (;;) 72 ; 73 } 74 75 void enable_caches(void) 76 { 77 #ifndef CONFIG_SYS_ICACHE_OFF 78 icache_enable(); 79 #endif 80 #ifndef CONFIG_SYS_DCACHE_OFF 81 dcache_enable(); 82 #endif 83 } 84 85 int mxs_wait_mask_set(struct mxs_register_32 *reg, uint32_t mask, unsigned 86 int timeout) 87 { 88 while (--timeout) { 89 if ((readl(®->reg) & mask) == mask) 90 break; 91 udelay(1); 92 } 93 94 return !timeout; 95 } 96 97 int mxs_wait_mask_clr(struct mxs_register_32 *reg, uint32_t mask, unsigned 98 int timeout) 99 { 100 while (--timeout) { 101 if ((readl(®->reg) & mask) == 0) 102 break; 103 udelay(1); 104 } 105 106 return !timeout; 107 } 108 109 int mxs_reset_block(struct mxs_register_32 *reg) 110 { 111 /* Clear SFTRST */ 112 writel(MXS_BLOCK_SFTRST, ®->reg_clr); 113 114 if (mxs_wait_mask_clr(reg, MXS_BLOCK_SFTRST, RESET_MAX_TIMEOUT)) 115 return 1; 116 117 /* Clear CLKGATE */ 118 writel(MXS_BLOCK_CLKGATE, ®->reg_clr); 119 120 /* Set SFTRST */ 121 writel(MXS_BLOCK_SFTRST, ®->reg_set); 122 123 /* Wait for CLKGATE being set */ 124 if (mxs_wait_mask_set(reg, MXS_BLOCK_CLKGATE, RESET_MAX_TIMEOUT)) 125 return 1; 126 127 /* Clear SFTRST */ 128 writel(MXS_BLOCK_SFTRST, ®->reg_clr); 129 130 if (mxs_wait_mask_clr(reg, MXS_BLOCK_SFTRST, RESET_MAX_TIMEOUT)) 131 return 1; 132 133 /* Clear CLKGATE */ 134 writel(MXS_BLOCK_CLKGATE, ®->reg_clr); 135 136 if (mxs_wait_mask_clr(reg, MXS_BLOCK_CLKGATE, RESET_MAX_TIMEOUT)) 137 return 1; 138 139 return 0; 140 } 141 142 void mx28_fixup_vt(uint32_t start_addr) 143 { 144 uint32_t *vt = (uint32_t *)0x20; 145 int i; 146 147 for (i = 0; i < 8; i++) 148 vt[i] = start_addr + (4 * i); 149 } 150 151 #ifdef CONFIG_ARCH_MISC_INIT 152 int arch_misc_init(void) 153 { 154 mx28_fixup_vt(gd->relocaddr); 155 return 0; 156 } 157 #endif 158 159 int arch_cpu_init(void) 160 { 161 struct mxs_clkctrl_regs *clkctrl_regs = 162 (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; 163 extern uint32_t _start; 164 165 mx28_fixup_vt((uint32_t)&_start); 166 167 /* 168 * Enable NAND clock 169 */ 170 /* Clear bypass bit */ 171 writel(CLKCTRL_CLKSEQ_BYPASS_GPMI, 172 &clkctrl_regs->hw_clkctrl_clkseq_set); 173 174 /* Set GPMI clock to ref_gpmi / 12 */ 175 clrsetbits_le32(&clkctrl_regs->hw_clkctrl_gpmi, 176 CLKCTRL_GPMI_CLKGATE | CLKCTRL_GPMI_DIV_MASK, 1); 177 178 udelay(1000); 179 180 /* 181 * Configure GPIO unit 182 */ 183 mxs_gpio_init(); 184 185 #ifdef CONFIG_APBH_DMA 186 /* Start APBH DMA */ 187 mxs_dma_init(); 188 #endif 189 190 return 0; 191 } 192 193 #if defined(CONFIG_DISPLAY_CPUINFO) 194 static const char *get_cpu_type(void) 195 { 196 struct mxs_digctl_regs *digctl_regs = 197 (struct mxs_digctl_regs *)MXS_DIGCTL_BASE; 198 199 switch (readl(&digctl_regs->hw_digctl_chipid) & HW_DIGCTL_CHIPID_MASK) { 200 case HW_DIGCTL_CHIPID_MX23: 201 return "23"; 202 case HW_DIGCTL_CHIPID_MX28: 203 return "28"; 204 default: 205 return "??"; 206 } 207 } 208 209 static const char *get_cpu_rev(void) 210 { 211 struct mxs_digctl_regs *digctl_regs = 212 (struct mxs_digctl_regs *)MXS_DIGCTL_BASE; 213 uint8_t rev = readl(&digctl_regs->hw_digctl_chipid) & 0x000000FF; 214 215 switch (readl(&digctl_regs->hw_digctl_chipid) & HW_DIGCTL_CHIPID_MASK) { 216 case HW_DIGCTL_CHIPID_MX23: 217 switch (rev) { 218 case 0x0: 219 return "1.0"; 220 case 0x1: 221 return "1.1"; 222 case 0x2: 223 return "1.2"; 224 case 0x3: 225 return "1.3"; 226 case 0x4: 227 return "1.4"; 228 default: 229 return "??"; 230 } 231 case HW_DIGCTL_CHIPID_MX28: 232 switch (rev) { 233 case 0x1: 234 return "1.2"; 235 default: 236 return "??"; 237 } 238 default: 239 return "??"; 240 } 241 } 242 243 int print_cpuinfo(void) 244 { 245 struct mxs_spl_data *data = (struct mxs_spl_data *) 246 ((CONFIG_SYS_TEXT_BASE - sizeof(struct mxs_spl_data)) & ~0xf); 247 248 printf("CPU: Freescale i.MX%s rev%s at %d MHz\n", 249 get_cpu_type(), 250 get_cpu_rev(), 251 mxc_get_clock(MXC_ARM_CLK) / 1000000); 252 printf("BOOT: %s\n", mxs_boot_modes[data->boot_mode_idx].mode); 253 return 0; 254 } 255 #endif 256 257 int do_mx28_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 258 { 259 printf("CPU: %3d MHz\n", mxc_get_clock(MXC_ARM_CLK) / 1000000); 260 printf("BUS: %3d MHz\n", mxc_get_clock(MXC_AHB_CLK) / 1000000); 261 printf("EMI: %3d MHz\n", mxc_get_clock(MXC_EMI_CLK)); 262 printf("GPMI: %3d MHz\n", mxc_get_clock(MXC_GPMI_CLK) / 1000000); 263 return 0; 264 } 265 266 /* 267 * Initializes on-chip ethernet controllers. 268 */ 269 #if defined(CONFIG_MX28) && defined(CONFIG_CMD_NET) 270 int cpu_eth_init(bd_t *bis) 271 { 272 struct mxs_clkctrl_regs *clkctrl_regs = 273 (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; 274 275 /* Turn on ENET clocks */ 276 clrbits_le32(&clkctrl_regs->hw_clkctrl_enet, 277 CLKCTRL_ENET_SLEEP | CLKCTRL_ENET_DISABLE); 278 279 /* Set up ENET PLL for 50 MHz */ 280 /* Power on ENET PLL */ 281 writel(CLKCTRL_PLL2CTRL0_POWER, 282 &clkctrl_regs->hw_clkctrl_pll2ctrl0_set); 283 284 udelay(10); 285 286 /* Gate on ENET PLL */ 287 writel(CLKCTRL_PLL2CTRL0_CLKGATE, 288 &clkctrl_regs->hw_clkctrl_pll2ctrl0_clr); 289 290 /* Enable pad output */ 291 setbits_le32(&clkctrl_regs->hw_clkctrl_enet, CLKCTRL_ENET_CLK_OUT_EN); 292 293 return 0; 294 } 295 #endif 296 297 __weak void mx28_adjust_mac(int dev_id, unsigned char *mac) 298 { 299 mac[0] = 0x00; 300 mac[1] = 0x04; /* Use FSL vendor MAC address by default */ 301 302 if (dev_id == 1) /* Let MAC1 be MAC0 + 1 by default */ 303 mac[5] += 1; 304 } 305 306 #ifdef CONFIG_MX28_FEC_MAC_IN_OCOTP 307 308 #define MXS_OCOTP_MAX_TIMEOUT 1000000 309 void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) 310 { 311 struct mxs_ocotp_regs *ocotp_regs = 312 (struct mxs_ocotp_regs *)MXS_OCOTP_BASE; 313 uint32_t data; 314 315 memset(mac, 0, 6); 316 317 writel(OCOTP_CTRL_RD_BANK_OPEN, &ocotp_regs->hw_ocotp_ctrl_set); 318 319 if (mxs_wait_mask_clr(&ocotp_regs->hw_ocotp_ctrl_reg, OCOTP_CTRL_BUSY, 320 MXS_OCOTP_MAX_TIMEOUT)) { 321 printf("MXS FEC: Can't get MAC from OCOTP\n"); 322 return; 323 } 324 325 data = readl(&ocotp_regs->hw_ocotp_cust0); 326 327 mac[2] = (data >> 24) & 0xff; 328 mac[3] = (data >> 16) & 0xff; 329 mac[4] = (data >> 8) & 0xff; 330 mac[5] = data & 0xff; 331 mx28_adjust_mac(dev_id, mac); 332 } 333 #else 334 void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) 335 { 336 memset(mac, 0, 6); 337 } 338 #endif 339 340 int mxs_dram_init(void) 341 { 342 struct mxs_spl_data *data = (struct mxs_spl_data *) 343 ((CONFIG_SYS_TEXT_BASE - sizeof(struct mxs_spl_data)) & ~0xf); 344 345 if (data->mem_dram_size == 0) { 346 printf("MXS:\n" 347 "Error, the RAM size passed up from SPL is 0!\n"); 348 hang(); 349 } 350 351 gd->ram_size = data->mem_dram_size; 352 return 0; 353 } 354 355 U_BOOT_CMD( 356 clocks, CONFIG_SYS_MAXARGS, 1, do_mx28_showclocks, 357 "display clocks", 358 "" 359 ); 360