call flow
msm_nand_probe() |-> msm_nand_parse_smem_ptable() |-> smem_get_entry(SMEM_AARM_PARTITION_TABLE) |-> mtd_device_parse_register()
code snippet, https://android.googlesource.com/kernel/msm/+/android-msm-hammerhead-3.4-kk-r1/drivers/mtd/devices/msm_qpic_nand.c
#define FLASH_PART_MAGIC1 0x55EE73AA #define FLASH_PART_MAGIC2 0xE35EBDDB #define FLASH_PTABLE_V3 3 #define FLASH_PTABLE_V4 4 #define FLASH_PTABLE_MAX_PARTS_V3 16 #define FLASH_PTABLE_MAX_PARTS_V4 32 #define FLASH_PTABLE_HDR_LEN (4*sizeof(uint32_t)) // Parititon Table Store in Flash. struct flash_partition_entry { char name[FLASH_PTABLE_ENTRY_NAME_SIZE]; u32 offset; /* Offset in blocks from beginning of device */ u32 length; /* Length of the partition in blocks */ u8 attr; /* Flags for this partition */ }; struct flash_partition_table { u32 magic1; u32 magic2; u32 version; u32 numparts; struct flash_partition_entry part_entry[FLASH_PTABLE_MAX_PARTS_V4]; }; static struct mtd_partition mtd_part[FLASH_PTABLE_MAX_PARTS_V4]; static int __devinit msm_nand_probe(struct platform_device *pdev) { ... err = msm_nand_parse_smem_ptable(&nr_parts); ... for (i = 0; i < nr_parts; i++) { mtd_part[i].offset *= info->mtd.erasesize; mtd_part[i].size *= info->mtd.erasesize; } err = mtd_device_parse_register(&info->mtd, NULL, NULL, &mtd_part[0], nr_parts); ... } // Get Partition Table from RAM/Flash via smem_get_entry(SMEM_AARM_PARTITION_TABLE). static int msm_nand_parse_smem_ptable(int *nr_parts) { uint32_t i, j; uint32_t len = FLASH_PTABLE_HDR_LEN; struct flash_partition_entry *pentry; char *delimiter = ":"; pr_info("Parsing partition table info from SMEM\n"); /* Read only the header portion of ptable */ ptable = *(struct flash_partition_table *) (smem_get_entry(SMEM_AARM_PARTITION_TABLE, &len)); /* Verify ptable magic */ if (ptable.magic1 != FLASH_PART_MAGIC1 || ptable.magic2 != FLASH_PART_MAGIC2) { pr_err("Partition table magic verification failed\n"); goto out; } /* Ensure that # of partitions is less than the max we have allocated */ if (ptable.numparts > FLASH_PTABLE_MAX_PARTS_V4) { pr_err("Partition numbers exceed the max limit\n"); goto out; } /* Find out length of partition data based on table version. */ if (ptable.version <= FLASH_PTABLE_V3) { len = FLASH_PTABLE_HDR_LEN + FLASH_PTABLE_MAX_PARTS_V3 * sizeof(struct flash_partition_entry); } else if (ptable.version == FLASH_PTABLE_V4) { len = FLASH_PTABLE_HDR_LEN + FLASH_PTABLE_MAX_PARTS_V4 * sizeof(struct flash_partition_entry); } else { pr_err("Unknown ptable version (%d)", ptable.version); goto out; } *nr_parts = ptable.numparts; ptable = *(struct flash_partition_table *) (smem_get_entry(SMEM_AARM_PARTITION_TABLE, &len)); for (i = 0; i < ptable.numparts; i++) { pentry = &ptable.part_entry[i]; if (pentry->name == '\0') continue; /* Convert name to lower case and discard the initial chars */ mtd_part[i].name = pentry->name; for (j = 0; j < strlen(mtd_part[i].name); j++) *(mtd_part[i].name + j) = tolower(*(mtd_part[i].name + j)); strsep(&(mtd_part[i].name), delimiter); mtd_part[i].offset = pentry->offset; mtd_part[i].mask_flags = pentry->attr; mtd_part[i].size = pentry->length; pr_debug("%d: %s offs=0x%08x size=0x%08x attr:0x%08x\n", i, pentry->name, pentry->offset, pentry->length, pentry->attr); } pr_info("SMEM partition table found: ver: %d len: %d\n", ptable.version, ptable.numparts); return 0; out: return -EINVAL; } static const struct of_device_id msm_nand_match_table[] = { { .compatible = "qcom,msm-nand", }, {}, };