]>
Commit | Line | Data |
---|---|---|
89f95492 HK |
1 | /* |
2 | * Copyright (C) 2011 Samsung Electronics | |
3 | * Heungjun Kim <riverful.kim@samsung.com> | |
4 | * Kyungmin Park <kyungmin.park@samsung.com> | |
5 | * | |
6 | * See file CREDITS for list of people who contributed to this | |
7 | * project. | |
8 | * | |
9 | * This program is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU General Public License as | |
11 | * published by the Free Software Foundation; either version 2 of | |
12 | * the License, or (at your option) any later version. | |
13 | * | |
14 | * This program is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | * GNU General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU General Public License | |
20 | * along with this program; if not, write to the Free Software | |
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
22 | * MA 02111-1307 USA | |
23 | */ | |
24 | ||
25 | #include <common.h> | |
26 | #include <asm/io.h> | |
27 | #include <asm/arch/cpu.h> | |
28 | #include <asm/arch/gpio.h> | |
29 | #include <asm/arch/mmc.h> | |
30 | #include <asm/arch/clock.h> | |
31 | #include <asm/arch/watchdog.h> | |
32 | #include <asm/arch/power.h> | |
33 | #include <pmic.h> | |
34 | #include <usb/s3c_udc.h> | |
35 | #include <max8998_pmic.h> | |
36 | ||
37 | #include "setup.h" | |
38 | ||
39 | DECLARE_GLOBAL_DATA_PTR; | |
40 | ||
41 | unsigned int board_rev; | |
42 | ||
43 | #ifdef CONFIG_REVISION_TAG | |
44 | u32 get_board_rev(void) | |
45 | { | |
46 | return board_rev; | |
47 | } | |
48 | #endif | |
49 | ||
50 | static void check_hw_revision(void); | |
51 | ||
52 | int board_init(void) | |
53 | { | |
54 | gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100; | |
55 | ||
56 | check_hw_revision(); | |
57 | printf("HW Revision:\t0x%x\n", board_rev); | |
58 | ||
59 | #if defined(CONFIG_PMIC) | |
60 | pmic_init(); | |
61 | #endif | |
62 | ||
63 | return 0; | |
64 | } | |
65 | ||
66 | int dram_init(void) | |
67 | { | |
68 | gd->ram_size = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE) + | |
69 | get_ram_size((long *)PHYS_SDRAM_2, PHYS_SDRAM_2_SIZE); | |
70 | ||
71 | return 0; | |
72 | } | |
73 | ||
74 | void dram_init_banksize(void) | |
75 | { | |
76 | gd->bd->bi_dram[0].start = PHYS_SDRAM_1; | |
77 | gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; | |
78 | gd->bd->bi_dram[1].start = PHYS_SDRAM_2; | |
79 | gd->bd->bi_dram[1].size = PHYS_SDRAM_2_SIZE; | |
80 | } | |
81 | ||
82 | static unsigned int get_hw_revision(void) | |
83 | { | |
84 | struct exynos4_gpio_part1 *gpio = | |
85 | (struct exynos4_gpio_part1 *)samsung_get_base_gpio_part1(); | |
86 | int hwrev = 0; | |
87 | int i; | |
88 | ||
89 | /* hw_rev[3:0] == GPE1[3:0] */ | |
90 | for (i = 0; i < 4; i++) { | |
91 | s5p_gpio_cfg_pin(&gpio->e1, i, GPIO_INPUT); | |
92 | s5p_gpio_set_pull(&gpio->e1, i, GPIO_PULL_NONE); | |
93 | } | |
94 | ||
95 | udelay(1); | |
96 | ||
97 | for (i = 0; i < 4; i++) | |
98 | hwrev |= (s5p_gpio_get_value(&gpio->e1, i) << i); | |
99 | ||
100 | debug("hwrev 0x%x\n", hwrev); | |
101 | ||
102 | return hwrev; | |
103 | } | |
104 | ||
105 | static void check_hw_revision(void) | |
106 | { | |
107 | int hwrev; | |
108 | ||
109 | hwrev = get_hw_revision(); | |
110 | ||
111 | board_rev |= hwrev; | |
112 | } | |
113 | ||
114 | #ifdef CONFIG_DISPLAY_BOARDINFO | |
115 | int checkboard(void) | |
116 | { | |
117 | puts("Board:\tTRATS\n"); | |
118 | return 0; | |
119 | } | |
120 | #endif | |
121 | ||
122 | #ifdef CONFIG_GENERIC_MMC | |
123 | int board_mmc_init(bd_t *bis) | |
124 | { | |
125 | struct exynos4_gpio_part2 *gpio = | |
126 | (struct exynos4_gpio_part2 *)samsung_get_base_gpio_part2(); | |
127 | int i, err; | |
128 | ||
129 | /* eMMC_EN: SD_0_CDn: GPK0[2] Output High */ | |
130 | s5p_gpio_direction_output(&gpio->k0, 2, 1); | |
131 | s5p_gpio_set_pull(&gpio->k0, 2, GPIO_PULL_NONE); | |
132 | ||
133 | /* | |
134 | * eMMC GPIO: | |
135 | * SDR 8-bit@48MHz at MMC0 | |
136 | * GPK0[0] SD_0_CLK(2) | |
137 | * GPK0[1] SD_0_CMD(2) | |
138 | * GPK0[2] SD_0_CDn -> Not used | |
139 | * GPK0[3:6] SD_0_DATA[0:3](2) | |
140 | * GPK1[3:6] SD_0_DATA[0:3](3) | |
141 | * | |
142 | * DDR 4-bit@26MHz at MMC4 | |
143 | * GPK0[0] SD_4_CLK(3) | |
144 | * GPK0[1] SD_4_CMD(3) | |
145 | * GPK0[2] SD_4_CDn -> Not used | |
146 | * GPK0[3:6] SD_4_DATA[0:3](3) | |
147 | * GPK1[3:6] SD_4_DATA[4:7](4) | |
148 | */ | |
149 | for (i = 0; i < 7; i++) { | |
150 | if (i == 2) | |
151 | continue; | |
152 | /* GPK0[0:6] special function 2 */ | |
153 | s5p_gpio_cfg_pin(&gpio->k0, i, 0x2); | |
154 | /* GPK0[0:6] pull disable */ | |
155 | s5p_gpio_set_pull(&gpio->k0, i, GPIO_PULL_NONE); | |
156 | /* GPK0[0:6] drv 4x */ | |
157 | s5p_gpio_set_drv(&gpio->k0, i, GPIO_DRV_4X); | |
158 | } | |
159 | ||
160 | for (i = 3; i < 7; i++) { | |
161 | /* GPK1[3:6] special function 3 */ | |
162 | s5p_gpio_cfg_pin(&gpio->k1, i, 0x3); | |
163 | /* GPK1[3:6] pull disable */ | |
164 | s5p_gpio_set_pull(&gpio->k1, i, GPIO_PULL_NONE); | |
165 | /* GPK1[3:6] drv 4x */ | |
166 | s5p_gpio_set_drv(&gpio->k1, i, GPIO_DRV_4X); | |
167 | } | |
168 | ||
169 | /* | |
170 | * MMC device init | |
171 | * mmc0 : eMMC (8-bit buswidth) | |
172 | * mmc2 : SD card (4-bit buswidth) | |
173 | */ | |
174 | err = s5p_mmc_init(0, 8); | |
175 | ||
176 | /* T-flash detect */ | |
177 | s5p_gpio_cfg_pin(&gpio->x3, 4, 0xf); | |
178 | s5p_gpio_set_pull(&gpio->x3, 4, GPIO_PULL_UP); | |
179 | ||
180 | /* | |
181 | * Check the T-flash detect pin | |
182 | * GPX3[4] T-flash detect pin | |
183 | */ | |
184 | if (!s5p_gpio_get_value(&gpio->x3, 4)) { | |
185 | /* | |
186 | * SD card GPIO: | |
187 | * GPK2[0] SD_2_CLK(2) | |
188 | * GPK2[1] SD_2_CMD(2) | |
189 | * GPK2[2] SD_2_CDn -> Not used | |
190 | * GPK2[3:6] SD_2_DATA[0:3](2) | |
191 | */ | |
192 | for (i = 0; i < 7; i++) { | |
193 | if (i == 2) | |
194 | continue; | |
195 | /* GPK2[0:6] special function 2 */ | |
196 | s5p_gpio_cfg_pin(&gpio->k2, i, 0x2); | |
197 | /* GPK2[0:6] pull disable */ | |
198 | s5p_gpio_set_pull(&gpio->k2, i, GPIO_PULL_NONE); | |
199 | /* GPK2[0:6] drv 4x */ | |
200 | s5p_gpio_set_drv(&gpio->k2, i, GPIO_DRV_4X); | |
201 | } | |
202 | err = s5p_mmc_init(2, 4); | |
203 | } | |
204 | ||
205 | return err; | |
206 | } | |
207 | #endif | |
208 | ||
209 | #ifdef CONFIG_USB_GADGET | |
210 | static int s5pc210_phy_control(int on) | |
211 | { | |
212 | int ret = 0; | |
213 | struct pmic *p = get_pmic(); | |
214 | ||
215 | if (pmic_probe(p)) | |
216 | return -1; | |
217 | ||
218 | if (on) { | |
219 | ret |= pmic_set_output(p, | |
220 | MAX8998_REG_BUCK_ACTIVE_DISCHARGE3, | |
221 | MAX8998_SAFEOUT1, LDO_ON); | |
222 | ret |= pmic_set_output(p, MAX8998_REG_ONOFF1, | |
223 | MAX8998_LDO3, LDO_ON); | |
224 | ret |= pmic_set_output(p, MAX8998_REG_ONOFF2, | |
225 | MAX8998_LDO8, LDO_ON); | |
226 | ||
227 | } else { | |
228 | ret |= pmic_set_output(p, MAX8998_REG_ONOFF2, | |
229 | MAX8998_LDO8, LDO_OFF); | |
230 | ret |= pmic_set_output(p, MAX8998_REG_ONOFF1, | |
231 | MAX8998_LDO3, LDO_OFF); | |
232 | ret |= pmic_set_output(p, | |
233 | MAX8998_REG_BUCK_ACTIVE_DISCHARGE3, | |
234 | MAX8998_SAFEOUT1, LDO_OFF); | |
235 | } | |
236 | ||
237 | if (ret) { | |
238 | puts("MAX8998 LDO setting error!\n"); | |
239 | return -1; | |
240 | } | |
241 | ||
242 | return 0; | |
243 | } | |
244 | ||
245 | struct s3c_plat_otg_data s5pc210_otg_data = { | |
246 | .phy_control = s5pc210_phy_control, | |
247 | .regs_phy = EXYNOS4_USBPHY_BASE, | |
248 | .regs_otg = EXYNOS4_USBOTG_BASE, | |
249 | .usb_phy_ctrl = EXYNOS4_USBPHY_CONTROL, | |
250 | .usb_flags = PHY0_SLEEP, | |
251 | }; | |
252 | #endif | |
253 | ||
254 | static void pmic_reset(void) | |
255 | { | |
256 | struct exynos4_gpio_part2 *gpio = | |
257 | (struct exynos4_gpio_part2 *)samsung_get_base_gpio_part2(); | |
258 | ||
259 | s5p_gpio_direction_output(&gpio->x0, 7, 1); | |
260 | s5p_gpio_set_pull(&gpio->x2, 7, GPIO_PULL_NONE); | |
261 | } | |
262 | ||
263 | static void board_clock_init(void) | |
264 | { | |
265 | struct exynos4_clock *clk = | |
266 | (struct exynos4_clock *)samsung_get_base_clock(); | |
267 | ||
268 | writel(CLK_SRC_CPU_VAL, (unsigned int)&clk->src_cpu); | |
269 | writel(CLK_SRC_TOP0_VAL, (unsigned int)&clk->src_top0); | |
270 | writel(CLK_SRC_FSYS_VAL, (unsigned int)&clk->src_fsys); | |
271 | writel(CLK_SRC_PERIL0_VAL, (unsigned int)&clk->src_peril0); | |
272 | ||
273 | writel(CLK_DIV_CPU0_VAL, (unsigned int)&clk->div_cpu0); | |
274 | writel(CLK_DIV_CPU1_VAL, (unsigned int)&clk->div_cpu1); | |
275 | writel(CLK_DIV_DMC0_VAL, (unsigned int)&clk->div_dmc0); | |
276 | writel(CLK_DIV_DMC1_VAL, (unsigned int)&clk->div_dmc1); | |
277 | writel(CLK_DIV_LEFTBUS_VAL, (unsigned int)&clk->div_leftbus); | |
278 | writel(CLK_DIV_RIGHTBUS_VAL, (unsigned int)&clk->div_rightbus); | |
279 | writel(CLK_DIV_TOP_VAL, (unsigned int)&clk->div_top); | |
280 | writel(CLK_DIV_FSYS1_VAL, (unsigned int)&clk->div_fsys1); | |
281 | writel(CLK_DIV_FSYS2_VAL, (unsigned int)&clk->div_fsys2); | |
282 | writel(CLK_DIV_FSYS3_VAL, (unsigned int)&clk->div_fsys3); | |
283 | writel(CLK_DIV_PERIL0_VAL, (unsigned int)&clk->div_peril0); | |
284 | writel(CLK_DIV_PERIL3_VAL, (unsigned int)&clk->div_peril3); | |
285 | ||
286 | writel(PLL_LOCKTIME, (unsigned int)&clk->apll_lock); | |
287 | writel(PLL_LOCKTIME, (unsigned int)&clk->mpll_lock); | |
288 | writel(PLL_LOCKTIME, (unsigned int)&clk->epll_lock); | |
289 | writel(PLL_LOCKTIME, (unsigned int)&clk->vpll_lock); | |
290 | writel(APLL_CON1_VAL, (unsigned int)&clk->apll_con1); | |
291 | writel(APLL_CON0_VAL, (unsigned int)&clk->apll_con0); | |
292 | writel(MPLL_CON1_VAL, (unsigned int)&clk->mpll_con1); | |
293 | writel(MPLL_CON0_VAL, (unsigned int)&clk->mpll_con0); | |
294 | writel(EPLL_CON1_VAL, (unsigned int)&clk->epll_con1); | |
295 | writel(EPLL_CON0_VAL, (unsigned int)&clk->epll_con0); | |
296 | writel(VPLL_CON1_VAL, (unsigned int)&clk->vpll_con1); | |
297 | writel(VPLL_CON0_VAL, (unsigned int)&clk->vpll_con0); | |
298 | ||
299 | writel(CLK_GATE_IP_CAM_VAL, (unsigned int)&clk->gate_ip_cam); | |
300 | writel(CLK_GATE_IP_VP_VAL, (unsigned int)&clk->gate_ip_tv); | |
301 | writel(CLK_GATE_IP_MFC_VAL, (unsigned int)&clk->gate_ip_mfc); | |
302 | writel(CLK_GATE_IP_G3D_VAL, (unsigned int)&clk->gate_ip_g3d); | |
303 | writel(CLK_GATE_IP_IMAGE_VAL, (unsigned int)&clk->gate_ip_image); | |
304 | writel(CLK_GATE_IP_LCD0_VAL, (unsigned int)&clk->gate_ip_lcd0); | |
305 | writel(CLK_GATE_IP_LCD1_VAL, (unsigned int)&clk->gate_ip_lcd1); | |
306 | writel(CLK_GATE_IP_FSYS_VAL, (unsigned int)&clk->gate_ip_fsys); | |
307 | writel(CLK_GATE_IP_GPS_VAL, (unsigned int)&clk->gate_ip_gps); | |
308 | writel(CLK_GATE_IP_PERIL_VAL, (unsigned int)&clk->gate_ip_peril); | |
309 | writel(CLK_GATE_IP_PERIR_VAL, (unsigned int)&clk->gate_ip_perir); | |
310 | writel(CLK_GATE_BLOCK_VAL, (unsigned int)&clk->gate_block); | |
311 | } | |
312 | ||
313 | static void board_watchdog_disable(void) | |
314 | { | |
315 | struct exynos4_watchdog *wd = | |
316 | (struct exynos4_watchdog *)samsung_get_base_watchdog(); | |
317 | ||
318 | writel(~(WTCON_EN | WTCON_INT), (unsigned int)&wd->wtcon); | |
319 | } | |
320 | ||
321 | static void board_power_init(void) | |
322 | { | |
323 | struct exynos4_power *pwr = | |
324 | (struct exynos4_power *)samsung_get_base_power(); | |
325 | ||
326 | /* PS HOLD */ | |
327 | writel(EXYNOS4_PS_HOLD_CON_VAL, (unsigned int)&pwr->ps_hold_control); | |
328 | ||
329 | /* Set power down */ | |
330 | writel(0, (unsigned int)&pwr->cam_configuration); | |
331 | writel(0, (unsigned int)&pwr->tv_configuration); | |
332 | writel(0, (unsigned int)&pwr->mfc_configuration); | |
333 | writel(0, (unsigned int)&pwr->g3d_configuration); | |
334 | writel(0, (unsigned int)&pwr->lcd1_configuration); | |
335 | writel(0, (unsigned int)&pwr->gps_configuration); | |
336 | writel(0, (unsigned int)&pwr->gps_alive_configuration); | |
337 | } | |
338 | ||
339 | static void board_uart_init(void) | |
340 | { | |
341 | struct exynos4_gpio_part1 *gpio1 = | |
342 | (struct exynos4_gpio_part1 *)samsung_get_base_gpio_part1(); | |
343 | struct exynos4_gpio_part2 *gpio2 = | |
344 | (struct exynos4_gpio_part2 *)samsung_get_base_gpio_part2(); | |
345 | int i; | |
346 | ||
347 | /* UART0-UART1 GPIOs (part1) : 0x22222222 */ | |
348 | for (i = 0; i < 7; i++) { | |
349 | s5p_gpio_set_pull(&gpio1->a0, i, GPIO_PULL_NONE); | |
350 | s5p_gpio_cfg_pin(&gpio1->a0, i, GPIO_FUNC(0x2)); | |
351 | } | |
352 | ||
353 | /* | |
354 | * UART2-UART3 GPIOs (part2) : 0x00223322 | |
355 | * GPA1CON[3] = I2C_3_SCL (3) | |
356 | * GPA1CON[2] = I2C_3_SDA (3) | |
357 | */ | |
358 | for (i = 0; i < 5; i++) { | |
359 | s5p_gpio_set_pull(&gpio1->a1, i, GPIO_PULL_NONE); | |
360 | s5p_gpio_cfg_pin(&gpio1->a1, i, | |
361 | GPIO_FUNC((i == 2 || i == 3) ? 0x3 : 0x2)); | |
362 | } | |
363 | ||
364 | /* UART_SEL GPY4[7] (part2) at EXYNOS4 */ | |
365 | s5p_gpio_set_pull(&gpio2->y4, 7, GPIO_PULL_UP); | |
366 | s5p_gpio_direction_output(&gpio2->y4, 7, 1); | |
367 | } | |
368 | ||
369 | int board_early_init_f(void) | |
370 | { | |
371 | board_watchdog_disable(); | |
372 | ||
373 | pmic_reset(); | |
374 | board_clock_init(); | |
375 | board_uart_init(); | |
376 | board_power_init(); | |
377 | ||
378 | return 0; | |
379 | } |