1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (C) 2008-2013 Eric Jarrige <eric.jarrige@armadeus.org>
4 *
5 * based on the files by
6 * Sascha Hauer, Pengutronix
7 */
8
9 #include <common.h>
10 #include <environment.h>
11 #include <jffs2/jffs2.h>
12 #include <nand.h>
13 #include <netdev.h>
14 #include <asm/io.h>
15 #include <asm/arch/imx-regs.h>
16 #include <asm/arch/gpio.h>
17 #include <asm/gpio.h>
18 #include <linux/errno.h>
19 #include <u-boot/crc.h>
20 #include "apf27.h"
21 #include "fpga.h"
22
23 DECLARE_GLOBAL_DATA_PTR;
24
25 /*
26 * Fuse bank 1 row 8 is "reserved for future use" and therefore available for
27 * customer use. The APF27 board uses this fuse to store the board revision:
28 * 0: initial board revision
29 * 1: first revision - Presence of the second RAM chip on the board is blown in
30 * fuse bank 1 row 9 bit 0 - No hardware change
31 * N: to be defined
32 */
get_board_rev(void)33 static u32 get_board_rev(void)
34 {
35 struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE;
36
37 return readl(&iim->bank[1].fuse_regs[8]);
38 }
39
40 /*
41 * Fuse bank 1 row 9 is "reserved for future use" and therefore available for
42 * customer use. The APF27 board revision 1 uses the bit 0 to permanently store
43 * the presence of the second RAM chip
44 * 0: AFP27 with 1 RAM of 64 MiB
45 * 1: AFP27 with 2 RAM chips of 64 MiB each (128MB)
46 */
get_num_ram_bank(void)47 static int get_num_ram_bank(void)
48 {
49 struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE;
50 int nr_dram_banks = 1;
51
52 if ((get_board_rev() > 0) && (CONFIG_NR_DRAM_BANKS > 1))
53 nr_dram_banks += readl(&iim->bank[1].fuse_regs[9]) & 0x01;
54 else
55 nr_dram_banks = CONFIG_NR_DRAM_POPULATED;
56
57 return nr_dram_banks;
58 }
59
apf27_port_init(int port,u32 gpio_dr,u32 ocr1,u32 ocr2,u32 iconfa1,u32 iconfa2,u32 iconfb1,u32 iconfb2,u32 icr1,u32 icr2,u32 imr,u32 gpio_dir,u32 gpr,u32 puen,u32 gius)60 static void apf27_port_init(int port, u32 gpio_dr, u32 ocr1, u32 ocr2,
61 u32 iconfa1, u32 iconfa2, u32 iconfb1, u32 iconfb2,
62 u32 icr1, u32 icr2, u32 imr, u32 gpio_dir, u32 gpr,
63 u32 puen, u32 gius)
64 {
65 struct gpio_port_regs *regs = (struct gpio_port_regs *)IMX_GPIO_BASE;
66
67 writel(gpio_dr, ®s->port[port].gpio_dr);
68 writel(ocr1, ®s->port[port].ocr1);
69 writel(ocr2, ®s->port[port].ocr2);
70 writel(iconfa1, ®s->port[port].iconfa1);
71 writel(iconfa2, ®s->port[port].iconfa2);
72 writel(iconfb1, ®s->port[port].iconfb1);
73 writel(iconfb2, ®s->port[port].iconfb2);
74 writel(icr1, ®s->port[port].icr1);
75 writel(icr2, ®s->port[port].icr2);
76 writel(imr, ®s->port[port].imr);
77 writel(gpio_dir, ®s->port[port].gpio_dir);
78 writel(gpr, ®s->port[port].gpr);
79 writel(puen, ®s->port[port].puen);
80 writel(gius, ®s->port[port].gius);
81 }
82
83 #define APF27_PORT_INIT(n) apf27_port_init(PORT##n, ACFG_DR_##n##_VAL, \
84 ACFG_OCR1_##n##_VAL, ACFG_OCR2_##n##_VAL, ACFG_ICFA1_##n##_VAL, \
85 ACFG_ICFA2_##n##_VAL, ACFG_ICFB1_##n##_VAL, ACFG_ICFB2_##n##_VAL, \
86 ACFG_ICR1_##n##_VAL, ACFG_ICR2_##n##_VAL, ACFG_IMR_##n##_VAL, \
87 ACFG_DDIR_##n##_VAL, ACFG_GPR_##n##_VAL, ACFG_PUEN_##n##_VAL, \
88 ACFG_GIUS_##n##_VAL)
89
apf27_iomux_init(void)90 static void apf27_iomux_init(void)
91 {
92 APF27_PORT_INIT(A);
93 APF27_PORT_INIT(B);
94 APF27_PORT_INIT(C);
95 APF27_PORT_INIT(D);
96 APF27_PORT_INIT(E);
97 APF27_PORT_INIT(F);
98 }
99
apf27_devices_init(void)100 static int apf27_devices_init(void)
101 {
102 int i;
103 unsigned int mode[] = {
104 PC5_PF_I2C2_DATA,
105 PC6_PF_I2C2_CLK,
106 PD17_PF_I2C_DATA,
107 PD18_PF_I2C_CLK,
108 };
109
110 for (i = 0; i < ARRAY_SIZE(mode); i++)
111 imx_gpio_mode(mode[i]);
112
113 #ifdef CONFIG_MXC_UART
114 mx27_uart1_init_pins();
115 #endif
116
117 #ifdef CONFIG_FEC_MXC
118 mx27_fec_init_pins();
119 #endif
120
121 #ifdef CONFIG_MMC_MXC
122 mx27_sd2_init_pins();
123 imx_gpio_mode((GPIO_PORTF | GPIO_OUT | GPIO_PUEN | GPIO_GPIO | 16));
124 gpio_request(PC_PWRON, "pc_pwron");
125 gpio_set_value(PC_PWRON, 1);
126 #endif
127 return 0;
128 }
129
apf27_setup_csx(void)130 static void apf27_setup_csx(void)
131 {
132 struct weim_regs *weim = (struct weim_regs *)IMX_WEIM_BASE;
133
134 writel(ACFG_CS0U_VAL, &weim->cs0u);
135 writel(ACFG_CS0L_VAL, &weim->cs0l);
136 writel(ACFG_CS0A_VAL, &weim->cs0a);
137
138 writel(ACFG_CS1U_VAL, &weim->cs1u);
139 writel(ACFG_CS1L_VAL, &weim->cs1l);
140 writel(ACFG_CS1A_VAL, &weim->cs1a);
141
142 writel(ACFG_CS2U_VAL, &weim->cs2u);
143 writel(ACFG_CS2L_VAL, &weim->cs2l);
144 writel(ACFG_CS2A_VAL, &weim->cs2a);
145
146 writel(ACFG_CS3U_VAL, &weim->cs3u);
147 writel(ACFG_CS3L_VAL, &weim->cs3l);
148 writel(ACFG_CS3A_VAL, &weim->cs3a);
149
150 writel(ACFG_CS4U_VAL, &weim->cs4u);
151 writel(ACFG_CS4L_VAL, &weim->cs4l);
152 writel(ACFG_CS4A_VAL, &weim->cs4a);
153
154 writel(ACFG_CS5U_VAL, &weim->cs5u);
155 writel(ACFG_CS5L_VAL, &weim->cs5l);
156 writel(ACFG_CS5A_VAL, &weim->cs5a);
157
158 writel(ACFG_EIM_VAL, &weim->eim);
159 }
160
apf27_setup_port(void)161 static void apf27_setup_port(void)
162 {
163 struct system_control_regs *system =
164 (struct system_control_regs *)IMX_SYSTEM_CTL_BASE;
165
166 writel(ACFG_FMCR_VAL, &system->fmcr);
167 }
168
board_init(void)169 int board_init(void)
170 {
171 gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
172
173 apf27_setup_csx();
174 apf27_setup_port();
175 apf27_iomux_init();
176 apf27_devices_init();
177 #if defined(CONFIG_FPGA)
178 APF27_init_fpga();
179 #endif
180
181
182 return 0;
183 }
184
dram_init(void)185 int dram_init(void)
186 {
187 gd->ram_size = get_ram_size((void *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE);
188 if (get_num_ram_bank() > 1)
189 gd->ram_size += get_ram_size((void *)PHYS_SDRAM_2,
190 PHYS_SDRAM_2_SIZE);
191
192 return 0;
193 }
194
dram_init_banksize(void)195 int dram_init_banksize(void)
196 {
197 gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
198 gd->bd->bi_dram[0].size = get_ram_size((void *)PHYS_SDRAM_1,
199 PHYS_SDRAM_1_SIZE);
200 gd->bd->bi_dram[1].start = PHYS_SDRAM_2;
201 if (get_num_ram_bank() > 1)
202 gd->bd->bi_dram[1].size = get_ram_size((void *)PHYS_SDRAM_2,
203 PHYS_SDRAM_2_SIZE);
204 else
205 gd->bd->bi_dram[1].size = 0;
206
207 return 0;
208 }
209
board_get_usable_ram_top(ulong total_size)210 ulong board_get_usable_ram_top(ulong total_size)
211 {
212 ulong ramtop;
213
214 if (get_num_ram_bank() > 1)
215 ramtop = PHYS_SDRAM_2 + get_ram_size((void *)PHYS_SDRAM_2,
216 PHYS_SDRAM_2_SIZE);
217 else
218 ramtop = PHYS_SDRAM_1 + get_ram_size((void *)PHYS_SDRAM_1,
219 PHYS_SDRAM_1_SIZE);
220
221 return ramtop;
222 }
223
checkboard(void)224 int checkboard(void)
225 {
226 printf("Board: Armadeus APF27 revision %d\n", get_board_rev());
227 return 0;
228 }
229
230 #ifdef CONFIG_SPL_BUILD
hang(void)231 inline void hang(void)
232 {
233 for (;;)
234 ;
235 }
236
board_init_f(ulong bootflag)237 void board_init_f(ulong bootflag)
238 {
239 /*
240 * copy ourselves from where we are running to where we were
241 * linked at. Use ulong pointers as all addresses involved
242 * are 4-byte-aligned.
243 */
244 ulong *start_ptr, *end_ptr, *link_ptr, *run_ptr, *dst;
245 asm volatile ("ldr %0, =_start" : "=r"(start_ptr));
246 asm volatile ("ldr %0, =_end" : "=r"(end_ptr));
247 asm volatile ("ldr %0, =board_init_f" : "=r"(link_ptr));
248 asm volatile ("adr %0, board_init_f" : "=r"(run_ptr));
249 for (dst = start_ptr; dst < end_ptr; dst++)
250 *dst = *(dst+(run_ptr-link_ptr));
251
252 /*
253 * branch to nand_boot's link-time address.
254 */
255 asm volatile("ldr pc, =nand_boot");
256 }
257 #endif /* CONFIG_SPL_BUILD */
258