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