nand_partitions.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /* arch/arm/mach-msm/nand_partitions.c
  2. *
  3. * Code to extract partition information from ATAG set up by the
  4. * bootloader.
  5. *
  6. * Copyright (C) 2007 Google, Inc.
  7. * Copyright (c) 2008-2009,2011,2013 The Linux Foundation. All rights reserved.
  8. * Author: Brian Swetland <swetland@google.com>
  9. *
  10. * This software is licensed under the terms of the GNU General Public
  11. * License version 2, as published by the Free Software Foundation, and
  12. * may be copied, distributed, and modified under those terms.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. */
  20. #include <linux/kernel.h>
  21. #include <linux/init.h>
  22. #include <linux/platform_device.h>
  23. #include <asm/mach/flash.h>
  24. #include <linux/io.h>
  25. #include <asm/setup.h>
  26. #include <linux/mtd/nand.h>
  27. #include <linux/mtd/partitions.h>
  28. #include <mach/msm_iomap.h>
  29. #include <mach/board.h>
  30. #ifdef CONFIG_MSM_SMD
  31. #include <mach/msm_smem.h>
  32. #endif
  33. /* configuration tags specific to msm */
  34. #define ATAG_MSM_PARTITION 0x4d534D70 /* MSMp */
  35. struct msm_ptbl_entry {
  36. char name[16];
  37. __u32 offset;
  38. __u32 size;
  39. __u32 flags;
  40. };
  41. #define MSM_MAX_PARTITIONS 18
  42. static struct mtd_partition msm_nand_partitions[MSM_MAX_PARTITIONS];
  43. static char msm_nand_names[MSM_MAX_PARTITIONS * 16];
  44. extern struct flash_platform_data msm_nand_data;
  45. static int __init parse_tag_msm_partition(const struct tag *tag)
  46. {
  47. struct mtd_partition *ptn = msm_nand_partitions;
  48. char *name = msm_nand_names;
  49. struct msm_ptbl_entry *entry = (void *) &tag->u;
  50. unsigned count, n;
  51. count = (tag->hdr.size - 2) /
  52. (sizeof(struct msm_ptbl_entry) / sizeof(__u32));
  53. if (count > MSM_MAX_PARTITIONS)
  54. count = MSM_MAX_PARTITIONS;
  55. for (n = 0; n < count; n++) {
  56. memcpy(name, entry->name, 15);
  57. name[15] = 0;
  58. ptn->name = name;
  59. ptn->offset = entry->offset;
  60. ptn->size = entry->size;
  61. printk(KERN_INFO "Partition (from atag) %s "
  62. "-- Offset:%llx Size:%llx\n",
  63. ptn->name, ptn->offset, ptn->size);
  64. name += 16;
  65. entry++;
  66. ptn++;
  67. }
  68. msm_nand_data.nr_parts = count;
  69. msm_nand_data.parts = msm_nand_partitions;
  70. return 0;
  71. }
  72. __tagtable(ATAG_MSM_PARTITION, parse_tag_msm_partition);
  73. #define FLASH_PART_MAGIC1 0x55EE73AA
  74. #define FLASH_PART_MAGIC2 0xE35EBDDB
  75. #define FLASH_PARTITION_VERSION 0x3
  76. #define LINUX_FS_PARTITION_NAME "0:EFS2APPS"
  77. struct flash_partition_entry {
  78. char name[16];
  79. u32 offset; /* Offset in blocks from beginning of device */
  80. u32 length; /* Length of the partition in blocks */
  81. u8 attrib1;
  82. u8 attrib2;
  83. u8 attrib3;
  84. u8 which_flash; /* Numeric ID (first = 0, second = 1) */
  85. };
  86. struct flash_partition_table {
  87. u32 magic1;
  88. u32 magic2;
  89. u32 version;
  90. u32 numparts;
  91. struct flash_partition_entry part_entry[16];
  92. };
  93. #ifdef CONFIG_MSM_SMD
  94. static int get_nand_partitions(void)
  95. {
  96. struct flash_partition_table *partition_table;
  97. struct flash_partition_entry *part_entry;
  98. struct mtd_partition *ptn = msm_nand_partitions;
  99. char *name = msm_nand_names;
  100. int part;
  101. if (msm_nand_data.nr_parts)
  102. return 0;
  103. partition_table = (struct flash_partition_table *)
  104. smem_alloc(SMEM_AARM_PARTITION_TABLE,
  105. sizeof(struct flash_partition_table));
  106. if (!partition_table) {
  107. printk(KERN_WARNING "%s: no flash partition table in shared "
  108. "memory\n", __func__);
  109. return -ENOENT;
  110. }
  111. if ((partition_table->magic1 != (u32) FLASH_PART_MAGIC1) ||
  112. (partition_table->magic2 != (u32) FLASH_PART_MAGIC2) ||
  113. (partition_table->version != (u32) FLASH_PARTITION_VERSION)) {
  114. printk(KERN_WARNING "%s: version mismatch -- magic1=%#x, "
  115. "magic2=%#x, version=%#x\n", __func__,
  116. partition_table->magic1,
  117. partition_table->magic2,
  118. partition_table->version);
  119. return -EFAULT;
  120. }
  121. msm_nand_data.nr_parts = 0;
  122. /* Get the LINUX FS partition info */
  123. for (part = 0; part < partition_table->numparts; part++) {
  124. part_entry = &partition_table->part_entry[part];
  125. /* Find a match for the Linux file system partition */
  126. if (strcmp(part_entry->name, LINUX_FS_PARTITION_NAME) == 0) {
  127. strcpy(name, part_entry->name);
  128. ptn->name = name;
  129. /*TODO: Get block count and size info */
  130. ptn->offset = part_entry->offset;
  131. /* For SMEM, -1 indicates remaining space in flash,
  132. * but for MTD it is 0
  133. */
  134. if (part_entry->length == (u32)-1)
  135. ptn->size = 0;
  136. else
  137. ptn->size = part_entry->length;
  138. msm_nand_data.nr_parts = 1;
  139. msm_nand_data.parts = msm_nand_partitions;
  140. printk(KERN_INFO "Partition(from smem) %s "
  141. "-- Offset:%llx Size:%llx\n",
  142. ptn->name, ptn->offset, ptn->size);
  143. return 0;
  144. }
  145. }
  146. printk(KERN_WARNING "%s: no partition table found!", __func__);
  147. return -ENODEV;
  148. }
  149. #else
  150. static int get_nand_partitions(void)
  151. {
  152. if (msm_nand_data.nr_parts)
  153. return 0;
  154. printk(KERN_WARNING "%s: no partition table found!", __func__);
  155. return -ENODEV;
  156. }
  157. #endif
  158. device_initcall(get_nand_partitions);