2 * Flash mapping for BCM947XX boards
4 * Copyright 2004, Broadcom Corporation
7 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
8 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
9 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
10 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
15 #include <linux/module.h>
16 #include <linux/types.h>
17 #include <linux/kernel.h>
19 #include <linux/mtd/mtd.h>
20 #include <linux/mtd/map.h>
21 #include <linux/mtd/partitions.h>
22 #include <linux/config.h>
32 /* Global SB handle */
33 extern void *bcm947xx_sbh
;
34 extern spinlock_t bcm947xx_sbh_lock
;
37 #define sbh bcm947xx_sbh
38 #define sbh_lock bcm947xx_sbh_lock
40 #ifdef CONFIG_MTD_PARTITIONS
41 extern struct mtd_partition
* init_mtd_partitions(struct mtd_info
*mtd
, size_t size
);
44 #define WINDOW_ADDR 0x1fc00000
45 #define WINDOW_SIZE 0x400000
48 /* e.g., flash=2M or flash=4M */
50 MODULE_PARM(flash
, "i");
52 bcm947xx_setup(char *str
)
54 flash
= memparse(str
, &str
);
57 __setup("flash=", bcm947xx_setup
);
59 static struct mtd_info
*bcm947xx_mtd
;
61 __u8
bcm947xx_map_read8(struct map_info
*map
, unsigned long ofs
)
63 if (map
->map_priv_2
== 1)
64 return __raw_readb(map
->map_priv_1
+ ofs
);
66 u16 val
= __raw_readw(map
->map_priv_1
+ (ofs
& ~1));
68 return ((val
>> 8) & 0xff);
73 __u16
bcm947xx_map_read16(struct map_info
*map
, unsigned long ofs
)
75 return __raw_readw(map
->map_priv_1
+ ofs
);
78 __u32
bcm947xx_map_read32(struct map_info
*map
, unsigned long ofs
)
80 return __raw_readl(map
->map_priv_1
+ ofs
);
83 void bcm947xx_map_copy_from(struct map_info
*map
, void *to
, unsigned long from
, ssize_t len
)
86 memcpy_fromio(to
, map
->map_priv_1
+ from
, len
);
89 u16
*dest
= (u16
*) to
;
90 u16
*src
= (u16
*) (map
->map_priv_1
+ from
);
91 for (i
= 0; i
< (len
/ 2); i
++) {
95 *((u8
*)dest
+len
-1) = src
[i
] & 0xff;
99 void bcm947xx_map_write8(struct map_info
*map
, __u8 d
, unsigned long adr
)
101 __raw_writeb(d
, map
->map_priv_1
+ adr
);
105 void bcm947xx_map_write16(struct map_info
*map
, __u16 d
, unsigned long adr
)
107 __raw_writew(d
, map
->map_priv_1
+ adr
);
111 void bcm947xx_map_write32(struct map_info
*map
, __u32 d
, unsigned long adr
)
113 __raw_writel(d
, map
->map_priv_1
+ adr
);
117 void bcm947xx_map_copy_to(struct map_info
*map
, unsigned long to
, const void *from
, ssize_t len
)
119 memcpy_toio(map
->map_priv_1
+ to
, from
, len
);
122 struct map_info bcm947xx_map
= {
123 name
: "Physically mapped flash",
126 read8
: bcm947xx_map_read8
,
127 read16
: bcm947xx_map_read16
,
128 read32
: bcm947xx_map_read32
,
129 copy_from
: bcm947xx_map_copy_from
,
130 write8
: bcm947xx_map_write8
,
131 write16
: bcm947xx_map_write16
,
132 write32
: bcm947xx_map_write32
,
133 copy_to
: bcm947xx_map_copy_to
136 #if LINUX_VERSION_CODE < 0x20212 && defined(MODULE)
137 #define init_bcm947xx_map init_module
138 #define cleanup_bcm947xx_map cleanup_module
141 mod_init_t
init_bcm947xx_map(void)
147 uint window_addr
= 0, window_size
= 0;
150 #ifdef CONFIG_MTD_PARTITIONS
151 struct mtd_partition
*parts
;
155 spin_lock_irqsave(&sbh_lock
, flags
);
156 coreidx
= sb_coreidx(sbh
);
158 /* Check strapping option if chipcommon exists */
159 if ((cc
= sb_setcore(sbh
, SB_CC
, 0))) {
160 fltype
= readl(&cc
->capabilities
) & CAP_FLASH_MASK
;
161 if (fltype
== PFLASH
) {
162 bcm947xx_map
.map_priv_2
= 1;
163 window_addr
= 0x1c000000;
164 bcm947xx_map
.size
= window_size
= 32 * 1024 * 1024;
165 if ((readl(&cc
->flash_config
) & CC_CFG_DS
) == 0)
166 bcm947xx_map
.buswidth
= 1;
170 bcm947xx_map
.map_priv_2
= 0;
171 window_addr
= WINDOW_ADDR
;
172 window_size
= WINDOW_SIZE
;
175 sb_setcoreidx(sbh
, coreidx
);
176 spin_unlock_irqrestore(&sbh_lock
, flags
);
178 if (fltype
!= PFLASH
) {
179 printk(KERN_ERR
"pflash: found no supported devices\n");
184 bcm947xx_map
.map_priv_1
= (unsigned long) ioremap(window_addr
, window_size
);
185 if (!bcm947xx_map
.map_priv_1
) {
186 printk(KERN_ERR
"pflash: ioremap failed\n");
191 if (!(bcm947xx_mtd
= do_map_probe("cfi_probe", &bcm947xx_map
))) {
192 printk(KERN_ERR
"pflash: cfi_probe failed\n");
197 bcm947xx_mtd
->module
= THIS_MODULE
;
199 /* Allow size override for testing */
200 size
= flash
? : bcm947xx_mtd
->size
;
202 printk(KERN_NOTICE
"Flash device: 0x%x at 0x%x\n", size
, window_addr
);
204 #ifdef CONFIG_MTD_PARTITIONS
205 parts
= init_mtd_partitions(bcm947xx_mtd
, size
);
206 for (i
= 0; parts
[i
].name
; i
++);
207 ret
= add_mtd_partitions(bcm947xx_mtd
, parts
, i
);
209 printk(KERN_ERR
"pflash: add_mtd_partitions failed\n");
218 map_destroy(bcm947xx_mtd
);
219 if (bcm947xx_map
.map_priv_1
)
220 iounmap((void *) bcm947xx_map
.map_priv_1
);
221 bcm947xx_map
.map_priv_1
= 0;
225 mod_exit_t
cleanup_bcm947xx_map(void)
227 #ifdef CONFIG_MTD_PARTITIONS
228 del_mtd_partitions(bcm947xx_mtd
);
230 map_destroy(bcm947xx_mtd
);
231 iounmap((void *) bcm947xx_map
.map_priv_1
);
232 bcm947xx_map
.map_priv_1
= 0;
235 module_init(init_bcm947xx_map
);
236 module_exit(cleanup_bcm947xx_map
);