1/* 2 * drivers/mtd/autcpu12.c 3 * 4 * Copyright (c) 2002 Thomas Gleixner <tgxl@linutronix.de> 5 * 6 * Derived from drivers/mtd/spia.c 7 * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) 8 * 9 * $Id: autcpu12.c,v 1.1.1.1 2007/08/03 18:52:44 Exp $ 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License version 2 as 13 * published by the Free Software Foundation. 14 * 15 * Overview: 16 * This is a device driver for the NAND flash device found on the 17 * autronix autcpu12 board, which is a SmartMediaCard. It supports 18 * 16MiB, 32MiB and 64MiB cards. 19 * 20 * 21 * 02-12-2002 TG Cleanup of module params 22 * 23 * 02-20-2002 TG adjusted for different rd/wr adress support 24 * added support for read device ready/busy line 25 * added page_cache 26 * 27 * 10-06-2002 TG 128K card support added 28 */ 29 30#include <linux/slab.h> 31#include <linux/init.h> 32#include <linux/module.h> 33#include <linux/mtd/mtd.h> 34#include <linux/mtd/nand.h> 35#include <linux/mtd/partitions.h> 36#include <asm/io.h> 37#include <asm/arch/hardware.h> 38#include <asm/sizes.h> 39#include <asm/arch/autcpu12.h> 40 41/* 42 * MTD structure for AUTCPU12 board 43 */ 44static struct mtd_info *autcpu12_mtd = NULL; 45static void __iomem *autcpu12_fio_base; 46 47/* 48 * Define partitions for flash devices 49 */ 50static struct mtd_partition partition_info16k[] = { 51 { .name = "AUTCPU12 flash partition 1", 52 .offset = 0, 53 .size = 8 * SZ_1M }, 54 { .name = "AUTCPU12 flash partition 2", 55 .offset = 8 * SZ_1M, 56 .size = 8 * SZ_1M }, 57}; 58 59static struct mtd_partition partition_info32k[] = { 60 { .name = "AUTCPU12 flash partition 1", 61 .offset = 0, 62 .size = 8 * SZ_1M }, 63 { .name = "AUTCPU12 flash partition 2", 64 .offset = 8 * SZ_1M, 65 .size = 24 * SZ_1M }, 66}; 67 68static struct mtd_partition partition_info64k[] = { 69 { .name = "AUTCPU12 flash partition 1", 70 .offset = 0, 71 .size = 16 * SZ_1M }, 72 { .name = "AUTCPU12 flash partition 2", 73 .offset = 16 * SZ_1M, 74 .size = 48 * SZ_1M }, 75}; 76 77static struct mtd_partition partition_info128k[] = { 78 { .name = "AUTCPU12 flash partition 1", 79 .offset = 0, 80 .size = 16 * SZ_1M }, 81 { .name = "AUTCPU12 flash partition 2", 82 .offset = 16 * SZ_1M, 83 .size = 112 * SZ_1M }, 84}; 85 86#define NUM_PARTITIONS16K 2 87#define NUM_PARTITIONS32K 2 88#define NUM_PARTITIONS64K 2 89#define NUM_PARTITIONS128K 2 90/* 91 * hardware specific access to control-lines 92 * 93 * ALE bit 4 autcpu12_pedr 94 * CLE bit 5 autcpu12_pedr 95 * NCE bit 0 fio_ctrl 96 * 97 */ 98static void autcpu12_hwcontrol(struct mtd_info *mtd, int cmd, 99 unsigned int ctrl) 100{ 101 struct nand_chip *chip = mtd->priv; 102 103 if (ctrl & NAND_CTRL_CHANGE) { 104 void __iomem *addr; 105 unsigned char bits; 106 107 addr = CS89712_VIRT_BASE + AUTCPU12_SMC_PORT_OFFSET; 108 bits = (ctrl & NAND_CLE) << 4; 109 bits |= (ctrl & NAND_ALE) << 2; 110 writeb((readb(addr) & ~0x30) | bits, addr); 111 112 addr = autcpu12_fio_base + AUTCPU12_SMC_SELECT_OFFSET; 113 writeb((readb(addr) & ~0x1) | (ctrl & NAND_NCE), addr); 114 } 115 116 if (cmd != NAND_CMD_NONE) 117 writeb(cmd, chip->IO_ADDR_W); 118} 119 120/* 121 * read device ready pin 122 */ 123int autcpu12_device_ready(struct mtd_info *mtd) 124{ 125 void __iomem *addr = CS89712_VIRT_BASE + AUTCPU12_SMC_PORT_OFFSET; 126 127 return readb(addr) & AUTCPU12_SMC_RDY; 128} 129 130/* 131 * Main initialization routine 132 */ 133static int __init autcpu12_init(void) 134{ 135 struct nand_chip *this; 136 int err = 0; 137 138 /* Allocate memory for MTD device structure and private data */ 139 autcpu12_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), 140 GFP_KERNEL); 141 if (!autcpu12_mtd) { 142 printk("Unable to allocate AUTCPU12 NAND MTD device structure.\n"); 143 err = -ENOMEM; 144 goto out; 145 } 146 147 /* map physical adress */ 148 autcpu12_fio_base = ioremap(AUTCPU12_PHYS_SMC, SZ_1K); 149 if (!autcpu12_fio_base) { 150 printk("Ioremap autcpu12 SmartMedia Card failed\n"); 151 err = -EIO; 152 goto out_mtd; 153 } 154 155 /* Get pointer to private data */ 156 this = (struct nand_chip *)(&autcpu12_mtd[1]); 157 158 /* Initialize structures */ 159 memset(autcpu12_mtd, 0, sizeof(struct mtd_info)); 160 memset(this, 0, sizeof(struct nand_chip)); 161 162 /* Link the private data with the MTD structure */ 163 autcpu12_mtd->priv = this; 164 autcpu12_mtd->owner = THIS_MODULE; 165 166 /* Set address of NAND IO lines */ 167 this->IO_ADDR_R = autcpu12_fio_base; 168 this->IO_ADDR_W = autcpu12_fio_base; 169 this->cmd_ctrl = autcpu12_hwcontrol; 170 this->dev_ready = autcpu12_device_ready; 171 /* 20 us command delay time */ 172 this->chip_delay = 20; 173 this->ecc.mode = NAND_ECC_SOFT; 174 175 /* Enable the following for a flash based bad block table */ 176 /* 177 this->options = NAND_USE_FLASH_BBT; 178 */ 179 this->options = NAND_USE_FLASH_BBT; 180 181 /* Scan to find existance of the device */ 182 if (nand_scan(autcpu12_mtd, 1)) { 183 err = -ENXIO; 184 goto out_ior; 185 } 186 187 /* Register the partitions */ 188 switch (autcpu12_mtd->size) { 189 case SZ_16M: 190 add_mtd_partitions(autcpu12_mtd, partition_info16k, 191 NUM_PARTITIONS16K); 192 break; 193 case SZ_32M: 194 add_mtd_partitions(autcpu12_mtd, partition_info32k, 195 NUM_PARTITIONS32K); 196 break; 197 case SZ_64M: 198 add_mtd_partitions(autcpu12_mtd, partition_info64k, 199 NUM_PARTITIONS64K); 200 break; 201 case SZ_128M: 202 add_mtd_partitions(autcpu12_mtd, partition_info128k, 203 NUM_PARTITIONS128K); 204 break; 205 default: 206 printk("Unsupported SmartMedia device\n"); 207 err = -ENXIO; 208 goto out_ior; 209 } 210 goto out; 211 212 out_ior: 213 iounmap(autcpu12_fio_base); 214 out_mtd: 215 kfree(autcpu12_mtd); 216 out: 217 return err; 218} 219 220module_init(autcpu12_init); 221 222/* 223 * Clean up routine 224 */ 225static void __exit autcpu12_cleanup(void) 226{ 227 /* Release resources, unregister device */ 228 nand_release(autcpu12_mtd); 229 230 /* unmap physical adress */ 231 iounmap(autcpu12_fio_base); 232 233 /* Free the MTD device structure */ 234 kfree(autcpu12_mtd); 235} 236 237module_exit(autcpu12_cleanup); 238 239MODULE_LICENSE("GPL"); 240MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>"); 241MODULE_DESCRIPTION("Glue layer for SmartMediaCard on autronix autcpu12"); 242