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