diff options
author | Jonas Gorski <jonas.gorski@gmail.com> | 2011-12-05 10:08:08 -0500 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2012-01-09 13:15:31 -0500 |
commit | 70a3c167c4bf38b5ffd07d8506230ecc20ef7ab1 (patch) | |
tree | 520c452c53100751d02e30bd105e633a8c3639f9 /drivers/mtd/bcm63xxpart.c | |
parent | ca105f4d9823f916a4718c4bc766fd14842056f2 (diff) |
mtd: maps: bcm963xx-flash: make CFE partition parsing an mtd parser
Recent BCM63XX devices support a variety of flash types (parallel, SPI,
NAND) and share the partition layout. To prevent code duplication make
the CFE partition parsing code a stand alone mtd parser to allow SPI or
NAND flash drivers to use it.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
Acked-by: Florian Fainelli <florian@openwrt.org>
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@linux.intel.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd/bcm63xxpart.c')
-rw-r--r-- | drivers/mtd/bcm63xxpart.c | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/drivers/mtd/bcm63xxpart.c b/drivers/mtd/bcm63xxpart.c new file mode 100644 index 000000000000..ac7d3c823949 --- /dev/null +++ b/drivers/mtd/bcm63xxpart.c | |||
@@ -0,0 +1,189 @@ | |||
1 | /* | ||
2 | * BCM63XX CFE image tag parser | ||
3 | * | ||
4 | * Copyright © 2006-2008 Florian Fainelli <florian@openwrt.org> | ||
5 | * Mike Albon <malbon@openwrt.org> | ||
6 | * Copyright © 2009-2010 Daniel Dickinson <openwrt@cshore.neomailbox.net> | ||
7 | * Copyright © 2011 Jonas Gorski <jonas.gorski@gmail.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
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 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
26 | |||
27 | #include <linux/module.h> | ||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/vmalloc.h> | ||
31 | #include <linux/mtd/mtd.h> | ||
32 | #include <linux/mtd/partitions.h> | ||
33 | |||
34 | #include <asm/mach-bcm63xx/bcm963xx_tag.h> | ||
35 | |||
36 | #define BCM63XX_EXTENDED_SIZE 0xBFC00000 /* Extended flash address */ | ||
37 | |||
38 | static int bcm63xx_detect_cfe(struct mtd_info *master) | ||
39 | { | ||
40 | int idoffset = 0x4e0; | ||
41 | static char idstring[8] = "CFE1CFE1"; | ||
42 | char buf[9]; | ||
43 | int ret; | ||
44 | size_t retlen; | ||
45 | |||
46 | ret = master->read(master, idoffset, 8, &retlen, (void *)buf); | ||
47 | buf[retlen] = 0; | ||
48 | pr_info("Read Signature value of %s\n", buf); | ||
49 | |||
50 | return strncmp(idstring, buf, 8); | ||
51 | } | ||
52 | |||
53 | static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, | ||
54 | struct mtd_partition **pparts, | ||
55 | struct mtd_part_parser_data *data) | ||
56 | { | ||
57 | /* CFE, NVRAM and global Linux are always present */ | ||
58 | int nrparts = 3, curpart = 0; | ||
59 | struct bcm_tag *buf; | ||
60 | struct mtd_partition *parts; | ||
61 | int ret; | ||
62 | size_t retlen; | ||
63 | unsigned int rootfsaddr, kerneladdr, spareaddr; | ||
64 | unsigned int rootfslen, kernellen, sparelen, totallen; | ||
65 | int namelen = 0; | ||
66 | int i; | ||
67 | char *boardid; | ||
68 | char *tagversion; | ||
69 | |||
70 | if (bcm63xx_detect_cfe(master)) | ||
71 | return -EINVAL; | ||
72 | |||
73 | /* Allocate memory for buffer */ | ||
74 | buf = vmalloc(sizeof(struct bcm_tag)); | ||
75 | if (!buf) | ||
76 | return -ENOMEM; | ||
77 | |||
78 | /* Get the tag */ | ||
79 | ret = master->read(master, master->erasesize, sizeof(struct bcm_tag), | ||
80 | &retlen, (void *)buf); | ||
81 | if (retlen != sizeof(struct bcm_tag)) { | ||
82 | vfree(buf); | ||
83 | return -EIO; | ||
84 | } | ||
85 | |||
86 | sscanf(buf->kernel_address, "%u", &kerneladdr); | ||
87 | sscanf(buf->kernel_length, "%u", &kernellen); | ||
88 | sscanf(buf->total_length, "%u", &totallen); | ||
89 | tagversion = &(buf->tag_version[0]); | ||
90 | boardid = &(buf->board_id[0]); | ||
91 | |||
92 | pr_info("CFE boot tag found with version %s and board type %s\n", | ||
93 | tagversion, boardid); | ||
94 | |||
95 | kerneladdr = kerneladdr - BCM63XX_EXTENDED_SIZE; | ||
96 | rootfsaddr = kerneladdr + kernellen; | ||
97 | spareaddr = roundup(totallen, master->erasesize) + master->erasesize; | ||
98 | sparelen = master->size - spareaddr - master->erasesize; | ||
99 | rootfslen = spareaddr - rootfsaddr; | ||
100 | |||
101 | /* Determine number of partitions */ | ||
102 | namelen = 8; | ||
103 | if (rootfslen > 0) { | ||
104 | nrparts++; | ||
105 | namelen += 6; | ||
106 | } | ||
107 | if (kernellen > 0) { | ||
108 | nrparts++; | ||
109 | namelen += 6; | ||
110 | } | ||
111 | |||
112 | /* Ask kernel for more memory */ | ||
113 | parts = kzalloc(sizeof(*parts) * nrparts + 10 * nrparts, GFP_KERNEL); | ||
114 | if (!parts) { | ||
115 | vfree(buf); | ||
116 | return -ENOMEM; | ||
117 | } | ||
118 | |||
119 | /* Start building partition list */ | ||
120 | parts[curpart].name = "CFE"; | ||
121 | parts[curpart].offset = 0; | ||
122 | parts[curpart].size = master->erasesize; | ||
123 | curpart++; | ||
124 | |||
125 | if (kernellen > 0) { | ||
126 | parts[curpart].name = "kernel"; | ||
127 | parts[curpart].offset = kerneladdr; | ||
128 | parts[curpart].size = kernellen; | ||
129 | curpart++; | ||
130 | } | ||
131 | |||
132 | if (rootfslen > 0) { | ||
133 | parts[curpart].name = "rootfs"; | ||
134 | parts[curpart].offset = rootfsaddr; | ||
135 | parts[curpart].size = rootfslen; | ||
136 | if (sparelen > 0) | ||
137 | parts[curpart].size += sparelen; | ||
138 | curpart++; | ||
139 | } | ||
140 | |||
141 | parts[curpart].name = "nvram"; | ||
142 | parts[curpart].offset = master->size - master->erasesize; | ||
143 | parts[curpart].size = master->erasesize; | ||
144 | |||
145 | /* Global partition "linux" to make easy firmware upgrade */ | ||
146 | curpart++; | ||
147 | parts[curpart].name = "linux"; | ||
148 | parts[curpart].offset = parts[0].size; | ||
149 | parts[curpart].size = master->size - parts[0].size - parts[3].size; | ||
150 | |||
151 | for (i = 0; i < nrparts; i++) | ||
152 | pr_info("Partition %d is %s offset %lx and length %lx\n", i, | ||
153 | parts[i].name, (long unsigned int)(parts[i].offset), | ||
154 | (long unsigned int)(parts[i].size)); | ||
155 | |||
156 | pr_info("Spare partition is offset %x and length %x\n", spareaddr, | ||
157 | sparelen); | ||
158 | |||
159 | *pparts = parts; | ||
160 | vfree(buf); | ||
161 | |||
162 | return nrparts; | ||
163 | }; | ||
164 | |||
165 | static struct mtd_part_parser bcm63xx_cfe_parser = { | ||
166 | .owner = THIS_MODULE, | ||
167 | .parse_fn = bcm63xx_parse_cfe_partitions, | ||
168 | .name = "bcm63xxpart", | ||
169 | }; | ||
170 | |||
171 | static int __init bcm63xx_cfe_parser_init(void) | ||
172 | { | ||
173 | return register_mtd_parser(&bcm63xx_cfe_parser); | ||
174 | } | ||
175 | |||
176 | static void __exit bcm63xx_cfe_parser_exit(void) | ||
177 | { | ||
178 | deregister_mtd_parser(&bcm63xx_cfe_parser); | ||
179 | } | ||
180 | |||
181 | module_init(bcm63xx_cfe_parser_init); | ||
182 | module_exit(bcm63xx_cfe_parser_exit); | ||
183 | |||
184 | MODULE_LICENSE("GPL"); | ||
185 | MODULE_AUTHOR("Daniel Dickinson <openwrt@cshore.neomailbox.net>"); | ||
186 | MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>"); | ||
187 | MODULE_AUTHOR("Mike Albon <malbon@openwrt.org>"); | ||
188 | MODULE_AUTHOR("Jonas Gorski <jonas.gorski@gmail.com"); | ||
189 | MODULE_DESCRIPTION("MTD partitioning for BCM63XX CFE bootloaders"); | ||