1/* 2 * drivers/mtd/nand/spia.c 3 * 4 * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) 5 * 6 * 7 * 10-29-2001 TG change to support hardwarespecific access 8 * to controllines (due to change in nand.c) 9 * page_cache added 10 * 11 * $Id: spia.c,v 1.1.1.1 2007/08/03 18:52:44 Exp $ 12 * 13 * This program is free software; you can redistribute it and/or modify 14 * it under the terms of the GNU General Public License version 2 as 15 * published by the Free Software Foundation. 16 * 17 * Overview: 18 * This is a device driver for the NAND flash device found on the 19 * SPIA board which utilizes the Toshiba TC58V64AFT part. This is 20 * a 64Mibit (8MiB x 8 bits) NAND flash device. 21 */ 22 23#include <linux/kernel.h> 24#include <linux/init.h> 25#include <linux/slab.h> 26#include <linux/module.h> 27#include <linux/mtd/mtd.h> 28#include <linux/mtd/nand.h> 29#include <linux/mtd/partitions.h> 30#include <asm/io.h> 31 32/* 33 * MTD structure for SPIA board 34 */ 35static struct mtd_info *spia_mtd = NULL; 36 37/* 38 * Values specific to the SPIA board (used with EP7212 processor) 39 */ 40#define SPIA_IO_BASE 0xd0000000 /* Start of EP7212 IO address space */ 41#define SPIA_FIO_BASE 0xf0000000 /* Address where flash is mapped */ 42#define SPIA_PEDR 0x0080 /* 43 * IO offset to Port E data register 44 * where the CLE, ALE and NCE pins 45 * are wired to. 46 */ 47#define SPIA_PEDDR 0x00c0 /* 48 * IO offset to Port E data direction 49 * register so we can control the IO 50 * lines. 51 */ 52 53/* 54 * Module stuff 55 */ 56 57static int spia_io_base = SPIA_IO_BASE; 58static int spia_fio_base = SPIA_FIO_BASE; 59static int spia_pedr = SPIA_PEDR; 60static int spia_peddr = SPIA_PEDDR; 61 62module_param(spia_io_base, int, 0); 63module_param(spia_fio_base, int, 0); 64module_param(spia_pedr, int, 0); 65module_param(spia_peddr, int, 0); 66 67/* 68 * Define partitions for flash device 69 */ 70static const struct mtd_partition partition_info[] = { 71 { 72 .name = "SPIA flash partition 1", 73 .offset = 0, 74 .size = 2 * 1024 * 1024}, 75 { 76 .name = "SPIA flash partition 2", 77 .offset = 2 * 1024 * 1024, 78 .size = 6 * 1024 * 1024} 79}; 80 81#define NUM_PARTITIONS 2 82 83/* 84 * hardware specific access to control-lines 85 * 86 * ctrl: 87 * NAND_CNE: bit 0 -> bit 2 88 * NAND_CLE: bit 1 -> bit 0 89 * NAND_ALE: bit 2 -> bit 1 90 */ 91static void spia_hwcontrol(struct mtd_info *mtd, int cmd) 92{ 93 struct nand_chip *chip = mtd->priv; 94 95 if (ctrl & NAND_CTRL_CHANGE) { 96 void __iomem *addr = spia_io_base + spia_pedr; 97 unsigned char bits; 98 99 bits = (ctrl & NAND_CNE) << 2; 100 bits |= (ctrl & NAND_CLE | NAND_ALE) >> 1; 101 writeb((readb(addr) & ~0x7) | bits, addr); 102 } 103 104 if (cmd != NAND_CMD_NONE) 105 writeb(cmd, chip->IO_ADDR_W); 106} 107 108/* 109 * Main initialization routine 110 */ 111static int __init spia_init(void) 112{ 113 struct nand_chip *this; 114 115 /* Allocate memory for MTD device structure and private data */ 116 spia_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL); 117 if (!spia_mtd) { 118 printk("Unable to allocate SPIA NAND MTD device structure.\n"); 119 return -ENOMEM; 120 } 121 122 /* Get pointer to private data */ 123 this = (struct nand_chip *)(&spia_mtd[1]); 124 125 /* Initialize structures */ 126 memset(spia_mtd, 0, sizeof(struct mtd_info)); 127 memset(this, 0, sizeof(struct nand_chip)); 128 129 /* Link the private data with the MTD structure */ 130 spia_mtd->priv = this; 131 spia_mtd->owner = THIS_MODULE; 132 133 /* 134 * Set GPIO Port E control register so that the pins are configured 135 * to be outputs for controlling the NAND flash. 136 */ 137 (*(volatile unsigned char *)(spia_io_base + spia_peddr)) = 0x07; 138 139 /* Set address of NAND IO lines */ 140 this->IO_ADDR_R = (void __iomem *)spia_fio_base; 141 this->IO_ADDR_W = (void __iomem *)spia_fio_base; 142 /* Set address of hardware control function */ 143 this->cmd_ctrl = spia_hwcontrol; 144 /* 15 us command delay time */ 145 this->chip_delay = 15; 146 147 /* Scan to find existence of the device */ 148 if (nand_scan(spia_mtd, 1)) { 149 kfree(spia_mtd); 150 return -ENXIO; 151 } 152 153 /* Register the partitions */ 154 add_mtd_partitions(spia_mtd, partition_info, NUM_PARTITIONS); 155 156 /* Return happy */ 157 return 0; 158} 159 160module_init(spia_init); 161 162/* 163 * Clean up routine 164 */ 165static void __exit spia_cleanup(void) 166{ 167 /* Release resources, unregister device */ 168 nand_release(spia_mtd); 169 170 /* Free the MTD device structure */ 171 kfree(spia_mtd); 172} 173 174module_exit(spia_cleanup); 175 176MODULE_LICENSE("GPL"); 177MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com"); 178MODULE_DESCRIPTION("Board-specific glue layer for NAND flash on SPIA board"); 179