Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Index: linux-2.6.21/drivers/mtd/maps/ralink-flash.c
- ===================================================================
- --- /dev/null 1970-01-01 00:00:00.000000000 +0000
- +++ linux-2.6.21/drivers/mtd/maps/ralink-flash.c 2009-06-08 15:45:07.000000000 +0200
- @@ -0,0 +1,307 @@
- +/* ralink-flash.c
- + *
- + * Steven Liu <steven_liu@ralinktech.com.tw>:
- + * - initial approach
- + *
- + * Winfred Lu <winfred_lu@ralinktech.com.tw>:
- + * - 32MB flash support for RT3052
- + */
- +
- +#include <linux/module.h>
- +#include <linux/types.h>
- +#include <linux/init.h>
- +#include <linux/kernel.h>
- +
- +#include <asm/io.h>
- +#include <linux/mtd/mtd.h>
- +#include <linux/mtd/map.h>
- +#include <linux/mtd/concat.h>
- +#include <linux/mtd/partitions.h>
- +#include <linux/vmalloc.h>
- +#include <linux/squashfs_fs.h>
- +#include <linux/err.h>
- +
- +
- +#define WINDOW_ADDR CONFIG_MTD_PHYSMAP_START
- +#define WINDOW_SIZE CONFIG_MTD_PHYSMAP_LEN
- +#define NUM_FLASH_BANKS 1
- +
- +#define BUSWIDTH CONFIG_MTD_PHYSMAP_BUSWIDTH
- +
- +static struct mtd_info *ramips_mtd;
- +static struct map_info ramips_map = {
- + .name = "Ralink SoC physically mapped flash",
- + .bankwidth = BUSWIDTH,
- + .size = WINDOW_SIZE,
- + .phys = WINDOW_ADDR
- +};
- +
- +static struct mtd_partition ramips_partitions[] = {
- + {
- + name: "Bootloader",
- + size: 0x30000,
- + offset: 0,
- + }, {
- + name: "Config",
- + size: 0x10000,
- + offset: MTDPART_OFS_APPEND,
- + mask_flags: 0
- + }, {
- + name: "Factory",
- + size: 0x10000,
- + offset: MTDPART_OFS_APPEND,
- + // mask_flags: 0
- + }, {
- + name: "rootfs",
- + // size: CONFIG_MTD_KERNEL_PART_SIZ,
- + size: 0x400000 - 0x50000,
- + offset: 0x50000,
- + }
- +};
- +
- +static int ramips_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
- +{
- + return 0;
- +}
- +
- +static int ramips_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
- +{
- + return 0;
- +}
- +
- +int
- +find_uImage_size(unsigned long start_offset){
- + unsigned long temp, temp2;
- + memcpy_fromio(&temp, ramips_map.virt + start_offset + 12, 4);
- + temp2 = temp >> 24;
- + temp2 += (temp >> 8) & 0xff00;
- + temp2 += (temp << 8) & 0xff0000;
- + printk(KERN_INFO "ramips_mtd: kernel size is %ld \n", temp2 + 0x40);
- + return temp2 + 0x40;
- +}
- +
- +int
- +detect_squashfs_partition(unsigned long start_offset){
- + unsigned long temp;
- + memcpy_fromio(&temp, ramips_map.virt + start_offset, 4);
- + return (temp == 0x71736873 /*SQUASHFS_MAGIC*/);
- +}
- +
- +int __init ramips_mtd_init(void)
- +{
- + int ret = -ENXIO;
- + int k_size = 0;
- +
- + ramips_map.virt = ioremap(ramips_map.phys, ramips_map.size);
- + if(!ramips_map.virt)
- + {
- + printk(KERN_ERR "ramips_mtd: failed to ioremap\n");
- + return -EIO;
- + }
- +
- + simple_map_init(&ramips_map);
- + ramips_mtd = do_map_probe("cfi_probe", &ramips_map);
- + if(!ramips_mtd)
- + {
- + iounmap(ramips_map.virt);
- + printk("ramips_mtd: now flash found\n");
- + return -ENXIO;
- + }
- +
- + ramips_mtd->owner = THIS_MODULE;
- + ramips_mtd->lock = ramips_lock;
- + ramips_mtd->unlock = ramips_unlock;
- +
- + k_size = find_uImage_size(ramips_partitions[3].offset);
- + if(detect_squashfs_partition(ramips_partitions[3].offset + k_size))
- + {
- + printk(KERN_INFO "found a squashfs directly behind uImage\n");
- + ramips_partitions[4].offset = ramips_partitions[3].offset + k_size;
- + ramips_partitions[4].size = 0x800000 - (ramips_partitions[3].offset + k_size);
- + }
- + ret = add_mtd_partitions(ramips_mtd, ramips_partitions,ARRAY_SIZE(ramips_partitions));
- +
- + printk(KERN_NOTICE "ramips_mtd: 0x%lx at 0x%x\n", ramips_map.size, ramips_map.phys);
- +
- + return ret;
- +}
- +
- +static void __exit ramips_mtd_cleanup(void)
- +{
- + if(ramips_mtd)
- + map_destroy(ramips_mtd);
- +
- + if(ramips_map.virt)
- + iounmap(ramips_map.virt);
- +}
- +
- +module_init(ramips_mtd_init);
- +module_exit(ramips_mtd_cleanup);
- +
- +MODULE_AUTHOR("Steven Liu <steven_liu@ralinktech.com.tw>");
- +MODULE_DESCRIPTION("Ralink APSoC Flash Map");
- +MODULE_LICENSE("GPL");
- +
- +
- +/*
- + * Flash API: ra_mtd_read, ra_mtd_write
- + * Arguments:
- + * - num: specific the mtd number
- + * - to/from: the offset to read from or written to
- + * - len: length
- + * - buf: data to be read/written
- + * Returns:
- + * - return -errno if failed
- + * - return the number of bytes read/written if successed
- + */
- +int ra_mtd_write(int num, loff_t to, size_t len, const u_char *buf)
- +{
- + int ret = -1;
- + size_t rdlen, wrlen;
- + struct mtd_info *mtd;
- + struct erase_info ei;
- + u_char *bak = NULL;
- +
- + mtd = get_mtd_device(NULL, num);
- + if (IS_ERR(mtd))
- + return (int)mtd;
- + if (len > mtd->erasesize) {
- + put_mtd_device(mtd);
- + return -E2BIG;
- + }
- +
- + bak = kmalloc(mtd->erasesize, GFP_KERNEL);
- + if (bak == NULL) {
- + put_mtd_device(mtd);
- + return -ENOMEM;
- + }
- +
- + ret = mtd->read(mtd, 0, mtd->erasesize, &rdlen, bak);
- + if (ret != 0) {
- + put_mtd_device(mtd);
- + kfree(bak);
- + return ret;
- + }
- + if (rdlen != mtd->erasesize)
- + printk("warning: ra_mtd_write: rdlen is not equal to erasesize\n");
- +
- + memcpy(bak + to, buf, len);
- +
- + ei.mtd = mtd;
- + ei.callback = NULL;
- + ei.addr = 0;
- + ei.len = mtd->erasesize;
- + ei.priv = 0;
- + ret = mtd->erase(mtd, &ei);
- + if (ret != 0) {
- + put_mtd_device(mtd);
- + kfree(bak);
- + return ret;
- + }
- +
- + ret = mtd->write(mtd, 0, mtd->erasesize, &wrlen, bak);
- +
- + put_mtd_device(mtd);
- + kfree(bak);
- + return ret;
- +}
- +
- +int ra_mtd_write_nm(char *name, loff_t to, size_t len, const u_char *buf)
- +{
- + int ret = -1;
- + size_t rdlen, wrlen;
- + struct mtd_info *mtd;
- + struct erase_info ei;
- + u_char *bak = NULL;
- +
- + mtd = get_mtd_device_nm(name);
- + if (IS_ERR(mtd))
- + return (int)mtd;
- + if (len > mtd->erasesize) {
- + put_mtd_device(mtd);
- + return -E2BIG;
- + }
- +
- + bak = kmalloc(mtd->erasesize, GFP_KERNEL);
- + if (bak == NULL) {
- + put_mtd_device(mtd);
- + return -ENOMEM;
- + }
- +
- + ret = mtd->read(mtd, 0, mtd->erasesize, &rdlen, bak);
- + if (ret != 0) {
- + put_mtd_device(mtd);
- + kfree(bak);
- + return ret;
- + }
- + if (rdlen != mtd->erasesize)
- + printk("warning: ra_mtd_write: rdlen is not equal to erasesize\n");
- +
- + memcpy(bak + to, buf, len);
- +
- + ei.mtd = mtd;
- + ei.callback = NULL;
- + ei.addr = 0;
- + ei.len = mtd->erasesize;
- + ei.priv = 0;
- + ret = mtd->erase(mtd, &ei);
- + if (ret != 0) {
- + put_mtd_device(mtd);
- + kfree(bak);
- + return ret;
- + }
- +
- + ret = mtd->write(mtd, 0, mtd->erasesize, &wrlen, bak);
- +
- + put_mtd_device(mtd);
- + kfree(bak);
- + return ret;
- +}
- +
- +int ra_mtd_read(int num, loff_t from, size_t len, u_char *buf)
- +{
- + int ret;
- + size_t rdlen;
- + struct mtd_info *mtd;
- +
- + mtd = get_mtd_device(NULL, num);
- + if (IS_ERR(mtd))
- + return (int)mtd;
- +
- + ret = mtd->read(mtd, from, len, &rdlen, buf);
- + if (rdlen != len)
- + printk("warning: ra_mtd_read: rdlen is not equal to len\n");
- +
- + put_mtd_device(mtd);
- + return ret;
- +}
- +
- +int ra_mtd_read_nm(char *name, loff_t from, size_t len, u_char *buf)
- +{
- + int ret;
- + size_t rdlen;
- + struct mtd_info *mtd;
- +
- + mtd = get_mtd_device_nm(name);
- + if (IS_ERR(mtd))
- + return (int)mtd;
- +
- + ret = mtd->read(mtd, from, len, &rdlen, buf);
- + if (rdlen != len)
- + printk("warning: ra_mtd_read_nm: rdlen is not equal to len\n");
- +
- + put_mtd_device(mtd);
- + return ret;
- +}
- +
- +EXPORT_SYMBOL(ra_mtd_write);
- +EXPORT_SYMBOL(ra_mtd_read);
- +EXPORT_SYMBOL(ra_mtd_write_nm);
- +EXPORT_SYMBOL(ra_mtd_read_nm);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement