linux/drivers/mtd/maps/omap_nor.c
<<
>>
Prefs
   1/*
   2 * Flash memory support for various TI OMAP boards
   3 *
   4 * Copyright (C) 2001-2002 MontaVista Software Inc.
   5 * Copyright (C) 2003-2004 Texas Instruments
   6 * Copyright (C) 2004 Nokia Corporation
   7 *
   8 *      Assembled using driver code copyright the companies above
   9 *      and written by David Brownell, Jian Zhang <jzhang@ti.com>,
  10 *      Tony Lindgren <tony@atomide.com> and others.
  11 *
  12 * This program is free software; you can redistribute it and/or modify it
  13 * under the terms of the GNU General Public License as published by the
  14 * Free Software Foundation; either version 2 of the License, or (at your
  15 * option) any later version.
  16 *
  17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
  20 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  23 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  24 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27 *
  28 * You should have received a copy of the  GNU General Public License along
  29 * with this program; if not, write  to the Free Software Foundation, Inc.,
  30 * 675 Mass Ave, Cambridge, MA 02139, USA.
  31 */
  32
  33#include <linux/platform_device.h>
  34#include <linux/module.h>
  35#include <linux/types.h>
  36#include <linux/kernel.h>
  37#include <linux/init.h>
  38#include <linux/ioport.h>
  39#include <linux/slab.h>
  40
  41#include <linux/mtd/mtd.h>
  42#include <linux/mtd/map.h>
  43#include <linux/mtd/partitions.h>
  44
  45#include <asm/io.h>
  46#include <mach/hardware.h>
  47#include <asm/mach/flash.h>
  48#include <mach/tc.h>
  49
  50#ifdef CONFIG_MTD_PARTITIONS
  51static const char *part_probes[] = { /* "RedBoot", */ "cmdlinepart", NULL };
  52#endif
  53
  54struct omapflash_info {
  55        struct mtd_partition    *parts;
  56        struct mtd_info         *mtd;
  57        struct map_info         map;
  58};
  59
  60static void omap_set_vpp(struct map_info *map, int enable)
  61{
  62        static int      count;
  63        u32 l;
  64
  65        if (cpu_class_is_omap1()) {
  66                if (enable) {
  67                        if (count++ == 0) {
  68                                l = omap_readl(EMIFS_CONFIG);
  69                                l |= OMAP_EMIFS_CONFIG_WP;
  70                                omap_writel(l, EMIFS_CONFIG);
  71                        }
  72                } else {
  73                        if (count && (--count == 0)) {
  74                                l = omap_readl(EMIFS_CONFIG);
  75                                l &= ~OMAP_EMIFS_CONFIG_WP;
  76                                omap_writel(l, EMIFS_CONFIG);
  77                        }
  78                }
  79        }
  80}
  81
  82static int __init omapflash_probe(struct platform_device *pdev)
  83{
  84        int err;
  85        struct omapflash_info *info;
  86        struct flash_platform_data *pdata = pdev->dev.platform_data;
  87        struct resource *res = pdev->resource;
  88        unsigned long size = res->end - res->start + 1;
  89
  90        info = kzalloc(sizeof(struct omapflash_info), GFP_KERNEL);
  91        if (!info)
  92                return -ENOMEM;
  93
  94        if (!request_mem_region(res->start, size, "flash")) {
  95                err = -EBUSY;
  96                goto out_free_info;
  97        }
  98
  99        info->map.virt          = ioremap(res->start, size);
 100        if (!info->map.virt) {
 101                err = -ENOMEM;
 102                goto out_release_mem_region;
 103        }
 104        info->map.name          = dev_name(&pdev->dev);
 105        info->map.phys          = res->start;
 106        info->map.size          = size;
 107        info->map.bankwidth     = pdata->width;
 108        info->map.set_vpp       = omap_set_vpp;
 109
 110        simple_map_init(&info->map);
 111        info->mtd = do_map_probe(pdata->map_name, &info->map);
 112        if (!info->mtd) {
 113                err = -EIO;
 114                goto out_iounmap;
 115        }
 116        info->mtd->owner = THIS_MODULE;
 117
 118        info->mtd->dev.parent = &pdev->dev;
 119
 120#ifdef CONFIG_MTD_PARTITIONS
 121        err = parse_mtd_partitions(info->mtd, part_probes, &info->parts, 0);
 122        if (err > 0)
 123                add_mtd_partitions(info->mtd, info->parts, err);
 124        else if (err <= 0 && pdata->parts)
 125                add_mtd_partitions(info->mtd, pdata->parts, pdata->nr_parts);
 126        else
 127#endif
 128                add_mtd_device(info->mtd);
 129
 130        platform_set_drvdata(pdev, info);
 131
 132        return 0;
 133
 134out_iounmap:
 135        iounmap(info->map.virt);
 136out_release_mem_region:
 137        release_mem_region(res->start, size);
 138out_free_info:
 139        kfree(info);
 140
 141        return err;
 142}
 143
 144static int __exit omapflash_remove(struct platform_device *pdev)
 145{
 146        struct omapflash_info *info = platform_get_drvdata(pdev);
 147
 148        platform_set_drvdata(pdev, NULL);
 149
 150        if (info) {
 151                if (info->parts) {
 152                        del_mtd_partitions(info->mtd);
 153                        kfree(info->parts);
 154                } else
 155                        del_mtd_device(info->mtd);
 156                map_destroy(info->mtd);
 157                release_mem_region(info->map.phys, info->map.size);
 158                iounmap((void __iomem *) info->map.virt);
 159                kfree(info);
 160        }
 161
 162        return 0;
 163}
 164
 165static struct platform_driver omapflash_driver = {
 166        .remove = __exit_p(omapflash_remove),
 167        .driver = {
 168                .name   = "omapflash",
 169                .owner  = THIS_MODULE,
 170        },
 171};
 172
 173static int __init omapflash_init(void)
 174{
 175        return platform_driver_probe(&omapflash_driver, omapflash_probe);
 176}
 177
 178static void __exit omapflash_exit(void)
 179{
 180        platform_driver_unregister(&omapflash_driver);
 181}
 182
 183module_init(omapflash_init);
 184module_exit(omapflash_exit);
 185
 186MODULE_LICENSE("GPL");
 187MODULE_DESCRIPTION("MTD NOR map driver for TI OMAP boards");
 188MODULE_ALIAS("platform:omapflash");
 189