]> git.sur5r.net Git - u-boot/blobdiff - common/cmd_mtdparts.c
smc911x: update SMC911X related configuration description
[u-boot] / common / cmd_mtdparts.c
index c8bf2c6392e8e9e99551455186c02ce80b60ef0b..b375feaad190023e9c11c4084af495e8dbbddffb 100644 (file)
  *
  */
 
-/*
- * JFFS2/CRAMFS support
- */
 #include <common.h>
 #include <command.h>
 #include <malloc.h>
-#include <jffs2/jffs2.h>
+#include <jffs2/load_kernel.h>
 #include <linux/list.h>
 #include <linux/ctype.h>
-#include <cramfs/cramfs_fs.h>
+#include <linux/err.h>
+#include <linux/mtd/mtd.h>
 
 #if defined(CONFIG_CMD_NAND)
-#ifdef CONFIG_NAND_LEGACY
-#include <linux/mtd/nand_legacy.h>
-#else /* !CONFIG_NAND_LEGACY */
 #include <linux/mtd/nand.h>
 #include <nand.h>
-#endif /* !CONFIG_NAND_LEGACY */
 #endif
 
 #if defined(CONFIG_CMD_ONENAND)
-#include <linux/mtd/mtd.h>
 #include <linux/mtd/onenand.h>
 #include <onenand_uboot.h>
 #endif
 #if defined(MTDIDS_DEFAULT)
 static const char *const mtdids_default = MTDIDS_DEFAULT;
 #else
-#warning "MTDIDS_DEFAULT not defined!"
 static const char *const mtdids_default = NULL;
 #endif
 
 #if defined(MTDPARTS_DEFAULT)
 static const char *const mtdparts_default = MTDPARTS_DEFAULT;
 #else
-#warning "MTDPARTS_DEFAULT not defined!"
 static const char *const mtdparts_default = NULL;
 #endif
 
@@ -169,8 +160,8 @@ struct list_head mtdids;
 struct list_head devices;
 
 /* current active device and partition number */
-static struct mtd_device *current_dev = NULL;
-static u8 current_partnum = 0;
+struct mtd_device *current_mtd_dev = NULL;
+u8 current_mtd_partnum = 0;
 
 static struct part_info* mtd_part_info(struct mtd_device *dev, unsigned int part_num);
 
@@ -254,12 +245,12 @@ static void index_partitions(void)
 
        DEBUGF("--- index partitions ---\n");
 
-       if (current_dev) {
+       if (current_mtd_dev) {
                mtddevnum = 0;
                list_for_each(dentry, &devices) {
                        dev = list_entry(dentry, struct mtd_device, link);
-                       if (dev == current_dev) {
-                               mtddevnum += current_partnum;
+                       if (dev == current_mtd_dev) {
+                               mtddevnum += current_mtd_partnum;
                                sprintf(buf, "%d", mtddevnum);
                                setenv("mtddevnum", buf);
                                break;
@@ -267,7 +258,7 @@ static void index_partitions(void)
                        mtddevnum += dev->num_parts;
                }
 
-               part = mtd_part_info(current_dev, current_partnum);
+               part = mtd_part_info(current_mtd_dev, current_mtd_partnum);
                setenv("mtddevname", part->name);
 
                DEBUGF("=> mtddevnum %d,\n=> mtddevname %s\n", mtddevnum, part->name);
@@ -288,9 +279,9 @@ static void current_save(void)
 
        DEBUGF("--- current_save ---\n");
 
-       if (current_dev) {
-               sprintf(buf, "%s%d,%d", MTD_DEV_TYPE(current_dev->id->type),
-                                       current_dev->id->num, current_partnum);
+       if (current_mtd_dev) {
+               sprintf(buf, "%s%d,%d", MTD_DEV_TYPE(current_mtd_dev->id->type),
+                                       current_mtd_dev->id->num, current_mtd_partnum);
 
                setenv("partition", buf);
                strncpy(last_partition, buf, 16);
@@ -306,137 +297,91 @@ static void current_save(void)
 }
 
 /**
- * Performs sanity check for supplied NOR flash partition. Table of existing
- * NOR flash devices is searched and partition device is located. Alignment
- * with the granularity of NOR flash sectors is verified.
+ * Performs sanity check for supplied flash partition.
+ * Table of existing MTD flash devices is searched and partition device
+ * is located. Alignment with the granularity of nand erasesize is verified.
  *
  * @param id of the parent device
  * @param part partition to validate
  * @return 0 if partition is valid, 1 otherwise
  */
-static int part_validate_nor(struct mtdids *id, struct part_info *part)
+static int part_validate_eraseblock(struct mtdids *id, struct part_info *part)
 {
-#if defined(CONFIG_CMD_FLASH)
-       /* info for FLASH chips */
-       extern flash_info_t flash_info[];
-       flash_info_t *flash;
-       int offset_aligned;
-       u32 end_offset, sector_size = 0;
-       int i;
-
-       flash = &flash_info[id->num];
-
-       /* size of last sector */
-       part->sector_size = flash->size -
-               (flash->start[flash->sector_count-1] - flash->start[0]);
-
-       offset_aligned = 0;
-       for (i = 0; i < flash->sector_count; i++) {
-               if ((flash->start[i] - flash->start[0]) == part->offset) {
-                       offset_aligned = 1;
-                       break;
-               }
-       }
-       if (offset_aligned == 0) {
-               printf("%s%d: partition (%s) start offset alignment incorrect\n",
-                               MTD_DEV_TYPE(id->type), id->num, part->name);
+       struct mtd_info *mtd;
+       char mtd_dev[16];
+       int i, j;
+       ulong start;
+
+       sprintf(mtd_dev, "%s%d", MTD_DEV_TYPE(id->type), id->num);
+       mtd = get_mtd_device_nm(mtd_dev);
+       if (IS_ERR(mtd)) {
+               printf("Partition %s not found on device %s!\n", part->name, mtd_dev);
                return 1;
        }
 
-       end_offset = part->offset + part->size;
-       offset_aligned = 0;
-       for (i = 0; i < flash->sector_count; i++) {
-               if (i) {
-                       sector_size = flash->start[i] - flash->start[i-1];
-                       if (part->sector_size < sector_size)
-                               part->sector_size = sector_size;
-               }
-               if ((flash->start[i] - flash->start[0]) == end_offset)
-                       offset_aligned = 1;
-       }
-
-       if (offset_aligned || flash->size == end_offset)
-               return 0;
-
-       printf("%s%d: partition (%s) size alignment incorrect\n",
-                       MTD_DEV_TYPE(id->type), id->num, part->name);
-#endif
-       return 1;
-}
-
-/**
- * Performs sanity check for supplied NAND flash partition. Table of existing
- * NAND flash devices is searched and partition device is located. Alignment
- * with the granularity of nand erasesize is verified.
- *
- * @param id of the parent device
- * @param part partition to validate
- * @return 0 if partition is valid, 1 otherwise
- */
-static int part_validate_nand(struct mtdids *id, struct part_info *part)
-{
-#if defined(CONFIG_JFFS2_NAND) && defined(CONFIG_CMD_NAND)
-       /* info for NAND chips */
-       nand_info_t *nand;
+       part->sector_size = mtd->erasesize;
 
-       nand = &nand_info[id->num];
+       if (!mtd->numeraseregions) {
+               /*
+                * Only one eraseregion (NAND, OneNAND or uniform NOR),
+                * checking for alignment is easy here
+                */
+               if ((unsigned long)part->offset % mtd->erasesize) {
+                       printf("%s%d: partition (%s) start offset"
+                              "alignment incorrect\n",
+                              MTD_DEV_TYPE(id->type), id->num, part->name);
+                       return 1;
+               }
 
-       part->sector_size = nand->erasesize;
+               if (part->size % mtd->erasesize) {
+                       printf("%s%d: partition (%s) size alignment incorrect\n",
+                              MTD_DEV_TYPE(id->type), id->num, part->name);
+                       return 1;
+               }
+       } else {
+               /*
+                * Multiple eraseregions (non-uniform NOR),
+                * checking for alignment is more complex here
+                */
+
+               /* Check start alignment */
+               for (i = 0; i < mtd->numeraseregions; i++) {
+                       start = mtd->eraseregions[i].offset;
+                       for (j = 0; j < mtd->eraseregions[i].numblocks; j++) {
+                               if (part->offset == start)
+                                       goto start_ok;
+                               start += mtd->eraseregions[i].erasesize;
+                       }
+               }
 
-       if ((unsigned long)(part->offset) % nand->erasesize) {
                printf("%s%d: partition (%s) start offset alignment incorrect\n",
-                               MTD_DEV_TYPE(id->type), id->num, part->name);
-               return 1;
-       }
-
-       if (part->size % nand->erasesize) {
-               printf("%s%d: partition (%s) size alignment incorrect\n",
-                               MTD_DEV_TYPE(id->type), id->num, part->name);
+                      MTD_DEV_TYPE(id->type), id->num, part->name);
                return 1;
-       }
 
-       return 0;
-#else
-       return 1;
-#endif
-}
+       start_ok:
 
-/**
- * Performs sanity check for supplied OneNAND flash partition.
- * Table of existing OneNAND flash devices is searched and partition device
- * is located. Alignment with the granularity of nand erasesize is verified.
- *
- * @param id of the parent device
- * @param part partition to validate
- * @return 0 if partition is valid, 1 otherwise
- */
-static int part_validate_onenand(struct mtdids *id, struct part_info *part)
-{
-#if defined(CONFIG_CMD_ONENAND)
-       /* info for OneNAND chips */
-       struct mtd_info *mtd;
-
-       mtd = &onenand_mtd;
-
-       part->sector_size = mtd->erasesize;
-
-       if ((unsigned long)(part->offset) % mtd->erasesize) {
-               printf("%s%d: partition (%s) start offset"
-                       "alignment incorrect\n",
-                               MTD_DEV_TYPE(id->type), id->num, part->name);
-               return 1;
-       }
+               /* Check end/size alignment */
+               for (i = 0; i < mtd->numeraseregions; i++) {
+                       start = mtd->eraseregions[i].offset;
+                       for (j = 0; j < mtd->eraseregions[i].numblocks; j++) {
+                               if ((part->offset + part->size) == start)
+                                       goto end_ok;
+                               start += mtd->eraseregions[i].erasesize;
+                       }
+               }
+               /* Check last sector alignment */
+               if ((part->offset + part->size) == start)
+                       goto end_ok;
 
-       if (part->size % mtd->erasesize) {
                printf("%s%d: partition (%s) size alignment incorrect\n",
-                               MTD_DEV_TYPE(id->type), id->num, part->name);
+                      MTD_DEV_TYPE(id->type), id->num, part->name);
                return 1;
+
+       end_ok:
+               return 0;
        }
 
        return 0;
-#else
-       return 1;
-#endif
 }
 
 
@@ -472,16 +417,11 @@ static int part_validate(struct mtdids *id, struct part_info *part)
                return 1;
        }
 
-       if (id->type == MTD_DEV_TYPE_NAND)
-               return part_validate_nand(id, part);
-       else if (id->type == MTD_DEV_TYPE_NOR)
-               return part_validate_nor(id, part);
-       else if (id->type == MTD_DEV_TYPE_ONENAND)
-               return part_validate_onenand(id, part);
-       else
-               DEBUGF("part_validate: invalid dev type\n");
-
-       return 1;
+       /*
+        * Now we need to check if the partition starts and ends on
+        * sector (eraseblock) regions
+        */
+       return part_validate_eraseblock(id, part);
 }
 
 /**
@@ -501,26 +441,23 @@ static int part_del(struct mtd_device *dev, struct part_info *part)
 
        /* otherwise just delete this partition */
 
-       if (dev == current_dev) {
+       if (dev == current_mtd_dev) {
                /* we are modyfing partitions for the current device,
                 * update current */
                struct part_info *curr_pi;
-               curr_pi = mtd_part_info(current_dev, current_partnum);
+               curr_pi = mtd_part_info(current_mtd_dev, current_mtd_partnum);
 
                if (curr_pi) {
                        if (curr_pi == part) {
                                printf("current partition deleted, resetting current to 0\n");
-                               current_partnum = 0;
+                               current_mtd_partnum = 0;
                        } else if (part->offset <= curr_pi->offset) {
-                               current_partnum--;
+                               current_mtd_partnum--;
                        }
                        current_save_needed = 1;
                }
        }
 
-#ifdef CONFIG_NAND_LEGACY
-       jffs2_free_cache(part);
-#endif
        list_del(&part->link);
        free(part);
        dev->num_parts--;
@@ -547,9 +484,6 @@ static void part_delall(struct list_head *head)
        list_for_each_safe(entry, n, head) {
                part_tmp = list_entry(entry, struct part_info, link);
 
-#ifdef CONFIG_NAND_LEGACY
-               jffs2_free_cache(part_tmp);
-#endif
                list_del(entry);
                free(part_tmp);
        }
@@ -582,8 +516,8 @@ static int part_sort_add(struct mtd_device *dev, struct part_info *part)
 
        /* get current partition info if we are updating current device */
        curr_pi = NULL;
-       if (dev == current_dev)
-               curr_pi = mtd_part_info(current_dev, current_partnum);
+       if (dev == current_mtd_dev)
+               curr_pi = mtd_part_info(current_mtd_dev, current_mtd_partnum);
 
        list_for_each(entry, &dev->parts) {
                struct part_info *pi;
@@ -603,7 +537,7 @@ static int part_sort_add(struct mtd_device *dev, struct part_info *part)
                        if (curr_pi && (pi->offset <= curr_pi->offset)) {
                                /* we are modyfing partitions for the current
                                 * device, update current */
-                               current_partnum++;
+                               current_mtd_partnum++;
                                current_save();
                        } else {
                                index_partitions();
@@ -765,48 +699,19 @@ static int part_parse(const char *const partdef, const char **ret, struct part_i
  */
 int mtd_device_validate(u8 type, u8 num, u32 *size)
 {
-       if (type == MTD_DEV_TYPE_NOR) {
-#if defined(CONFIG_CMD_FLASH)
-               if (num < CONFIG_SYS_MAX_FLASH_BANKS) {
-                       extern flash_info_t flash_info[];
-                       *size = flash_info[num].size;
-
-                       return 0;
-               }
+       struct mtd_info *mtd;
+       char mtd_dev[16];
 
-               printf("no such FLASH device: %s%d (valid range 0 ... %d\n",
-                               MTD_DEV_TYPE(type), num, CONFIG_SYS_MAX_FLASH_BANKS - 1);
-#else
-               printf("support for FLASH devices not present\n");
-#endif
-       } else if (type == MTD_DEV_TYPE_NAND) {
-#if defined(CONFIG_JFFS2_NAND) && defined(CONFIG_CMD_NAND)
-               if (num < CONFIG_SYS_MAX_NAND_DEVICE) {
-#ifndef CONFIG_NAND_LEGACY
-                       *size = nand_info[num].size;
-#else
-                       extern struct nand_chip nand_dev_desc[CONFIG_SYS_MAX_NAND_DEVICE];
-                       *size = nand_dev_desc[num].totlen;
-#endif
-                       return 0;
-               }
+       sprintf(mtd_dev, "%s%d", MTD_DEV_TYPE(type), num);
+       mtd = get_mtd_device_nm(mtd_dev);
+       if (IS_ERR(mtd)) {
+               printf("Device %s not found!\n", mtd_dev);
+               return 1;
+       }
 
-               printf("no such NAND device: %s%d (valid range 0 ... %d)\n",
-                               MTD_DEV_TYPE(type), num, CONFIG_SYS_MAX_NAND_DEVICE - 1);
-#else
-               printf("support for NAND devices not present\n");
-#endif
-       } else if (type == MTD_DEV_TYPE_ONENAND) {
-#if defined(CONFIG_CMD_ONENAND)
-               *size = onenand_mtd.size;
-               return 0;
-#else
-               printf("support for OneNAND devices not present\n");
-#endif
-       } else
-               printf("Unknown defice type %d\n", type);
+       *size = mtd->size;
 
-       return 1;
+       return 0;
 }
 
 /**
@@ -845,15 +750,15 @@ static int device_del(struct mtd_device *dev)
        list_del(&dev->link);
        free(dev);
 
-       if (dev == current_dev) {
+       if (dev == current_mtd_dev) {
                /* we just deleted current device */
                if (list_empty(&devices)) {
-                       current_dev = NULL;
+                       current_mtd_dev = NULL;
                } else {
                        /* reset first partition from first dev from the
                         * devices list as current */
-                       current_dev = list_entry(devices.next, struct mtd_device, link);
-                       current_partnum = 0;
+                       current_mtd_dev = list_entry(devices.next, struct mtd_device, link);
+                       current_mtd_partnum = 0;
                }
                current_save();
                return 0;
@@ -896,8 +801,8 @@ static void device_add(struct mtd_device *dev)
        u8 current_save_needed = 0;
 
        if (list_empty(&devices)) {
-               current_dev = dev;
-               current_partnum = 0;
+               current_mtd_dev = dev;
+               current_mtd_partnum = 0;
                current_save_needed = 1;
        }
 
@@ -1053,7 +958,7 @@ static int device_parse(const char *const mtd_dev, const char **ret, struct mtd_
 static int mtd_devices_init(void)
 {
        last_parts[0] = '\0';
-       current_dev = NULL;
+       current_mtd_dev = NULL;
        current_save();
 
        return device_delall(&devices);
@@ -1317,7 +1222,7 @@ static void list_partitions(void)
                printf("\ndevice %s%d <%s>, # parts = %d\n",
                                MTD_DEV_TYPE(dev->id->type), dev->id->num,
                                dev->id->mtd_id, dev->num_parts);
-               printf(" #: name\t\t\tsize\t\toffset\t\tmask_flags\n");
+               printf(" #: name\t\tsize\t\toffset\t\tmask_flags\n");
 
                /* list partitions for given device */
                part_num = 0;
@@ -1333,13 +1238,13 @@ static void list_partitions(void)
        if (list_empty(&devices))
                printf("no partitions defined\n");
 
-       /* current_dev is not NULL only when we have non empty device list */
-       if (current_dev) {
-               part = mtd_part_info(current_dev, current_partnum);
+       /* current_mtd_dev is not NULL only when we have non empty device list */
+       if (current_mtd_dev) {
+               part = mtd_part_info(current_mtd_dev, current_mtd_partnum);
                if (part) {
                        printf("\nactive partition: %s%d,%d - (%s) 0x%08x @ 0x%08x\n",
-                                       MTD_DEV_TYPE(current_dev->id->type),
-                                       current_dev->id->num, current_partnum,
+                                       MTD_DEV_TYPE(current_mtd_dev->id->type),
+                                       current_mtd_dev->id->num, current_mtd_partnum,
                                        part->name, part->size, part->offset);
                } else {
                        printf("could not get current partition info\n\n");
@@ -1347,8 +1252,10 @@ static void list_partitions(void)
        }
 
        printf("\ndefaults:\n");
-       printf("mtdids  : %s\n", mtdids_default);
-       printf("mtdparts: %s\n", mtdparts_default);
+       printf("mtdids  : %s\n",
+               mtdids_default ? mtdids_default : "none");
+       printf("mtdparts: %s\n",
+               mtdparts_default ? mtdparts_default : "none");
 }
 
 /**
@@ -1429,7 +1336,7 @@ static int delete_partition(const char *id)
 
        if (find_dev_and_part(id, &dev, &pnum, &part) == 0) {
 
-               DEBUGF("delete_partition: device = %s%d, partition %d = (%s) 0x%08lx@0x%08lx\n",
+               DEBUGF("delete_partition: device = %s%d, partition %d = (%s) 0x%08x@0x%08x\n",
                                MTD_DEV_TYPE(dev->id->type), dev->id->num, pnum,
                                part->name, part->size, part->offset);
 
@@ -1712,13 +1619,13 @@ int mtdparts_init(void)
                strncpy(last_parts, parts, MTDPARTS_MAXLEN);
 
                /* reset first partition from first dev from the list as current */
-               current_dev = list_entry(devices.next, struct mtd_device, link);
-               current_partnum = 0;
+               current_mtd_dev = list_entry(devices.next, struct mtd_device, link);
+               current_mtd_partnum = 0;
                current_save();
 
-               DEBUGF("mtdparts_init: current_dev  = %s%d, current_partnum = %d\n",
-                               MTD_DEV_TYPE(current_dev->id->type),
-                               current_dev->id->num, current_partnum);
+               DEBUGF("mtdparts_init: current_mtd_dev  = %s%d, current_mtd_partnum = %d\n",
+                               MTD_DEV_TYPE(current_mtd_dev->id->type),
+                               current_mtd_dev->id->num, current_mtd_partnum);
        }
 
        /* mtdparts variable was reset to NULL, delete all devices/partitions */
@@ -1738,8 +1645,8 @@ int mtdparts_init(void)
                DEBUGF("--- getting current partition: %s\n", tmp_ep);
 
                if (find_dev_and_part(tmp_ep, &cdev, &pnum, &p) == 0) {
-                       current_dev = cdev;
-                       current_partnum = pnum;
+                       current_mtd_dev = cdev;
+                       current_mtd_partnum = pnum;
                        current_save();
                }
        } else if (getenv("partition") == NULL) {
@@ -1823,8 +1730,8 @@ int do_chpart(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
        if (find_dev_and_part(argv[1], &dev, &pnum, &part) != 0)
                return 1;
 
-       current_dev = dev;
-       current_partnum = pnum;
+       current_mtd_dev = dev;
+       current_mtd_partnum = pnum;
        current_save();
 
        printf("partition changed to %s%d,%d\n",
@@ -1946,7 +1853,7 @@ U_BOOT_CMD(
        chpart, 2,      0,      do_chpart,
        "change active partition",
        "part-id\n"
-       "    - change active partition (e.g. part-id = nand0,1)\n"
+       "    - change active partition (e.g. part-id = nand0,1)"
 );
 
 U_BOOT_CMD(
@@ -1981,6 +1888,6 @@ U_BOOT_CMD(
        "<size>     := standard linux memsize OR '-' to denote all remaining space\n"
        "<offset>   := partition start offset within the device\n"
        "<name>     := '(' NAME ')'\n"
-       "<ro-flag>  := when set to 'ro' makes partition read-only (not used, passed to kernel)\n"
+       "<ro-flag>  := when set to 'ro' makes partition read-only (not used, passed to kernel)"
 );
 /***************************************************/