Please note as of Wednesday, August 15th, 2018 this wiki has been set to read only. If you are a TI Employee and require Edit ability please contact x0211426 from the company directory.


From Texas Instruments Wiki
Jump to: navigation, search

OMAP Linux cannot support more than 256MB of SDRAM by default because of software conflicts. This article presents a patch that optimizes Linux to support 512MB (and possibly up to 768MB). A short background and an explanation of the changes are given.


A 32-bit architecture, such as the OMAP3 processor family, can address 4GB (2^32) of physical memory.

High level operating systems like Linux use the processor’s Memory Management Unit (MMU) to support virtual memory. When the kernel forks a new process, the process receives a new virtual address space.

Linux splits this address space into two regions: Kernel and Process (User Space) Virtual Space. The Process Virtual Space is user-space accessible and is process specific. The Kernel Virtual Space appears the same for each process.

Virtual Memory Layout

The default memory split is 3GB for Process and 1GB for Kernel Virtual Space. This virtual layout places the Process Space from location 0 up to 3GB and the Kernel Space from 3 to 4GB.

The Kernel Virtual Area contains at least 3 things: 1) a mapping of all physical memory, 2) an area reserved for vmalloc and 3) a mapping of all memory mapped registers.

It is impossible to support 1GB of memory with the default 3/1 split because the mapping of physical memory will be larger than the space itself. Support of memory >= 1GB requires either adjusting the split setup or using the Linux High Memory feature. Support for memory between 256MB and 768MB may be accomplished by reoganizing the Kernel Virtual Space.

Note: First pass examination of Android's default setup suggests there are application dependencies on the 3/1 split. The Android dynamic linker (/system/bin/linker) may depend on virtual memory above 2G, making this patch ideal for an Android system

Memory Conflicts

Under Linux OMAP, memory mapped registers consume approximately 600MB of the 1GB kernel virtual space. The physical start of memory mapped registers on OMAP3 is at 0x4800 0000 with L4 registers and runs through 0x6E00 0000 with L3 registers. The virtual mapping preserves this layout. Even without considering space reserved for vmalloc, it is impossible to support more then 256MB of memory in the default configuration because the virtual mapping of physical memory and the virtual mapping of registers will not fit into 1GB.

Summary of Changes and Source Link

This patch supports 512MB of memory by optimizing the kernel virtual space.

The full patch is included below. Code has been verified working under Android on a Texas Instruments Zoom™ OMAP34x-II MDP (256MB) and on custom 512 MB hardware both using kernel 2.6.27

Two versions of the patch are presented. Both versions are described, but the original patch is documented in example below. The second version attached attempts to maintain some backward compatibility with the original macros.

There are 3 main changes in this patch: 1) The memory mapped registers are rearranged to consume less space, 2) the vmalloc space is shifted and 3) the driver register access macros are updated for the new register locations.

  1. Changes for 1) are contained in io.h and sram.c. Defined locations for memory mapped registers and on-chip sram are shifted to avoid overlap with virtual mapped physical memory.
  2. Changes for 2) are contained in vmalloc.h. OMAP Linux defines two values to locate the vmalloc space: VMALLOC_END and VMALLOC_MIN. We change the value of VMALLOC_END to shift the entire space.
  3. Changes for 3) are cotained in multiple files. The original 3 macros __IO_ADDRESS, io_p2v and io_v2p retain their name and will work for L4 peripherals. 3 new macros are added for l3 peripheral access: __L3_IO_ADDRESS, l3_io_p2v and l3_io_v2p. New l3 macros must be used in drivers that access l3 peripheral registers.

An additional patch is added for those who want to minimize the use of the l3 macros. This patch makes use of the __ASSEMBLY__ definition and a unified set of macros. This is required because the unified macro will not compile when used in assembly code. The __ASSEMBLY__ directive allows the l3 macros to be used when required and a new unified macro to be used in all other cases.

Code Examples



The old driver register access macros are based on a single offset. This approach is creates no overhead and is easy to debug, but wastes memory. In the patch fragment below, the registers area is split into two, each with a different offset. Drivers using L3 peripherals (ex. RAM, FLASH) must change to use the new macro series. Other drivers are unchanged.

Old Code

#define IO_OFFSET		0x90000000
#define __IO_ADDRESS(pa)	((pa) + IO_OFFSET)/* Works for L3 and L4 */
#define __OMAP2_IO_ADDRESS(pa)	((pa) + IO_OFFSET)/* Works for L3 and L4 */
#define io_v2p(va)		((va) - IO_OFFSET)/* Works for L3 and L4 */

New Code

#define L3_IO_OFFSET		0x90000000
#define __L3_IO_ADDRESS(pa)	((pa) + L3_IO_OFFSET)/* Works for L3 */
#define __OMAP2_L3_IO_ADDRESS(pa)	((pa) + L3_IO_OFFSET)/* Works for L3 */
#define l3_io_v2p(va)		((va) - L3_IO_OFFSET)/* Works for L3 */
#define IO_OFFSET		0xb2000000
#define __IO_ADDRESS(pa)	((pa) + IO_OFFSET)/* Works for L4  */
#define __OMAP2_IO_ADDRESS(pa)	((pa) + IO_OFFSET)/* Works for L4 */
#define io_v2p(va)		((va) - IO_OFFSET)/* Works for L4*/

Driver Changes

Notice how drivers that use L3 peripherals are changed to use the new macro. Only these drivers need to be updated. Also note that magic values need to be cleaned up to use correct macros.


/* ... */
#define SDRC_SCRATCHPAD_SEM	0xd800291C

New Code

/* ... */

Kernel 29

Kernel 29 requires some changes to the attached patch files, but the intent is the same. A final version of the k29 patch can be see here in the Omapzoom Gerrit Site:

OMAPZoom Gerrit

Patch Files

  1. Original Patch:
  2. Additional Backward Compatibility


  1. High Memory In The Linux Kernel