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