162306a36Sopenharmony_ci/****************************************************************************/ 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci/* 462306a36Sopenharmony_ci * uclinux.c -- generic memory mapped MTD driver for uclinux 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com) 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * License: GPL 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci/****************************************************************************/ 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <linux/moduleparam.h> 1462306a36Sopenharmony_ci#include <linux/types.h> 1562306a36Sopenharmony_ci#include <linux/init.h> 1662306a36Sopenharmony_ci#include <linux/kernel.h> 1762306a36Sopenharmony_ci#include <linux/fs.h> 1862306a36Sopenharmony_ci#include <linux/mm.h> 1962306a36Sopenharmony_ci#include <linux/major.h> 2062306a36Sopenharmony_ci#include <linux/mtd/mtd.h> 2162306a36Sopenharmony_ci#include <linux/mtd/map.h> 2262306a36Sopenharmony_ci#include <linux/mtd/partitions.h> 2362306a36Sopenharmony_ci#include <asm/io.h> 2462306a36Sopenharmony_ci#include <asm/sections.h> 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci/****************************************************************************/ 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#ifdef CONFIG_MTD_ROM 2962306a36Sopenharmony_ci#define MAP_NAME "rom" 3062306a36Sopenharmony_ci#else 3162306a36Sopenharmony_ci#define MAP_NAME "ram" 3262306a36Sopenharmony_ci#endif 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistatic struct map_info uclinux_ram_map = { 3562306a36Sopenharmony_ci .name = MAP_NAME, 3662306a36Sopenharmony_ci .size = 0, 3762306a36Sopenharmony_ci}; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistatic unsigned long physaddr = -1; 4062306a36Sopenharmony_cimodule_param(physaddr, ulong, S_IRUGO); 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_cistatic struct mtd_info *uclinux_ram_mtdinfo; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci/****************************************************************************/ 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_cistatic const struct mtd_partition uclinux_romfs[] = { 4762306a36Sopenharmony_ci { .name = "ROMfs" } 4862306a36Sopenharmony_ci}; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci#define NUM_PARTITIONS ARRAY_SIZE(uclinux_romfs) 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci/****************************************************************************/ 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_cistatic int uclinux_point(struct mtd_info *mtd, loff_t from, size_t len, 5562306a36Sopenharmony_ci size_t *retlen, void **virt, resource_size_t *phys) 5662306a36Sopenharmony_ci{ 5762306a36Sopenharmony_ci struct map_info *map = mtd->priv; 5862306a36Sopenharmony_ci *virt = map->virt + from; 5962306a36Sopenharmony_ci if (phys) 6062306a36Sopenharmony_ci *phys = map->phys + from; 6162306a36Sopenharmony_ci *retlen = len; 6262306a36Sopenharmony_ci return(0); 6362306a36Sopenharmony_ci} 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci/****************************************************************************/ 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_cistatic int __init uclinux_mtd_init(void) 6862306a36Sopenharmony_ci{ 6962306a36Sopenharmony_ci struct mtd_info *mtd; 7062306a36Sopenharmony_ci struct map_info *mapp; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci mapp = &uclinux_ram_map; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci if (physaddr == -1) 7562306a36Sopenharmony_ci mapp->phys = (resource_size_t)__bss_stop; 7662306a36Sopenharmony_ci else 7762306a36Sopenharmony_ci mapp->phys = physaddr; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci if (!mapp->size) 8062306a36Sopenharmony_ci mapp->size = PAGE_ALIGN(ntohl(*((unsigned long *)(mapp->phys + 8)))); 8162306a36Sopenharmony_ci mapp->bankwidth = 4; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci printk("uclinux[mtd]: probe address=0x%x size=0x%x\n", 8462306a36Sopenharmony_ci (int) mapp->phys, (int) mapp->size); 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci /* 8762306a36Sopenharmony_ci * The filesystem is guaranteed to be in direct mapped memory. It is 8862306a36Sopenharmony_ci * directly following the kernels own bss region. Following the same 8962306a36Sopenharmony_ci * mechanism used by architectures setting up traditional initrds we 9062306a36Sopenharmony_ci * use phys_to_virt to get the virtual address of its start. 9162306a36Sopenharmony_ci */ 9262306a36Sopenharmony_ci mapp->virt = phys_to_virt(mapp->phys); 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci if (mapp->virt == 0) { 9562306a36Sopenharmony_ci printk("uclinux[mtd]: no virtual mapping?\n"); 9662306a36Sopenharmony_ci return(-EIO); 9762306a36Sopenharmony_ci } 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci simple_map_init(mapp); 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci mtd = do_map_probe("map_" MAP_NAME, mapp); 10262306a36Sopenharmony_ci if (!mtd) { 10362306a36Sopenharmony_ci printk("uclinux[mtd]: failed to find a mapping?\n"); 10462306a36Sopenharmony_ci return(-ENXIO); 10562306a36Sopenharmony_ci } 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci mtd->owner = THIS_MODULE; 10862306a36Sopenharmony_ci mtd->_point = uclinux_point; 10962306a36Sopenharmony_ci mtd->priv = mapp; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci uclinux_ram_mtdinfo = mtd; 11262306a36Sopenharmony_ci mtd_device_register(mtd, uclinux_romfs, NUM_PARTITIONS); 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci return(0); 11562306a36Sopenharmony_ci} 11662306a36Sopenharmony_cidevice_initcall(uclinux_mtd_init); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci/****************************************************************************/ 119