linux/drivers/mtd/nand/ppchameleonevb.c
<<
>>
Prefs
   1/*
   2 *  drivers/mtd/nand/ppchameleonevb.c
   3 *
   4 *  Copyright (C) 2003 DAVE Srl (info@wawnet.biz)
   5 *
   6 *  Derived from drivers/mtd/nand/edb7312.c
   7 *
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License version 2 as
  11 * published by the Free Software Foundation.
  12 *
  13 *  Overview:
  14 *   This is a device driver for the NAND flash devices found on the
  15 *   PPChameleon/PPChameleonEVB system.
  16 *   PPChameleon options (autodetected):
  17 *   - BA model: no NAND
  18 *   - ME model: 32MB (Samsung K9F5608U0B)
  19 *   - HI model: 128MB (Samsung K9F1G08UOM)
  20 *   PPChameleonEVB options:
  21 *   - 32MB (Samsung K9F5608U0B)
  22 */
  23
  24#include <linux/init.h>
  25#include <linux/slab.h>
  26#include <linux/module.h>
  27#include <linux/mtd/mtd.h>
  28#include <linux/mtd/nand.h>
  29#include <linux/mtd/partitions.h>
  30#include <asm/io.h>
  31#include <platforms/PPChameleonEVB.h>
  32
  33#undef USE_READY_BUSY_PIN
  34#define USE_READY_BUSY_PIN
  35/* see datasheets (tR) */
  36#define NAND_BIG_DELAY_US               25
  37#define NAND_SMALL_DELAY_US             10
  38
  39/* handy sizes */
  40#define SZ_4M                           0x00400000
  41#define NAND_SMALL_SIZE                 0x02000000
  42#define NAND_MTD_NAME           "ppchameleon-nand"
  43#define NAND_EVB_MTD_NAME       "ppchameleonevb-nand"
  44
  45/* GPIO pins used to drive NAND chip mounted on processor module */
  46#define NAND_nCE_GPIO_PIN               (0x80000000 >> 1)
  47#define NAND_CLE_GPIO_PIN               (0x80000000 >> 2)
  48#define NAND_ALE_GPIO_PIN               (0x80000000 >> 3)
  49#define NAND_RB_GPIO_PIN                (0x80000000 >> 4)
  50/* GPIO pins used to drive NAND chip mounted on EVB */
  51#define NAND_EVB_nCE_GPIO_PIN   (0x80000000 >> 14)
  52#define NAND_EVB_CLE_GPIO_PIN   (0x80000000 >> 15)
  53#define NAND_EVB_ALE_GPIO_PIN   (0x80000000 >> 16)
  54#define NAND_EVB_RB_GPIO_PIN    (0x80000000 >> 31)
  55
  56/*
  57 * MTD structure for PPChameleonEVB board
  58 */
  59static struct mtd_info *ppchameleon_mtd = NULL;
  60static struct mtd_info *ppchameleonevb_mtd = NULL;
  61
  62/*
  63 * Module stuff
  64 */
  65static unsigned long ppchameleon_fio_pbase = CFG_NAND0_PADDR;
  66static unsigned long ppchameleonevb_fio_pbase = CFG_NAND1_PADDR;
  67
  68#ifdef MODULE
  69module_param(ppchameleon_fio_pbase, ulong, 0);
  70module_param(ppchameleonevb_fio_pbase, ulong, 0);
  71#else
  72__setup("ppchameleon_fio_pbase=", ppchameleon_fio_pbase);
  73__setup("ppchameleonevb_fio_pbase=", ppchameleonevb_fio_pbase);
  74#endif
  75
  76/*
  77 * Define static partitions for flash devices
  78 */
  79static struct mtd_partition partition_info_hi[] = {
  80      { .name = "PPChameleon HI Nand Flash",
  81        .offset = 0,
  82        .size = 128 * 1024 * 1024
  83      }
  84};
  85
  86static struct mtd_partition partition_info_me[] = {
  87      { .name = "PPChameleon ME Nand Flash",
  88        .offset = 0,
  89        .size = 32 * 1024 * 1024
  90      }
  91};
  92
  93static struct mtd_partition partition_info_evb[] = {
  94      { .name = "PPChameleonEVB Nand Flash",
  95        .offset = 0,
  96        .size = 32 * 1024 * 1024
  97      }
  98};
  99
 100#define NUM_PARTITIONS 1
 101
 102/*
 103 *      hardware specific access to control-lines
 104 */
 105static void ppchameleon_hwcontrol(struct mtd_info *mtdinfo, int cmd,
 106                                  unsigned int ctrl)
 107{
 108        struct nand_chip *chip = mtd->priv;
 109
 110        if (ctrl & NAND_CTRL_CHANGE) {
 111#error Missing headerfiles. No way to fix this. -tglx
 112                switch (cmd) {
 113                case NAND_CTL_SETCLE:
 114                        MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND0_PADDR);
 115                        break;
 116                case NAND_CTL_CLRCLE:
 117                        MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND0_PADDR);
 118                        break;
 119                case NAND_CTL_SETALE:
 120                        MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND0_PADDR);
 121                        break;
 122                case NAND_CTL_CLRALE:
 123                        MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND0_PADDR);
 124                        break;
 125                case NAND_CTL_SETNCE:
 126                        MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND0_PADDR);
 127                        break;
 128                case NAND_CTL_CLRNCE:
 129                        MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND0_PADDR);
 130                        break;
 131                }
 132        }
 133        if (cmd != NAND_CMD_NONE)
 134                writeb(cmd, chip->IO_ADDR_W);
 135}
 136
 137static void ppchameleonevb_hwcontrol(struct mtd_info *mtdinfo, int cmd,
 138                                     unsigned int ctrl)
 139{
 140        struct nand_chip *chip = mtd->priv;
 141
 142        if (ctrl & NAND_CTRL_CHANGE) {
 143#error Missing headerfiles. No way to fix this. -tglx
 144                switch (cmd) {
 145                case NAND_CTL_SETCLE:
 146                        MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND1_PADDR);
 147                        break;
 148                case NAND_CTL_CLRCLE:
 149                        MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND1_PADDR);
 150                        break;
 151                case NAND_CTL_SETALE:
 152                        MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND1_PADDR);
 153                        break;
 154                case NAND_CTL_CLRALE:
 155                        MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND1_PADDR);
 156                        break;
 157                case NAND_CTL_SETNCE:
 158                        MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND1_PADDR);
 159                        break;
 160                case NAND_CTL_CLRNCE:
 161                        MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND1_PADDR);
 162                        break;
 163                }
 164        }
 165        if (cmd != NAND_CMD_NONE)
 166                writeb(cmd, chip->IO_ADDR_W);
 167}
 168
 169#ifdef USE_READY_BUSY_PIN
 170/*
 171 *      read device ready pin
 172 */
 173static int ppchameleon_device_ready(struct mtd_info *minfo)
 174{
 175        if (in_be32((volatile unsigned *)GPIO0_IR) & NAND_RB_GPIO_PIN)
 176                return 1;
 177        return 0;
 178}
 179
 180static int ppchameleonevb_device_ready(struct mtd_info *minfo)
 181{
 182        if (in_be32((volatile unsigned *)GPIO0_IR) & NAND_EVB_RB_GPIO_PIN)
 183                return 1;
 184        return 0;
 185}
 186#endif
 187
 188/*
 189 * Main initialization routine
 190 */
 191static int __init ppchameleonevb_init(void)
 192{
 193        struct nand_chip *this;
 194        void __iomem *ppchameleon_fio_base;
 195        void __iomem *ppchameleonevb_fio_base;
 196
 197        /*********************************
 198        * Processor module NAND (if any) *
 199        *********************************/
 200        /* Allocate memory for MTD device structure and private data */
 201        ppchameleon_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
 202        if (!ppchameleon_mtd) {
 203                printk("Unable to allocate PPChameleon NAND MTD device structure.\n");
 204                return -ENOMEM;
 205        }
 206
 207        /* map physical address */
 208        ppchameleon_fio_base = ioremap(ppchameleon_fio_pbase, SZ_4M);
 209        if (!ppchameleon_fio_base) {
 210                printk("ioremap PPChameleon NAND flash failed\n");
 211                kfree(ppchameleon_mtd);
 212                return -EIO;
 213        }
 214
 215        /* Get pointer to private data */
 216        this = (struct nand_chip *)(&ppchameleon_mtd[1]);
 217
 218        /* Initialize structures */
 219        memset(ppchameleon_mtd, 0, sizeof(struct mtd_info));
 220        memset(this, 0, sizeof(struct nand_chip));
 221
 222        /* Link the private data with the MTD structure */
 223        ppchameleon_mtd->priv = this;
 224        ppchameleon_mtd->owner = THIS_MODULE;
 225
 226        /* Initialize GPIOs */
 227        /* Pin mapping for NAND chip */
 228        /*
 229           CE   GPIO_01
 230           CLE  GPIO_02
 231           ALE  GPIO_03
 232           R/B  GPIO_04
 233         */
 234        /* output select */
 235        out_be32((volatile unsigned *)GPIO0_OSRH, in_be32((volatile unsigned *)GPIO0_OSRH) & 0xC0FFFFFF);
 236        /* three-state select */
 237        out_be32((volatile unsigned *)GPIO0_TSRH, in_be32((volatile unsigned *)GPIO0_TSRH) & 0xC0FFFFFF);
 238        /* enable output driver */
 239        out_be32((volatile unsigned *)GPIO0_TCR,
 240                 in_be32((volatile unsigned *)GPIO0_TCR) | NAND_nCE_GPIO_PIN | NAND_CLE_GPIO_PIN | NAND_ALE_GPIO_PIN);
 241#ifdef USE_READY_BUSY_PIN
 242        /* three-state select */
 243        out_be32((volatile unsigned *)GPIO0_TSRH, in_be32((volatile unsigned *)GPIO0_TSRH) & 0xFF3FFFFF);
 244        /* high-impedecence */
 245        out_be32((volatile unsigned *)GPIO0_TCR, in_be32((volatile unsigned *)GPIO0_TCR) & (~NAND_RB_GPIO_PIN));
 246        /* input select */
 247        out_be32((volatile unsigned *)GPIO0_ISR1H,
 248                 (in_be32((volatile unsigned *)GPIO0_ISR1H) & 0xFF3FFFFF) | 0x00400000);
 249#endif
 250
 251        /* insert callbacks */
 252        this->IO_ADDR_R = ppchameleon_fio_base;
 253        this->IO_ADDR_W = ppchameleon_fio_base;
 254        this->cmd_ctrl = ppchameleon_hwcontrol;
 255#ifdef USE_READY_BUSY_PIN
 256        this->dev_ready = ppchameleon_device_ready;
 257#endif
 258        this->chip_delay = NAND_BIG_DELAY_US;
 259        /* ECC mode */
 260        this->ecc.mode = NAND_ECC_SOFT;
 261
 262        /* Scan to find existence of the device (it could not be mounted) */
 263        if (nand_scan(ppchameleon_mtd, 1)) {
 264                iounmap((void *)ppchameleon_fio_base);
 265                ppchameleon_fio_base = NULL;
 266                kfree(ppchameleon_mtd);
 267                goto nand_evb_init;
 268        }
 269#ifndef USE_READY_BUSY_PIN
 270        /* Adjust delay if necessary */
 271        if (ppchameleon_mtd->size == NAND_SMALL_SIZE)
 272                this->chip_delay = NAND_SMALL_DELAY_US;
 273#endif
 274
 275        ppchameleon_mtd->name = "ppchameleon-nand";
 276
 277        /* Register the partitions */
 278        mtd_device_parse_register(ppchameleon_mtd, NULL, NULL,
 279                                  ppchameleon_mtd->size == NAND_SMALL_SIZE ?
 280                                        partition_info_me : partition_info_hi,
 281                                  NUM_PARTITIONS);
 282
 283 nand_evb_init:
 284        /****************************
 285        * EVB NAND (always present) *
 286        ****************************/
 287        /* Allocate memory for MTD device structure and private data */
 288        ppchameleonevb_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
 289        if (!ppchameleonevb_mtd) {
 290                printk("Unable to allocate PPChameleonEVB NAND MTD device structure.\n");
 291                if (ppchameleon_fio_base)
 292                        iounmap(ppchameleon_fio_base);
 293                return -ENOMEM;
 294        }
 295
 296        /* map physical address */
 297        ppchameleonevb_fio_base = ioremap(ppchameleonevb_fio_pbase, SZ_4M);
 298        if (!ppchameleonevb_fio_base) {
 299                printk("ioremap PPChameleonEVB NAND flash failed\n");
 300                kfree(ppchameleonevb_mtd);
 301                if (ppchameleon_fio_base)
 302                        iounmap(ppchameleon_fio_base);
 303                return -EIO;
 304        }
 305
 306        /* Get pointer to private data */
 307        this = (struct nand_chip *)(&ppchameleonevb_mtd[1]);
 308
 309        /* Initialize structures */
 310        memset(ppchameleonevb_mtd, 0, sizeof(struct mtd_info));
 311        memset(this, 0, sizeof(struct nand_chip));
 312
 313        /* Link the private data with the MTD structure */
 314        ppchameleonevb_mtd->priv = this;
 315
 316        /* Initialize GPIOs */
 317        /* Pin mapping for NAND chip */
 318        /*
 319           CE   GPIO_14
 320           CLE  GPIO_15
 321           ALE  GPIO_16
 322           R/B  GPIO_31
 323         */
 324        /* output select */
 325        out_be32((volatile unsigned *)GPIO0_OSRH, in_be32((volatile unsigned *)GPIO0_OSRH) & 0xFFFFFFF0);
 326        out_be32((volatile unsigned *)GPIO0_OSRL, in_be32((volatile unsigned *)GPIO0_OSRL) & 0x3FFFFFFF);
 327        /* three-state select */
 328        out_be32((volatile unsigned *)GPIO0_TSRH, in_be32((volatile unsigned *)GPIO0_TSRH) & 0xFFFFFFF0);
 329        out_be32((volatile unsigned *)GPIO0_TSRL, in_be32((volatile unsigned *)GPIO0_TSRL) & 0x3FFFFFFF);
 330        /* enable output driver */
 331        out_be32((volatile unsigned *)GPIO0_TCR, in_be32((volatile unsigned *)GPIO0_TCR) | NAND_EVB_nCE_GPIO_PIN |
 332                 NAND_EVB_CLE_GPIO_PIN | NAND_EVB_ALE_GPIO_PIN);
 333#ifdef USE_READY_BUSY_PIN
 334        /* three-state select */
 335        out_be32((volatile unsigned *)GPIO0_TSRL, in_be32((volatile unsigned *)GPIO0_TSRL) & 0xFFFFFFFC);
 336        /* high-impedecence */
 337        out_be32((volatile unsigned *)GPIO0_TCR, in_be32((volatile unsigned *)GPIO0_TCR) & (~NAND_EVB_RB_GPIO_PIN));
 338        /* input select */
 339        out_be32((volatile unsigned *)GPIO0_ISR1L,
 340                 (in_be32((volatile unsigned *)GPIO0_ISR1L) & 0xFFFFFFFC) | 0x00000001);
 341#endif
 342
 343        /* insert callbacks */
 344        this->IO_ADDR_R = ppchameleonevb_fio_base;
 345        this->IO_ADDR_W = ppchameleonevb_fio_base;
 346        this->cmd_ctrl = ppchameleonevb_hwcontrol;
 347#ifdef USE_READY_BUSY_PIN
 348        this->dev_ready = ppchameleonevb_device_ready;
 349#endif
 350        this->chip_delay = NAND_SMALL_DELAY_US;
 351
 352        /* ECC mode */
 353        this->ecc.mode = NAND_ECC_SOFT;
 354
 355        /* Scan to find existence of the device */
 356        if (nand_scan(ppchameleonevb_mtd, 1)) {
 357                iounmap((void *)ppchameleonevb_fio_base);
 358                kfree(ppchameleonevb_mtd);
 359                if (ppchameleon_fio_base)
 360                        iounmap(ppchameleon_fio_base);
 361                return -ENXIO;
 362        }
 363
 364        ppchameleonevb_mtd->name = NAND_EVB_MTD_NAME;
 365
 366        /* Register the partitions */
 367        mtd_device_parse_register(ppchameleonevb_mtd, NULL, NULL,
 368                                  ppchameleon_mtd->size == NAND_SMALL_SIZE ?
 369                                  partition_info_me : partition_info_hi,
 370                                  NUM_PARTITIONS);
 371
 372        /* Return happy */
 373        return 0;
 374}
 375
 376module_init(ppchameleonevb_init);
 377
 378/*
 379 * Clean up routine
 380 */
 381static void __exit ppchameleonevb_cleanup(void)
 382{
 383        struct nand_chip *this;
 384
 385        /* Release resources, unregister device(s) */
 386        nand_release(ppchameleon_mtd);
 387        nand_release(ppchameleonevb_mtd);
 388
 389        /* Release iomaps */
 390        this = (struct nand_chip *) &ppchameleon_mtd[1];
 391        iounmap((void *) this->IO_ADDR_R);
 392        this = (struct nand_chip *) &ppchameleonevb_mtd[1];
 393        iounmap((void *) this->IO_ADDR_R);
 394
 395        /* Free the MTD device structure */
 396        kfree (ppchameleon_mtd);
 397        kfree (ppchameleonevb_mtd);
 398}
 399module_exit(ppchameleonevb_cleanup);
 400
 401MODULE_LICENSE("GPL");
 402MODULE_AUTHOR("DAVE Srl <support-ppchameleon@dave-tech.it>");
 403MODULE_DESCRIPTION("MTD map driver for DAVE Srl PPChameleonEVB board");
 404