549ef2bd99187954c6940a79a74cb35a81a11500
[oweals/u-boot.git] / arch / arm / mach-imx / misc.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2013 Stefan Roese <sr@denx.de>
4  */
5
6 #include <common.h>
7 #include <lmb.h>
8 #include <log.h>
9 #include <asm/arch/sys_proto.h>
10 #include <linux/errno.h>
11 #include <asm/io.h>
12 #include <asm/mach-imx/regs-common.h>
13
14 DECLARE_GLOBAL_DATA_PTR;
15
16 /* 1 second delay should be plenty of time for block reset. */
17 #define RESET_MAX_TIMEOUT       1000000
18
19 #define MXS_BLOCK_SFTRST        (1 << 31)
20 #define MXS_BLOCK_CLKGATE       (1 << 30)
21
22 int mxs_wait_mask_set(struct mxs_register_32 *reg, uint32_t mask, unsigned
23                                                                 int timeout)
24 {
25         while (--timeout) {
26                 if ((readl(&reg->reg) & mask) == mask)
27                         break;
28                 udelay(1);
29         }
30
31         return !timeout;
32 }
33
34 int mxs_wait_mask_clr(struct mxs_register_32 *reg, uint32_t mask, unsigned
35                                                                 int timeout)
36 {
37         while (--timeout) {
38                 if ((readl(&reg->reg) & mask) == 0)
39                         break;
40                 udelay(1);
41         }
42
43         return !timeout;
44 }
45
46 int mxs_reset_block(struct mxs_register_32 *reg)
47 {
48         /* Clear SFTRST */
49         writel(MXS_BLOCK_SFTRST, &reg->reg_clr);
50
51         if (mxs_wait_mask_clr(reg, MXS_BLOCK_SFTRST, RESET_MAX_TIMEOUT))
52                 return 1;
53
54         /* Clear CLKGATE */
55         writel(MXS_BLOCK_CLKGATE, &reg->reg_clr);
56
57         /* Set SFTRST */
58         writel(MXS_BLOCK_SFTRST, &reg->reg_set);
59
60         /* Wait for CLKGATE being set */
61         if (mxs_wait_mask_set(reg, MXS_BLOCK_CLKGATE, RESET_MAX_TIMEOUT))
62                 return 1;
63
64         /* Clear SFTRST */
65         writel(MXS_BLOCK_SFTRST, &reg->reg_clr);
66
67         if (mxs_wait_mask_clr(reg, MXS_BLOCK_SFTRST, RESET_MAX_TIMEOUT))
68                 return 1;
69
70         /* Clear CLKGATE */
71         writel(MXS_BLOCK_CLKGATE, &reg->reg_clr);
72
73         if (mxs_wait_mask_clr(reg, MXS_BLOCK_CLKGATE, RESET_MAX_TIMEOUT))
74                 return 1;
75
76         return 0;
77 }
78
79 static ulong get_sp(void)
80 {
81         ulong ret;
82
83         asm("mov %0, sp" : "=r"(ret) : );
84         return ret;
85 }
86
87 void board_lmb_reserve(struct lmb *lmb)
88 {
89         ulong sp, bank_end;
90         int bank;
91
92         sp = get_sp();
93         debug("## Current stack ends at 0x%08lx ", sp);
94
95         /* adjust sp by 16K to be safe */
96         sp -= 4096 << 2;
97         for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
98                 if (sp < gd->bd->bi_dram[bank].start)
99                         continue;
100                 bank_end = gd->bd->bi_dram[bank].start +
101                         gd->bd->bi_dram[bank].size;
102                 if (sp >= bank_end)
103                         continue;
104                 lmb_reserve(lmb, sp, bank_end - sp);
105                 break;
106         }
107 }