1/* 2 * linux/drivers/mtd/nand/cmx270-nand.c 3 * 4 * Copyright (C) 2006 Compulab, Ltd. 5 * Mike Rapoport <mike@compulab.co.il> 6 * 7 * Derived from drivers/mtd/nand/h1910.c 8 * Copyright (C) 2002 Marius Gröger (mag@sysgo.de) 9 * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) 10 * 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 * CM-X270 board. 19 */ 20 21#include <linux/mtd/nand.h> 22#include <linux/mtd/partitions.h> 23#include <linux/slab.h> 24#include <linux/gpio.h> 25#include <linux/module.h> 26 27#include <asm/io.h> 28#include <asm/irq.h> 29#include <asm/mach-types.h> 30 31#include <mach/pxa2xx-regs.h> 32 33#define GPIO_NAND_CS (11) 34#define GPIO_NAND_RB (89) 35 36/* MTD structure for CM-X270 board */ 37static struct mtd_info *cmx270_nand_mtd; 38 39/* remaped IO address of the device */ 40static void __iomem *cmx270_nand_io; 41 42/* 43 * Define static partitions for flash device 44 */ 45static struct mtd_partition partition_info[] = { 46 [0] = { 47 .name = "cmx270-0", 48 .offset = 0, 49 .size = MTDPART_SIZ_FULL 50 } 51}; 52#define NUM_PARTITIONS (ARRAY_SIZE(partition_info)) 53 54static u_char cmx270_read_byte(struct mtd_info *mtd) 55{ 56 struct nand_chip *this = mtd->priv; 57 58 return (readl(this->IO_ADDR_R) >> 16); 59} 60 61static void cmx270_write_buf(struct mtd_info *mtd, const u_char *buf, int len) 62{ 63 int i; 64 struct nand_chip *this = mtd->priv; 65 66 for (i=0; i<len; i++) 67 writel((*buf++ << 16), this->IO_ADDR_W); 68} 69 70static void cmx270_read_buf(struct mtd_info *mtd, u_char *buf, int len) 71{ 72 int i; 73 struct nand_chip *this = mtd->priv; 74 75 for (i=0; i<len; i++) 76 *buf++ = readl(this->IO_ADDR_R) >> 16; 77} 78 79static inline void nand_cs_on(void) 80{ 81 gpio_set_value(GPIO_NAND_CS, 0); 82} 83 84static void nand_cs_off(void) 85{ 86 dsb(); 87 88 gpio_set_value(GPIO_NAND_CS, 1); 89} 90 91/* 92 * hardware specific access to control-lines 93 */ 94static void cmx270_hwcontrol(struct mtd_info *mtd, int dat, 95 unsigned int ctrl) 96{ 97 struct nand_chip* this = mtd->priv; 98 unsigned int nandaddr = (unsigned int)this->IO_ADDR_W; 99 100 dsb(); 101 102 if (ctrl & NAND_CTRL_CHANGE) { 103 if ( ctrl & NAND_ALE ) 104 nandaddr |= (1 << 3); 105 else 106 nandaddr &= ~(1 << 3); 107 if ( ctrl & NAND_CLE ) 108 nandaddr |= (1 << 2); 109 else 110 nandaddr &= ~(1 << 2); 111 if ( ctrl & NAND_NCE ) 112 nand_cs_on(); 113 else 114 nand_cs_off(); 115 } 116 117 dsb(); 118 this->IO_ADDR_W = (void __iomem*)nandaddr; 119 if (dat != NAND_CMD_NONE) 120 writel((dat << 16), this->IO_ADDR_W); 121 122 dsb(); 123} 124 125/* 126 * read device ready pin 127 */ 128static int cmx270_device_ready(struct mtd_info *mtd) 129{ 130 dsb(); 131 132 return (gpio_get_value(GPIO_NAND_RB)); 133} 134 135/* 136 * Main initialization routine 137 */ 138static int __init cmx270_init(void) 139{ 140 struct nand_chip *this; 141 int ret; 142 143 if (!(machine_is_armcore() && cpu_is_pxa27x())) 144 return -ENODEV; 145 146 ret = gpio_request(GPIO_NAND_CS, "NAND CS"); 147 if (ret) { 148 pr_warning("CM-X270: failed to request NAND CS gpio\n"); 149 return ret; 150 } 151 152 gpio_direction_output(GPIO_NAND_CS, 1); 153 154 ret = gpio_request(GPIO_NAND_RB, "NAND R/B"); 155 if (ret) { 156 pr_warning("CM-X270: failed to request NAND R/B gpio\n"); 157 goto err_gpio_request; 158 } 159 160 gpio_direction_input(GPIO_NAND_RB); 161 162 /* Allocate memory for MTD device structure and private data */ 163 cmx270_nand_mtd = kzalloc(sizeof(struct mtd_info) + 164 sizeof(struct nand_chip), 165 GFP_KERNEL); 166 if (!cmx270_nand_mtd) { 167 ret = -ENOMEM; 168 goto err_kzalloc; 169 } 170 171 cmx270_nand_io = ioremap(PXA_CS1_PHYS, 12); 172 if (!cmx270_nand_io) { 173 pr_debug("Unable to ioremap NAND device\n"); 174 ret = -EINVAL; 175 goto err_ioremap; 176 } 177 178 /* Get pointer to private data */ 179 this = (struct nand_chip *)(&cmx270_nand_mtd[1]); 180 181 /* Link the private data with the MTD structure */ 182 cmx270_nand_mtd->owner = THIS_MODULE; 183 cmx270_nand_mtd->priv = this; 184 185 /* insert callbacks */ 186 this->IO_ADDR_R = cmx270_nand_io; 187 this->IO_ADDR_W = cmx270_nand_io; 188 this->cmd_ctrl = cmx270_hwcontrol; 189 this->dev_ready = cmx270_device_ready; 190 191 /* 15 us command delay time */ 192 this->chip_delay = 20; 193 this->ecc.mode = NAND_ECC_SOFT; 194 195 /* read/write functions */ 196 this->read_byte = cmx270_read_byte; 197 this->read_buf = cmx270_read_buf; 198 this->write_buf = cmx270_write_buf; 199 200 /* Scan to find existence of the device */ 201 if (nand_scan (cmx270_nand_mtd, 1)) { 202 pr_notice("No NAND device\n"); 203 ret = -ENXIO; 204 goto err_scan; 205 } 206 207 /* Register the partitions */ 208 ret = mtd_device_parse_register(cmx270_nand_mtd, NULL, NULL, 209 partition_info, NUM_PARTITIONS); 210 if (ret) 211 goto err_scan; 212 213 /* Return happy */ 214 return 0; 215 216err_scan: 217 iounmap(cmx270_nand_io); 218err_ioremap: 219 kfree(cmx270_nand_mtd); 220err_kzalloc: 221 gpio_free(GPIO_NAND_RB); 222err_gpio_request: 223 gpio_free(GPIO_NAND_CS); 224 225 return ret; 226 227} 228module_init(cmx270_init); 229 230/* 231 * Clean up routine 232 */ 233static void __exit cmx270_cleanup(void) 234{ 235 /* Release resources, unregister device */ 236 nand_release(cmx270_nand_mtd); 237 238 gpio_free(GPIO_NAND_RB); 239 gpio_free(GPIO_NAND_CS); 240 241 iounmap(cmx270_nand_io); 242 243 /* Free the MTD device structure */ 244 kfree (cmx270_nand_mtd); 245} 246module_exit(cmx270_cleanup); 247 248MODULE_LICENSE("GPL"); 249MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>"); 250MODULE_DESCRIPTION("NAND flash driver for Compulab CM-X270 Module"); 251