Hey all,
I am looking for a way to use the 128 KB on-chip SRAM from our Linux platform (mainline 3.10.x). In the reference manual, I see that the SRAM is part of the DIGCTL block and in the DeviceTree I see a digctl@8001c000 part. But I have no idea how to enable this and how I would be able to use this part of memory, preferably from user-space. Can anyone help me in the right direction?
Regards,
Ruud
You can use the generic SRAM allocator: drivers/misc/sram.c
Search for "mmio-sram" inside arch/arm/boot/dts for examples of its usage.
As an example (from imx6q.dtis):
soc { | ||
ocram: sram@00900000 { | ||
compatible = "mmio-sram"; | ||
reg = <0x00900000 0x40000>; | ||
clocks = <&clks IMX6QDL_CLK_OCRAM>; | ||
}; |
Hello Fabio,
I understand that a part from adding in device tree, the "mmio-sram" compatibility, in order to access sram from userspace we need to use "/dev/mem"
It raise 2 questions:
1. Is it that /dev/mem can't access sram without adding "mmio-sram" section in device tree ? I mean, if sram is a plain ram, does it really need a driver or will it work even without it ?
2. /dev/mem required root privilidege. Is there any other alternative for userspace ?
Regards,
Ran
Hi Ran,
What I did for using the internal RAM fro userspace, is to use the 'mmap' function:
/*!
\brief Function to get a mapped to pointer to a specific address area
in memory. The address should be 4K (blocksize) aligned
\param address The 4K aligned physical address to map to
\param size The size in bytes to be mapped
\return The pointer to the mapped memory, NULL if mapping fails
*/
void * NonVolStorage::MapMemory(uint32_t address, size_t size)
{
int fd;
void *ret_addr;
fd = open("/dev/mem", O_RDWR | O_SYNC);
if (fd == -1) {
perror("open");
return NULL;
}
ret_addr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, address);
if (ret_addr == MAP_FAILED) {
perror("mmap");
ret_addr = NULL;
}
if (close(fd) == -1) {
perror("close");
}
return ret_addr;
}
I call this function with the below defined address and size:
#define NV_RAM_ADDRESS 0x1B000
#define NV_RAM_SIZE 4096
I did not add an mmio-sram part to the device-tree.
Hope this helps. Regards,
Ruud
Hi Ran,
The example I pointed out is for the kernel to use the internal RAM.
Regards,
Fabio Estevam
Hi Fabio, thanks for your reply.
I looked for this dts code, but it seems that the example code is from a newer kernel version. If I look at the documentation for 3.10 (sram.txt), I see an example like:
sram: sram@5c000000 {
compatible = "mmio-sram";
reg = <0x5c000000 0x40000>; /* 256 KiB SRAM at address 0x5c000000 */
};
I tried to adjust this to the i.mx28 address range and enabled the CONFIG_SRAM in the kernel, but sofar no luck. So I have another few questions:
Thanks again for your answers.
1. The compatible string is 'mmio-sram'
2; From 0x0
3. No, the allocation of SRM memory is a generic operation handled by a generic driver, so nothing FSL specific here
4. The use cases I saw was SRAM to be accessed by kernel drivers
OK, not sure if this would be the right solution for me then.
What I am trying to achieve, is to use a block of RAM from user-space as "persistent RAM". In other words: RAM that keeps its contents over a reboot.
I noticed the PRAMFS, but that is not part of the mainline kernel and I am not to sure about the status of this part. Therefore I thought to use the internal SRAM for this purpose.
I did some new attempts this week by using the "mmap" function, and it seems to me that it is working. By using mmap with a 4K (pagesize) aligned value for the offset in the SRAM area and a file descriptor to /dev/mem, I am able to read and write from this part of RAM. In the i.mx28 reference manual, chapter 12.4, I read that this RAM is also used by the ROM boot code. And I noticed after reboot, that this contents is indeed overwritten, for instance at address 0 or 0x10000. However, when using the reserved area from 0xF000 - 0xFFFF, the test contents I wrote to it was still there after reboot. So I seem to have achieved what I wanted, but I'm not sure if this is indeed a proper solution:
Regards,
Ruud
OK, I did some further testing and it appeared to be that only the 1st 1K of the 0xF000 - 0xFFFF area was preserved at reboot. The contents of the upper 3K was overwritten. So I did a 2nd attempt on the reserved 6K area form 0x1A800 - 0x1BFFF. Since 1A800 is not a 4K aligned address, I only used the 4K part from 0x1B000 - 0x1BFFF. And for this block the contents does seem to be preserved at reboot (writing 00-FF repeatedly to the whole 4K block and dump the contents after reboot).
So, again, I think to have found a solution for my problem, but the question about reliability is still open. If anyone from Freescale could answer this question, I would be more than happy. Regards,
Ruud
Hello Ruud,
it's been while, but maybe you want to share the additions to the device tree you used and how did you did the tests?
Best regards
Jörg Krause
Okay, this wasn't to hard:
ocram: ocram@00000000 {
compatible = "mmio-sram";
reg = <0x00000000 0x20000>;
};