2 * Handle mapping of the flash memory access routines
3 * on Amazon based devices.
5 * Copyright(C) 2004 peng.liu@infineon.com
10 // 000005:fchang 2005/6/2 Modified by Bingtao to double check if the EBU is enabled/disabled
11 // 506231:tc.chen 2005/06/23 increase firmware partition size form 192KB to 256KB
12 // 050701:linmars 2005/07/01 fix flash size wrong alignment after increase firmware partition
13 // 165001:henryhsu 2005/8/18 Remove the support for Intel flash because of 2.1 not enough rootfs partition size
14 // 165001:henryhsu 2005/9/7 Rolback to support INtel flash
15 // 509071:tc.chen 2005/09/07 Reduced flash writing time
16 // 511046:linmars 2005/11/04 change bootloader size from 128 into 64
17 // 511241:linmars 2005/11/24 merge TaiChen's IRM patch
19 // copyright 2005 infineon
21 // copyright 2007 john crispin <blogic@openwrt.org>
22 // copyright 2007 felix fietkau <nbd@openwrt.org>
23 // copyright 2009 hauke mehrtens <hauke@hauke-m.de>
25 #include <linux/module.h>
26 #include <linux/types.h>
27 #include <linux/kernel.h>
30 #include <linux/init.h>
31 #include <linux/mtd/mtd.h>
32 #include <linux/mtd/map.h>
33 #include <linux/mtd/partitions.h>
34 #include <linux/mtd/cfi.h>
35 #include <linux/mutex.h>
36 #include <linux/platform_device.h>
37 #include <asm/amazon/amazon.h>
39 #define AMAZON_PCI_ARB_CTL_ALT 0xb100205c
40 #define AMAZON_MTD_REG32( addr ) (*(volatile u32 *)(addr))
43 static struct map_info amazon_map
= {
44 .name
= "AMAZON_FLASH",
48 static map_word
amazon_read16(struct map_info
* map
, unsigned long ofs
)
52 temp
.x
[0] = *((__u16
*) (map
->virt
+ ofs
));
56 static void amazon_write16(struct map_info
*map
, map_word d
, unsigned long adr
)
59 *((__u16
*) (map
->virt
+ adr
)) = d
.x
[0];
62 void amazon_copy_from(struct map_info
*map
, void *to
, unsigned long from
, ssize_t len
)
66 from
= (unsigned long) (from
+ map
->virt
);
74 void amazon_copy_to(struct map_info
*map
, unsigned long to
, const void *from
, ssize_t len
)
78 to
+= (unsigned long) map
->virt
;
85 #define UBOOT_SIZE 0x40000
87 static struct mtd_partition amazon_partitions
[3] = {
89 name
:"U-Boot", /* U-Boot firmware */
91 size
:UBOOT_SIZE
, /* 128k */
94 name
:"kernel", /* firmware */
96 size
:0x00100000, /* 192K */
99 name
:"rootfs", /* default partition */
105 unsigned long uImage_size
= 0x10000d;
107 int find_uImage_size(unsigned long start_offset
)
111 amazon_copy_from(&amazon_map
, &magic
, start_offset
, 4);
112 if (!(ntohl(magic
) == 0x27051956)) {
113 printk(KERN_INFO
"amazon_mtd: invalid magic (0x%08X) of kernel at 0x%08lx \n", ntohl(magic
), start_offset
);
116 amazon_copy_from(&amazon_map
, &temp
, start_offset
+ 12, 4);
117 printk(KERN_INFO
"amazon_mtd: kernel size is %ld \n", temp
+ 0x40);
121 static int __init
amazon_mtd_probe(struct platform_device
*dev
)
123 unsigned long uimage_size
;
124 struct mtd_info
*mymtd
= NULL
;
125 struct mtd_partition
*parts
= NULL
;
127 *AMAZON_EBU_BUSCON0
= 0x1d7ff;
129 amazon_map
.read
= amazon_read16
;
130 amazon_map
.write
= amazon_write16
;
131 amazon_map
.copy_from
= amazon_copy_from
;
132 amazon_map
.copy_to
= amazon_copy_to
;
134 amazon_map
.phys
= dev
->resource
->start
;
135 amazon_map
.size
= dev
->resource
->end
- amazon_map
.phys
+ 1;
136 amazon_map
.virt
= ioremap_nocache(amazon_map
.phys
, amazon_map
.size
);
138 if (!amazon_map
.virt
) {
139 printk(KERN_WARNING
"amazon_mtd: Failed to ioremap!\n");
143 mymtd
= (struct mtd_info
*) do_map_probe("cfi_probe", &amazon_map
);
145 iounmap(amazon_map
.virt
);
146 printk(KERN_WARNING
"amazon_mtd: probing failed\n");
150 mymtd
->owner
= THIS_MODULE
;
151 parts
= &amazon_partitions
[0];
153 /* Some Samsung devices are containing a 16 MB flash chip with a bigger U-Boot partition. */
154 if(mymtd
->size
== 0x01000000 && mymtd
->erasesize
== 0x00020000) {
155 printk(KERN_INFO
"amazon_mtd: Found big flash chip!\n");
156 amazon_partitions
[0].size
= 0x60000;
157 amazon_partitions
[1].offset
= 0x60000;
158 uimage_size
= find_uImage_size(amazon_partitions
[1].offset
);
159 amazon_partitions
[1].size
= uimage_size
;
160 amazon_partitions
[2].offset
= 0x60000 + uimage_size
;
161 amazon_partitions
[2].size
= mymtd
->size
- amazon_partitions
[2].offset
- mymtd
->erasesize
;
163 printk(KERN_INFO
"amazon_mtd: Found small flash chip!\n");
164 uimage_size
= find_uImage_size(amazon_partitions
[1].offset
);
165 amazon_partitions
[1].size
= uimage_size
;
166 amazon_partitions
[2].offset
= UBOOT_SIZE
+ uimage_size
;
167 amazon_partitions
[2].size
= mymtd
->size
- amazon_partitions
[2].offset
- (2 * mymtd
->erasesize
);
170 add_mtd_partitions(mymtd
, parts
, 3);
172 printk(KERN_INFO
"amazon_mtd: added %s flash with %dMB\n",
173 amazon_map
.name
, ((int)mymtd
->size
) >> 20);
177 static struct platform_driver amazon_mtd_driver
= {
178 .probe
= amazon_mtd_probe
,
180 .name
= "amazon_mtd",
181 .owner
= THIS_MODULE
,
185 static int __init
amazon_mtd_init(void)
187 int ret
= platform_driver_register(&amazon_mtd_driver
);
189 printk(KERN_WARNING
"amazon_mtd: error registering platfom driver!\n");
193 static void __exit
amazon_mtd_cleanup(void)
195 platform_driver_unregister(&amazon_mtd_driver
);
198 module_init(amazon_mtd_init
);
199 module_exit(amazon_mtd_cleanup
);
201 MODULE_LICENSE("GPL");
202 MODULE_AUTHOR("john crispin blogic@openwrt.org");
203 MODULE_DESCRIPTION("MTD map driver for AMAZON boards");