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