Commit 0b0dc113 authored by Tony Lindgren's avatar Tony Lindgren

MTD: OMAP: Add various OMAP drivers

Adds NOR and NAND drivers for OMAP.
Signed-off-by: default avatarTony Lindgren <tony@atomide.com>
parent 56023db1
...@@ -588,6 +588,15 @@ config MTD_MPC1211 ...@@ -588,6 +588,15 @@ config MTD_MPC1211
This enables access to the flash chips on the Interface MPC-1211(CTP/PCI/MPC-SH02). This enables access to the flash chips on the Interface MPC-1211(CTP/PCI/MPC-SH02).
If you have such a board, say 'Y'. If you have such a board, say 'Y'.
config MTD_OMAP_NOR
tristate "TI OMAP board mappings"
depends on MTD_CFI && ARCH_OMAP
help
This enables access to the NOR flash chips on TI OMAP-based
boards defining flash platform devices and flash platform data.
These boards include the Innovator, H2, H3, OSK, Perseus2, and
more. If you have such a board, say 'Y'.
# This needs CFI or JEDEC, depending on the cards found. # This needs CFI or JEDEC, depending on the cards found.
config MTD_PCI config MTD_PCI
tristate "PCI MTD driver" tristate "PCI MTD driver"
......
...@@ -71,3 +71,4 @@ obj-$(CONFIG_MTD_IXP2000) += ixp2000.o ...@@ -71,3 +71,4 @@ obj-$(CONFIG_MTD_IXP2000) += ixp2000.o
obj-$(CONFIG_MTD_WRSBC8260) += wr_sbc82xx_flash.o obj-$(CONFIG_MTD_WRSBC8260) += wr_sbc82xx_flash.o
obj-$(CONFIG_MTD_DMV182) += dmv182.o obj-$(CONFIG_MTD_DMV182) += dmv182.o
obj-$(CONFIG_MTD_SHARP_SL) += sharpsl-flash.o obj-$(CONFIG_MTD_SHARP_SL) += sharpsl-flash.o
obj-$(CONFIG_MTD_OMAP_NOR) += omap_nor.o
/*
* Flash memory support for various TI OMAP boards
*
* Copyright (C) 2001-2002 MontaVista Software Inc.
* Copyright (C) 2003-2004 Texas Instruments
* Copyright (C) 2004 Nokia Corporation
*
* Assembled using driver code copyright the companies above
* and written by David Brownell, Jian Zhang <jzhang@ti.com>,
* Tony Lindgren <tony@atomide.com> and others.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/device.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
#include <asm/mach/flash.h>
#include <asm/arch/tc.h>
#ifdef CONFIG_MTD_PARTITIONS
static const char *part_probes[] = { /* "RedBoot", */ "cmdlinepart", NULL };
#endif
struct omapflash_info {
struct mtd_partition *parts;
struct mtd_info *mtd;
struct map_info map;
};
static void omap_set_vpp(struct map_info *map, int enable)
{
static int count;
if (enable) {
if (count++ == 0)
OMAP_EMIFS_CONFIG_REG |= OMAP_EMIFS_CONFIG_WP;
} else {
if (count && (--count == 0))
OMAP_EMIFS_CONFIG_REG &= ~OMAP_EMIFS_CONFIG_WP;
}
}
static int __devinit omapflash_probe(struct device *dev)
{
int err;
struct omapflash_info *info;
struct platform_device *pdev = to_platform_device(dev);
struct flash_platform_data *pdata = pdev->dev.platform_data;
struct resource *res = pdev->resource;
unsigned long size = res->end - res->start + 1;
info = kmalloc(sizeof(struct omapflash_info), GFP_KERNEL);
if (!info)
return -ENOMEM;
memset(info, 0, sizeof(struct omapflash_info));
if (!request_mem_region(res->start, size, "flash")) {
err = -EBUSY;
goto out_free_info;
}
info->map.virt = ioremap(res->start, size);
if (!info->map.virt) {
err = -ENOMEM;
goto out_release_mem_region;
}
info->map.name = pdev->dev.bus_id;
info->map.phys = res->start;
info->map.size = size;
info->map.bankwidth = pdata->width;
info->map.set_vpp = omap_set_vpp;
simple_map_init(&info->map);
info->mtd = do_map_probe(pdata->map_name, &info->map);
if (!info->mtd) {
err = -EIO;
goto out_iounmap;
}
info->mtd->owner = THIS_MODULE;
#ifdef CONFIG_MTD_PARTITIONS
err = parse_mtd_partitions(info->mtd, part_probes, &info->parts, 0);
if (err > 0)
add_mtd_partitions(info->mtd, info->parts, err);
else if (err < 0 && pdata->parts)
add_mtd_partitions(info->mtd, pdata->parts, pdata->nr_parts);
else
#endif
add_mtd_device(info->mtd);
dev_set_drvdata(&pdev->dev, info);
return 0;
out_iounmap:
iounmap(info->map.virt);
out_release_mem_region:
release_mem_region(res->start, size);
out_free_info:
kfree(info);
return err;
}
static int __devexit omapflash_remove(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct omapflash_info *info = dev_get_drvdata(&pdev->dev);
dev_set_drvdata(&pdev->dev, NULL);
if (info) {
if (info->parts) {
del_mtd_partitions(info->mtd);
kfree(info->parts);
} else
del_mtd_device(info->mtd);
map_destroy(info->mtd);
release_mem_region(info->map.phys, info->map.size);
iounmap((void __iomem *) info->map.virt);
kfree(info);
}
return 0;
}
static struct device_driver omapflash_driver = {
.name = "omapflash",
.bus = &platform_bus_type,
.probe = omapflash_probe,
.remove = __devexit_p(omapflash_remove),
};
static int __init omapflash_init(void)
{
return driver_register(&omapflash_driver);
}
static void __exit omapflash_exit(void)
{
driver_unregister(&omapflash_driver);
}
module_init(omapflash_init);
module_exit(omapflash_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("MTD NOR map driver for TI OMAP boards");
...@@ -49,6 +49,12 @@ config MTD_NAND_SPIA ...@@ -49,6 +49,12 @@ config MTD_NAND_SPIA
help help
If you had to ask, you don't have one. Say 'N'. If you had to ask, you don't have one. Say 'N'.
config MTD_NAND_OMAP
tristate "NAND Flash device on OMAP H3/H2 board"
depends on ARM && ARCH_OMAP1 && MTD_NAND && (MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_NETSTAR)
help
Support for NAND flash on Texas Instruments H3/H2 platform.
config MTD_NAND_TOTO config MTD_NAND_TOTO
tristate "NAND Flash device on TOTO board" tristate "NAND Flash device on TOTO board"
depends on ARM && ARCH_OMAP && MTD_NAND depends on ARM && ARCH_OMAP && MTD_NAND
...@@ -203,5 +209,12 @@ config MTD_NAND_DISKONCHIP_BBTWRITE ...@@ -203,5 +209,12 @@ config MTD_NAND_DISKONCHIP_BBTWRITE
help help
The simulator may simulate verious NAND flash chips for the The simulator may simulate verious NAND flash chips for the
MTD nand layer. MTD nand layer.
config MTD_NAND_OMAP_HW
bool "OMAP HW NAND Flash controller support"
depends on ARM && ARCH_OMAP16XX && MTD_NAND
help
Driver for TI OMAP16xx hardware NAND flash controller.
endmenu endmenu
...@@ -20,5 +20,7 @@ obj-$(CONFIG_MTD_NAND_H1900) += h1910.o ...@@ -20,5 +20,7 @@ obj-$(CONFIG_MTD_NAND_H1900) += h1910.o
obj-$(CONFIG_MTD_NAND_RTC_FROM4) += rtc_from4.o obj-$(CONFIG_MTD_NAND_RTC_FROM4) += rtc_from4.o
obj-$(CONFIG_MTD_NAND_SHARPSL) += sharpsl.o obj-$(CONFIG_MTD_NAND_SHARPSL) += sharpsl.o
obj-$(CONFIG_MTD_NAND_NANDSIM) += nandsim.o obj-$(CONFIG_MTD_NAND_NANDSIM) += nandsim.o
obj-$(CONFIG_MTD_NAND_OMAP) += omap-nand-flash.o
obj-$(CONFIG_MTD_NAND_OMAP_HW) += omap-hw.o
nand-objs = nand_base.o nand_bbt.o nand-objs = nand_base.o nand_bbt.o
This diff is collapsed.
/*
* drivers/mtd/nand/omap-nand-flash.c
*
* Copyright (c) 2004 Texas Instruments
* Jian Zhang <jzhang@ti.com>
* Copyright (c) 2004 David Brownell
*
* Derived from drivers/mtd/autcpu12.c
*
* Copyright (c) 2002 Thomas Gleixner <tgxl@linutronix.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Overview:
* This is a device driver for the NAND flash device found on the
* TI H3/H2 boards. It supports 16-bit 32MiB Samsung k9f5616 chip.
*
*/
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
#include <asm/arch/hardware.h>
#include <asm/arch/gpio.h>
#include <asm/arch/mux.h>
#include <asm/arch/tc.h>
#include <asm/sizes.h>
#include <asm/mach-types.h>
#define H3_NAND_RB_GPIO_PIN 10
#define H2_NAND_RB_GPIO_PIN 62
#define NETSTAR_NAND_RB_GPIO_PIN 1
/*
* MTD structure for H3 board
*/
static struct mtd_info *omap_nand_mtd = NULL;
static void __iomem *omap_nand_flash_base;
/*
* Define partitions for flash devices
*/
#ifdef CONFIG_MTD_PARTITIONS
static struct mtd_partition static_partition[] = {
{ .name = "Booting Image",
.offset = 0,
.size = 64 * 1024,
.mask_flags = MTD_WRITEABLE /* force read-only */
},
{ .name = "U-Boot",
.offset = MTDPART_OFS_APPEND,
.size = 256 * 1024,
.mask_flags = MTD_WRITEABLE /* force read-only */
},
{ .name = "U-Boot Environment",
.offset = MTDPART_OFS_APPEND,
.size = 192 * 1024
},
{ .name = "Kernel",
.offset = MTDPART_OFS_APPEND,
.size = 2 * SZ_1M
},
{ .name = "File System",
.size = MTDPART_SIZ_FULL,
.offset = MTDPART_OFS_APPEND,
},
};
const char *part_probes[] = { "cmdlinepart", NULL, };
#endif
/* H2/H3 maps two address LSBs to CLE and ALE; MSBs make CS_2B */
#define MASK_CLE 0x02
#define MASK_ALE 0x04
/*
* hardware specific access to control-lines
*/
static void omap_nand_hwcontrol(struct mtd_info *mtd, int cmd)
{
struct nand_chip *this = mtd->priv;
u32 IO_ADDR_W = (u32) this->IO_ADDR_W;
IO_ADDR_W &= ~(MASK_ALE|MASK_CLE);
switch(cmd){
case NAND_CTL_SETCLE: IO_ADDR_W |= MASK_CLE; break;
case NAND_CTL_SETALE: IO_ADDR_W |= MASK_ALE; break;
}
this->IO_ADDR_W = (void __iomem *) IO_ADDR_W;
}
/*
* chip busy R/B detection
*/
static int omap_nand_ready(struct mtd_info *mtd)
{
if (machine_is_omap_h3())
return omap_get_gpio_datain(H3_NAND_RB_GPIO_PIN);
if (machine_is_omap_h2())
return omap_get_gpio_datain(H2_NAND_RB_GPIO_PIN);
if (machine_is_netstar())
return omap_get_gpio_datain(NETSTAR_NAND_RB_GPIO_PIN);
}
/* Scan to find existance of the device at omap_nand_flash_base.
This also allocates oob and data internal buffers */
static int probe_nand_chip(void)
{
struct nand_chip *this;
this = (struct nand_chip *) (&omap_nand_mtd[1]);
/* Initialize structures */
memset((char *) this, 0, sizeof(struct nand_chip));
this->IO_ADDR_R = omap_nand_flash_base;
this->IO_ADDR_W = omap_nand_flash_base;
this->options = NAND_SAMSUNG_LP_OPTIONS;
this->hwcontrol = omap_nand_hwcontrol;
this->eccmode = NAND_ECC_SOFT;
/* try 16-bit chip first */
this->options |= NAND_BUSWIDTH_16;
if (nand_scan (omap_nand_mtd, 1)) {
if (machine_is_omap_h3())
return -ENXIO;
/* then try 8-bit chip for H2 */
memset((char *) this, 0, sizeof(struct nand_chip));
this->IO_ADDR_R = omap_nand_flash_base;
this->IO_ADDR_W = omap_nand_flash_base;
this->options = NAND_SAMSUNG_LP_OPTIONS;
this->hwcontrol = omap_nand_hwcontrol;
this->eccmode = NAND_ECC_SOFT;
if (nand_scan (omap_nand_mtd, 1)) {
return -ENXIO;
}
}
return 0;
}
/*
* Main initialization routine
*/
int __init omap_nand_init (void)
{
struct nand_chip *this;
struct mtd_partition *dynamic_partition = 0;
int err = 0;
int nandboot = 0;
if (!(machine_is_omap_h2() || machine_is_omap_h3() || machine_is_netstar()))
return -ENODEV;
/* Allocate memory for MTD device structure and private data */
omap_nand_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip),
GFP_KERNEL);
if (!omap_nand_mtd) {
printk (KERN_WARNING "Unable to allocate NAND MTD device structure.\n");
err = -ENOMEM;
goto out;
}
/* Get pointer to private data */
this = (struct nand_chip *) (&omap_nand_mtd[1]);
/* Initialize structures */
memset((char *) omap_nand_mtd, 0, sizeof(struct mtd_info) + sizeof(struct nand_chip));
/* Link the private data with the MTD structure */
omap_nand_mtd->priv = this;
if (machine_is_omap_h2()) {
/* FIXME on H2, R/B needs M7_1610_GPIO62 ... */
this->chip_delay = 15;
omap_cfg_reg(L3_1610_FLASH_CS2B_OE);
omap_cfg_reg(M8_1610_FLASH_CS2B_WE);
} else if (machine_is_omap_h3()) {
if (omap_request_gpio(H3_NAND_RB_GPIO_PIN) != 0) {
printk(KERN_ERR "NAND: Unable to get GPIO pin for R/B, use delay\n");
/* 15 us command delay time */
this->chip_delay = 15;
} else {
/* GPIO10 for input. it is in GPIO1 module */
omap_set_gpio_direction(H3_NAND_RB_GPIO_PIN, 1);
/* GPIO10 Func_MUX_CTRL reg bit 29:27, Configure V2 to mode1 as GPIO */
/* GPIO10 pullup/down register, Enable pullup on GPIO10 */
omap_cfg_reg(V2_1710_GPIO10);
this->dev_ready = omap_nand_ready;
}
} else if (machine_is_netstar()) {
if (omap_request_gpio(NETSTAR_NAND_RB_GPIO_PIN) != 0) {
printk(KERN_ERR "NAND: Unable to get GPIO pin for R/B, use delay\n");
/* 15 us command delay time */
this->chip_delay = 15;
} else {
omap_set_gpio_direction(NETSTAR_NAND_RB_GPIO_PIN, 1);
this->dev_ready = omap_nand_ready;
}
}
/* try the first address */
omap_nand_flash_base = ioremap(OMAP_NAND_FLASH_START1, SZ_4K);
if (probe_nand_chip()){
nandboot = 1;
/* try the second address */
iounmap(omap_nand_flash_base);
omap_nand_flash_base = ioremap(OMAP_NAND_FLASH_START2, SZ_4K);
if (probe_nand_chip()){
iounmap(omap_nand_flash_base);
err = -ENXIO;
goto out_mtd;
}
}
/* Register the partitions */
switch(omap_nand_mtd->size) {
case SZ_128M:
if (!(machine_is_netstar()))
goto out_unsupported;
/* fall through */
case SZ_32M:
#ifdef CONFIG_MTD_PARTITIONS
err = parse_mtd_partitions(omap_nand_mtd, part_probes,
&dynamic_partition, 0);
if (err > 0)
err = add_mtd_partitions(omap_nand_mtd,
dynamic_partition, err);
else if (nandboot)
err = add_mtd_partitions(omap_nand_mtd,
static_partition,
ARRAY_SIZE(static_partition));
else
#endif
err = add_mtd_device(omap_nand_mtd);
if (err)
goto out_buf;
break;
out_unsupported:
default:
printk(KERN_WARNING "Unsupported NAND device\n");
err = -ENXIO;
goto out_buf;
}
goto out;
out_buf:
nand_release (omap_nand_mtd);
if (this->dev_ready) {
if (machine_is_omap_h2())
omap_free_gpio(H2_NAND_RB_GPIO_PIN);
else if (machine_is_omap_h3())
omap_free_gpio(H3_NAND_RB_GPIO_PIN);
else if (machine_is_netstar())
omap_free_gpio(NETSTAR_NAND_RB_GPIO_PIN);
}
iounmap(omap_nand_flash_base);
out_mtd:
kfree (omap_nand_mtd);
out:
return err;
}
module_init(omap_nand_init);
/*
* Clean up routine
*/
static void __exit omap_nand_cleanup (void)
{
struct nand_chip *this = omap_nand_mtd->priv;
if (this->dev_ready) {
if (machine_is_omap_h2())
omap_free_gpio(H2_NAND_RB_GPIO_PIN);
else if (machine_is_omap_h3())
omap_free_gpio(H3_NAND_RB_GPIO_PIN);
else if (machine_is_netstar())
omap_free_gpio(NETSTAR_NAND_RB_GPIO_PIN);
}
/* nand_release frees MTD partitions, MTD structure
and nand internal buffers*/
nand_release (omap_nand_mtd);
kfree (omap_nand_mtd);
iounmap(omap_nand_flash_base);
}
module_exit(omap_nand_cleanup);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jian Zhang <jzhang@ti.com>");
MODULE_DESCRIPTION("Glue layer for NAND flash on H2/H3 boards");
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment