linux/drivers/mtd/nand/cmx270_nand.c
<<
>>
Prefs
   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