]>
Commit | Line | Data |
---|---|---|
98d62e61 PB |
1 | /* |
2 | * Copyright (C) 2015 Beckhoff Automation GmbH & Co. KG | |
3 | * Patrick Bruenn <p.bruenn@beckhoff.com> | |
4 | * | |
5 | * Based on <u-boot>/board/freescale/mx53loco/mx53loco.c | |
6 | * Copyright (C) 2011 Freescale Semiconductor, Inc. | |
7 | * | |
8 | * SPDX-License-Identifier: GPL-2.0+ | |
9 | */ | |
10 | ||
11 | #include <common.h> | |
9d922450 | 12 | #include <dm.h> |
98d62e61 PB |
13 | #include <asm/io.h> |
14 | #include <asm/arch/imx-regs.h> | |
15 | #include <asm/arch/sys_proto.h> | |
16 | #include <asm/arch/crm_regs.h> | |
17 | #include <asm/arch/clock.h> | |
18 | #include <asm/arch/iomux-mx53.h> | |
19 | #include <asm/arch/clock.h> | |
552a848e | 20 | #include <asm/mach-imx/mx5_video.h> |
98d62e61 PB |
21 | #include <ACEX1K.h> |
22 | #include <netdev.h> | |
23 | #include <i2c.h> | |
24 | #include <mmc.h> | |
25 | #include <fsl_esdhc.h> | |
26 | #include <asm/gpio.h> | |
27 | #include <linux/fb.h> | |
28 | #include <ipu_pixfmt.h> | |
29 | #include <fs.h> | |
98d62e61 PB |
30 | #include <dm/platform_data/serial_mxc.h> |
31 | ||
32 | enum LED_GPIOS { | |
33 | GPIO_SD1_CD = IMX_GPIO_NR(1, 1), | |
34 | GPIO_SD2_CD = IMX_GPIO_NR(1, 4), | |
35 | GPIO_LED_SD2_R = IMX_GPIO_NR(3, 16), | |
36 | GPIO_LED_SD2_B = IMX_GPIO_NR(3, 17), | |
37 | GPIO_LED_SD2_G = IMX_GPIO_NR(3, 18), | |
38 | GPIO_LED_SD1_R = IMX_GPIO_NR(3, 19), | |
39 | GPIO_LED_SD1_B = IMX_GPIO_NR(3, 20), | |
40 | GPIO_LED_SD1_G = IMX_GPIO_NR(3, 21), | |
41 | GPIO_LED_PWR_R = IMX_GPIO_NR(3, 22), | |
42 | GPIO_LED_PWR_B = IMX_GPIO_NR(3, 23), | |
43 | GPIO_LED_PWR_G = IMX_GPIO_NR(3, 24), | |
44 | GPIO_SUPS_INT = IMX_GPIO_NR(3, 31), | |
45 | GPIO_C3_CONFIG = IMX_GPIO_NR(6, 8), | |
46 | GPIO_C3_STATUS = IMX_GPIO_NR(6, 7), | |
47 | GPIO_C3_DONE = IMX_GPIO_NR(6, 9), | |
48 | }; | |
49 | ||
50 | #define CCAT_BASE_ADDR ((void *)0xf0000000) | |
51 | #define CCAT_END_ADDR (CCAT_BASE_ADDR + (1024 * 1024 * 32)) | |
52 | #define CCAT_SIZE 1191788 | |
53 | #define CCAT_SIGN_ADDR (CCAT_BASE_ADDR + 12) | |
54 | static const char CCAT_SIGNATURE[] = "CCAT"; | |
55 | ||
56 | static const u32 CCAT_MODE_CONFIG = 0x0024DC81; | |
57 | static const u32 CCAT_MODE_RUN = 0x0033DC8F; | |
58 | ||
59 | DECLARE_GLOBAL_DATA_PTR; | |
60 | ||
61 | static uint32_t mx53_dram_size[2]; | |
62 | ||
63 | phys_size_t get_effective_memsize(void) | |
64 | { | |
65 | /* | |
66 | * WARNING: We must override get_effective_memsize() function here | |
67 | * to report only the size of the first DRAM bank. This is to make | |
68 | * U-Boot relocator place U-Boot into valid memory, that is, at the | |
69 | * end of the first DRAM bank. If we did not override this function | |
70 | * like so, U-Boot would be placed at the address of the first DRAM | |
71 | * bank + total DRAM size - sizeof(uboot), which in the setup where | |
72 | * each DRAM bank contains 512MiB of DRAM would result in placing | |
73 | * U-Boot into invalid memory area close to the end of the first | |
74 | * DRAM bank. | |
75 | */ | |
76 | return mx53_dram_size[0]; | |
77 | } | |
78 | ||
79 | int dram_init(void) | |
80 | { | |
81 | mx53_dram_size[0] = get_ram_size((void *)PHYS_SDRAM_1, 1 << 30); | |
82 | mx53_dram_size[1] = get_ram_size((void *)PHYS_SDRAM_2, 1 << 30); | |
83 | ||
84 | gd->ram_size = mx53_dram_size[0] + mx53_dram_size[1]; | |
85 | ||
86 | return 0; | |
87 | } | |
88 | ||
76b00aca | 89 | int dram_init_banksize(void) |
98d62e61 PB |
90 | { |
91 | gd->bd->bi_dram[0].start = PHYS_SDRAM_1; | |
92 | gd->bd->bi_dram[0].size = mx53_dram_size[0]; | |
93 | ||
94 | gd->bd->bi_dram[1].start = PHYS_SDRAM_2; | |
95 | gd->bd->bi_dram[1].size = mx53_dram_size[1]; | |
76b00aca SG |
96 | |
97 | return 0; | |
98d62e61 PB |
98 | } |
99 | ||
100 | u32 get_board_rev(void) | |
101 | { | |
102 | struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE; | |
103 | struct fuse_bank *bank = &iim->bank[0]; | |
104 | struct fuse_bank0_regs *fuse = | |
105 | (struct fuse_bank0_regs *)bank->fuse_regs; | |
106 | ||
107 | int rev = readl(&fuse->gp[6]); | |
108 | ||
109 | return (get_cpu_rev() & ~(0xF << 8)) | (rev & 0xF) << 8; | |
110 | } | |
111 | ||
112 | /* | |
113 | * Set CCAT mode | |
114 | * @mode: use CCAT_MODE_CONFIG or CCAT_MODE_RUN | |
115 | */ | |
116 | void weim_cs0_settings(u32 mode) | |
117 | { | |
118 | struct weim *weim_regs = (struct weim *)WEIM_BASE_ADDR; | |
119 | ||
120 | writel(0x0, &weim_regs->cs0gcr1); | |
121 | writel(mode, &weim_regs->cs0gcr1); | |
122 | writel(0x00001002, &weim_regs->cs0gcr2); | |
123 | ||
124 | writel(0x04000000, &weim_regs->cs0rcr1); | |
125 | writel(0x00000000, &weim_regs->cs0rcr2); | |
126 | ||
127 | writel(0x04000000, &weim_regs->cs0wcr1); | |
128 | writel(0x00000000, &weim_regs->cs0wcr2); | |
129 | } | |
130 | ||
131 | static void setup_gpio_eim(void) | |
132 | { | |
133 | gpio_direction_input(GPIO_C3_STATUS); | |
134 | gpio_direction_input(GPIO_C3_DONE); | |
135 | gpio_direction_output(GPIO_C3_CONFIG, 1); | |
136 | ||
137 | weim_cs0_settings(CCAT_MODE_RUN); | |
138 | } | |
139 | ||
140 | static void setup_gpio_sups(void) | |
141 | { | |
142 | gpio_direction_input(GPIO_SUPS_INT); | |
143 | ||
144 | static const int BLINK_INTERVALL = 50000; | |
145 | int status = 1; | |
146 | while (gpio_get_value(GPIO_SUPS_INT)) { | |
147 | /* signal "CX SUPS power fail" */ | |
148 | gpio_set_value(GPIO_LED_PWR_R, | |
149 | (++status / BLINK_INTERVALL) % 2); | |
150 | } | |
151 | ||
152 | /* signal "CX power up" */ | |
153 | gpio_set_value(GPIO_LED_PWR_R, 1); | |
154 | } | |
155 | ||
156 | static void setup_gpio_leds(void) | |
157 | { | |
158 | gpio_direction_output(GPIO_LED_SD2_R, 0); | |
159 | gpio_direction_output(GPIO_LED_SD2_B, 0); | |
160 | gpio_direction_output(GPIO_LED_SD2_G, 0); | |
161 | gpio_direction_output(GPIO_LED_SD1_R, 0); | |
162 | gpio_direction_output(GPIO_LED_SD1_B, 0); | |
163 | gpio_direction_output(GPIO_LED_SD1_G, 0); | |
164 | gpio_direction_output(GPIO_LED_PWR_R, 0); | |
165 | gpio_direction_output(GPIO_LED_PWR_B, 0); | |
166 | gpio_direction_output(GPIO_LED_PWR_G, 0); | |
167 | } | |
168 | ||
169 | #ifdef CONFIG_USB_EHCI_MX5 | |
170 | int board_ehci_hcd_init(int port) | |
171 | { | |
172 | /* request VBUS power enable pin, GPIO7_8 */ | |
173 | gpio_direction_output(IMX_GPIO_NR(7, 8), 1); | |
174 | return 0; | |
175 | } | |
176 | #endif | |
177 | ||
178 | #ifdef CONFIG_FSL_ESDHC | |
179 | struct fsl_esdhc_cfg esdhc_cfg[2] = { | |
180 | {MMC_SDHC1_BASE_ADDR}, | |
181 | {MMC_SDHC2_BASE_ADDR}, | |
182 | }; | |
183 | ||
184 | int board_mmc_getcd(struct mmc *mmc) | |
185 | { | |
186 | struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv; | |
187 | int ret; | |
188 | ||
189 | gpio_direction_input(GPIO_SD1_CD); | |
190 | gpio_direction_input(GPIO_SD2_CD); | |
191 | ||
192 | if (cfg->esdhc_base == MMC_SDHC1_BASE_ADDR) | |
193 | ret = !gpio_get_value(GPIO_SD1_CD); | |
194 | else | |
195 | ret = !gpio_get_value(GPIO_SD2_CD); | |
196 | ||
197 | return ret; | |
198 | } | |
199 | ||
200 | int board_mmc_init(bd_t *bis) | |
201 | { | |
202 | u32 index; | |
203 | int ret; | |
204 | ||
205 | esdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK); | |
206 | esdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK); | |
207 | ||
208 | for (index = 0; index < CONFIG_SYS_FSL_ESDHC_NUM; index++) { | |
209 | switch (index) { | |
210 | case 0: | |
211 | break; | |
212 | case 1: | |
213 | break; | |
214 | default: | |
215 | printf("Warning: you configured more ESDHC controller(%d) as supported by the board(2)\n", | |
216 | CONFIG_SYS_FSL_ESDHC_NUM); | |
217 | return -EINVAL; | |
218 | } | |
219 | ret = fsl_esdhc_initialize(bis, &esdhc_cfg[index]); | |
220 | if (ret) | |
221 | return ret; | |
222 | } | |
223 | ||
224 | return 0; | |
225 | } | |
226 | #endif | |
227 | ||
228 | static int power_init(void) | |
229 | { | |
230 | /* nothing to do on CX9020 */ | |
231 | return 0; | |
232 | } | |
233 | ||
234 | static void clock_1GHz(void) | |
235 | { | |
236 | int ret; | |
237 | u32 ref_clk = MXC_HCLK; | |
238 | /* | |
239 | * After increasing voltage to 1.25V, we can switch | |
240 | * CPU clock to 1GHz and DDR to 400MHz safely | |
241 | */ | |
242 | ret = mxc_set_clock(ref_clk, 1000, MXC_ARM_CLK); | |
243 | if (ret) | |
244 | printf("CPU: Switch CPU clock to 1GHZ failed\n"); | |
245 | ||
246 | ret = mxc_set_clock(ref_clk, 400, MXC_PERIPH_CLK); | |
247 | ret |= mxc_set_clock(ref_clk, 400, MXC_DDR_CLK); | |
248 | if (ret) | |
249 | printf("CPU: Switch DDR clock to 400MHz failed\n"); | |
250 | } | |
251 | ||
252 | int board_early_init_f(void) | |
253 | { | |
254 | setup_gpio_leds(); | |
255 | setup_gpio_sups(); | |
256 | setup_gpio_eim(); | |
257 | setup_iomux_lcd(); | |
258 | ||
259 | return 0; | |
260 | } | |
261 | ||
262 | /* | |
263 | * Do not overwrite the console | |
264 | * Use always serial for U-Boot console | |
265 | */ | |
266 | int overwrite_console(void) | |
267 | { | |
268 | return 1; | |
269 | } | |
270 | ||
271 | int board_init(void) | |
272 | { | |
273 | gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100; | |
274 | ||
275 | mxc_set_sata_internal_clock(); | |
276 | ||
277 | return 0; | |
278 | } | |
279 | ||
280 | int checkboard(void) | |
281 | { | |
282 | puts("Board: Beckhoff CX9020\n"); | |
283 | ||
284 | return 0; | |
285 | } | |
286 | ||
287 | static int ccat_config_fn(int assert_config, int flush, int cookie) | |
288 | { | |
289 | /* prepare FPGA for programming */ | |
290 | weim_cs0_settings(CCAT_MODE_CONFIG); | |
291 | gpio_set_value(GPIO_C3_CONFIG, 0); | |
292 | udelay(1); | |
293 | gpio_set_value(GPIO_C3_CONFIG, 1); | |
294 | udelay(230); | |
295 | ||
296 | return FPGA_SUCCESS; | |
297 | } | |
298 | ||
299 | static int ccat_status_fn(int cookie) | |
300 | { | |
301 | return FPGA_FAIL; | |
302 | } | |
303 | ||
304 | static int ccat_write_fn(const void *buf, size_t buf_len, int flush, int cookie) | |
305 | { | |
306 | const uint8_t *const buffer = buf; | |
307 | ||
308 | /* program CCAT */ | |
309 | int i; | |
310 | for (i = 0; i < buf_len; ++i) | |
311 | writeb(buffer[i], CCAT_BASE_ADDR); | |
312 | ||
313 | writeb(0xff, CCAT_BASE_ADDR); | |
314 | writeb(0xff, CCAT_BASE_ADDR); | |
315 | ||
316 | return FPGA_SUCCESS; | |
317 | } | |
318 | ||
319 | static int ccat_done_fn(int cookie) | |
320 | { | |
321 | /* programming complete? */ | |
322 | return gpio_get_value(GPIO_C3_DONE); | |
323 | } | |
324 | ||
325 | static int ccat_post_fn(int cookie) | |
326 | { | |
327 | /* switch to FPGA run mode */ | |
328 | weim_cs0_settings(CCAT_MODE_RUN); | |
329 | invalidate_dcache_range((ulong) CCAT_BASE_ADDR, (ulong) CCAT_END_ADDR); | |
330 | ||
331 | if (memcmp(CCAT_SIGN_ADDR, CCAT_SIGNATURE, sizeof(CCAT_SIGNATURE))) { | |
332 | printf("Verifing CCAT firmware failed, signature not found\n"); | |
333 | return FPGA_FAIL; | |
334 | } | |
335 | ||
336 | /* signal "CX booting OS" */ | |
337 | gpio_set_value(GPIO_LED_PWR_R, 1); | |
338 | gpio_set_value(GPIO_LED_PWR_G, 1); | |
339 | gpio_set_value(GPIO_LED_PWR_B, 0); | |
340 | return FPGA_SUCCESS; | |
341 | } | |
342 | ||
343 | static Altera_CYC2_Passive_Serial_fns ccat_fns = { | |
344 | .config = ccat_config_fn, | |
345 | .status = ccat_status_fn, | |
346 | .done = ccat_done_fn, | |
347 | .write = ccat_write_fn, | |
348 | .abort = ccat_post_fn, | |
349 | .post = ccat_post_fn, | |
350 | }; | |
351 | ||
352 | static Altera_desc ccat_fpga = { | |
353 | .family = Altera_CYC2, | |
354 | .iface = passive_serial, | |
355 | .size = CCAT_SIZE, | |
356 | .iface_fns = &ccat_fns, | |
357 | .base = CCAT_BASE_ADDR, | |
358 | }; | |
359 | ||
360 | int board_late_init(void) | |
361 | { | |
362 | if (!power_init()) | |
363 | clock_1GHz(); | |
364 | ||
365 | fpga_init(); | |
366 | fpga_add(fpga_altera, &ccat_fpga); | |
367 | ||
368 | return 0; | |
369 | } |