blob: ee82763b02b8f18ba66690bd10d26c1bb965f813 [file] [log] [blame]
Tony Lindgren92105bb2005-09-07 17:20:26 +01001/*
2 * linux/arch/arm/plat-omap/sram.c
3 *
4 * OMAP SRAM detection and management
5 *
6 * Copyright (C) 2005 Nokia Corporation
7 * Written by Tony Lindgren <tony@atomide.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/config.h>
15#include <linux/module.h>
16#include <linux/kernel.h>
17#include <linux/init.h>
18
19#include <asm/mach/map.h>
Tony Lindgren53d9cc72006-02-08 22:06:45 +000020#include <asm/tlb.h>
Tony Lindgren92105bb2005-09-07 17:20:26 +010021#include <asm/io.h>
22#include <asm/cacheflush.h>
23
Tony Lindgren1a8bfa12005-11-10 14:26:50 +000024#include <asm/arch/sram.h>
Tony Lindgren92105bb2005-09-07 17:20:26 +010025
Tony Lindgren1a8bfa12005-11-10 14:26:50 +000026#define OMAP1_SRAM_PA 0x20000000
27#define OMAP1_SRAM_VA 0xd0000000
28#define OMAP2_SRAM_PA 0x40200000
29#define OMAP2_SRAM_VA 0xd0000000
30
Tony Lindgren92105bb2005-09-07 17:20:26 +010031#define SRAM_BOOTLOADER_SZ 0x80
32
33static unsigned long omap_sram_base;
34static unsigned long omap_sram_size;
35static unsigned long omap_sram_ceil;
36
37/*
Tony Lindgren1a8bfa12005-11-10 14:26:50 +000038 * The amount of SRAM depends on the core type.
Tony Lindgren92105bb2005-09-07 17:20:26 +010039 * Note that we cannot try to test for SRAM here because writes
40 * to secure SRAM will hang the system. Also the SRAM is not
41 * yet mapped at this point.
42 */
43void __init omap_detect_sram(void)
44{
Tony Lindgren1a8bfa12005-11-10 14:26:50 +000045 if (!cpu_is_omap24xx())
46 omap_sram_base = OMAP1_SRAM_VA;
47 else
48 omap_sram_base = OMAP2_SRAM_VA;
Tony Lindgren92105bb2005-09-07 17:20:26 +010049
50 if (cpu_is_omap730())
Tony Lindgren1a8bfa12005-11-10 14:26:50 +000051 omap_sram_size = 0x32000; /* 200K */
52 else if (cpu_is_omap15xx())
53 omap_sram_size = 0x30000; /* 192K */
Tony Lindgren92105bb2005-09-07 17:20:26 +010054 else if (cpu_is_omap1610() || cpu_is_omap1621() || cpu_is_omap1710())
Tony Lindgren1a8bfa12005-11-10 14:26:50 +000055 omap_sram_size = 0x4000; /* 16K */
Tony Lindgren92105bb2005-09-07 17:20:26 +010056 else if (cpu_is_omap1611())
Tony Lindgren1a8bfa12005-11-10 14:26:50 +000057 omap_sram_size = 0x3e800; /* 250K */
58 else if (cpu_is_omap2420())
59 omap_sram_size = 0xa0014; /* 640K */
Tony Lindgren92105bb2005-09-07 17:20:26 +010060 else {
61 printk(KERN_ERR "Could not detect SRAM size\n");
62 omap_sram_size = 0x4000;
63 }
64
Tony Lindgren92105bb2005-09-07 17:20:26 +010065 omap_sram_ceil = omap_sram_base + omap_sram_size;
66}
67
68static struct map_desc omap_sram_io_desc[] __initdata = {
Deepak Saxena9fe133b2005-10-28 15:19:00 +010069 { /* .length gets filled in at runtime */
Tony Lindgren1a8bfa12005-11-10 14:26:50 +000070 .virtual = OMAP1_SRAM_VA,
71 .pfn = __phys_to_pfn(OMAP1_SRAM_PA),
Deepak Saxena9fe133b2005-10-28 15:19:00 +010072 .type = MT_DEVICE
73 }
Tony Lindgren92105bb2005-09-07 17:20:26 +010074};
75
76/*
77 * In order to use last 2kB of SRAM on 1611b, we must round the size
78 * up to multiple of PAGE_SIZE. We cannot use ioremap for SRAM, as
79 * clock init needs SRAM early.
80 */
81void __init omap_map_sram(void)
82{
83 if (omap_sram_size == 0)
84 return;
85
Tony Lindgren1a8bfa12005-11-10 14:26:50 +000086 if (cpu_is_omap24xx()) {
87 omap_sram_io_desc[0].virtual = OMAP2_SRAM_VA;
88 omap_sram_io_desc[0].pfn = __phys_to_pfn(OMAP2_SRAM_PA);
89 }
90
Tony Lindgren92105bb2005-09-07 17:20:26 +010091 omap_sram_io_desc[0].length = (omap_sram_size + PAGE_SIZE-1)/PAGE_SIZE;
92 omap_sram_io_desc[0].length *= PAGE_SIZE;
93 iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc));
94
Tony Lindgren1a8bfa12005-11-10 14:26:50 +000095 printk(KERN_INFO "SRAM: Mapped pa 0x%08lx to va 0x%08lx size: 0x%lx\n",
96 omap_sram_io_desc[0].pfn, omap_sram_io_desc[0].virtual,
97 omap_sram_io_desc[0].length);
98
Tony Lindgren92105bb2005-09-07 17:20:26 +010099 /*
Tony Lindgren53d9cc72006-02-08 22:06:45 +0000100 * Normally devicemaps_init() would flush caches and tlb after
101 * mdesc->map_io(), but since we're called from map_io(), we
102 * must do it here.
103 */
104 local_flush_tlb_all();
105 flush_cache_all();
106
107 /*
Tony Lindgren92105bb2005-09-07 17:20:26 +0100108 * Looks like we need to preserve some bootloader code at the
109 * beginning of SRAM for jumping to flash for reboot to work...
110 */
111 memset((void *)omap_sram_base + SRAM_BOOTLOADER_SZ, 0,
112 omap_sram_size - SRAM_BOOTLOADER_SZ);
113}
114
Tony Lindgren92105bb2005-09-07 17:20:26 +0100115void * omap_sram_push(void * start, unsigned long size)
116{
117 if (size > (omap_sram_ceil - (omap_sram_base + SRAM_BOOTLOADER_SZ))) {
118 printk(KERN_ERR "Not enough space in SRAM\n");
119 return NULL;
120 }
121 omap_sram_ceil -= size;
122 omap_sram_ceil &= ~0x3;
123 memcpy((void *)omap_sram_ceil, start, size);
124
125 return (void *)omap_sram_ceil;
126}
127
Tony Lindgren1a8bfa12005-11-10 14:26:50 +0000128static void omap_sram_error(void)
129{
130 panic("Uninitialized SRAM function\n");
131}
132
133#ifdef CONFIG_ARCH_OMAP1
134
135static void (*_omap_sram_reprogram_clock)(u32 dpllctl, u32 ckctl);
136
137void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl)
138{
139 if (!_omap_sram_reprogram_clock)
140 omap_sram_error();
141
142 return _omap_sram_reprogram_clock(dpllctl, ckctl);
143}
144
145int __init omap1_sram_init(void)
146{
147 _omap_sram_reprogram_clock = omap_sram_push(sram_reprogram_clock,
148 sram_reprogram_clock_sz);
149
150 return 0;
151}
152
153#else
154#define omap1_sram_init() do {} while (0)
155#endif
156
157#ifdef CONFIG_ARCH_OMAP2
158
159static void (*_omap2_sram_ddr_init)(u32 *slow_dll_ctrl, u32 fast_dll_ctrl,
160 u32 base_cs, u32 force_unlock);
161
162void omap2_sram_ddr_init(u32 *slow_dll_ctrl, u32 fast_dll_ctrl,
163 u32 base_cs, u32 force_unlock)
164{
165 if (!_omap2_sram_ddr_init)
166 omap_sram_error();
167
168 return _omap2_sram_ddr_init(slow_dll_ctrl, fast_dll_ctrl,
169 base_cs, force_unlock);
170}
171
172static void (*_omap2_sram_reprogram_sdrc)(u32 perf_level, u32 dll_val,
173 u32 mem_type);
174
175void omap2_sram_reprogram_sdrc(u32 perf_level, u32 dll_val, u32 mem_type)
176{
177 if (!_omap2_sram_reprogram_sdrc)
178 omap_sram_error();
179
180 return _omap2_sram_reprogram_sdrc(perf_level, dll_val, mem_type);
181}
182
183static u32 (*_omap2_set_prcm)(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass);
184
185u32 omap2_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass)
186{
187 if (!_omap2_set_prcm)
188 omap_sram_error();
189
190 return _omap2_set_prcm(dpll_ctrl_val, sdrc_rfr_val, bypass);
191}
192
193int __init omap2_sram_init(void)
194{
195 _omap2_sram_ddr_init = omap_sram_push(sram_ddr_init, sram_ddr_init_sz);
196
197 _omap2_sram_reprogram_sdrc = omap_sram_push(sram_reprogram_sdrc,
198 sram_reprogram_sdrc_sz);
199 _omap2_set_prcm = omap_sram_push(sram_set_prcm, sram_set_prcm_sz);
200
201 return 0;
202}
203#else
204#define omap2_sram_init() do {} while (0)
205#endif
206
207int __init omap_sram_init(void)
Tony Lindgren92105bb2005-09-07 17:20:26 +0100208{
209 omap_detect_sram();
210 omap_map_sram();
Tony Lindgren1a8bfa12005-11-10 14:26:50 +0000211
212 if (!cpu_is_omap24xx())
213 omap1_sram_init();
214 else
215 omap2_sram_init();
216
217 return 0;
Tony Lindgren92105bb2005-09-07 17:20:26 +0100218}