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