Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/arm/mach-omap1/sram-init.c
26292 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* OMAP SRAM detection and management
4
*
5
* Copyright (C) 2005 Nokia Corporation
6
* Written by Tony Lindgren <[email protected]>
7
*/
8
9
#include <linux/module.h>
10
#include <linux/kernel.h>
11
#include <linux/init.h>
12
#include <linux/io.h>
13
#include <linux/set_memory.h>
14
15
#include <asm/fncpy.h>
16
#include <asm/tlb.h>
17
#include <asm/cacheflush.h>
18
19
#include <asm/mach/map.h>
20
21
#include "soc.h"
22
#include "sram.h"
23
24
#define OMAP1_SRAM_PA 0x20000000
25
#define SRAM_BOOTLOADER_SZ 0x80
26
#define ROUND_DOWN(value, boundary) ((value) & (~((boundary) - 1)))
27
28
static void __iomem *omap_sram_base;
29
static unsigned long omap_sram_start;
30
static unsigned long omap_sram_skip;
31
static unsigned long omap_sram_size;
32
static void __iomem *omap_sram_ceil;
33
34
/*
35
* Memory allocator for SRAM: calculates the new ceiling address
36
* for pushing a function using the fncpy API.
37
*
38
* Note that fncpy requires the returned address to be aligned
39
* to an 8-byte boundary.
40
*/
41
static void *omap_sram_push_address(unsigned long size)
42
{
43
unsigned long available, new_ceil = (unsigned long)omap_sram_ceil;
44
45
available = omap_sram_ceil - (omap_sram_base + omap_sram_skip);
46
47
if (size > available) {
48
pr_err("Not enough space in SRAM\n");
49
return NULL;
50
}
51
52
new_ceil -= size;
53
new_ceil = ROUND_DOWN(new_ceil, FNCPY_ALIGN);
54
omap_sram_ceil = IOMEM(new_ceil);
55
56
return (void __force *)omap_sram_ceil;
57
}
58
59
void *omap_sram_push(void *funcp, unsigned long size)
60
{
61
void *sram;
62
unsigned long base;
63
int pages;
64
void *dst = NULL;
65
66
sram = omap_sram_push_address(size);
67
if (!sram)
68
return NULL;
69
70
base = (unsigned long)sram & PAGE_MASK;
71
pages = PAGE_ALIGN(size) / PAGE_SIZE;
72
73
set_memory_rw(base, pages);
74
75
dst = fncpy(sram, funcp, size);
76
77
set_memory_rox(base, pages);
78
79
return dst;
80
}
81
82
/*
83
* The amount of SRAM depends on the core type.
84
* Note that we cannot try to test for SRAM here because writes
85
* to secure SRAM will hang the system. Also the SRAM is not
86
* yet mapped at this point.
87
* Note that we cannot use ioremap for SRAM, as clock init needs SRAM early.
88
*/
89
static void __init omap_detect_and_map_sram(void)
90
{
91
unsigned long base;
92
int pages;
93
94
omap_sram_skip = SRAM_BOOTLOADER_SZ;
95
omap_sram_start = OMAP1_SRAM_PA;
96
97
if (cpu_is_omap15xx())
98
omap_sram_size = 0x30000; /* 192K */
99
else if (cpu_is_omap1610() || cpu_is_omap1611() ||
100
cpu_is_omap1621() || cpu_is_omap1710())
101
omap_sram_size = 0x4000; /* 16K */
102
else {
103
pr_err("Could not detect SRAM size\n");
104
omap_sram_size = 0x4000;
105
}
106
107
omap_sram_start = ROUND_DOWN(omap_sram_start, PAGE_SIZE);
108
omap_sram_base = __arm_ioremap_exec(omap_sram_start, omap_sram_size, 1);
109
if (!omap_sram_base) {
110
pr_err("SRAM: Could not map\n");
111
return;
112
}
113
114
omap_sram_ceil = omap_sram_base + omap_sram_size;
115
116
/*
117
* Looks like we need to preserve some bootloader code at the
118
* beginning of SRAM for jumping to flash for reboot to work...
119
*/
120
memset_io(omap_sram_base + omap_sram_skip, 0,
121
omap_sram_size - omap_sram_skip);
122
123
base = (unsigned long)omap_sram_base;
124
pages = PAGE_ALIGN(omap_sram_size) / PAGE_SIZE;
125
126
set_memory_rox(base, pages);
127
}
128
129
static void (*_omap_sram_reprogram_clock)(u32 dpllctl, u32 ckctl);
130
131
void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl)
132
{
133
BUG_ON(!_omap_sram_reprogram_clock);
134
_omap_sram_reprogram_clock(dpllctl, ckctl);
135
}
136
137
int __init omap1_sram_init(void)
138
{
139
omap_detect_and_map_sram();
140
_omap_sram_reprogram_clock =
141
omap_sram_push(omap1_sram_reprogram_clock,
142
omap1_sram_reprogram_clock_sz);
143
144
return 0;
145
}
146
147