root/drivers/mtd/nand/raw/cmx270_nand.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cmx270_read_byte
  2. cmx270_write_buf
  3. cmx270_read_buf
  4. nand_cs_on
  5. nand_cs_off
  6. cmx270_hwcontrol
  7. cmx270_device_ready
  8. cmx270_init
  9. cmx270_cleanup

   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 */
  31 static struct mtd_info *cmx270_nand_mtd;
  32 
  33 /* remaped IO address of the device */
  34 static void __iomem *cmx270_nand_io;
  35 
  36 /*
  37  * Define static partitions for flash device
  38  */
  39 static 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 
  48 static u_char cmx270_read_byte(struct nand_chip *this)
  49 {
  50         return (readl(this->legacy.IO_ADDR_R) >> 16);
  51 }
  52 
  53 static 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 
  62 static 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 
  70 static inline void nand_cs_on(void)
  71 {
  72         gpio_set_value(GPIO_NAND_CS, 0);
  73 }
  74 
  75 static 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  */
  85 static 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  */
 118 static 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  */
 128 static 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 
 203 err_scan:
 204         iounmap(cmx270_nand_io);
 205 err_ioremap:
 206         kfree(this);
 207 err_kzalloc:
 208         gpio_free(GPIO_NAND_RB);
 209 err_gpio_request:
 210         gpio_free(GPIO_NAND_CS);
 211 
 212         return ret;
 213 
 214 }
 215 module_init(cmx270_init);
 216 
 217 /*
 218  * Clean up routine
 219  */
 220 static 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 }
 232 module_exit(cmx270_cleanup);
 233 
 234 MODULE_LICENSE("GPL");
 235 MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
 236 MODULE_DESCRIPTION("NAND flash driver for Compulab CM-X270 Module");

/* [<][>][^][v][top][bottom][index][help] */