1/* 2 * drivers/mtd/nand/h1910.c 3 * 4 * Copyright (C) 2003 Joshua Wise (joshua@joshuawise.com) 5 * 6 * Derived from drivers/mtd/nand/edb7312.c 7 * Copyright (C) 2002 Marius Gr��ger (mag@sysgo.de) 8 * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) 9 * 10 * $Id: h1910.c,v 1.1.1.1 2007/08/03 18:52:44 Exp $ 11 * 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License version 2 as 14 * published by the Free Software Foundation. 15 * 16 * Overview: 17 * This is a device driver for the NAND flash device found on the 18 * iPAQ h1910 board which utilizes the Samsung K9F2808 part. This is 19 * a 128Mibit (16MiB x 8 bits) NAND flash device. 20 */ 21 22#include <linux/slab.h> 23#include <linux/init.h> 24#include <linux/module.h> 25#include <linux/mtd/mtd.h> 26#include <linux/mtd/nand.h> 27#include <linux/mtd/partitions.h> 28#include <asm/io.h> 29#include <asm/arch/hardware.h> /* for CLPS7111_VIRT_BASE */ 30#include <asm/sizes.h> 31#include <asm/arch/h1900-gpio.h> 32#include <asm/arch/ipaq.h> 33 34/* 35 * MTD structure for EDB7312 board 36 */ 37static struct mtd_info *h1910_nand_mtd = NULL; 38 39/* 40 * Module stuff 41 */ 42 43#ifdef CONFIG_MTD_PARTITIONS 44/* 45 * Define static partitions for flash device 46 */ 47static struct mtd_partition partition_info[] = { 48 {name:"h1910 NAND Flash", 49 offset:0, 50 size:16 * 1024 * 1024} 51}; 52 53#define NUM_PARTITIONS 1 54 55#endif 56 57/* 58 * hardware specific access to control-lines 59 * 60 * NAND_NCE: bit 0 - don't care 61 * NAND_CLE: bit 1 - address bit 2 62 * NAND_ALE: bit 2 - address bit 3 63 */ 64static void h1910_hwcontrol(struct mtd_info *mtd, int cmd, 65 unsigned int ctrl) 66{ 67 struct nand_chip *chip = mtd->priv; 68 69 if (cmd != NAND_CMD_NONE) 70 writeb(cmd, chip->IO_ADDR_W | ((ctrl & 0x6) << 1)); 71} 72 73/* 74 * read device ready pin 75 */ 76 77/* 78 * Main initialization routine 79 */ 80static int __init h1910_init(void) 81{ 82 struct nand_chip *this; 83 const char *part_type = 0; 84 int mtd_parts_nb = 0; 85 struct mtd_partition *mtd_parts = 0; 86 void __iomem *nandaddr; 87 88 if (!machine_is_h1900()) 89 return -ENODEV; 90 91 nandaddr = ioremap(0x08000000, 0x1000); 92 if (!nandaddr) { 93 printk("Failed to ioremap nand flash.\n"); 94 return -ENOMEM; 95 } 96 97 /* Allocate memory for MTD device structure and private data */ 98 h1910_nand_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL); 99 if (!h1910_nand_mtd) { 100 printk("Unable to allocate h1910 NAND MTD device structure.\n"); 101 iounmap((void *)nandaddr); 102 return -ENOMEM; 103 } 104 105 /* Get pointer to private data */ 106 this = (struct nand_chip *)(&h1910_nand_mtd[1]); 107 108 /* Initialize structures */ 109 memset(h1910_nand_mtd, 0, sizeof(struct mtd_info)); 110 memset(this, 0, sizeof(struct nand_chip)); 111 112 /* Link the private data with the MTD structure */ 113 h1910_nand_mtd->priv = this; 114 h1910_nand_mtd->owner = THIS_MODULE; 115 116 /* 117 * Enable VPEN 118 */ 119 GPSR(37) = GPIO_bit(37); 120 121 /* insert callbacks */ 122 this->IO_ADDR_R = nandaddr; 123 this->IO_ADDR_W = nandaddr; 124 this->cmd_ctrl = h1910_hwcontrol; 125 this->dev_ready = NULL; /* unknown whether that was correct or not so we will just do it like this */ 126 /* 15 us command delay time */ 127 this->chip_delay = 50; 128 this->ecc.mode = NAND_ECC_SOFT; 129 this->options = NAND_NO_AUTOINCR; 130 131 /* Scan to find existence of the device */ 132 if (nand_scan(h1910_nand_mtd, 1)) { 133 printk(KERN_NOTICE "No NAND device - returning -ENXIO\n"); 134 kfree(h1910_nand_mtd); 135 iounmap((void *)nandaddr); 136 return -ENXIO; 137 } 138#ifdef CONFIG_MTD_CMDLINE_PARTS 139 mtd_parts_nb = parse_cmdline_partitions(h1910_nand_mtd, &mtd_parts, "h1910-nand"); 140 if (mtd_parts_nb > 0) 141 part_type = "command line"; 142 else 143 mtd_parts_nb = 0; 144#endif 145 if (mtd_parts_nb == 0) { 146 mtd_parts = partition_info; 147 mtd_parts_nb = NUM_PARTITIONS; 148 part_type = "static"; 149 } 150 151 /* Register the partitions */ 152 printk(KERN_NOTICE "Using %s partition definition\n", part_type); 153 add_mtd_partitions(h1910_nand_mtd, mtd_parts, mtd_parts_nb); 154 155 /* Return happy */ 156 return 0; 157} 158 159module_init(h1910_init); 160 161/* 162 * Clean up routine 163 */ 164static void __exit h1910_cleanup(void) 165{ 166 struct nand_chip *this = (struct nand_chip *)&h1910_nand_mtd[1]; 167 168 /* Release resources, unregister device */ 169 nand_release(h1910_nand_mtd); 170 171 /* Release io resource */ 172 iounmap((void *)this->IO_ADDR_W); 173 174 /* Free the MTD device structure */ 175 kfree(h1910_nand_mtd); 176} 177 178module_exit(h1910_cleanup); 179 180MODULE_LICENSE("GPL"); 181MODULE_AUTHOR("Joshua Wise <joshua at joshuawise dot com>"); 182MODULE_DESCRIPTION("NAND flash driver for iPAQ h1910"); 183