1/* 2 * Flash mapping for BCM947XX boards 3 * 4 * Copyright (C) 2010, Broadcom Corporation. All Rights Reserved. 5 * 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. 9 * 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. 17 * 18 * $Id: bcm947xx-flash.c,v 1.6 2009-07-27 07:34:33 Exp $ 19 */ 20 21#include <linux/module.h> 22#include <linux/types.h> 23#include <linux/kernel.h> 24#include <linux/init.h> 25#include <asm/io.h> 26#include <linux/mtd/mtd.h> 27#include <linux/mtd/map.h> 28#include <linux/mtd/partitions.h> 29#include <linux/config.h> 30 31#include <typedefs.h> 32#include <bcmnvram.h> 33#include <bcmutils.h> 34#include <hndsoc.h> 35#include <sbchipc.h> 36#include <siutils.h> 37#include <trxhdr.h> 38 39/* Global SB handle */ 40extern void *bcm947xx_sih; 41extern spinlock_t bcm947xx_sih_lock; 42 43/* Convenience */ 44#define sih bcm947xx_sih 45#define sih_lock bcm947xx_sih_lock 46 47#ifdef CONFIG_MTD_PARTITIONS 48extern struct mtd_partition * init_mtd_partitions(struct mtd_info *mtd, size_t size); 49#endif 50 51#define WINDOW_ADDR 0x1fc00000 52#define WINDOW_SIZE 0x400000 53#define BUSWIDTH 2 54 55/* e.g., flash=2M or flash=4M */ 56static int flash = 0; 57module_param(flash, int, 0); 58static int __init 59bcm947xx_setup(char *str) 60{ 61 flash = memparse(str, &str); 62 return 1; 63} 64__setup("flash=", bcm947xx_setup); 65 66static struct mtd_info *bcm947xx_mtd; 67 68 69#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) 70#define init_bcm947xx_map init_module 71#define cleanup_bcm947xx_map cleanup_module 72#endif 73 74struct map_info bcm947xx_map = { 75 .name = "Physically mapped flash", 76 .size = WINDOW_SIZE, 77 .bankwidth = BUSWIDTH 78}; 79 80static int __init 81init_bcm947xx_map(void) 82{ 83 ulong flags; 84 uint coreidx; 85 chipcregs_t *cc; 86 uint32 fltype; 87 uint window_addr = 0, window_size = 0; 88 size_t size; 89 int ret = 0; 90#ifdef CONFIG_MTD_PARTITIONS 91 struct mtd_partition *parts; 92 int i; 93#endif 94 95 spin_lock_irqsave(&sih_lock, flags); 96 coreidx = si_coreidx(sih); 97 98 /* Check strapping option if chipcommon exists */ 99 if ((cc = si_setcore(sih, CC_CORE_ID, 0))) { 100 fltype = readl(&cc->capabilities) & CC_CAP_FLASH_MASK; 101 if (fltype == PFLASH) { 102 bcm947xx_map.map_priv_2 = 1; 103 window_addr = 0x1c000000; 104 bcm947xx_map.size = window_size = 32 * 1024 * 1024; 105 if ((readl(&cc->flash_config) & CC_CFG_DS) == 0) 106 bcm947xx_map.bankwidth = 1; 107 } 108 } else { 109 fltype = PFLASH; 110 bcm947xx_map.map_priv_2 = 0; 111 window_addr = WINDOW_ADDR; 112 bcm947xx_map.size = window_size = WINDOW_SIZE; 113 } 114 115 si_setcoreidx(sih, coreidx); 116 spin_unlock_irqrestore(&sih_lock, flags); 117 118 if (fltype != PFLASH) { 119 printk(KERN_ERR "pflash: found no supported devices\n"); 120 ret = -ENODEV; 121 goto fail; 122 } 123 124 bcm947xx_map.virt = ioremap(window_addr, window_size); 125 if (bcm947xx_map.virt == NULL) { 126 printk(KERN_ERR "pflash: ioremap failed\n"); 127 ret = -EIO; 128 goto fail; 129 } 130 131 if ((bcm947xx_mtd = do_map_probe("cfi_probe", &bcm947xx_map)) == NULL) { 132 printk(KERN_ERR "pflash: cfi_probe failed\n"); 133 ret = -ENXIO; 134 goto fail; 135 } 136 137 bcm947xx_mtd->owner = THIS_MODULE; 138 bcm947xx_mtd->mutex = partitions_mutex_init(); 139 140 /* Allow size override for testing */ 141 size = flash ? : bcm947xx_mtd->size; 142 143 printk(KERN_NOTICE "Flash device: 0x%x at 0x%x\n", size, window_addr); 144 145#ifdef CONFIG_MTD_PARTITIONS 146 parts = init_mtd_partitions(bcm947xx_mtd, size); 147 for (i = 0; parts[i].name; i++); 148 ret = add_mtd_partitions(bcm947xx_mtd, parts, i); 149 if (ret) { 150 printk(KERN_ERR "pflash: add_mtd_partitions failed\n"); 151 goto fail; 152 } 153#endif 154 155 return 0; 156 157 fail: 158 if (bcm947xx_mtd) 159 map_destroy(bcm947xx_mtd); 160 if (bcm947xx_map.map_priv_1) 161 iounmap((void *) bcm947xx_map.map_priv_1); 162 bcm947xx_map.map_priv_1 = 0; 163 return ret; 164} 165 166static void __exit 167cleanup_bcm947xx_map(void) 168{ 169#ifdef CONFIG_MTD_PARTITIONS 170 del_mtd_partitions(bcm947xx_mtd); 171#endif 172 map_destroy(bcm947xx_mtd); 173 iounmap((void *) bcm947xx_map.map_priv_1); 174 bcm947xx_map.map_priv_1 = 0; 175} 176 177module_init(init_bcm947xx_map); 178module_exit(cleanup_bcm947xx_map); 179