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