odroid: fix g2d sclk rate
[platform/kernel/u-boot.git] / board / samsung / common / exynos4-dt.c
1 /*
2          * Copyright (C) 2014 Samsung Electronics
3  * Przemyslaw Marczak <p.marczak@samsung.com>
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 #include <common.h>
9 #include <asm/sections.h>
10 #include <asm/arch/pinmux.h>
11 #include <asm/arch/power.h>
12 #include <asm/arch/clock.h>
13 #include <asm/arch/gpio.h>
14 #include <asm/gpio.h>
15 #include <asm/arch/cpu.h>
16 #include <power/pmic.h>
17 #include <power/max77686_pmic.h>
18 #include <power/battery.h>
19 #include <power/max77693_pmic.h>
20 #include <power/max77693_muic.h>
21 #include <power/max77693_fg.h>
22 #include <errno.h>
23 #include <usb.h>
24 #include <usb/s3c_udc.h>
25 #include <usb_mass_storage.h>
26 #include <fdt.h>
27 #include <lcd.h>
28 #include <asm/arch/mipi_dsim.h>
29 #include <samsung/misc.h>
30 #include <libtizen.h>
31 #include "setup.h"
32
33 DECLARE_GLOBAL_DATA_PTR;
34
35 #define HWREV_TRATS2_CFG_REG    0x11000280
36 #define HWREV_TRATS2_CFG        0x0
37 #define HWREV_TRATS2_PULL_REG   0x11000288
38 #define HWREV_TRATS2_PULL       0x33000033
39 #define HWREV_TRATS2_DAT_REG    0x11000284
40 #define HWREV_TRATS2_DAT_MASK   0xf0
41
42 #define CPU_MAIN_REV_MASK       0xf0
43 #define CPU_MAIN_REV_SHIFT      0x4
44 #define CPU_MAIN_REV(x)         ((x >> CPU_MAIN_REV_SHIFT) & CPU_MAIN_REV_MASK)
45
46 #define DTB_PADDING             0x4
47
48 /* For global battery and charger functions */
49 static struct power_battery *pbat;
50 static struct pmic *p_chrg, *p_muic, *p_fg, *p_bat;
51 static int power_init_done;
52
53 #ifdef CONFIG_BOARD_TYPES
54 /* Supported Exynos4 boards */
55 enum {
56         BOARD_TYPE_TRATS2,
57         BOARD_TYPE_ODROID_U3,
58         BOARD_TYPE_ODROID_X2,
59         BOARD_TYPES_NUM,
60 };
61
62 static const int board_arch_num[] = {
63         MACH_TYPE_SMDK4412,
64         MACH_TYPE_ODROIDX,
65         MACH_TYPE_ODROIDX,
66 };
67
68 static const char *board_compat[] = {
69         "samsung,trats2",
70         "samsung,odroid",
71         "samsung,odroid",
72 };
73
74 static const char *board_name[] = {
75         "trats",
76         "odroid",
77         "odroid",
78 };
79
80 static const char *board_model[] = {
81         "2",
82         "u3",
83         "x2",
84 };
85
86 extern void sdelay(unsigned long);
87
88 void set_board_type(void)
89 {
90         int hwrev = 0;
91         unsigned int addr;
92
93         /* GPM1[5:2] as input */
94         writel(HWREV_TRATS2_CFG, HWREV_TRATS2_CFG_REG);
95         writel(HWREV_TRATS2_PULL, HWREV_TRATS2_PULL_REG);
96         hwrev = readl(HWREV_TRATS2_DAT_REG) & HWREV_TRATS2_DAT_MASK;
97
98         /* Any Trats2 revision is valid */
99         if (hwrev) {
100                 gd->board_type = BOARD_TYPE_TRATS2;
101                 return;
102         }
103
104         /* Set GPA1 pin 1 to HI - enable XCL205 output */
105         /* GPA1CON 0x11400020 */
106         addr = 0x11400020;
107         writel(0x10, addr);
108
109         /* GPA1DAT 0x11400024 */
110         addr = 0x11400024;
111         writel(0x2, addr);
112
113         /* GPA1PUD 0x11400028 */
114         addr = 0x11400028;
115         writel(0xc, addr);
116
117         /* GPA1DRV 0x1140002c */
118         addr = 0x1140002c;
119         writel(0xc, addr);
120
121         /* Check GPC1 pin 2 input */
122         /* GPC1CON 0x11400020 */
123         addr = 0x11400080;
124         writel(0x0, addr);
125
126         /* GPC1PUD 0x11400028 */
127         addr = 0x11400088;
128         writel(0x0, addr);
129
130         /* XCL205 - needs some latch time */
131         sdelay(200000);
132
133         /* GPC1DAT 0x11400024 */
134         addr = 0x11400084;
135
136         /* Check GPC1 pin2 - LED supplied by XCL205 - X2 only */
137         if (readl(addr) & 0x4)
138                 gd->board_type = BOARD_TYPE_ODROID_X2;
139         else
140                 gd->board_type = BOARD_TYPE_ODROID_U3;
141 }
142
143 int board_is_trats2(void)
144 {
145         if (gd->board_type == BOARD_TYPE_TRATS2)
146                 return 1;
147
148         return 0;
149 }
150
151 int board_is_odroid_x2(void)
152 {
153         if (gd->board_type == BOARD_TYPE_ODROID_X2)
154                 return 1;
155
156         return 0;
157 }
158
159 int board_is_odroid_u3(void)
160 {
161         if (gd->board_type == BOARD_TYPE_ODROID_U3)
162                 return 1;
163
164         return 0;
165 }
166
167 const char *get_board_name(void)
168 {
169         return board_name[gd->board_type];
170 }
171
172 const char *get_board_type(void)
173 {
174         return board_model[gd->board_type];
175 }
176 #endif
177
178 #ifdef CONFIG_OF_MULTI
179 unsigned long *get_board_fdt(void)
180 {
181         unsigned long *fdt = (unsigned long *)&_end;
182         unsigned long size;
183         char *compat = NULL;
184         int i;
185
186         set_board_type();
187
188         for (i = 0; i < BOARD_TYPES_NUM; i++) {
189                 if (!fdt || fdt_magic(fdt) != FDT_MAGIC)
190                         break;
191
192                 compat = (char *) fdt_getprop(fdt, 0, "compatible", NULL);
193                 if (compat && !strcmp(board_compat[gd->board_type], compat))
194                                 return fdt;
195
196                 /* Byte size */
197                 size = fdt_totalsize(fdt);
198
199                 fdt += (unsigned long)(roundup(size, DTB_PADDING) >> 2);
200         }
201
202         return NULL;
203 }
204 #endif
205
206 #ifdef CONFIG_SET_DFU_ALT_INFO
207 char *get_dfu_alt_system(void)
208 {
209         char *alt_system;
210
211         if (board_is_trats2())
212                 alt_system = DFU_ALT_SYSTEM_TRATS2;
213         else
214                 alt_system = DFU_ALT_SYSTEM_ODROID;
215
216         return alt_system;
217 }
218
219 char *get_dfu_alt_boot(void)
220 {
221         char *alt_boot;
222
223         switch (get_boot_mode()) {
224         case BOOT_MODE_SD:
225                 if (board_is_trats2())
226                         alt_boot = DFU_ALT_BOOT_SD_TRATS2;
227                 else
228                         alt_boot = DFU_ALT_BOOT_SD_ODROID;
229                 break;
230         case BOOT_MODE_EMMC:
231         case BOOT_MODE_EMMC_SD:
232                 if (board_is_trats2())
233                         alt_boot = DFU_ALT_BOOT_EMMC_TRATS2;
234                 else
235                         alt_boot = DFU_ALT_BOOT_EMMC_ODROID;
236                 break;
237         default:
238                 alt_boot = NULL;
239                 break;
240         }
241
242         if (!alt_boot)
243                 return alt_boot;
244
245         return alt_boot;
246 }
247 #endif
248
249 static void board_clock_init(void)
250 {
251         unsigned int set, clr, clr_src_cpu, clr_pll_con0, clr_src_dmc;
252         struct exynos4x12_clock *clk = (struct exynos4x12_clock *)
253                                                 samsung_get_base_clock();
254
255         /*
256          * CMU_CPU clocks src to MPLL
257          * Bit values:                 0  ; 1
258          * MUX_APLL_SEL:        FIN_PLL   ; FOUT_APLL
259          * MUX_CORE_SEL:        MOUT_APLL ; SCLK_MPLL
260          * MUX_HPM_SEL:         MOUT_APLL ; SCLK_MPLL_USER_C
261          * MUX_MPLL_USER_SEL_C: FIN_PLL   ; SCLK_MPLL
262         */
263         clr_src_cpu = MUX_APLL_SEL(0x1) | MUX_CORE_SEL(0x1) |
264                       MUX_HPM_SEL(0x1) | MUX_MPLL_USER_SEL_C(0x1);
265         set = MUX_APLL_SEL(0) | MUX_CORE_SEL(1) | MUX_HPM_SEL(1) |
266               MUX_MPLL_USER_SEL_C(1);
267
268         clrsetbits_le32(&clk->src_cpu, clr_src_cpu, set);
269
270         /* Wait for mux change */
271         while (readl(&clk->mux_stat_cpu) & MUX_STAT_CPU_CHANGING)
272                 continue;
273
274         /* Set APLL to 1000MHz */
275         clr_pll_con0 = SDIV(0x7) | PDIV(0x3f) | MDIV(0x3ff) | FSEL(0x1);
276         set = SDIV(0) | PDIV(3) | MDIV(125) | FSEL(1);
277
278         clrsetbits_le32(&clk->apll_con0, clr_pll_con0, set);
279
280         /* Wait for PLL to be locked */
281         while (!(readl(&clk->apll_con0) & PLL_LOCKED_BIT))
282                 continue;
283
284         /* Set CMU_CPU clocks src to APLL */
285         set = MUX_APLL_SEL(1) | MUX_CORE_SEL(0) | MUX_HPM_SEL(0) |
286               MUX_MPLL_USER_SEL_C(1);
287         clrsetbits_le32(&clk->src_cpu, clr_src_cpu, set);
288
289         /* Wait for mux change */
290         while (readl(&clk->mux_stat_cpu) & MUX_STAT_CPU_CHANGING)
291                 continue;
292
293         set = CORE_RATIO(0) | COREM0_RATIO(2) | COREM1_RATIO(5) |
294               PERIPH_RATIO(0) | ATB_RATIO(4) | PCLK_DBG_RATIO(1) |
295               APLL_RATIO(0) | CORE2_RATIO(0);
296         /*
297          * Set dividers for MOUTcore = 1000 MHz
298          * coreout =      MOUT / (ratio + 1) = 1000 MHz (0)
299          * corem0 =     armclk / (ratio + 1) = 333 MHz (2)
300          * corem1 =     armclk / (ratio + 1) = 166 MHz (5)
301          * periph =     armclk / (ratio + 1) = 1000 MHz (0)
302          * atbout =       MOUT / (ratio + 1) = 200 MHz (4)
303          * pclkdbgout = atbout / (ratio + 1) = 100 MHz (1)
304          * sclkapll = MOUTapll / (ratio + 1) = 1000 MHz (0)
305          * core2out = core_out / (ratio + 1) = 1000 MHz (0) (armclk)
306         */
307         clr = CORE_RATIO(0x7) | COREM0_RATIO(0x7) | COREM1_RATIO(0x7) |
308               PERIPH_RATIO(0x7) | ATB_RATIO(0x7) | PCLK_DBG_RATIO(0x7) |
309               APLL_RATIO(0x7) | CORE2_RATIO(0x7);
310
311         clrsetbits_le32(&clk->div_cpu0, clr, set);
312
313         /* Wait for divider ready status */
314         while (readl(&clk->div_stat_cpu0) & DIV_STAT_CPU0_CHANGING)
315                 continue;
316
317         /*
318          * For MOUThpm = 1000 MHz (MOUTapll)
319          * doutcopy = MOUThpm / (ratio + 1) = 200 (4)
320          * sclkhpm = doutcopy / (ratio + 1) = 200 (4)
321          * cores_out = armclk / (ratio + 1) = 1000 (0)
322          */
323         clr = COPY_RATIO(0x7) | HPM_RATIO(0x7) | CORES_RATIO(0x7);
324         set = COPY_RATIO(4) | HPM_RATIO(4) | CORES_RATIO(0);
325
326         clrsetbits_le32(&clk->div_cpu1, clr, set);
327
328         /* Wait for divider ready status */
329         while (readl(&clk->div_stat_cpu1) & DIV_STAT_CPU1_CHANGING)
330                 continue;
331
332         /*
333          * Set CMU_DMC clocks src to APLL
334          * Bit values:             0  ; 1
335          * MUX_C2C_SEL:      SCLKMPLL ; SCLKAPLL
336          * MUX_DMC_BUS_SEL:  SCLKMPLL ; SCLKAPLL
337          * MUX_DPHY_SEL:     SCLKMPLL ; SCLKAPLL
338          * MUX_MPLL_SEL:     FINPLL   ; MOUT_MPLL_FOUT
339          * MUX_PWI_SEL:      0110 (MPLL); 0111 (EPLL); 1000 (VPLL); 0(XXTI)
340          * MUX_G2D_ACP0_SEL: SCLKMPLL ; SCLKAPLL
341          * MUX_G2D_ACP1_SEL: SCLKEPLL ; SCLKVPLL
342          * MUX_G2D_ACP_SEL:  OUT_ACP0 ; OUT_ACP1
343         */
344         clr_src_dmc = MUX_C2C_SEL(0x1) | MUX_DMC_BUS_SEL(0x1) |
345                       MUX_DPHY_SEL(0x1) | MUX_MPLL_SEL(0x1) |
346                       MUX_PWI_SEL(0xf) | MUX_G2D_ACP0_SEL(0x1) |
347                       MUX_G2D_ACP1_SEL(0x1) | MUX_G2D_ACP_SEL(0x1);
348         set = MUX_C2C_SEL(1) | MUX_DMC_BUS_SEL(1) | MUX_DPHY_SEL(1) |
349               MUX_MPLL_SEL(0) | MUX_PWI_SEL(0) | MUX_G2D_ACP0_SEL(1) |
350               MUX_G2D_ACP1_SEL(1) | MUX_G2D_ACP_SEL(1);
351
352         clrsetbits_le32(&clk->src_dmc, clr_src_dmc, set);
353
354         /* Wait for mux change */
355         while (readl(&clk->mux_stat_dmc) & MUX_STAT_DMC_CHANGING)
356                 continue;
357
358         /* Set MPLL to 800MHz */
359         set = SDIV(0) | PDIV(3) | MDIV(100) | FSEL(0) | PLL_ENABLE(1);
360
361         clrsetbits_le32(&clk->mpll_con0, clr_pll_con0, set);
362
363         /* Wait for PLL to be locked */
364         while (!(readl(&clk->mpll_con0) & PLL_LOCKED_BIT))
365                 continue;
366
367         /* Switch back CMU_DMC mux */
368         set = MUX_C2C_SEL(0) | MUX_DMC_BUS_SEL(0) | MUX_DPHY_SEL(0) |
369               MUX_MPLL_SEL(1) | MUX_PWI_SEL(8) | MUX_G2D_ACP0_SEL(0) |
370               MUX_G2D_ACP1_SEL(0) | MUX_G2D_ACP_SEL(0);
371
372         clrsetbits_le32(&clk->src_dmc, clr_src_dmc, set);
373
374         /* Wait for mux change */
375         while (readl(&clk->mux_stat_dmc) & MUX_STAT_DMC_CHANGING)
376                 continue;
377
378         /* CLK_DIV_DMC0 */
379         clr = ACP_RATIO(0x7) | ACP_PCLK_RATIO(0x7) | DPHY_RATIO(0x7) |
380               DMC_RATIO(0x7) | DMCD_RATIO(0x7) | DMCP_RATIO(0x7);
381         /*
382          * For:
383          * MOUTdmc = 800 MHz
384          * MOUTdphy = 800 MHz
385          *
386          * aclk_acp = MOUTdmc / (ratio + 1) = 200 (3)
387          * pclk_acp = aclk_acp / (ratio + 1) = 100 (1)
388          * sclk_dphy = MOUTdphy / (ratio + 1) = 400 (1)
389          * sclk_dmc = MOUTdmc / (ratio + 1) = 400 (1)
390          * aclk_dmcd = sclk_dmc / (ratio + 1) = 200 (1)
391          * aclk_dmcp = aclk_dmcd / (ratio + 1) = 100 (1)
392          */
393         set = ACP_RATIO(3) | ACP_PCLK_RATIO(1) | DPHY_RATIO(1) |
394               DMC_RATIO(1) | DMCD_RATIO(1) | DMCP_RATIO(1);
395
396         clrsetbits_le32(&clk->div_dmc0, clr, set);
397
398         /* Wait for divider ready status */
399         while (readl(&clk->div_stat_dmc0) & DIV_STAT_DMC0_CHANGING)
400                 continue;
401
402         /* CLK_DIV_DMC1 */
403         clr = G2D_ACP_RATIO(0xf) | C2C_RATIO(0x7) | PWI_RATIO(0xf) |
404               C2C_ACLK_RATIO(0x7) | DVSEM_RATIO(0x7f) | DPM_RATIO(0x7f);
405         /*
406          * For:
407          * MOUTg2d = 800 MHz
408          * MOUTc2c = 800 Mhz
409          * MOUTpwi = 108 MHz
410          *
411          * sclk_g2d_acp = MOUTg2d / (ratio + 1) = 200 (3)
412          * sclk_c2c = MOUTc2c / (ratio + 1) = 400 (1)
413          * aclk_c2c = sclk_c2c / (ratio + 1) = 200 (1)
414          * sclk_pwi = MOUTpwi / (ratio + 1) = 18 (5)
415          */
416         set = G2D_ACP_RATIO(3) | C2C_RATIO(1) | PWI_RATIO(5) |
417               C2C_ACLK_RATIO(1) | DVSEM_RATIO(1) | DPM_RATIO(1);
418
419         clrsetbits_le32(&clk->div_dmc1, clr, set);
420
421         /* Wait for divider ready status */
422         while (readl(&clk->div_stat_dmc1) & DIV_STAT_DMC1_CHANGING)
423                 continue;
424
425         /* CLK_SRC_PERIL0 */
426         clr = UART0_SEL(0xf) | UART1_SEL(0xf) | UART2_SEL(0xf) |
427               UART3_SEL(0xf) | UART4_SEL(0xf);
428         /*
429          * Set CLK_SRC_PERIL0 clocks src to MPLL
430          * src values: 0(XXTI); 1(XusbXTI); 2(SCLK_HDMI24M); 3(SCLK_USBPHY0);
431          *             5(SCLK_HDMIPHY); 6(SCLK_MPLL_USER_T); 7(SCLK_EPLL);
432          *             8(SCLK_VPLL)
433          *
434          * Set all to SCLK_MPLL_USER_T
435          */
436         set = UART0_SEL(6) | UART1_SEL(6) | UART2_SEL(6) | UART3_SEL(6) |
437               UART4_SEL(6);
438
439         clrsetbits_le32(&clk->src_peril0, clr, set);
440
441         /* CLK_DIV_PERIL0 */
442         clr = UART0_RATIO(0xf) | UART1_RATIO(0xf) | UART2_RATIO(0xf) |
443               UART3_RATIO(0xf) | UART4_RATIO(0xf);
444         /*
445          * For MOUTuart0-4: 800MHz
446          *
447          * SCLK_UARTx = MOUTuartX / (ratio + 1) = 100 (7)
448         */
449         set = UART0_RATIO(7) | UART1_RATIO(7) | UART2_RATIO(7) |
450               UART3_RATIO(7) | UART4_RATIO(7);
451
452         clrsetbits_le32(&clk->div_peril0, clr, set);
453
454         while (readl(&clk->div_stat_peril0) & DIV_STAT_PERIL0_CHANGING)
455                 continue;
456
457         /* CLK_DIV_FSYS1 */
458         clr = MMC0_RATIO(0xf) | MMC0_PRE_RATIO(0xff) | MMC1_RATIO(0xf) |
459               MMC1_PRE_RATIO(0xff);
460         /*
461          * For MOUTmmc0-3 = 800 MHz (MPLL)
462          *
463          * DOUTmmc1 = MOUTmmc1 / (ratio + 1) = 100 (7)
464          * sclk_mmc1 = DOUTmmc1 / (ratio + 1) = 50 (1)
465          * DOUTmmc0 = MOUTmmc0 / (ratio + 1) = 100 (7)
466          * sclk_mmc0 = DOUTmmc0 / (ratio + 1) = 50 (1)
467         */
468         set = MMC0_RATIO(7) | MMC0_PRE_RATIO(1) | MMC1_RATIO(7) |
469               MMC1_PRE_RATIO(1);
470
471         clrsetbits_le32(&clk->div_fsys1, clr, set);
472
473         /* Wait for divider ready status */
474         while (readl(&clk->div_stat_fsys1) & DIV_STAT_FSYS1_CHANGING)
475                 continue;
476
477         /* CLK_DIV_FSYS2 */
478         clr = MMC2_RATIO(0xf) | MMC2_PRE_RATIO(0xff) | MMC3_RATIO(0xf) |
479               MMC3_PRE_RATIO(0xff);
480         /*
481          * For MOUTmmc0-3 = 800 MHz (MPLL)
482          *
483          * DOUTmmc3 = MOUTmmc3 / (ratio + 1) = 100 (7)
484          * sclk_mmc3 = DOUTmmc3 / (ratio + 1) = 50 (1)
485          * DOUTmmc2 = MOUTmmc2 / (ratio + 1) = 100 (7)
486          * sclk_mmc2 = DOUTmmc2 / (ratio + 1) = 50 (1)
487         */
488         set = MMC2_RATIO(7) | MMC2_PRE_RATIO(1) | MMC3_RATIO(7) |
489               MMC3_PRE_RATIO(1);
490
491         clrsetbits_le32(&clk->div_fsys2, clr, set);
492
493         /* Wait for divider ready status */
494         while (readl(&clk->div_stat_fsys2) & DIV_STAT_FSYS2_CHANGING)
495                 continue;
496
497         /* CLK_DIV_FSYS3 */
498         clr = MMC4_RATIO(0xf) | MMC4_PRE_RATIO(0xff);
499         /*
500          * For MOUTmmc4 = 800 MHz (MPLL)
501          *
502          * DOUTmmc4 = MOUTmmc4 / (ratio + 1) = 100 (7)
503          * sclk_mmc4 = DOUTmmc4 / (ratio + 1) = 100 (0)
504         */
505         set = MMC4_RATIO(7) | MMC4_PRE_RATIO(0);
506
507         clrsetbits_le32(&clk->div_fsys3, clr, set);
508
509         /* Wait for divider ready status */
510         while (readl(&clk->div_stat_fsys3) & DIV_STAT_FSYS3_CHANGING)
511                 continue;
512
513         return;
514 }
515
516 static void board_gpio_init(void)
517 {
518         if (board_is_trats2()) {
519                 /* PS_ALS_INT */
520                 gpio_set_pull(EXYNOS4X12_GPIO_X02, S5P_GPIO_PULL_NONE);
521                 /* TSP_nINT */
522                 gpio_set_pull(EXYNOS4X12_GPIO_X04, S5P_GPIO_PULL_NONE);
523                 /* AP_PMIC_IRQ*/
524                 gpio_set_pull(EXYNOS4X12_GPIO_X07, S5P_GPIO_PULL_NONE);
525                 /* IF_PMIC_IRQ*/
526                 gpio_set_pull(EXYNOS4X12_GPIO_X15, S5P_GPIO_PULL_NONE);
527                 /* VOL_UP */
528                 gpio_set_pull(EXYNOS4X12_GPIO_X20, S5P_GPIO_PULL_NONE);
529                 /* VOL_DOWN */
530                 gpio_set_pull(EXYNOS4X12_GPIO_X21, S5P_GPIO_PULL_NONE);
531                 /* FUEL_ALERT */
532                 gpio_set_pull(EXYNOS4X12_GPIO_X23, S5P_GPIO_PULL_NONE);
533                 /* ADC_INT */
534                 gpio_set_pull(EXYNOS4X12_GPIO_X24, S5P_GPIO_PULL_NONE);
535                 /* nPOWER */
536                 gpio_set_pull(EXYNOS4X12_GPIO_X27, S5P_GPIO_PULL_NONE);
537                 /* WPC_INT */
538                 gpio_set_pull(EXYNOS4X12_GPIO_X30, S5P_GPIO_PULL_NONE);
539                 /* OK_KEY */
540                 gpio_set_pull(EXYNOS4X12_GPIO_X35, S5P_GPIO_PULL_NONE);
541                 /* HDMI_HPD */
542                 gpio_set_pull(EXYNOS4X12_GPIO_X37, S5P_GPIO_PULL_NONE);
543         } else {
544                 /* eMMC reset */
545                 gpio_cfg_pin(EXYNOS4X12_GPIO_K12, S5P_GPIO_FUNC(0x1));
546                 gpio_set_pull(EXYNOS4X12_GPIO_K12, S5P_GPIO_PULL_NONE);
547                 gpio_set_drv(EXYNOS4X12_GPIO_K12, S5P_GPIO_DRV_4X);
548
549                 /* Enable FAN (Odroid U3) */
550                 gpio_set_pull(EXYNOS4X12_GPIO_D00, S5P_GPIO_PULL_UP);
551                 gpio_set_drv(EXYNOS4X12_GPIO_D00, S5P_GPIO_DRV_4X);
552                 gpio_direction_output(EXYNOS4X12_GPIO_D00, 1);
553
554                 /* OTG Vbus output (Odroid U3+) */
555                 gpio_set_pull(EXYNOS4X12_GPIO_L20, S5P_GPIO_PULL_NONE);
556                 gpio_set_drv(EXYNOS4X12_GPIO_L20, S5P_GPIO_DRV_4X);
557                 gpio_direction_output(EXYNOS4X12_GPIO_L20, 0);
558
559                 /* OTG INT (Odroid U3+) */
560                 gpio_set_pull(EXYNOS4X12_GPIO_X31, S5P_GPIO_PULL_UP);
561                 gpio_set_drv(EXYNOS4X12_GPIO_X31, S5P_GPIO_DRV_4X);
562                 gpio_direction_input(EXYNOS4X12_GPIO_X31);
563         }
564 }
565
566 static int pmic_init_max77686(void)
567 {
568         struct pmic *p = pmic_get("MAX77686_PMIC");
569
570         if (pmic_probe(p))
571                 return -ENODEV;
572
573         if (board_is_trats2()) {
574                 /* BUCK/LDO Output Voltage */
575                 max77686_set_ldo_voltage(p, 21, 2800000);       /* LDO21 VTF_2.8V */
576                 max77686_set_ldo_voltage(p, 23, 3300000);       /* LDO23 TSP_AVDD_3.3V*/
577                 max77686_set_ldo_voltage(p, 24, 1800000);       /* LDO24 TSP_VDD_1.8V */
578
579                 /* BUCK/LDO Output Mode */
580                 max77686_set_buck_mode(p, 1, OPMODE_STANDBY);   /* BUCK1 VMIF_1.1V_AP */
581                 max77686_set_buck_mode(p, 2, OPMODE_ON);        /* BUCK2 VARM_1.0V_AP */
582                 max77686_set_buck_mode(p, 3, OPMODE_ON);        /* BUCK3 VINT_1.0V_AP */
583                 max77686_set_buck_mode(p, 4, OPMODE_ON);        /* BUCK4 VG3D_1.0V_AP */
584                 max77686_set_buck_mode(p, 5, OPMODE_ON);        /* BUCK5 VMEM_1.2V_AP */
585                 max77686_set_buck_mode(p, 6, OPMODE_ON);        /* BUCK6 VCC_SUB_1.35V*/
586                 max77686_set_buck_mode(p, 7, OPMODE_ON);        /* BUCK7 VCC_SUB_2.0V */
587                 max77686_set_buck_mode(p, 8, OPMODE_OFF);       /* VMEM_VDDF_2.85V */
588                 max77686_set_buck_mode(p, 9, OPMODE_OFF);       /* CAM_ISP_CORE_1.2V*/
589
590                 max77686_set_ldo_mode(p, 1, OPMODE_LPM);        /* LDO1 VALIVE_1.0V_AP*/
591                 max77686_set_ldo_mode(p, 2, OPMODE_STANDBY);    /* LDO2 VM1M2_1.2V_AP */
592                 max77686_set_ldo_mode(p, 3, OPMODE_LPM);        /* LDO3 VCC_1.8V_AP */
593                 max77686_set_ldo_mode(p, 4, OPMODE_LPM);        /* LDO4 VCC_2.8V_AP */
594                 max77686_set_ldo_mode(p, 5, OPMODE_OFF);        /* LDO5_VCC_1.8V_IO */
595                 max77686_set_ldo_mode(p, 6, OPMODE_STANDBY);    /* LDO6 VMPLL_1.0V_AP */
596                 max77686_set_ldo_mode(p, 7, OPMODE_STANDBY);    /* LDO7 VPLL_1.0V_AP */
597                 max77686_set_ldo_mode(p, 8, OPMODE_LPM);        /* LDO8 VMIPI_1.0V_AP */
598                 max77686_set_ldo_mode(p, 9, OPMODE_OFF);        /* CAM_ISP_MIPI_1.2*/
599                 max77686_set_ldo_mode(p, 10, OPMODE_LPM);       /* LDO10 VMIPI_1.8V_AP*/
600                 max77686_set_ldo_mode(p, 11, OPMODE_STANDBY);   /* LDO11 VABB1_1.8V_AP*/
601                 max77686_set_ldo_mode(p, 12, OPMODE_LPM);       /* LDO12 VUOTG_3.0V_AP*/
602                 max77686_set_ldo_mode(p, 13, OPMODE_OFF);       /* LDO13 VC2C_1.8V_AP */
603                 max77686_set_ldo_mode(p, 14, OPMODE_STANDBY);   /* VABB02_1.8V_AP */
604                 max77686_set_ldo_mode(p, 15, OPMODE_STANDBY);   /* LDO15 VHSIC_1.0V_AP*/
605                 max77686_set_ldo_mode(p, 16, OPMODE_STANDBY);   /* LDO16 VHSIC_1.8V_AP*/
606                 max77686_set_ldo_mode(p, 17, OPMODE_OFF);       /* CAM_SENSOR_CORE_1.2*/
607                 max77686_set_ldo_mode(p, 18, OPMODE_OFF);       /* CAM_ISP_SEN_IO_1.8V*/
608                 max77686_set_ldo_mode(p, 19, OPMODE_OFF);       /* LDO19 VT_CAM_1.8V */
609                 max77686_set_ldo_mode(p, 20, OPMODE_ON);        /* LDO20 VDDQ_PRE_1.8V*/
610                 max77686_set_ldo_mode(p, 21, OPMODE_OFF);       /* LDO21 VTF_2.8V */
611                 max77686_set_ldo_mode(p, 22, OPMODE_OFF);       /* LDO22 VMEM_VDD_2.8V*/
612                 max77686_set_ldo_mode(p, 23, OPMODE_OFF);       /* LDO23 TSP_AVDD_3.3V*/
613                 max77686_set_ldo_mode(p, 24, OPMODE_OFF);       /* LDO24 TSP_VDD_1.8V */
614                 max77686_set_ldo_mode(p, 25, OPMODE_OFF);       /* LDO25 VCC_3.3V_LCD */
615                 max77686_set_ldo_mode(p, 26, OPMODE_OFF);       /*LDO26 VCC_3.0V_MOTOR*/
616         } else {
617                 /* Set LDO Voltage */
618                 max77686_set_ldo_voltage(p, 20, 1800000);       /* LDO20 eMMC */
619                 max77686_set_ldo_voltage(p, 21, 2800000);       /* LDO21 SD */
620                 max77686_set_ldo_voltage(p, 22, 2800000);       /* LDO22 eMMC */
621         }
622
623         return 0;
624 }
625
626 #ifdef CONFIG_SYS_I2C_INIT_BOARD
627 static void board_init_i2c(void)
628 {
629         int i2c_id;
630
631         if (board_is_trats2()) {
632                 i2c_id = PERIPH_ID_I2C7;
633
634                 /* I2C_8 */
635                 gpio_direction_output(EXYNOS4X12_GPIO_F14, 1);
636                 gpio_direction_output(EXYNOS4X12_GPIO_F15, 1);
637
638                 /* I2C_9 */
639                 gpio_direction_output(EXYNOS4X12_GPIO_M21, 1);
640                 gpio_direction_output(EXYNOS4X12_GPIO_M20, 1);
641         } else {
642                 i2c_id = PERIPH_ID_I2C0;
643         }
644
645         if (exynos_pinmux_config(i2c_id, PINMUX_FLAG_NONE))
646                 debug("I2C%d not configured\n", i2c_id - PERIPH_ID_I2C0);
647 }
648 #endif
649
650 #ifdef CONFIG_SYS_I2C_SOFT
651 int get_soft_i2c_scl_pin(void)
652 {
653         if (I2C_ADAP_HWNR)
654                 return EXYNOS4X12_GPIO_M21; /* I2C9 */
655         else
656                 return EXYNOS4X12_GPIO_F14; /* I2C8 */
657 }
658
659 int get_soft_i2c_sda_pin(void)
660 {
661         if (I2C_ADAP_HWNR)
662                 return EXYNOS4X12_GPIO_M20; /* I2C9 */
663         else
664                 return EXYNOS4X12_GPIO_F15; /* I2C8 */
665 }
666 #endif
667
668 int exynos_early_init_f(void)
669 {
670         board_clock_init();
671         board_gpio_init();
672
673         return 0;
674 }
675
676 int exynos_init(void)
677 {
678         struct exynos4_power *pwr =
679                 (struct exynos4_power *)samsung_get_base_power();
680
681         gd->bd->bi_arch_number = board_arch_num[gd->board_type];
682
683         if (!board_is_trats2())
684                 return 0;
685
686         writel(0, &pwr->inform4);
687         writel(0, &pwr->inform5);
688
689         return 0;
690 }
691
692 int exynos_power_init(void)
693 {
694 #ifdef CONFIG_SYS_I2C_INIT_BOARD
695         board_init_i2c();
696 #endif
697         /* bus number taken from FDT */
698         pmic_init(0);
699         pmic_init_max77686();
700
701         if (!board_is_trats2())
702                 goto done;
703
704         /* I2C adapter 10 - bus name soft1 */
705         pmic_init_max77693(I2C_10);
706         /* I2C adapter 10 - bus name soft1 */
707         power_muic_init(I2C_10);
708         /* I2C adapter 9 - bus name soft0 */
709         power_fg_init(I2C_9);
710         power_bat_init(0);
711
712         p_chrg = pmic_get("MAX77693_PMIC");
713         if (!p_chrg) {
714                 puts("MAX77693_PMIC: Not found\n");
715                 return -ENODEV;
716         }
717
718         p_muic = pmic_get("MAX77693_MUIC");
719         if (!p_muic) {
720                 puts("MAX77693_MUIC: Not found\n");
721                 return -ENODEV;
722         }
723
724         p_fg = pmic_get("MAX77693_FG");
725         if (!p_fg) {
726                 puts("MAX17042_FG: Not found\n");
727                 return -ENODEV;
728         }
729
730         if (p_chrg->chrg->chrg_bat_present(p_chrg) == 0)
731                 puts("No battery detected\n");
732
733         p_bat = pmic_get("BAT_TRATS2");
734         if (!p_bat) {
735                 puts("BAT_TRATS2: Not found\n");
736                 return -ENODEV;
737         }
738
739         p_fg->parent =  p_bat;
740         p_chrg->parent = p_bat;
741         p_muic->parent = p_bat;
742
743 #ifdef CONFIG_INTERACTIVE_CHARGER
744         p_bat->low_power_mode = board_low_power_mode;
745 #endif
746         p_bat->pbat->battery_init(p_bat, p_fg, p_chrg, p_muic);
747
748         pbat = p_bat->pbat;
749
750 done:
751         power_init_done = 1;
752
753         return 0;
754 }
755
756 #ifdef CONFIG_USB_GADGET
757 static int s5pc210_phy_control(int on)
758 {
759         struct pmic *p_pmic;
760
761         p_pmic = pmic_get("MAX77686_PMIC");
762         if (!p_pmic)
763                 return -ENODEV;
764
765         if (pmic_probe(p_pmic))
766                 return -1;
767
768         if (on)
769                 return max77686_set_ldo_mode(p_pmic, 12, OPMODE_ON);
770         else
771                 return max77686_set_ldo_mode(p_pmic, 12, OPMODE_LPM);
772 }
773
774 struct s3c_plat_otg_data s5pc210_otg_data = {
775         .phy_control    = s5pc210_phy_control,
776         .regs_phy       = EXYNOS4X12_USBPHY_BASE,
777         .regs_otg       = EXYNOS4X12_USBOTG_BASE,
778         .usb_phy_ctrl   = EXYNOS4X12_USBPHY_CONTROL,
779         .usb_flags      = PHY0_SLEEP,
780 };
781
782 int board_usb_init(int index, enum usb_init_type init)
783 {
784         debug("USB_udc_probe\n");
785         return s3c_udc_probe(&s5pc210_otg_data);
786 }
787 #endif
788
789 void reset_misc(void)
790 {
791         if (board_is_trats2())
792                 return;
793
794         /* Reset eMMC*/
795         gpio_set_value(EXYNOS4X12_GPIO_K12, 0);
796         mdelay(10);
797         gpio_set_value(EXYNOS4X12_GPIO_K12, 1);
798 }
799
800 /*
801  * LCD
802  */
803 #ifdef CONFIG_LCD
804 int mipi_power(void)
805 {
806         struct pmic *p;
807
808         if (!board_is_trats2())
809                 return 0;
810
811         p = pmic_get("MAX77686_PMIC");
812
813         /* LDO8 VMIPI_1.0V_AP */
814         max77686_set_ldo_mode(p, 8, OPMODE_ON);
815         /* LDO10 VMIPI_1.8V_AP */
816         max77686_set_ldo_mode(p, 10, OPMODE_ON);
817
818         return 0;
819 }
820
821 void exynos_lcd_power_on(void)
822 {
823         struct pmic *p;
824
825         if (!board_is_trats2())
826                 return;
827
828         p = pmic_get("MAX77686_PMIC");
829
830         /* LCD_2.2V_EN: GPC0[1] */
831         gpio_set_pull(EXYNOS4X12_GPIO_C01, S5P_GPIO_PULL_UP);
832         gpio_direction_output(EXYNOS4X12_GPIO_C01, 1);
833
834         /* LDO25 VCC_3.1V_LCD */
835         pmic_probe(p);
836         max77686_set_ldo_voltage(p, 25, 3100000);
837         max77686_set_ldo_mode(p, 25, OPMODE_LPM);
838 }
839
840 void exynos_reset_lcd(void)
841 {
842         if (!board_is_trats2())
843                 return;
844
845         /* reset lcd */
846         gpio_direction_output(EXYNOS4X12_GPIO_F21, 0);
847         udelay(10);
848         gpio_set_value(EXYNOS4X12_GPIO_F21, 1);
849 }
850
851 void exynos_lcd_misc_init(vidinfo_t *vid)
852 {
853         if (!board_is_trats2())
854                 return;
855 #ifdef CONFIG_TIZEN
856         get_tizen_logo_info(vid);
857 #endif
858 #ifdef CONFIG_S6E8AX0
859         s6e8ax0_init();
860 #endif
861 }
862 #endif /* LCD */
863
864 void low_clock_mode(void)
865 {
866         struct exynos4x12_clock *clk = (struct exynos4x12_clock *)
867                                         samsung_get_base_clock();
868
869         unsigned int cfg_apll_con0;
870         unsigned int cfg_src_cpu;
871         unsigned int cfg_div_cpu0;
872         unsigned int cfg_div_cpu1;
873         unsigned int clk_gate_cfg;
874
875         /* Turn off unnecessary clocks */
876         clk_gate_cfg = 0x0;
877         writel(clk_gate_cfg, &clk->gate_ip_image);              /* IMAGE */
878         writel(clk_gate_cfg, &clk->gate_ip_cam);                /* CAM */
879         writel(clk_gate_cfg, &clk->gate_ip_tv);                 /* TV */
880         writel(clk_gate_cfg, &clk->gate_ip_mfc);                /* MFC */
881         writel(clk_gate_cfg, &clk->gate_ip_g3d);                /* G3D */
882         writel(clk_gate_cfg, &clk->gate_ip_gps);                /* GPS */
883         writel(clk_gate_cfg, &clk->gate_ip_isp1);               /* ISP1 */
884
885         /*
886          * Set CMU_CPU clocks src to MPLL
887          * Bit values:                 0 ; 1
888          * MUX_APLL_SEL:        FIN_PLL;   FOUT_APLL
889          * MUX_CORE_SEL:        MOUT_APLL; SCLK_MPLL
890          * MUX_HPM_SEL:         MOUT_APLL; SCLK_MPLL_USER_C
891          * MUX_MPLL_USER_SEL_C: FIN_PLL;   SCLK_MPLL
892         */
893         cfg_src_cpu = MUX_APLL_SEL(1) | MUX_CORE_SEL(1) | MUX_HPM_SEL(1) |
894                       MUX_MPLL_USER_SEL_C(1);
895         writel(cfg_src_cpu, &clk->src_cpu);
896
897         /* Disable APLL */
898         cfg_apll_con0 = readl(&clk->apll_con0);
899         writel(cfg_apll_con0 & ~PLL_ENABLE(1), &clk->apll_con0);
900
901         /* Set APLL to 200MHz */
902         cfg_apll_con0 = SDIV(2) | PDIV(3) | MDIV(100) | FSEL(1) | PLL_ENABLE(1);
903         writel(cfg_apll_con0, &clk->apll_con0);
904
905         /* Wait for PLL to be locked */
906         while (!(readl(&clk->apll_con0) & PLL_LOCKED_BIT))
907                 continue;
908
909         /* Set CMU_CPU clock src to APLL */
910         cfg_src_cpu = MUX_APLL_SEL(1) | MUX_CORE_SEL(0) | MUX_HPM_SEL(0) |
911                       MUX_MPLL_USER_SEL_C(0);
912         writel(cfg_src_cpu, &clk->src_cpu);
913
914         /* Wait for MUX ready status */
915         while (readl(&clk->src_cpu) & MUX_STAT_CPU_CHANGING)
916                 continue;
917
918         /*
919          * Set dividers for MOUTcore = 200 MHz
920          * coreout =      MOUT / (ratio + 1) = 200 MHz
921          * corem0 =     armclk / (ratio + 1) = 200 MHz
922          * corem1 =     armclk / (ratio + 1) = 200 MHz
923          * periph =     armclk / (ratio + 1) = 200 MHz
924          * atbout =       MOUT / (ratio + 1) = 200 MHz
925          * pclkdbgout = atbout / (ratio + 1) = 200 MHz
926          * sclkapll = MOUTapll / (ratio + 1) = 50 MHz
927          * armclk =   core_out / (ratio + 1) = 200 MHz
928         */
929         cfg_div_cpu0 = CORE_RATIO(0) | COREM0_RATIO(0) | COREM1_RATIO(0) |
930                        PERIPH_RATIO(0) | ATB_RATIO(0) | PCLK_DBG_RATIO(1) |
931                        APLL_RATIO(3) | CORE2_RATIO(0);
932         writel(cfg_div_cpu0, &clk->div_cpu0);
933
934         /* Wait for divider ready status */
935         while (readl(&clk->div_stat_cpu0) & DIV_STAT_CPU0_CHANGING)
936                 continue;
937
938         /*
939          * For MOUThpm = 200 MHz (MOUTapll)
940          * doutcopy = MOUThpm / (ratio + 1) = 100
941          * sclkhpm = doutcopy / (ratio + 1) = 100
942          * cores_out = armclk / (ratio + 1) = 200
943          */
944         cfg_div_cpu1 = COPY_RATIO(1) | HPM_RATIO(0) | CORES_RATIO(0);
945         writel(cfg_div_cpu1, &clk->div_cpu1);   /* DIV_CPU1 */
946
947         /* Wait for divider ready status */
948         while (readl(&clk->div_stat_cpu1) & DIV_STAT_CPU1_CHANGING)
949                 continue;
950 }
951
952 #ifdef CONFIG_INTERACTIVE_CHARGER
953 static int low_power_mode_set;
954
955 void board_low_power_mode(void)
956 {
957         struct exynos4x12_power *pwr = (struct exynos4x12_power *)
958                                         samsung_get_base_power();
959
960         unsigned int pwr_core_cfg = 0x0;
961         unsigned int pwr_cfg = 0x0;
962
963         /* Set low power mode only once */
964         if (low_power_mode_set)
965                 return;
966
967         /* Power down CORES: 1, 2, 3 */
968         /* LOCAL_PWR_CFG [1:0] 0x3 EN, 0x0 DIS */
969         writel(pwr_core_cfg, &pwr->arm_core1_configuration);
970         writel(pwr_core_cfg, &pwr->arm_core2_configuration);
971         writel(pwr_core_cfg, &pwr->arm_core3_configuration);
972
973         /* Turn off unnecessary power domains */
974         writel(pwr_cfg, &pwr->xxti_configuration);              /* XXTI */
975         writel(pwr_cfg, &pwr->cam_configuration);               /* CAM */
976         writel(pwr_cfg, &pwr->tv_configuration);                /* TV */
977         writel(pwr_cfg, &pwr->mfc_configuration);               /* MFC */
978         writel(pwr_cfg, &pwr->g3d_configuration);               /* G3D */
979         writel(pwr_cfg, &pwr->gps_configuration);               /* GPS */
980         writel(pwr_cfg, &pwr->gps_alive_configuration);         /* GPS_ALIVE */
981
982         /* Set CPU clock to 200MHz */
983         low_clock_mode();
984
985         low_power_mode_set = 1;
986 }
987 #endif
988
989 #ifdef CONFIG_CMD_POWEROFF
990 void board_poweroff(void)
991 {
992         unsigned int val;
993         struct exynos4x12_power *power =
994                 (struct exynos4x12_power *)samsung_get_base_power();
995
996         val = readl(&power->ps_hold_control);
997         val |= EXYNOS_PS_HOLD_CONTROL_EN_OUTPUT; /* set to output */
998         val &= ~EXYNOS_PS_HOLD_CONTROL_DATA_HIGH; /* set state to low */
999         writel(val, &power->ps_hold_control);
1000
1001         while (1);
1002         /* Should not reach here */
1003 }
1004 #endif
1005
1006 /* Functions for interactive charger in board/samsung/common/misc.c */
1007 #ifdef CONFIG_INTERACTIVE_CHARGER
1008 int charger_enable(void)
1009 {
1010         if (!power_init_done) {
1011                 if (exynos_power_init()) {
1012                         puts("Can't init board power subsystem");
1013                         return -EIO;
1014                 }
1015         }
1016
1017         if (!pbat) {
1018                 puts("No such device!\n");
1019                 return -ENODEV;
1020         }
1021
1022         if (!pbat->battery_charge) {
1023                 puts("Can't enable charger\n");
1024                 return -ENODEV;
1025         }
1026
1027         /* Enable charger */
1028         if (pbat->battery_charge(p_bat)) {
1029                 puts("Charger enable error\n");
1030                 return -EIO;
1031         }
1032
1033         return 0;
1034 }
1035
1036 int charger_type(void)
1037 {
1038         if (!power_init_done) {
1039                 if (exynos_power_init()) {
1040                         puts("Can't init board power subsystem");
1041                         return -EIO;
1042                 }
1043         }
1044
1045         if (!p_muic) {
1046                 puts("No such device!\n");
1047                 return -ENODEV;
1048         }
1049
1050         if (!p_muic->chrg->chrg_type) {
1051                 puts("Can't get charger type\n");
1052                 return -ENODEV;
1053         }
1054
1055         return p_muic->chrg->chrg_type(p_muic);
1056 }
1057
1058 int battery_present(void)
1059 {
1060         if (!power_init_done) {
1061                 if (exynos_power_init()) {
1062                         puts("Can't init board power subsystem");
1063                         return 0;
1064                 }
1065         }
1066
1067         if (!p_chrg) {
1068                 puts("No such device!\n");
1069                 return 0;
1070         }
1071
1072         if (!p_chrg->chrg->chrg_bat_present) {
1073                 puts("Can't get battery state\n");
1074                 return 0;;
1075         }
1076
1077         if (!p_chrg->chrg->chrg_bat_present(p_chrg)) {
1078                 puts("Battery not present.\n");
1079                 return 0;
1080         }
1081
1082         return 1;
1083 }
1084
1085 int battery_state(unsigned int *soc)
1086 {
1087         struct battery *bat = pbat->bat;
1088
1089         if (!power_init_done) {
1090                 if (exynos_power_init()) {
1091                         printf("Can't init board power subsystem");
1092                         return -EIO;
1093                 }
1094         }
1095
1096         if (!p_fg) {
1097                 puts("No such device!\n");
1098                 return -ENODEV;
1099         }
1100
1101         if (!p_fg->fg->fg_battery_update) {
1102                 puts("Can't update battery state\n");
1103                 return -EIO;
1104         }
1105
1106         /* Check battery state */
1107         if (p_fg->fg->fg_battery_update(p_fg, p_bat)) {
1108                 puts("Battery update error\n");
1109                 return -EIO;
1110         }
1111
1112         debug("[BAT]:\n#state:%u\n#soc:%3.1u\n#vcell:%u\n", bat->state,
1113                                                             bat->state_of_chrg,
1114                                                             bat->voltage_uV);
1115
1116         *soc = bat->state_of_chrg;
1117
1118         return 0;
1119 }
1120 #endif