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 <hang.h>
11 #include <init.h>
12 #include <asm/global_data.h>
13 #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>
20 #include <linux/errno.h>
21 #include <u-boot/crc.h>
22 #include "apf27.h"
23 #include "fpga.h"
24 
25 DECLARE_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  */
get_board_rev(void)35 static 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  */
get_num_ram_bank(void)49 static 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 
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)62 static 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 
apf27_iomux_init(void)92 static 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 
apf27_devices_init(void)102 static 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 
123 #ifdef CONFIG_MMC_MXC
124 	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 
apf27_setup_csx(void)132 static 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 
apf27_setup_port(void)163 static 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 
board_init(void)171 int 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();
179 #if defined(CONFIG_FPGA)
180 	APF27_init_fpga();
181 #endif
182 
183 
184 	return 0;
185 }
186 
dram_init(void)187 int 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 
dram_init_banksize(void)197 int dram_init_banksize(void)
198 {
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;
208 
209 	return 0;
210 }
211 
board_get_usable_ram_top(ulong total_size)212 ulong 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 
checkboard(void)226 int checkboard(void)
227 {
228 	printf("Board: Armadeus APF27 revision %d\n", get_board_rev());
229 	return 0;
230 }
231 
232 #ifdef CONFIG_SPL_BUILD
hang(void)233 inline void hang(void)
234 {
235 	for (;;)
236 		;
237 }
238 
board_init_f(ulong bootflag)239 void 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 */
260