1/* 2* Copyright (C) 2005 - 2007 by Basler Vision Technologies AG 3* Author: Thomas Koeller <thomas.koeller.qbaslerweb.com> 4* Original code by Thies Moeller <thies.moeller@baslerweb.com> 5* 6* This program is free software; you can redistribute it and/or modify 7* it under the terms of the GNU General Public License as published by 8* the Free Software Foundation; either version 2 of the License, or 9* (at your option) any later version. 10* 11* This program is distributed in the hope that it will be useful, 12* but WITHOUT ANY WARRANTY; without even the implied warranty of 13* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14* GNU General Public License for more details. 15* 16* You should have received a copy of the GNU General Public License 17* along with this program; if not, write to the Free Software 18* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19*/ 20 21#include <linux/module.h> 22#include <linux/types.h> 23#include <linux/init.h> 24#include <linux/kernel.h> 25#include <linux/string.h> 26#include <linux/ioport.h> 27#include <linux/platform_device.h> 28#include <linux/delay.h> 29#include <linux/err.h> 30#include <linux/kernel.h> 31 32#include <linux/mtd/mtd.h> 33#include <linux/mtd/nand.h> 34#include <linux/mtd/nand_ecc.h> 35#include <linux/mtd/partitions.h> 36 37#include <asm/io.h> 38#include <asm/rm9k-ocd.h> 39 40#include <excite_nandflash.h> 41 42#define EXCITE_NANDFLASH_VERSION "0.1" 43 44/* I/O register offsets */ 45#define EXCITE_NANDFLASH_DATA_BYTE 0x00 46#define EXCITE_NANDFLASH_STATUS_BYTE 0x0c 47#define EXCITE_NANDFLASH_ADDR_BYTE 0x10 48#define EXCITE_NANDFLASH_CMD_BYTE 0x14 49 50/* prefix for debug output */ 51static const char module_id[] = "excite_nandflash"; 52 53/* 54 * partition definition 55 */ 56static const struct mtd_partition partition_info[] = { 57 { 58 .name = "eXcite RootFS", 59 .offset = 0, 60 .size = MTDPART_SIZ_FULL 61 } 62}; 63 64static inline const struct resource * 65excite_nand_get_resource(struct platform_device *d, unsigned long flags, 66 const char *basename) 67{ 68 char buf[80]; 69 70 if (snprintf(buf, sizeof buf, "%s_%u", basename, d->id) >= sizeof buf) 71 return NULL; 72 return platform_get_resource_byname(d, flags, buf); 73} 74 75static inline void __iomem * 76excite_nand_map_regs(struct platform_device *d, const char *basename) 77{ 78 void *result = NULL; 79 const struct resource *const r = 80 excite_nand_get_resource(d, IORESOURCE_MEM, basename); 81 82 if (r) 83 result = ioremap_nocache(r->start, r->end + 1 - r->start); 84 return result; 85} 86 87/* controller and mtd information */ 88struct excite_nand_drvdata { 89 struct mtd_info board_mtd; 90 struct nand_chip board_chip; 91 void __iomem *regs; 92 void __iomem *tgt; 93}; 94 95/* Control function */ 96static void excite_nand_control(struct mtd_info *mtd, int cmd, 97 unsigned int ctrl) 98{ 99 struct excite_nand_drvdata * const d = 100 container_of(mtd, struct excite_nand_drvdata, board_mtd); 101 102 switch (ctrl) { 103 case NAND_CTRL_CHANGE | NAND_CTRL_CLE: 104 d->tgt = d->regs + EXCITE_NANDFLASH_CMD_BYTE; 105 break; 106 case NAND_CTRL_CHANGE | NAND_CTRL_ALE: 107 d->tgt = d->regs + EXCITE_NANDFLASH_ADDR_BYTE; 108 break; 109 case NAND_CTRL_CHANGE | NAND_NCE: 110 d->tgt = d->regs + EXCITE_NANDFLASH_DATA_BYTE; 111 break; 112 } 113 114 if (cmd != NAND_CMD_NONE) 115 __raw_writeb(cmd, d->tgt); 116} 117 118/* Return 0 if flash is busy, 1 if ready */ 119static int excite_nand_devready(struct mtd_info *mtd) 120{ 121 struct excite_nand_drvdata * const drvdata = 122 container_of(mtd, struct excite_nand_drvdata, board_mtd); 123 124 return __raw_readb(drvdata->regs + EXCITE_NANDFLASH_STATUS_BYTE); 125} 126 127/* 128 * Called by device layer to remove the driver. 129 * The binding to the mtd and all allocated 130 * resources are released. 131 */ 132static int __exit excite_nand_remove(struct device *dev) 133{ 134 struct excite_nand_drvdata * const this = dev_get_drvdata(dev); 135 136 dev_set_drvdata(dev, NULL); 137 138 if (unlikely(!this)) { 139 printk(KERN_ERR "%s: called %s without private data!!", 140 module_id, __func__); 141 return -EINVAL; 142 } 143 144 /* first thing we need to do is release our mtd 145 * then go through freeing the resource used 146 */ 147 nand_release(&this->board_mtd); 148 149 /* free the common resources */ 150 iounmap(this->regs); 151 kfree(this); 152 153 DEBUG(MTD_DEBUG_LEVEL1, "%s: removed\n", module_id); 154 return 0; 155} 156 157/* 158 * Called by device layer when it finds a device matching 159 * one our driver can handle. This code checks to see if 160 * it can allocate all necessary resources then calls the 161 * nand layer to look for devices. 162*/ 163static int __init excite_nand_probe(struct device *dev) 164{ 165 struct platform_device * const pdev = to_platform_device(dev); 166 struct excite_nand_drvdata *drvdata; /* private driver data */ 167 struct nand_chip *board_chip; /* private flash chip data */ 168 struct mtd_info *board_mtd; /* mtd info for this board */ 169 int scan_res; 170 171 drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL); 172 if (unlikely(!drvdata)) { 173 printk(KERN_ERR "%s: no memory for drvdata\n", 174 module_id); 175 return -ENOMEM; 176 } 177 178 /* bind private data into driver */ 179 dev_set_drvdata(dev, drvdata); 180 181 /* allocate and map the resource */ 182 drvdata->regs = 183 excite_nand_map_regs(pdev, EXCITE_NANDFLASH_RESOURCE_REGS); 184 185 if (unlikely(!drvdata->regs)) { 186 printk(KERN_ERR "%s: cannot reserve register region\n", 187 module_id); 188 kfree(drvdata); 189 return -ENXIO; 190 } 191 192 drvdata->tgt = drvdata->regs + EXCITE_NANDFLASH_DATA_BYTE; 193 194 /* initialise our chip */ 195 board_chip = &drvdata->board_chip; 196 board_chip->IO_ADDR_R = board_chip->IO_ADDR_W = 197 drvdata->regs + EXCITE_NANDFLASH_DATA_BYTE; 198 board_chip->cmd_ctrl = excite_nand_control; 199 board_chip->dev_ready = excite_nand_devready; 200 board_chip->chip_delay = 25; 201 board_chip->ecc.mode = NAND_ECC_SOFT; 202 203 /* link chip to mtd */ 204 board_mtd = &drvdata->board_mtd; 205 board_mtd->priv = board_chip; 206 207 DEBUG(MTD_DEBUG_LEVEL2, "%s: device scan\n", module_id); 208 scan_res = nand_scan(&drvdata->board_mtd, 1); 209 210 if (likely(!scan_res)) { 211 DEBUG(MTD_DEBUG_LEVEL2, "%s: register partitions\n", module_id); 212 add_mtd_partitions(&drvdata->board_mtd, partition_info, 213 sizeof partition_info / sizeof partition_info[0]); 214 } else { 215 iounmap(drvdata->regs); 216 kfree(drvdata); 217 printk(KERN_ERR "%s: device scan failed\n", module_id); 218 return -EIO; 219 } 220 return 0; 221} 222 223static struct device_driver excite_nand_driver = { 224 .name = "excite_nand", 225 .bus = &platform_bus_type, 226 .probe = excite_nand_probe, 227 .remove = __exit_p(excite_nand_remove) 228}; 229 230static int __init excite_nand_init(void) 231{ 232 pr_info("Basler eXcite nand flash driver Version " 233 EXCITE_NANDFLASH_VERSION "\n"); 234 return driver_register(&excite_nand_driver); 235} 236 237static void __exit excite_nand_exit(void) 238{ 239 driver_unregister(&excite_nand_driver); 240} 241 242module_init(excite_nand_init); 243module_exit(excite_nand_exit); 244 245MODULE_AUTHOR("Thomas Koeller <thomas.koeller@baslerweb.com>"); 246MODULE_DESCRIPTION("Basler eXcite NAND-Flash driver"); 247MODULE_LICENSE("GPL"); 248MODULE_VERSION(EXCITE_NANDFLASH_VERSION) 249