source: branches/buildroot-ng/openwrt/target/linux/brcm-2.4/patches/004-flash.patch @ 4634

Last change on this file since 4634 was 4634, checked in by nbd, 10 years ago

don't try to create mtd partitions on bcm947xx when the trx header is not found - should fix #318

File size: 24.9 KB
  • drivers/mtd/devices/Config.in

    diff -urN linux.old/drivers/mtd/devices/Config.in linux.dev/drivers/mtd/devices/Config.in
    old new  
    55mainmenu_option next_comment 
    66 
    77comment 'Self-contained MTD device drivers' 
     8bool '  Broadcom Chipcommon Serial Flash support' CONFIG_MTD_SFLASH 
    89dep_tristate '  Ramix PMC551 PCI Mezzanine RAM card support' CONFIG_MTD_PMC551 $CONFIG_MTD $CONFIG_PCI 
    910if [ "$CONFIG_MTD_PMC551" = "y" -o  "$CONFIG_MTD_PMC551" = "m" ]; then 
    1011   bool '    PMC551 256M DRAM Bugfix' CONFIG_MTD_PMC551_BUGFIX 
  • drivers/mtd/devices/Makefile

    diff -urN linux.old/drivers/mtd/devices/Makefile linux.dev/drivers/mtd/devices/Makefile
    old new  
    33# 
    44# $Id: Makefile,v 1.4 2001/06/26 21:10:05 spse Exp $ 
    55 
     6EXTRA_CFLAGS := -I$(TOPDIR)/arch/mips/bcm947xx/include 
     7 
    68O_TARGET        := devlink.o 
    79 
    810#                       *** BIG UGLY NOTE *** 
     
    1214# here where previously there was none.  We now have to ensure that 
    1315# doc200[01].o are linked before docprobe.o 
    1416 
     17obj-$(CONFIG_MTD_SFLASH)        += sflash.o 
    1518obj-$(CONFIG_MTD_DOC1000)       += doc1000.o 
    1619obj-$(CONFIG_MTD_DOC2000)       += doc2000.o 
    1720obj-$(CONFIG_MTD_DOC2001)       += doc2001.o 
  • drivers/mtd/devices/sflash.c

    diff -urN linux.old/drivers/mtd/devices/sflash.c linux.dev/drivers/mtd/devices/sflash.c
    old new  
     1/* 
     2 * Broadcom SiliconBackplane chipcommon serial flash interface 
     3 * 
     4 * Copyright 2001-2003, Broadcom Corporation    
     5 * All Rights Reserved.    
     6 *     
     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.    
     11 * 
     12 * $Id: sflash.c,v 1.1.1.3 2003/11/10 17:43:38 hyin Exp $ 
     13 */ 
     14 
     15#include <linux/config.h> 
     16#include <linux/module.h> 
     17#include <linux/slab.h> 
     18#include <linux/ioport.h> 
     19#include <linux/mtd/compatmac.h> 
     20#include <linux/mtd/mtd.h> 
     21#include <linux/mtd/partitions.h> 
     22#include <linux/errno.h> 
     23#include <linux/pci.h> 
     24#include <linux/delay.h> 
     25#include <asm/io.h> 
     26 
     27#ifdef CONFIG_MTD_PARTITIONS 
     28#include <linux/mtd/mtd.h> 
     29#include <linux/mtd/partitions.h> 
     30#include <linux/minix_fs.h> 
     31#include <linux/ext2_fs.h> 
     32#include <linux/romfs_fs.h> 
     33#include <linux/cramfs_fs.h> 
     34#include <linux/jffs2.h> 
     35#endif 
     36 
     37#include <typedefs.h> 
     38#include <bcmdevs.h> 
     39#include <bcmutils.h> 
     40#include <osl.h> 
     41#include <bcmutils.h> 
     42#include <bcmnvram.h> 
     43#include <sbconfig.h> 
     44#include <sbchipc.h> 
     45#include <sflash.h> 
     46#include <trxhdr.h> 
     47 
     48#ifdef CONFIG_MTD_PARTITIONS 
     49extern struct mtd_partition * init_mtd_partitions(struct mtd_info *mtd, size_t size); 
     50#endif 
     51 
     52struct sflash_mtd { 
     53        chipcregs_t *cc; 
     54        struct semaphore lock; 
     55        struct mtd_info mtd; 
     56        struct mtd_erase_region_info regions[1]; 
     57}; 
     58 
     59/* Private global state */ 
     60static struct sflash_mtd sflash; 
     61 
     62static int 
     63sflash_mtd_poll(struct sflash_mtd *sflash, unsigned int offset, int timeout) 
     64{ 
     65        int now = jiffies; 
     66        int ret = 0; 
     67 
     68        for (;;) { 
     69                if (!sflash_poll(sflash->cc, offset)) { 
     70                        ret = 0; 
     71                        break; 
     72                } 
     73                if (time_after(jiffies, now + timeout)) { 
     74                        printk(KERN_ERR "sflash: timeout\n"); 
     75                        ret = -ETIMEDOUT; 
     76                        break; 
     77                } 
     78                if (current->need_resched) { 
     79                        set_current_state(TASK_UNINTERRUPTIBLE); 
     80                        schedule_timeout(timeout / 10); 
     81                } else 
     82                        udelay(1); 
     83        } 
     84 
     85        return ret; 
     86} 
     87 
     88static int 
     89sflash_mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) 
     90{ 
     91        struct sflash_mtd *sflash = (struct sflash_mtd *) mtd->priv; 
     92        int bytes, ret = 0; 
     93 
     94        /* Check address range */ 
     95        if (!len) 
     96                return 0; 
     97        if ((from + len) > mtd->size) 
     98                return -EINVAL; 
     99         
     100        down(&sflash->lock); 
     101 
     102        *retlen = 0; 
     103        while (len) { 
     104                if ((bytes = sflash_read(sflash->cc, (uint) from, len, buf)) < 0) { 
     105                        ret = bytes; 
     106                        break; 
     107                } 
     108                from += (loff_t) bytes; 
     109                len -= bytes; 
     110                buf += bytes; 
     111                *retlen += bytes; 
     112        } 
     113 
     114        up(&sflash->lock); 
     115 
     116        return ret; 
     117} 
     118 
     119static int 
     120sflash_mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) 
     121{ 
     122        struct sflash_mtd *sflash = (struct sflash_mtd *) mtd->priv; 
     123        int bytes, ret = 0; 
     124 
     125        /* Check address range */ 
     126        if (!len) 
     127                return 0; 
     128        if ((to + len) > mtd->size) 
     129                return -EINVAL; 
     130 
     131        down(&sflash->lock); 
     132 
     133        *retlen = 0; 
     134        while (len) { 
     135                if ((bytes = sflash_write(sflash->cc, (uint) to, len, buf)) < 0) { 
     136                        ret = bytes; 
     137                        break; 
     138                } 
     139                if ((ret = sflash_mtd_poll(sflash, (unsigned int) to, HZ / 10))) 
     140                        break; 
     141                to += (loff_t) bytes; 
     142                len -= bytes; 
     143                buf += bytes; 
     144                *retlen += bytes; 
     145        } 
     146 
     147        up(&sflash->lock); 
     148 
     149        return ret; 
     150} 
     151 
     152static int 
     153sflash_mtd_erase(struct mtd_info *mtd, struct erase_info *erase) 
     154{ 
     155        struct sflash_mtd *sflash = (struct sflash_mtd *) mtd->priv; 
     156        int i, j, ret = 0; 
     157        unsigned int addr, len; 
     158 
     159        /* Check address range */ 
     160        if (!erase->len) 
     161                return 0; 
     162        if ((erase->addr + erase->len) > mtd->size) 
     163                return -EINVAL; 
     164 
     165        addr = erase->addr; 
     166        len = erase->len; 
     167 
     168        down(&sflash->lock); 
     169 
     170        /* Ensure that requested region is aligned */ 
     171        for (i = 0; i < mtd->numeraseregions; i++) { 
     172                for (j = 0; j < mtd->eraseregions[i].numblocks; j++) { 
     173                        if (addr == mtd->eraseregions[i].offset + mtd->eraseregions[i].erasesize * j && 
     174                            len >= mtd->eraseregions[i].erasesize) { 
     175                                if ((ret = sflash_erase(sflash->cc, addr)) < 0) 
     176                                        break; 
     177                                if ((ret = sflash_mtd_poll(sflash, addr, 10 * HZ))) 
     178                                        break; 
     179                                addr += mtd->eraseregions[i].erasesize; 
     180                                len -= mtd->eraseregions[i].erasesize; 
     181                        } 
     182                } 
     183                if (ret) 
     184                        break; 
     185        } 
     186 
     187        up(&sflash->lock); 
     188 
     189        /* Set erase status */ 
     190        if (ret) 
     191                erase->state = MTD_ERASE_FAILED; 
     192        else  
     193                erase->state = MTD_ERASE_DONE; 
     194 
     195        /* Call erase callback */ 
     196        if (erase->callback) 
     197                erase->callback(erase); 
     198 
     199        return ret; 
     200} 
     201 
     202#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) 
     203#define sflash_mtd_init init_module 
     204#define sflash_mtd_exit cleanup_module 
     205#endif 
     206 
     207mod_init_t 
     208sflash_mtd_init(void) 
     209{ 
     210        struct pci_dev *pdev; 
     211        int ret = 0; 
     212        struct sflash *info; 
     213        uint bank, i; 
     214#ifdef CONFIG_MTD_PARTITIONS 
     215        struct mtd_partition *parts; 
     216#endif 
     217 
     218        if (!(pdev = pci_find_device(VENDOR_BROADCOM, SB_CC, NULL))) { 
     219                printk(KERN_ERR "sflash: chipcommon not found\n"); 
     220                return -ENODEV; 
     221        } 
     222 
     223        memset(&sflash, 0, sizeof(struct sflash_mtd)); 
     224        init_MUTEX(&sflash.lock); 
     225 
     226        /* Map registers and flash base */ 
     227        if (!(sflash.cc = ioremap_nocache(pci_resource_start(pdev, 0), 
     228                                          pci_resource_len(pdev, 0)))) { 
     229                printk(KERN_ERR "sflash: error mapping registers\n"); 
     230                ret = -EIO; 
     231                goto fail; 
     232        } 
     233 
     234        /* Initialize serial flash access */ 
     235        info = sflash_init(sflash.cc); 
     236 
     237        if (!info) { 
     238                printk(KERN_ERR "sflash: found no supported devices\n"); 
     239                ret = -ENODEV; 
     240                goto fail; 
     241        } 
     242 
     243        /* Setup banks */ 
     244        sflash.regions[0].offset = 0; 
     245        sflash.regions[0].erasesize = info->blocksize; 
     246        sflash.regions[0].numblocks = info->numblocks; 
     247        if (sflash.regions[0].erasesize > sflash.mtd.erasesize) 
     248                sflash.mtd.erasesize = sflash.regions[0].erasesize; 
     249        if (sflash.regions[0].erasesize * sflash.regions[0].numblocks) { 
     250                sflash.mtd.size += sflash.regions[0].erasesize * sflash.regions[0].numblocks; 
     251        } 
     252        sflash.mtd.numeraseregions = 1; 
     253        ASSERT(sflash.mtd.size == info->size); 
     254 
     255        /* Register with MTD */ 
     256        sflash.mtd.name = "sflash"; 
     257        sflash.mtd.type = MTD_NORFLASH; 
     258        sflash.mtd.flags = MTD_CAP_NORFLASH; 
     259        sflash.mtd.eraseregions = sflash.regions; 
     260        sflash.mtd.module = THIS_MODULE; 
     261        sflash.mtd.erase = sflash_mtd_erase; 
     262        sflash.mtd.read = sflash_mtd_read; 
     263        sflash.mtd.write = sflash_mtd_write; 
     264        sflash.mtd.priv = &sflash; 
     265 
     266#ifdef CONFIG_MTD_PARTITIONS 
     267        parts = init_mtd_partitions(&sflash.mtd, sflash.mtd.size); 
     268        for (i = 0; parts[i].name; i++); 
     269        ret = add_mtd_partitions(&sflash.mtd, parts, i); 
     270#else 
     271        ret = add_mtd_device(&sflash.mtd); 
     272#endif 
     273        if (ret) { 
     274                printk(KERN_ERR "sflash: add_mtd failed\n"); 
     275                goto fail; 
     276        } 
     277 
     278        return 0; 
     279 
     280 fail: 
     281        if (sflash.cc) 
     282                iounmap((void *) sflash.cc); 
     283        return ret; 
     284} 
     285 
     286mod_exit_t 
     287sflash_mtd_exit(void) 
     288{ 
     289#ifdef CONFIG_MTD_PARTITIONS 
     290        del_mtd_partitions(&sflash.mtd); 
     291#else 
     292        del_mtd_device(&sflash.mtd); 
     293#endif 
     294        iounmap((void *) sflash.cc); 
     295} 
     296 
     297module_init(sflash_mtd_init); 
     298module_exit(sflash_mtd_exit); 
  • drivers/mtd/maps/bcm947xx-flash.c

    diff -urN linux.old/drivers/mtd/maps/bcm947xx-flash.c linux.dev/drivers/mtd/maps/bcm947xx-flash.c
    old new  
     1/* 
     2 *  Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org> 
     3 *  Copyright (C) 2005 Waldemar Brodkorb <wbx@openwrt.org> 
     4 *  Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.org) 
     5 * 
     6 *  original functions for finding root filesystem from Mike Baker  
     7 * 
     8 *  This program is free software; you can redistribute  it and/or modify it 
     9 *  under  the terms of  the GNU General  Public License as published by the 
     10 *  Free Software Foundation;  either version 2 of the  License, or (at your 
     11 *  option) any later version. 
     12 * 
     13 *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED 
     14 *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF 
     15 *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN 
     16 *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT, 
     17 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
     18 *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF 
     19 *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
     20 *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT 
     21 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 
     22 *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
     23 * 
     24 *  You should have received a copy of the  GNU General Public License along 
     25 *  with this program; if not, write  to the Free Software Foundation, Inc., 
     26 *  675 Mass Ave, Cambridge, MA 02139, USA. 
     27 *  
     28 * 
     29 * Copyright 2004, Broadcom Corporation 
     30 * All Rights Reserved. 
     31 *  
     32 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY 
     33 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM 
     34 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS 
     35 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. 
     36 * 
     37 * Flash mapping for BCM947XX boards 
     38 * 
     39 */ 
     40 
     41#include <linux/module.h> 
     42#include <linux/types.h> 
     43#include <linux/kernel.h> 
     44#include <linux/wait.h> 
     45#include <linux/mtd/mtd.h> 
     46#include <linux/mtd/map.h> 
     47#ifdef CONFIG_MTD_PARTITIONS 
     48#include <linux/mtd/partitions.h> 
     49#endif 
     50#include <linux/config.h> 
     51#include <linux/squashfs_fs.h> 
     52#include <linux/jffs2.h> 
     53#include <linux/crc32.h> 
     54#include <asm/io.h> 
     55 
     56#include <typedefs.h> 
     57#include <osl.h> 
     58#include <bcmnvram.h> 
     59#include <bcmutils.h> 
     60#include <sbconfig.h> 
     61#include <sbchipc.h> 
     62#include <sbutils.h> 
     63#include <trxhdr.h> 
     64 
     65/* Global SB handle */ 
     66extern void *bcm947xx_sbh; 
     67extern spinlock_t bcm947xx_sbh_lock; 
     68 
     69/* Convenience */ 
     70#define sbh bcm947xx_sbh 
     71#define sbh_lock bcm947xx_sbh_lock 
     72 
     73#define WINDOW_ADDR 0x1fc00000 
     74#define WINDOW_SIZE 0x400000 
     75#define BUSWIDTH 2 
     76 
     77static struct mtd_info *bcm947xx_mtd; 
     78 
     79__u8 bcm947xx_map_read8(struct map_info *map, unsigned long ofs) 
     80{ 
     81        if (map->map_priv_2 == 1) 
     82                return __raw_readb(map->map_priv_1 + ofs); 
     83 
     84        u16 val = __raw_readw(map->map_priv_1 + (ofs & ~1)); 
     85        if (ofs & 1) 
     86                return ((val >> 8) & 0xff); 
     87        else 
     88                return (val & 0xff); 
     89} 
     90 
     91__u16 bcm947xx_map_read16(struct map_info *map, unsigned long ofs) 
     92{ 
     93        return __raw_readw(map->map_priv_1 + ofs); 
     94} 
     95 
     96__u32 bcm947xx_map_read32(struct map_info *map, unsigned long ofs) 
     97{ 
     98        return __raw_readl(map->map_priv_1 + ofs); 
     99} 
     100 
     101void bcm947xx_map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) 
     102{ 
     103        if (len==1) { 
     104                memcpy_fromio(to, map->map_priv_1 + from, len); 
     105        } else { 
     106                int i; 
     107                u16 *dest = (u16 *) to; 
     108                u16 *src  = (u16 *) (map->map_priv_1 + from); 
     109                for (i = 0; i < (len / 2); i++) { 
     110                        dest[i] = src[i]; 
     111                } 
     112                if (len & 1) 
     113                        *((u8 *)dest+len-1) = src[i] & 0xff; 
     114        } 
     115} 
     116 
     117void bcm947xx_map_write8(struct map_info *map, __u8 d, unsigned long adr) 
     118{ 
     119        __raw_writeb(d, map->map_priv_1 + adr); 
     120        mb(); 
     121} 
     122 
     123void bcm947xx_map_write16(struct map_info *map, __u16 d, unsigned long adr) 
     124{ 
     125        __raw_writew(d, map->map_priv_1 + adr); 
     126        mb(); 
     127} 
     128 
     129void bcm947xx_map_write32(struct map_info *map, __u32 d, unsigned long adr) 
     130{ 
     131        __raw_writel(d, map->map_priv_1 + adr); 
     132        mb(); 
     133} 
     134 
     135void bcm947xx_map_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) 
     136{ 
     137        memcpy_toio(map->map_priv_1 + to, from, len); 
     138} 
     139 
     140struct map_info bcm947xx_map = { 
     141        name: "Physically mapped flash", 
     142        size: WINDOW_SIZE, 
     143        buswidth: BUSWIDTH, 
     144        read8: bcm947xx_map_read8, 
     145        read16: bcm947xx_map_read16, 
     146        read32: bcm947xx_map_read32, 
     147        copy_from: bcm947xx_map_copy_from, 
     148        write8: bcm947xx_map_write8, 
     149        write16: bcm947xx_map_write16, 
     150        write32: bcm947xx_map_write32, 
     151        copy_to: bcm947xx_map_copy_to 
     152}; 
     153 
     154#ifdef CONFIG_MTD_PARTITIONS 
     155 
     156static struct mtd_partition bcm947xx_parts[] = { 
     157        { name: "cfe",  offset: 0, size: 0, mask_flags: MTD_WRITEABLE, }, 
     158        { name: "linux", offset: 0, size: 0, }, 
     159        { name: "rootfs", offset: 0, size: 0, }, 
     160        { name: "nvram", offset: 0, size: 0, }, 
     161        { name: "OpenWrt", offset: 0, size: 0, }, 
     162        { name: NULL, }, 
     163}; 
     164 
     165static int __init 
     166find_cfe_size(struct mtd_info *mtd, size_t size) 
     167{ 
     168        struct trx_header *trx; 
     169        unsigned char buf[512]; 
     170        int off; 
     171        size_t len; 
     172        int blocksize; 
     173 
     174        trx = (struct trx_header *) buf; 
     175 
     176        blocksize = mtd->erasesize; 
     177        if (blocksize < 0x10000) 
     178                blocksize = 0x10000; 
     179 
     180        for (off = (128*1024); off < size; off += blocksize) { 
     181                memset(buf, 0xe5, sizeof(buf)); 
     182 
     183                /* 
     184                 * Read into buffer  
     185                 */ 
     186                if (MTD_READ(mtd, off, sizeof(buf), &len, buf) || 
     187                    len != sizeof(buf)) 
     188                        continue; 
     189 
     190                /* found a TRX header */ 
     191                if (le32_to_cpu(trx->magic) == TRX_MAGIC) { 
     192                        goto found; 
     193                } 
     194        } 
     195 
     196        printk(KERN_NOTICE 
     197               "%s: Couldn't find bootloader size\n", 
     198               mtd->name); 
     199        return -1; 
     200 
     201 found: 
     202        printk(KERN_NOTICE "bootloader size: %d\n", off); 
     203        return off; 
     204 
     205} 
     206 
     207/* 
     208 * Copied from mtdblock.c 
     209 * 
     210 * Cache stuff... 
     211 *  
     212 * Since typical flash erasable sectors are much larger than what Linux's 
     213 * buffer cache can handle, we must implement read-modify-write on flash 
     214 * sectors for each block write requests.  To avoid over-erasing flash sectors 
     215 * and to speed things up, we locally cache a whole flash sector while it is 
     216 * being written to until a different sector is required. 
     217 */ 
     218 
     219static void erase_callback(struct erase_info *done) 
     220{ 
     221        wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv; 
     222        wake_up(wait_q); 
     223} 
     224 
     225static int erase_write (struct mtd_info *mtd, unsigned long pos,  
     226                        int len, const char *buf) 
     227{ 
     228        struct erase_info erase; 
     229        DECLARE_WAITQUEUE(wait, current); 
     230        wait_queue_head_t wait_q; 
     231        size_t retlen; 
     232        int ret; 
     233 
     234        /* 
     235         * First, let's erase the flash block. 
     236         */ 
     237 
     238        init_waitqueue_head(&wait_q); 
     239        erase.mtd = mtd; 
     240        erase.callback = erase_callback; 
     241        erase.addr = pos; 
     242        erase.len = len; 
     243        erase.priv = (u_long)&wait_q; 
     244 
     245        set_current_state(TASK_INTERRUPTIBLE); 
     246        add_wait_queue(&wait_q, &wait); 
     247 
     248        ret = MTD_ERASE(mtd, &erase); 
     249        if (ret) { 
     250                set_current_state(TASK_RUNNING); 
     251                remove_wait_queue(&wait_q, &wait); 
     252                printk (KERN_WARNING "erase of region [0x%lx, 0x%x] " 
     253                                     "on \"%s\" failed\n", 
     254                        pos, len, mtd->name); 
     255                return ret; 
     256        } 
     257 
     258        schedule();  /* Wait for erase to finish. */ 
     259        remove_wait_queue(&wait_q, &wait); 
     260 
     261        /* 
     262         * Next, writhe data to flash. 
     263         */ 
     264 
     265        ret = MTD_WRITE (mtd, pos, len, &retlen, buf); 
     266        if (ret) 
     267                return ret; 
     268        if (retlen != len) 
     269                return -EIO; 
     270        return 0; 
     271} 
     272 
     273 
     274 
     275 
     276static int __init 
     277find_root(struct mtd_info *mtd, size_t size, struct mtd_partition *part) 
     278{ 
     279        struct trx_header trx, *trx2; 
     280        unsigned char buf[512], *block; 
     281        int off, blocksize; 
     282        u32 i, crc = ~0; 
     283        size_t len; 
     284        struct squashfs_super_block *sb = (struct squashfs_super_block *) buf; 
     285 
     286        blocksize = mtd->erasesize; 
     287        if (blocksize < 0x10000) 
     288                blocksize = 0x10000; 
     289 
     290        for (off = (128*1024); off < size; off += blocksize) { 
     291                memset(&trx, 0xe5, sizeof(trx)); 
     292 
     293                /* 
     294                 * Read into buffer  
     295                 */ 
     296                if (MTD_READ(mtd, off, sizeof(trx), &len, (char *) &trx) || 
     297                    len != sizeof(trx)) 
     298                        continue; 
     299 
     300                /* found a TRX header */ 
     301                if (le32_to_cpu(trx.magic) == TRX_MAGIC) { 
     302                        part->offset = le32_to_cpu(trx.offsets[2]) ? :  
     303                                le32_to_cpu(trx.offsets[1]); 
     304                        part->size = le32_to_cpu(trx.len);  
     305 
     306                        part->size -= part->offset; 
     307                        part->offset += off; 
     308 
     309                        goto found; 
     310                } 
     311        } 
     312 
     313        printk(KERN_NOTICE 
     314               "%s: Couldn't find root filesystem\n", 
     315               mtd->name); 
     316        return -1; 
     317 
     318 found: 
     319        if (part->size == 0) 
     320                return 0; 
     321         
     322        if (MTD_READ(mtd, part->offset, sizeof(buf), &len, buf) || len != sizeof(buf)) 
     323                return 0; 
     324 
     325        if (*((__u32 *) buf) == SQUASHFS_MAGIC) { 
     326                printk(KERN_INFO "%s: Filesystem type: squashfs, size=0x%x\n", mtd->name, (u32) sb->bytes_used); 
     327 
     328                /* Update the squashfs partition size based on the superblock info */ 
     329                part->size = sb->bytes_used; 
     330                len = part->offset + part->size; 
     331                len +=  (mtd->erasesize - 1); 
     332                len &= ~(mtd->erasesize - 1); 
     333                part->size = len - part->offset; 
     334        } else if (*((__u16 *) buf) == JFFS2_MAGIC_BITMASK) { 
     335                printk(KERN_INFO "%s: Filesystem type: jffs2\n", mtd->name); 
     336 
     337                /* Move the squashfs outside of the trx */ 
     338                part->size = 0; 
     339        } else { 
     340                printk(KERN_INFO "%s: Filesystem type: unknown\n", mtd->name); 
     341                return 0; 
     342        } 
     343 
     344        if (trx.len != part->offset + part->size - off) { 
     345                /* Update the trx offsets and length */ 
     346                trx.len = part->offset + part->size - off; 
     347         
     348                /* Update the trx crc32 */ 
     349                for (i = (u32) &(((struct trx_header *)NULL)->flag_version); i <= trx.len; i += sizeof(buf)) { 
     350                        if (MTD_READ(mtd, off + i, sizeof(buf), &len, buf) || len != sizeof(buf)) 
     351                                return 0; 
     352                        crc = crc32_le(crc, buf, min(sizeof(buf), trx.len - i)); 
     353                } 
     354                trx.crc32 = crc; 
     355 
     356                /* read first eraseblock from the trx */ 
     357                trx2 = block = kmalloc(mtd->erasesize, GFP_KERNEL); 
     358                if (MTD_READ(mtd, off, mtd->erasesize, &len, block) || len != mtd->erasesize) { 
     359                        printk("Error accessing the first trx eraseblock\n"); 
     360                        return 0; 
     361                } 
     362                 
     363                printk("Updating TRX offsets and length:\n"); 
     364                printk("old trx = [0x%08x, 0x%08x, 0x%08x], len=0x%08x crc32=0x%08x\n", trx2->offsets[0], trx2->offsets[1], trx2->offsets[2], trx2->len, trx2->crc32); 
     365                printk("new trx = [0x%08x, 0x%08x, 0x%08x], len=0x%08x crc32=0x%08x\n",   trx.offsets[0],   trx.offsets[1],   trx.offsets[2],   trx.len, trx.crc32); 
     366 
     367                /* Write updated trx header to the flash */ 
     368                memcpy(block, &trx, sizeof(trx)); 
     369                if (mtd->unlock) 
     370                        mtd->unlock(mtd, off, mtd->erasesize); 
     371                erase_write(mtd, off, mtd->erasesize, block); 
     372                if (mtd->sync) 
     373                        mtd->sync(mtd); 
     374                kfree(block); 
     375                printk("Done\n"); 
     376        } 
     377         
     378        return part->size; 
     379} 
     380 
     381struct mtd_partition * __init 
     382init_mtd_partitions(struct mtd_info *mtd, size_t size) 
     383{ 
     384        int cfe_size; 
     385 
     386        if ((cfe_size = find_cfe_size(mtd,size)) < 0) 
     387                return NULL; 
     388 
     389        /* boot loader */ 
     390        bcm947xx_parts[0].offset = 0; 
     391        bcm947xx_parts[0].size   = cfe_size; 
     392 
     393        /* nvram */ 
     394        if (cfe_size != 384 * 1024) { 
     395                bcm947xx_parts[3].offset = size - ROUNDUP(NVRAM_SPACE, mtd->erasesize); 
     396                bcm947xx_parts[3].size   = ROUNDUP(NVRAM_SPACE, mtd->erasesize); 
     397        } else { 
     398                /* nvram (old 128kb config partition on netgear wgt634u) */ 
     399                bcm947xx_parts[3].offset = bcm947xx_parts[0].size; 
     400                bcm947xx_parts[3].size   = ROUNDUP(NVRAM_SPACE, mtd->erasesize); 
     401        } 
     402 
     403        /* linux (kernel and rootfs) */ 
     404        if (cfe_size != 384 * 1024) { 
     405                bcm947xx_parts[1].offset = bcm947xx_parts[0].size; 
     406                bcm947xx_parts[1].size   = bcm947xx_parts[3].offset -  
     407                        bcm947xx_parts[1].offset; 
     408        } else { 
     409                /* do not count the elf loader, which is on one block */ 
     410                bcm947xx_parts[1].offset = bcm947xx_parts[0].size +  
     411                        bcm947xx_parts[3].size + mtd->erasesize; 
     412                bcm947xx_parts[1].size   = size -  
     413                        bcm947xx_parts[0].size -  
     414                        (2*bcm947xx_parts[3].size) -  
     415                        mtd->erasesize; 
     416        } 
     417 
     418        /* find and size rootfs */ 
     419        if (find_root(mtd,size,&bcm947xx_parts[2])==0) { 
     420                /* entirely jffs2 */ 
     421                bcm947xx_parts[4].name = NULL; 
     422                bcm947xx_parts[2].size = size - bcm947xx_parts[2].offset -  
     423                                bcm947xx_parts[3].size; 
     424        } else { 
     425                /* legacy setup */ 
     426                /* calculate leftover flash, and assign it to the jffs2 partition */ 
     427                if (cfe_size != 384 * 1024) { 
     428                        bcm947xx_parts[4].offset = bcm947xx_parts[2].offset +  
     429                                bcm947xx_parts[2].size; 
     430                        if ((bcm947xx_parts[4].offset % mtd->erasesize) > 0) { 
     431                                bcm947xx_parts[4].offset += mtd->erasesize -  
     432                                        (bcm947xx_parts[4].offset % mtd->erasesize); 
     433                        } 
     434                        bcm947xx_parts[4].size = bcm947xx_parts[3].offset -  
     435                                bcm947xx_parts[4].offset; 
     436                } else { 
     437                        bcm947xx_parts[4].offset = bcm947xx_parts[2].offset +  
     438                                bcm947xx_parts[2].size; 
     439                        if ((bcm947xx_parts[4].offset % mtd->erasesize) > 0) { 
     440                                bcm947xx_parts[4].offset += mtd->erasesize -  
     441                                        (bcm947xx_parts[4].offset % mtd->erasesize); 
     442                        } 
     443                        bcm947xx_parts[4].size = size - bcm947xx_parts[3].size -  
     444                                bcm947xx_parts[4].offset; 
     445                } 
     446        } 
     447 
     448        return bcm947xx_parts; 
     449} 
     450 
     451#endif 
     452 
     453 
     454mod_init_t init_bcm947xx_map(void) 
     455{ 
     456        ulong flags; 
     457        uint coreidx; 
     458        chipcregs_t *cc; 
     459        uint32 fltype; 
     460        uint window_addr = 0, window_size = 0; 
     461        size_t size; 
     462        int ret = 0; 
     463#ifdef CONFIG_MTD_PARTITIONS 
     464        struct mtd_partition *parts; 
     465        int i; 
     466#endif 
     467 
     468        spin_lock_irqsave(&sbh_lock, flags); 
     469        coreidx = sb_coreidx(sbh); 
     470 
     471        /* Check strapping option if chipcommon exists */ 
     472        if ((cc = sb_setcore(sbh, SB_CC, 0))) { 
     473                fltype = readl(&cc->capabilities) & CAP_FLASH_MASK; 
     474                if (fltype == PFLASH) { 
     475                        bcm947xx_map.map_priv_2 = 1; 
     476                        window_addr = 0x1c000000; 
     477                        bcm947xx_map.size = window_size = 32 * 1024 * 1024; 
     478                        if ((readl(&cc->flash_config) & CC_CFG_DS) == 0) 
     479                                bcm947xx_map.buswidth = 1; 
     480                } 
     481        } else { 
     482                fltype = PFLASH; 
     483                bcm947xx_map.map_priv_2 = 0; 
     484                window_addr = WINDOW_ADDR; 
     485                window_size = WINDOW_SIZE; 
     486        } 
     487 
     488        sb_setcoreidx(sbh, coreidx); 
     489        spin_unlock_irqrestore(&sbh_lock, flags); 
     490 
     491        if (fltype != PFLASH) { 
     492                printk(KERN_ERR "pflash: found no supported devices\n"); 
     493                ret = -ENODEV; 
     494                goto fail; 
     495        } 
     496 
     497        bcm947xx_map.map_priv_1 = (unsigned long) ioremap(window_addr, window_size); 
     498 
     499        if (!bcm947xx_map.map_priv_1) { 
     500                printk(KERN_ERR "Failed to ioremap\n"); 
     501                return -EIO; 
     502        } 
     503 
     504        if (!(bcm947xx_mtd = do_map_probe("cfi_probe", &bcm947xx_map))) { 
     505                printk(KERN_ERR "pflash: cfi_probe failed\n"); 
     506                iounmap((void *)bcm947xx_map.map_priv_1); 
     507                return -ENXIO; 
     508        } 
     509 
     510        bcm947xx_mtd->module = THIS_MODULE; 
     511 
     512        size = bcm947xx_mtd->size; 
     513 
     514        printk(KERN_NOTICE "Flash device: 0x%x at 0x%x\n", size, window_addr); 
     515 
     516#ifdef CONFIG_MTD_PARTITIONS 
     517        parts = init_mtd_partitions(bcm947xx_mtd, size); 
     518        for (i = 0; parts[i].name; i++); 
     519        ret = add_mtd_partitions(bcm947xx_mtd, parts, i); 
     520        if (ret) { 
     521                printk(KERN_ERR "Flash: add_mtd_partitions failed\n"); 
     522                goto fail; 
     523        } 
     524#endif 
     525 
     526        return 0; 
     527 
     528 fail: 
     529        if (bcm947xx_mtd) 
     530                map_destroy(bcm947xx_mtd); 
     531        if (bcm947xx_map.map_priv_1) 
     532                iounmap((void *) bcm947xx_map.map_priv_1); 
     533        bcm947xx_map.map_priv_1 = 0; 
     534        return ret; 
     535} 
     536 
     537mod_exit_t cleanup_bcm947xx_map(void) 
     538{ 
     539#ifdef CONFIG_MTD_PARTITIONS 
     540        del_mtd_partitions(bcm947xx_mtd); 
     541#endif 
     542        map_destroy(bcm947xx_mtd); 
     543        iounmap((void *) bcm947xx_map.map_priv_1); 
     544        bcm947xx_map.map_priv_1 = 0; 
     545} 
     546 
     547module_init(init_bcm947xx_map); 
     548module_exit(cleanup_bcm947xx_map); 
  • drivers/mtd/maps/Config.in

    diff -urN linux.old/drivers/mtd/maps/Config.in linux.dev/drivers/mtd/maps/Config.in
    old new  
    4848fi 
    4949 
    5050if [ "$CONFIG_MIPS" = "y" ]; then 
     51   dep_tristate '  CFI Flash device mapped on Broadcom BCM947XX boards' CONFIG_MTD_BCM947XX $CONFIG_MTD_CFI 
    5152   dep_tristate '  Pb1000 MTD support' CONFIG_MTD_PB1000 $CONFIG_MIPS_PB1000 
    5253   dep_tristate '  Pb1500 MTD support' CONFIG_MTD_PB1500 $CONFIG_MIPS_PB1500 
    5354   dep_tristate '  Pb1100 MTD support' CONFIG_MTD_PB1100 $CONFIG_MIPS_PB1100 
  • drivers/mtd/maps/Makefile

    diff -urN linux.old/drivers/mtd/maps/Makefile linux.dev/drivers/mtd/maps/Makefile
    old new  
    33# 
    44# $Id: Makefile,v 1.37 2003/01/24 14:26:38 dwmw2 Exp $ 
    55 
     6EXTRA_CFLAGS := -I$(TOPDIR)/arch/mips/bcm947xx/include 
     7 
    68BELOW25         := $(shell echo $(PATCHLEVEL) | sed s/[1234]/y/) 
    79 
    810ifeq ($(BELOW25),y) 
     
    1012endif 
    1113 
    1214# Chip mappings 
     15obj-$(CONFIG_MTD_BCM947XX)      += bcm947xx-flash.o 
    1316obj-$(CONFIG_MTD_CDB89712)      += cdb89712.o 
    1417obj-$(CONFIG_MTD_ARM_INTEGRATOR)+= integrator-flash.o 
    1518obj-$(CONFIG_MTD_CFI_FLAGADM)   += cfi_flagadm.o 
Note: See TracBrowser for help on using the repository browser.