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