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