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