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", },
{},
};
