1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * board.c 4 * 5 * Board functions for B&R BRPPT1 6 * 7 * Copyright (C) 2013 Hannes Schmelzer <oe5hpm@oevsv.at> 8 * Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com 9 * 10 */ 11 12 #include <common.h> 13 #include <errno.h> 14 #include <spl.h> 15 #include <asm/arch/cpu.h> 16 #include <asm/arch/hardware.h> 17 #include <asm/arch/omap.h> 18 #include <asm/arch/ddr_defs.h> 19 #include <asm/arch/clock.h> 20 #include <asm/arch/gpio.h> 21 #include <asm/arch/sys_proto.h> 22 #include <asm/arch/mem.h> 23 #include <asm/io.h> 24 #include <asm/emif.h> 25 #include <asm/gpio.h> 26 #include <i2c.h> 27 #include <power/tps65217.h> 28 #include "../common/bur_common.h" 29 #include <watchdog.h> 30 31 DECLARE_GLOBAL_DATA_PTR; 32 33 /* --------------------------------------------------------------------------*/ 34 /* -- defines for GPIO -- */ 35 #define REPSWITCH (0+20) /* GPIO0_20 */ 36 37 #if defined(CONFIG_SPL_BUILD) 38 /* TODO: check ram-timing ! */ 39 static const struct ddr_data ddr3_data = { 40 .datardsratio0 = MT41K256M16HA125E_RD_DQS, 41 .datawdsratio0 = MT41K256M16HA125E_WR_DQS, 42 .datafwsratio0 = MT41K256M16HA125E_PHY_FIFO_WE, 43 .datawrsratio0 = MT41K256M16HA125E_PHY_WR_DATA, 44 }; 45 46 static const struct cmd_control ddr3_cmd_ctrl_data = { 47 .cmd0csratio = MT41K256M16HA125E_RATIO, 48 .cmd0iclkout = MT41K256M16HA125E_INVERT_CLKOUT, 49 50 .cmd1csratio = MT41K256M16HA125E_RATIO, 51 .cmd1iclkout = MT41K256M16HA125E_INVERT_CLKOUT, 52 53 .cmd2csratio = MT41K256M16HA125E_RATIO, 54 .cmd2iclkout = MT41K256M16HA125E_INVERT_CLKOUT, 55 }; 56 57 static struct emif_regs ddr3_emif_reg_data = { 58 .sdram_config = MT41K256M16HA125E_EMIF_SDCFG, 59 .ref_ctrl = MT41K256M16HA125E_EMIF_SDREF, 60 .sdram_tim1 = MT41K256M16HA125E_EMIF_TIM1, 61 .sdram_tim2 = MT41K256M16HA125E_EMIF_TIM2, 62 .sdram_tim3 = MT41K256M16HA125E_EMIF_TIM3, 63 .zq_config = MT41K256M16HA125E_ZQ_CFG, 64 .emif_ddr_phy_ctlr_1 = MT41K256M16HA125E_EMIF_READ_LATENCY, 65 }; 66 67 static const struct ctrl_ioregs ddr3_ioregs = { 68 .cm0ioctl = MT41K256M16HA125E_IOCTRL_VALUE, 69 .cm1ioctl = MT41K256M16HA125E_IOCTRL_VALUE, 70 .cm2ioctl = MT41K256M16HA125E_IOCTRL_VALUE, 71 .dt0ioctl = MT41K256M16HA125E_IOCTRL_VALUE, 72 .dt1ioctl = MT41K256M16HA125E_IOCTRL_VALUE, 73 }; 74 75 #define OSC (V_OSCK/1000000) 76 static const struct dpll_params dpll_ddr3 = { 400, OSC-1, 1, -1, -1, -1, -1}; 77 78 void am33xx_spl_board_init(void) 79 { 80 int rc; 81 82 struct cm_perpll *const cmper = (struct cm_perpll *)CM_PER; 83 /*struct cm_wkuppll *const cmwkup = (struct cm_wkuppll *)CM_WKUP;*/ 84 struct cm_dpll *const cmdpll = (struct cm_dpll *)CM_DPLL; 85 86 /* 87 * in TRM they write a reset value of 1 (=CLK_M_OSC) for the 88 * CLKSEL_TIMER6_CLK Register, in fact reset value is 0, so we need set 89 * the source of timer6 clk to CLK_M_OSC 90 */ 91 writel(0x01, &cmdpll->clktimer6clk); 92 93 /* enable additional clocks of modules which are accessed later */ 94 u32 *const clk_domains[] = { 95 &cmper->lcdcclkstctrl, 96 0 97 }; 98 99 u32 *const clk_modules_tsspecific[] = { 100 &cmper->lcdclkctrl, 101 &cmper->timer5clkctrl, 102 &cmper->timer6clkctrl, 103 0 104 }; 105 do_enable_clocks(clk_domains, clk_modules_tsspecific, 1); 106 107 /* setup I2C */ 108 enable_i2c_pin_mux(); 109 110 pmicsetup(0, 0); 111 112 /* peripheral reset */ 113 rc = gpio_request(64 + 29, "GPMC_WAIT1"); 114 if (rc != 0) 115 printf("cannot request GPMC_WAIT1 GPIO!\n"); 116 rc = gpio_direction_output(64 + 29, 1); 117 if (rc != 0) 118 printf("cannot set GPMC_WAIT1 GPIO!\n"); 119 120 rc = gpio_request(64 + 28, "GPMC_WAIT0"); 121 if (rc != 0) 122 printf("cannot request GPMC_WAIT0 GPIO!\n"); 123 rc = gpio_direction_output(64 + 28, 1); 124 if (rc != 0) 125 printf("cannot set GPMC_WAIT0 GPIO!\n"); 126 127 } 128 129 const struct dpll_params *get_dpll_ddr_params(void) 130 { 131 return &dpll_ddr3; 132 } 133 134 void sdram_init(void) 135 { 136 config_ddr(400, &ddr3_ioregs, 137 &ddr3_data, 138 &ddr3_cmd_ctrl_data, 139 &ddr3_emif_reg_data, 0); 140 } 141 #endif /* CONFIG_SPL_BUILD */ 142 143 /* Basic board specific setup. Pinmux has been handled already. */ 144 int board_init(void) 145 { 146 #if defined(CONFIG_HW_WATCHDOG) 147 hw_watchdog_init(); 148 #endif 149 gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100; 150 #ifdef CONFIG_NAND 151 gpmc_init(); 152 #endif 153 return 0; 154 } 155 156 #ifdef CONFIG_BOARD_LATE_INIT 157 static char *bootmodeascii[16] = { 158 "BOOT", "reserved", "reserved", "reserved", 159 "RUN", "reserved", "reserved", "reserved", 160 "reserved", "reserved", "reserved", "reserved", 161 "PME", "reserved", "reserved", "DIAG", 162 }; 163 164 int board_late_init(void) 165 { 166 unsigned char bmode = 0; 167 ulong bootcount = 0; 168 int rc; 169 170 bootcount = bootcount_load() & 0xF; 171 172 rc = gpio_request(REPSWITCH, "REPSWITCH"); 173 174 if (rc != 0 || gpio_get_value(REPSWITCH) == 0 || bootcount == 12) 175 bmode = 12; 176 else if (bootcount > 0) 177 bmode = 0; 178 else 179 bmode = 4; 180 181 printf("Mode: %s\n", bootmodeascii[bmode & 0x0F]); 182 env_set_ulong("b_mode", bmode); 183 184 /* get sure that bootcmd isn't affected by any bootcount value */ 185 env_set_ulong("bootlimit", 0); 186 187 return 0; 188 } 189 #endif /* CONFIG_BOARD_LATE_INIT */ 190