mirror of
https://github.com/torvalds/linux.git
synced 2024-11-07 20:51:47 +00:00
08a3c4bc23
The uclinux.c mapping driver uses ioremap_nocache() to map its physical mapping address to a system virtual address. Problem is that the region it is mapping is not device memory. It is ordinary system RAM. On most non-MMU systems this doesn't matter, and the mapping is always a 1:1 translation of the address. On paged memory systems on some architectures the page table mappings are not compatible between normal RAM and device memory. If we want to use the uclinux.c mapping driver on real MMU enabled systems we should be using the kernel virtual address that the mapping is at. For architectures that support the traditional initrd they use phys_to_virt or __va to convert the physical start initrd address to a kernel usable virtual address. The uclinux filesystem mapping is even more restrictive than the typical initrd, it always follows the kernels own bss section (so always in directly mapped memory). Therefore we can use the usual phys_to_virt to translate the physical start address to a virtual address. Signed-off-by: Greg Ungerer <gerg@uclinux.org> Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
124 lines
3.1 KiB
C
124 lines
3.1 KiB
C
/****************************************************************************/
|
|
|
|
/*
|
|
* uclinux.c -- generic memory mapped MTD driver for uclinux
|
|
*
|
|
* (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com)
|
|
*/
|
|
|
|
/****************************************************************************/
|
|
|
|
#include <linux/module.h>
|
|
#include <linux/types.h>
|
|
#include <linux/init.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/major.h>
|
|
#include <linux/mtd/mtd.h>
|
|
#include <linux/mtd/map.h>
|
|
#include <linux/mtd/partitions.h>
|
|
#include <asm/io.h>
|
|
#include <asm/sections.h>
|
|
|
|
/****************************************************************************/
|
|
|
|
struct map_info uclinux_ram_map = {
|
|
.name = "RAM",
|
|
.phys = (unsigned long)__bss_stop,
|
|
.size = 0,
|
|
};
|
|
|
|
static struct mtd_info *uclinux_ram_mtdinfo;
|
|
|
|
/****************************************************************************/
|
|
|
|
static struct mtd_partition uclinux_romfs[] = {
|
|
{ .name = "ROMfs" }
|
|
};
|
|
|
|
#define NUM_PARTITIONS ARRAY_SIZE(uclinux_romfs)
|
|
|
|
/****************************************************************************/
|
|
|
|
static int uclinux_point(struct mtd_info *mtd, loff_t from, size_t len,
|
|
size_t *retlen, void **virt, resource_size_t *phys)
|
|
{
|
|
struct map_info *map = mtd->priv;
|
|
*virt = map->virt + from;
|
|
if (phys)
|
|
*phys = map->phys + from;
|
|
*retlen = len;
|
|
return(0);
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
static int __init uclinux_mtd_init(void)
|
|
{
|
|
struct mtd_info *mtd;
|
|
struct map_info *mapp;
|
|
|
|
mapp = &uclinux_ram_map;
|
|
if (!mapp->size)
|
|
mapp->size = PAGE_ALIGN(ntohl(*((unsigned long *)(mapp->phys + 8))));
|
|
mapp->bankwidth = 4;
|
|
|
|
printk("uclinux[mtd]: RAM probe address=0x%x size=0x%x\n",
|
|
(int) mapp->phys, (int) mapp->size);
|
|
|
|
/*
|
|
* The filesystem is guaranteed to be in direct mapped memory. It is
|
|
* directly following the kernels own bss region. Following the same
|
|
* mechanism used by architectures setting up traditional initrds we
|
|
* use phys_to_virt to get the virtual address of its start.
|
|
*/
|
|
mapp->virt = phys_to_virt(mapp->phys);
|
|
|
|
if (mapp->virt == 0) {
|
|
printk("uclinux[mtd]: no virtual mapping?\n");
|
|
return(-EIO);
|
|
}
|
|
|
|
simple_map_init(mapp);
|
|
|
|
mtd = do_map_probe("map_ram", mapp);
|
|
if (!mtd) {
|
|
printk("uclinux[mtd]: failed to find a mapping?\n");
|
|
return(-ENXIO);
|
|
}
|
|
|
|
mtd->owner = THIS_MODULE;
|
|
mtd->_point = uclinux_point;
|
|
mtd->priv = mapp;
|
|
|
|
uclinux_ram_mtdinfo = mtd;
|
|
mtd_device_register(mtd, uclinux_romfs, NUM_PARTITIONS);
|
|
|
|
return(0);
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
static void __exit uclinux_mtd_cleanup(void)
|
|
{
|
|
if (uclinux_ram_mtdinfo) {
|
|
mtd_device_unregister(uclinux_ram_mtdinfo);
|
|
map_destroy(uclinux_ram_mtdinfo);
|
|
uclinux_ram_mtdinfo = NULL;
|
|
}
|
|
if (uclinux_ram_map.virt)
|
|
uclinux_ram_map.virt = 0;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
module_init(uclinux_mtd_init);
|
|
module_exit(uclinux_mtd_cleanup);
|
|
|
|
MODULE_LICENSE("GPL");
|
|
MODULE_AUTHOR("Greg Ungerer <gerg@snapgear.com>");
|
|
MODULE_DESCRIPTION("Generic RAM based MTD for uClinux");
|
|
|
|
/****************************************************************************/
|