2 * Flash mapping for BCM947XX boards
4 * Copyright (C) 2012, Broadcom Corporation. All Rights Reserved.
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 * $Id: bcm947xx-flash.c,v 1.6 2009-07-27 07:34:33 $
21 #include <linux/version.h>
22 #include <linux/module.h>
23 #include <linux/types.h>
24 #include <linux/kernel.h>
25 #include <linux/init.h>
27 #include <linux/mtd/mtd.h>
28 #include <linux/mtd/map.h>
29 #include <linux/mtd/partitions.h>
31 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
32 #include <linux/config.h>
43 /* Global SB handle */
44 extern void *bcm947xx_sih
;
45 extern spinlock_t bcm947xx_sih_lock
;
48 #define sih bcm947xx_sih
49 #define sih_lock bcm947xx_sih_lock
51 #ifdef CONFIG_MTD_PARTITIONS
52 extern struct mtd_partition
* init_mtd_partitions(struct mtd_info
*mtd
, size_t size
);
55 #define WINDOW_ADDR 0x1fc00000
56 #define WINDOW_SIZE 0x400000
59 /* e.g., flash=2M or flash=4M */
61 module_param(flash
, int, 0);
63 bcm947xx_setup(char *str
)
65 flash
= memparse(str
, &str
);
68 __setup("flash=", bcm947xx_setup
);
70 static struct mtd_info
*bcm947xx_mtd
;
73 #if LINUX_VERSION_CODE < 0x20212 && defined(MODULE)
74 #define init_bcm947xx_map init_module
75 #define cleanup_bcm947xx_map cleanup_module
78 struct map_info bcm947xx_map
= {
79 .name
= "Physically mapped flash",
85 init_bcm947xx_map(void)
91 uint window_addr
= 0, window_size
= 0;
94 #ifdef CONFIG_MTD_PARTITIONS
95 struct mtd_partition
*parts
;
99 spin_lock_irqsave(&sih_lock
, flags
);
100 coreidx
= si_coreidx(sih
);
102 /* Check strapping option if chipcommon exists */
103 if ((cc
= si_setcore(sih
, CC_CORE_ID
, 0))) {
104 fltype
= readl(&cc
->capabilities
) & CC_CAP_FLASH_MASK
;
105 if (fltype
== PFLASH
) {
106 bcm947xx_map
.map_priv_2
= 1;
107 window_addr
= 0x1c000000;
108 bcm947xx_map
.size
= window_size
= 32 * 1024 * 1024;
109 if ((readl(&cc
->flash_config
) & CC_CFG_DS
) == 0)
110 bcm947xx_map
.bankwidth
= 1;
114 bcm947xx_map
.map_priv_2
= 0;
115 window_addr
= WINDOW_ADDR
;
116 bcm947xx_map
.size
= window_size
= WINDOW_SIZE
;
119 si_setcoreidx(sih
, coreidx
);
120 spin_unlock_irqrestore(&sih_lock
, flags
);
122 if (fltype
!= PFLASH
) {
123 printk(KERN_ERR
"pflash: found no supported devices\n");
128 bcm947xx_map
.virt
= ioremap(window_addr
, window_size
);
129 if (bcm947xx_map
.virt
== NULL
) {
130 printk(KERN_ERR
"pflash: ioremap failed\n");
135 if ((bcm947xx_mtd
= do_map_probe("cfi_probe", &bcm947xx_map
)) == NULL
) {
136 printk(KERN_ERR
"pflash: cfi_probe failed\n");
141 bcm947xx_mtd
->owner
= THIS_MODULE
;
143 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
144 bcm947xx_mtd
->mutex
= partitions_mutex_init();
146 /* The mutex does not seem to be needed anymore */
149 /* Allow size override for testing */
150 size
= flash
? : bcm947xx_mtd
->size
;
152 printk(KERN_NOTICE
"Flash device: 0x%x at 0x%x\n", size
, window_addr
);
154 #ifdef CONFIG_MTD_PARTITIONS
155 parts
= init_mtd_partitions(bcm947xx_mtd
, size
);
156 for (i
= 0; parts
[i
].name
; i
++);
157 ret
= add_mtd_partitions(bcm947xx_mtd
, parts
, i
);
159 printk(KERN_ERR
"pflash: add_mtd_partitions failed\n");
168 map_destroy(bcm947xx_mtd
);
169 if (bcm947xx_map
.map_priv_1
)
170 iounmap((void *) bcm947xx_map
.map_priv_1
);
171 bcm947xx_map
.map_priv_1
= 0;
176 cleanup_bcm947xx_map(void)
178 #ifdef CONFIG_MTD_PARTITIONS
179 del_mtd_partitions(bcm947xx_mtd
);
181 map_destroy(bcm947xx_mtd
);
182 iounmap((void *) bcm947xx_map
.map_priv_1
);
183 bcm947xx_map
.map_priv_1
= 0;
186 module_init(init_bcm947xx_map
);
187 module_exit(cleanup_bcm947xx_map
);