2 * Flash memory access on SA11x0 based devices
4 * (C) 2000 Nicolas Pitre <nico@cam.org>
6 * $Id: sa1100-flash.c,v 1.29 2002/09/06 14:36:19 abz Exp $
9 #include <linux/config.h>
10 #include <linux/module.h>
11 #include <linux/types.h>
12 #include <linux/ioport.h>
13 #include <linux/kernel.h>
15 #include <linux/mtd/mtd.h>
16 #include <linux/mtd/map.h>
17 #include <linux/mtd/partitions.h>
19 #include <asm/hardware.h>
23 #ifndef CONFIG_ARCH_SA1100
24 #error This is for SA1100 architecture only
28 #define WINDOW_ADDR 0xe8000000
30 static __u8 sa1100_read8(struct map_info *map, unsigned long ofs)
32 return readb(map->map_priv_1 + ofs);
35 static __u16 sa1100_read16(struct map_info *map, unsigned long ofs)
37 return readw(map->map_priv_1 + ofs);
40 static __u32 sa1100_read32(struct map_info *map, unsigned long ofs)
42 return readl(map->map_priv_1 + ofs);
45 static void sa1100_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
47 memcpy(to, (void *)(map->map_priv_1 + from), len);
50 static void sa1100_write8(struct map_info *map, __u8 d, unsigned long adr)
52 writeb(d, map->map_priv_1 + adr);
55 static void sa1100_write16(struct map_info *map, __u16 d, unsigned long adr)
57 writew(d, map->map_priv_1 + adr);
60 static void sa1100_write32(struct map_info *map, __u32 d, unsigned long adr)
62 writel(d, map->map_priv_1 + adr);
65 static void sa1100_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
67 memcpy((void *)(map->map_priv_1 + to), from, len);
70 static struct map_info sa1100_map = {
73 read16: sa1100_read16,
74 read32: sa1100_read32,
75 copy_from: sa1100_copy_from,
76 write8: sa1100_write8,
77 write16: sa1100_write16,
78 write32: sa1100_write32,
79 copy_to: sa1100_copy_to,
81 map_priv_1: WINDOW_ADDR,
87 * Here are partition information for all known SA1100-based devices.
88 * See include/linux/mtd/partitions.h for definition of the mtd_partition
91 * The *_max_flash_size is the maximum possible mapped flash size which
92 * is not necessarily the actual flash size. It must be no more than
93 * the value specified in the "struct map_desc *_io_desc" mapping
94 * definition for the corresponding machine.
96 * Please keep these in alphabetical order, and formatted as per existing
100 #ifdef CONFIG_SA1100_ADSBITSY
101 #define ADSBITSY_FLASH_SIZE 0x02000000
102 static struct mtd_partition adsbitsy_partitions[] = {
107 mask_flags: MTD_WRITEABLE, /* force read-only */
111 offset: MTDPART_OFS_APPEND,
112 mask_flags: MTD_WRITEABLE, /* force read-only */
116 offset: MTDPART_OFS_APPEND,
117 mask_flags: MTD_WRITEABLE, /* force read-only */
120 size: MTDPART_SIZ_FULL,
121 offset: MTDPART_OFS_APPEND,
126 #ifdef CONFIG_SA1100_ASSABET
127 /* Phase 4 Assabet has two 28F160B3 flash parts in bank 0: */
128 #define ASSABET4_FLASH_SIZE 0x00400000
129 static struct mtd_partition assabet4_partitions[] = {
134 mask_flags: MTD_WRITEABLE,
136 name: "bootloader params",
138 offset: MTDPART_OFS_APPEND,
139 mask_flags: MTD_WRITEABLE,
142 size: MTDPART_SIZ_FULL,
143 offset: MTDPART_OFS_APPEND,
147 /* Phase 5 Assabet has two 28F128J3A flash parts in bank 0: */
148 #define ASSABET5_FLASH_SIZE 0x02000000
149 static struct mtd_partition assabet5_partitions[] = {
154 mask_flags: MTD_WRITEABLE,
156 name: "bootloader params",
158 offset: MTDPART_OFS_APPEND,
159 mask_flags: MTD_WRITEABLE,
162 size: MTDPART_SIZ_FULL,
163 offset: MTDPART_OFS_APPEND,
167 #define ASSABET_FLASH_SIZE ASSABET5_FLASH_SIZE
168 #define assabet_partitions assabet5_partitions
171 #ifdef CONFIG_SA1100_BADGE4
174 * 1 x Intel 28F320C3BA100 Advanced+ Boot Block Flash (32 Mi bit)
175 * Eight 4 KiW Parameter Bottom Blocks (64 KiB)
176 * Sixty-three 32 KiW Main Blocks (4032 Ki b)
178 #define BADGE4_FLASH_SIZE 0x00400000
179 static struct mtd_partition badge4_partitions[] = {
181 name: "BLOB boot loader",
186 offset: MTDPART_OFS_APPEND,
190 offset: MTDPART_OFS_APPEND,
194 offset: MTDPART_OFS_APPEND,
195 size: MTDPART_SIZ_FULL
202 #ifdef CONFIG_SA1100_CERF
203 #ifdef CONFIG_SA1100_CERF_FLASH_32MB
204 #define CERF_FLASH_SIZE 0x02000000
205 static struct mtd_partition cerf_partitions[] = {
224 #elif defined CONFIG_SA1100_CERF_FLASH_16MB
225 #define CERF_FLASH_SIZE 0x01000000
226 static struct mtd_partition cerf_partitions[] = {
245 #elif defined CONFIG_SA1100_CERF_FLASH_8MB
246 # error "Unwritten type definition"
248 # error "Undefined memory orientation for CERF in sa1100-flash.c"
252 #ifdef CONFIG_SA1100_CONSUS
253 #define CONSUS_FLASH_SIZE 0x02000000
254 static struct mtd_partition consus_partitions[] = {
256 name: "Consus boot firmware",
259 mask_flags: MTD_WRITABLE, /* force read-only */
261 name: "Consus kernel",
268 /* The rest (up to 16M) for jffs. We could put 0 and
269 make it find the size automatically, but right now
270 i have 32 megs. jffs will use all 32 megs if given
271 the chance, and this leads to horrible problems
272 when you try to re-flash the image because blob
273 won't erase the whole partition. */
274 size: 0x01000000 - 0x00140000,
277 /* this disk is a secondary disk, which can be used as
278 needed, for simplicity, make it the size of the other
279 consus partition, although realistically it could be
280 the remainder of the disk (depending on the file
282 name: "Consus disk2",
284 size: 0x01000000 - 0x00140000,
290 #ifdef CONFIG_SA1100_FLEXANET
291 /* Flexanet has two 28F128J3A flash parts in bank 0: */
292 #define FLEXANET_FLASH_SIZE 0x02000000
293 static struct mtd_partition flexanet_partitions[] = {
298 mask_flags: MTD_WRITEABLE,
300 name: "bootloader params",
302 offset: MTDPART_OFS_APPEND,
303 mask_flags: MTD_WRITEABLE,
307 offset: MTDPART_OFS_APPEND,
308 mask_flags: MTD_WRITEABLE,
312 offset: MTDPART_OFS_APPEND,
313 mask_flags: MTD_WRITEABLE,
317 offset: MTDPART_OFS_APPEND,
318 mask_flags: MTD_WRITEABLE,
322 offset: MTDPART_OFS_APPEND,
323 mask_flags: MTD_WRITEABLE,
327 offset: MTDPART_OFS_APPEND,
328 mask_flags: MTD_WRITEABLE,
331 size: MTDPART_SIZ_FULL,
332 offset: MTDPART_OFS_APPEND,
333 mask_flags: MTD_WRITEABLE,
338 #ifdef CONFIG_SA1100_FREEBIRD
339 #define FREEBIRD_FLASH_SIZE 0x02000000
340 static struct mtd_partition freebird_partitions[] = {
341 #if CONFIG_SA1100_FREEBIRD_NEW
346 mask_flags: MTD_WRITEABLE, /* force read-only */
369 size: MTDPART_SIZ_FULL,
378 offset: MTDPART_OFS_APPEND,
381 offset: MTDPART_OFS_APPEND,
383 size: MTDPART_SIZ_FULL,
384 offset: MTDPART_OFS_APPEND,
390 #ifdef CONFIG_SA1100_FRODO
391 /* Frodo has 2 x 16M 28F128J3A flash chips in bank 0: */
392 #define FRODO_FLASH_SIZE 0x02000000
393 static struct mtd_partition frodo_partitions[] =
400 name: "Parameter Block",
402 offset: MTDPART_OFS_APPEND
404 name: "Linux Kernel",
406 offset: MTDPART_OFS_APPEND
410 offset: MTDPART_OFS_APPEND
412 name: "Flash File System",
413 size: MTDPART_SIZ_FULL,
414 offset: MTDPART_OFS_APPEND
419 #ifdef CONFIG_SA1100_GRAPHICSCLIENT
420 #define GRAPHICSCLIENT_FLASH_SIZE 0x02000000
421 static struct mtd_partition graphicsclient_partitions[] = {
426 mask_flags: MTD_WRITEABLE, /* force read-only */
430 offset: MTDPART_OFS_APPEND,
431 mask_flags: MTD_WRITEABLE, /* force read-only */
434 size: MTDPART_SIZ_FULL,
435 offset: MTDPART_OFS_APPEND,
440 #ifdef CONFIG_SA1100_GRAPHICSMASTER
441 #define GRAPHICSMASTER_FLASH_SIZE 0x01000000
442 static struct mtd_partition graphicsmaster_partitions[] = {
447 mask_flags: MTD_WRITEABLE, /* force read-only */
452 offset: MTDPART_OFS_APPEND,
453 mask_flags: MTD_WRITEABLE, /* force read-only */
457 size: MTDPART_SIZ_FULL,
458 offset: MTDPART_OFS_APPEND,
463 #ifdef CONFIG_SA1100_H3600
464 #define H3600_FLASH_SIZE 0x02000000
465 static struct mtd_partition h3600_partitions[] = {
467 name: "H3600 boot firmware",
470 mask_flags: MTD_WRITEABLE, /* force read-only */
472 name: "H3600 kernel",
476 name: "H3600 params",
480 #ifdef CONFIG_JFFS2_FS
481 name: "H3600 root jffs2",
482 size: MTDPART_SIZ_FULL,
485 name: "H3600 initrd",
489 name: "H3600 root cramfs",
493 name: "H3600 usr cramfs",
497 name: "H3600 usr local",
498 size: MTDPART_SIZ_FULL,
504 static void h3600_set_vpp(struct map_info *map, int vpp)
506 assign_h3600_egpio(IPAQ_EGPIO_VPP_ON, vpp);
510 #ifdef CONFIG_SA1100_HUW_WEBPANEL
511 #define HUW_WEBPANEL_FLASH_SIZE 0x01000000
512 static struct mtd_partition huw_webpanel_partitions[] = {
520 offset: MTDPART_OFS_APPEND,
522 size: MTDPART_SIZ_FULL,
523 offset: MTDPART_OFS_APPEND,
528 #ifdef CONFIG_SA1100_JORNADA720
529 #define JORNADA720_FLASH_SIZE 0x02000000
530 static struct mtd_partition jornada720_partitions[] = {
532 name: "JORNADA720 boot firmware",
535 mask_flags: MTD_WRITEABLE, /* force read-only */
537 name: "JORNADA720 kernel",
541 name: "JORNADA720 params",
545 name: "JORNADA720 initrd",
549 name: "JORNADA720 root cramfs",
553 name: "JORNADA720 usr cramfs",
557 name: "JORNADA720 usr local",
558 size: 0 /* will expand to the end of the flash */
563 static void jornada720_set_vpp(int vpp)
574 #ifdef CONFIG_SA1100_PANGOLIN
575 #define PANGOLIN_FLASH_SIZE 0x04000000
576 static struct mtd_partition pangolin_partitions[] = {
578 name: "boot firmware",
581 mask_flags: MTD_WRITEABLE, /* force read-only */
598 #ifdef CONFIG_SA1100_PT_SYSTEM3
599 /* erase size is 0x40000 == 256k partitions have to have this boundary */
600 #define SYSTEM3_FLASH_SIZE 0x01000000
601 static struct mtd_partition system3_partitions[] = {
606 mask_flags: MTD_WRITEABLE, /* force read-only */
610 offset: MTDPART_OFS_APPEND,
614 offset: MTDPART_OFS_APPEND,
617 size: MTDPART_SIZ_FULL,
618 offset: MTDPART_OFS_APPEND,
623 #ifdef CONFIG_SA1100_SHANNON
624 #define SHANNON_FLASH_SIZE 0x00400000
625 static struct mtd_partition shannon_partitions[] = {
627 name: "BLOB boot loader",
633 offset: MTDPART_OFS_APPEND,
638 offset: MTDPART_OFS_APPEND,
639 size: MTDPART_SIZ_FULL
645 #ifdef CONFIG_SA1100_SHERMAN
646 #define SHERMAN_FLASH_SIZE 0x02000000
647 static struct mtd_partition sherman_partitions[] = {
653 offset: MTDPART_OFS_APPEND,
656 offset: MTDPART_OFS_APPEND,
659 offset: MTDPART_OFS_APPEND,
664 #ifdef CONFIG_SA1100_SIMPAD
665 #define SIMPAD_FLASH_SIZE 0x02000000
666 static struct mtd_partition simpad_partitions[] = {
668 name: "SIMpad boot firmware",
671 mask_flags: MTD_WRITEABLE, /* force read-only */
673 name: "SIMpad kernel",
677 #ifdef CONFIG_JFFS2_FS
678 name: "SIMpad root jffs2",
679 size: MTDPART_SIZ_FULL,
682 name: "SIMpad initrd",
686 name: "SIMpad root cramfs",
690 name: "SIMpad usr cramfs",
694 name: "SIMpad usr local",
695 size: MTDPART_SIZ_FULL,
700 #endif /* CONFIG_SA1100_SIMPAD */
702 #ifdef CONFIG_SA1100_STORK
703 #define STORK_FLASH_SIZE 0x02000000
704 static struct mtd_partition stork_partitions[] = {
706 name: "STORK boot firmware",
709 mask_flags: MTD_WRITEABLE, /* force read-only */
711 name: "STORK params",
715 name: "STORK kernel",
719 #ifdef CONFIG_JFFS2_FS
720 name: "STORK root jffs2",
722 size: MTDPART_SIZ_FULL,
724 name: "STORK initrd",
728 name: "STORK root cramfs",
732 name: "STORK usr cramfs",
736 name: "STORK usr local",
738 size: MTDPART_SIZ_FULL,
744 #ifdef CONFIG_SA1100_YOPY
745 #define YOPY_FLASH_SIZE 0x08000000
746 static struct mtd_partition yopy_partitions[] = {
748 name: "boot firmware",
751 mask_flags: MTD_WRITEABLE, /* force read-only */
768 extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts);
769 extern int parse_bootldr_partitions(struct mtd_info *master, struct mtd_partition **pparts);
771 static struct mtd_partition *parsed_parts;
772 static struct mtd_info *mymtd;
774 int __init sa1100_mtd_init(void)
776 struct mtd_partition *parts;
777 int nb_parts = 0, ret;
778 int parsed_nr_parts = 0;
779 const char *part_type;
780 unsigned long base = -1UL;
782 /* Default flash buswidth */
783 sa1100_map.buswidth = (MSC0 & MSC_RBW) ? 2 : 4;
786 * Static partition definition selection
788 part_type = "static";
790 #ifdef CONFIG_SA1100_ADSBITSY
791 if (machine_is_adsbitsy()) {
792 parts = adsbitsy_partitions;
793 nb_parts = ARRAY_SIZE(adsbitsy_partitions);
794 sa1100_map.size = ADSBITSY_FLASH_SIZE;
795 sa1100_map.buswidth = (MSC1 & MSC_RBW) ? 2 : 4;
798 #ifdef CONFIG_SA1100_ASSABET
799 if (machine_is_assabet()) {
800 parts = assabet_partitions;
801 nb_parts = ARRAY_SIZE(assabet_partitions);
802 sa1100_map.size = ASSABET_FLASH_SIZE;
805 #ifdef CONFIG_SA1100_BADGE4
806 if (machine_is_badge4()) {
807 parts = badge4_partitions;
808 nb_parts = ARRAY_SIZE(badge4_partitions);
809 sa1100_map.size = BADGE4_FLASH_SIZE;
812 #ifdef CONFIG_SA1100_CERF
813 if (machine_is_cerf()) {
814 parts = cerf_partitions;
815 nb_parts = ARRAY_SIZE(cerf_partitions);
816 sa1100_map.size = CERF_FLASH_SIZE;
819 #ifdef CONFIG_SA1100_CONSUS
820 if (machine_is_consus()) {
821 parts = consus_partitions;
822 nb_parts = ARRAY_SIZE(consus_partitions);
823 sa1100_map.size = CONSUS_FLASH_SIZE;
826 #ifdef CONFIG_SA1100_FLEXANET
827 if (machine_is_flexanet()) {
828 parts = flexanet_partitions;
829 nb_parts = ARRAY_SIZE(flexanet_partitions);
830 sa1100_map.size = FLEXANET_FLASH_SIZE;
833 #ifdef CONFIG_SA1100_FREEBIRD
834 if (machine_is_freebird()) {
835 parts = freebird_partitions;
836 nb_parts = ARRAY_SIZE(freebird_partitions);
837 sa1100_map.size = FREEBIRD_FLASH_SIZE;
840 #ifdef CONFIG_SA1100_FRODO
841 if (machine_is_frodo()) {
842 parts = frodo_partitions;
843 nb_parts = ARRAY_SIZE(frodo_partitions);
844 sa1100_map.size = FRODO_FLASH_SIZE;
848 #ifdef CONFIG_SA1100_GRAPHICSCLIENT
849 if (machine_is_graphicsclient()) {
850 parts = graphicsclient_partitions;
851 nb_parts = ARRAY_SIZE(graphicsclient_partitions);
852 sa1100_map.size = GRAPHICSCLIENT_FLASH_SIZE;
853 sa1100_map.buswidth = (MSC1 & MSC_RBW) ? 2:4;
856 #ifdef CONFIG_SA1100_GRAPHICSMASTER
857 if (machine_is_graphicsmaster()) {
858 parts = graphicsmaster_partitions;
859 nb_parts = ARRAY_SIZE(graphicsmaster_partitions);
860 sa1100_map.size = GRAPHICSMASTER_FLASH_SIZE;
861 sa1100_map.buswidth = (MSC1 & MSC_RBW) ? 2:4;
864 #ifdef CONFIG_SA1100_H3600
865 if (machine_is_h3600()) {
866 parts = h3600_partitions;
867 nb_parts = ARRAY_SIZE(h3600_partitions);
868 sa1100_map.size = H3600_FLASH_SIZE;
869 sa1100_map.set_vpp = h3600_set_vpp;
872 #ifdef CONFIG_SA1100_HUW_WEBPANEL
873 if (machine_is_huw_webpanel()) {
874 parts = huw_webpanel_partitions;
875 nb_parts = ARRAY_SIZE(huw_webpanel_partitions);
876 sa1100_map.size = HUW_WEBPANEL_FLASH_SIZE;
879 #ifdef CONFIG_SA1100_JORNADA720
880 if (machine_is_jornada720()) {
881 parts = jornada720_partitions;
882 nb_parts = ARRAY_SIZE(jornada720_partitions);
883 sa1100_map.size = JORNADA720_FLASH_SIZE;
884 sa1100_map.set_vpp = jornada720_set_vpp;
887 #ifdef CONFIG_SA1100_PANGOLIN
888 if (machine_is_pangolin()) {
889 parts = pangolin_partitions;
890 nb_parts = ARRAY_SIZE(pangolin_partitions);
891 sa1100_map.size = PANGOLIN_FLASH_SIZE;
894 #ifdef CONFIG_SA1100_PT_SYSTEM3
895 if (machine_is_pt_system3()) {
896 parts = system3_partitions;
897 nb_parts = ARRAY_SIZE(system3_partitions);
898 sa1100_map.size = SYSTEM3_FLASH_SIZE;
901 #ifdef CONFIG_SA1100_SHANNON
902 if (machine_is_shannon()) {
903 parts = shannon_partitions;
904 nb_parts = ARRAY_SIZE(shannon_partitions);
905 sa1100_map.size = SHANNON_FLASH_SIZE;
908 #ifdef CONFIG_SA1100_SHERMAN
909 if (machine_is_sherman()) {
910 parts = sherman_partitions;
911 nb_parts = ARRAY_SIZE(sherman_partitions);
912 sa1100_map.size = SHERMAN_FLASH_SIZE;
915 #ifdef CONFIG_SA1100_SIMPAD
916 if (machine_is_simpad()) {
917 parts = simpad_partitions;
918 nb_parts = ARRAY_SIZE(simpad_partitions);
919 sa1100_map.size = SIMPAD_FLASH_SIZE;
922 #ifdef CONFIG_SA1100_STORK
923 if (machine_is_stork()) {
924 parts = stork_partitions;
925 nb_parts = ARRAY_SIZE(stork_partitions);
926 sa1100_map.size = STORK_FLASH_SIZE;
929 #ifdef CONFIG_SA1100_YOPY
930 if (machine_is_yopy()) {
931 parts = yopy_partitions;
932 nb_parts = ARRAY_SIZE(yopy_partitions);
933 sa1100_map.size = YOPY_FLASH_SIZE;
938 * For simple flash devices, use ioremap to map the flash.
940 if (base != (unsigned long)-1) {
941 if (!request_mem_region(base, sa1100_map.size, "flash"))
943 sa1100_map.map_priv_2 = base;
944 sa1100_map.map_priv_1 = (unsigned long)
945 ioremap(base, sa1100_map.size);
947 if (!sa1100_map.map_priv_1)
952 * Now let's probe for the actual flash. Do it here since
953 * specific machine settings might have been set above.
955 printk(KERN_NOTICE "SA1100 flash: probing %d-bit flash bus\n", sa1100_map.buswidth*8);
956 mymtd = do_map_probe("cfi_probe", &sa1100_map);
960 mymtd->module = THIS_MODULE;
963 * Dynamic partition selection stuff (might override the static ones)
965 #ifdef CONFIG_MTD_REDBOOT_PARTS
966 if (parsed_nr_parts == 0) {
967 int ret = parse_redboot_partitions(mymtd, &parsed_parts);
970 part_type = "RedBoot";
971 parsed_nr_parts = ret;
975 #ifdef CONFIG_MTD_CMDLINE_PARTS
976 if (parsed_nr_parts == 0) {
977 int ret = parse_cmdline_partitions(mymtd, &parsed_parts, "sa1100");
979 part_type = "Command Line";
980 parsed_nr_parts = ret;
985 if (parsed_nr_parts > 0) {
986 parts = parsed_parts;
987 nb_parts = parsed_nr_parts;
991 printk(KERN_NOTICE "SA1100 flash: no partition info available, registering whole flash at once\n");
992 add_mtd_device(mymtd);
994 printk(KERN_NOTICE "Using %s partition definition\n", part_type);
995 add_mtd_partitions(mymtd, parts, nb_parts);
1000 if (sa1100_map.map_priv_2 != -1) {
1001 iounmap((void *)sa1100_map.map_priv_1);
1002 release_mem_region(sa1100_map.map_priv_2, sa1100_map.size);
1007 static void __exit sa1100_mtd_cleanup(void)
1010 del_mtd_partitions(mymtd);
1013 kfree(parsed_parts);
1015 if (sa1100_map.map_priv_2 != -1) {
1016 iounmap((void *)sa1100_map.map_priv_1);
1017 release_mem_region(sa1100_map.map_priv_2, sa1100_map.size);
1021 module_init(sa1100_mtd_init);
1022 module_exit(sa1100_mtd_cleanup);
1024 MODULE_AUTHOR("Nicolas Pitre");
1025 MODULE_DESCRIPTION("SA1100 CFI map driver");
1026 MODULE_LICENSE("GPL");