This source file includes following definitions.
- au_read_byte
- au_write_byte
- au_read_byte16
- au_write_byte16
- au_write_buf
- au_read_buf
- au_write_buf16
- au_read_buf16
- au1550_hwcontrol
- au1550_device_ready
- au1550_select_chip
- au1550_command
- find_nand_cs
- au1550nd_probe
- au1550nd_remove
   1 
   2 
   3 
   4 
   5 
   6 #include <linux/slab.h>
   7 #include <linux/module.h>
   8 #include <linux/interrupt.h>
   9 #include <linux/mtd/mtd.h>
  10 #include <linux/mtd/rawnand.h>
  11 #include <linux/mtd/partitions.h>
  12 #include <linux/platform_device.h>
  13 #include <asm/io.h>
  14 #include <asm/mach-au1x00/au1000.h>
  15 #include <asm/mach-au1x00/au1550nd.h>
  16 
  17 
  18 struct au1550nd_ctx {
  19         struct nand_chip chip;
  20 
  21         int cs;
  22         void __iomem *base;
  23         void (*write_byte)(struct nand_chip *, u_char);
  24 };
  25 
  26 
  27 
  28 
  29 
  30 
  31 
  32 static u_char au_read_byte(struct nand_chip *this)
  33 {
  34         u_char ret = readb(this->legacy.IO_ADDR_R);
  35         wmb(); 
  36         return ret;
  37 }
  38 
  39 
  40 
  41 
  42 
  43 
  44 
  45 
  46 static void au_write_byte(struct nand_chip *this, u_char byte)
  47 {
  48         writeb(byte, this->legacy.IO_ADDR_W);
  49         wmb(); 
  50 }
  51 
  52 
  53 
  54 
  55 
  56 
  57 
  58 static u_char au_read_byte16(struct nand_chip *this)
  59 {
  60         u_char ret = (u_char) cpu_to_le16(readw(this->legacy.IO_ADDR_R));
  61         wmb(); 
  62         return ret;
  63 }
  64 
  65 
  66 
  67 
  68 
  69 
  70 
  71 
  72 static void au_write_byte16(struct nand_chip *this, u_char byte)
  73 {
  74         writew(le16_to_cpu((u16) byte), this->legacy.IO_ADDR_W);
  75         wmb(); 
  76 }
  77 
  78 
  79 
  80 
  81 
  82 
  83 
  84 
  85 
  86 static void au_write_buf(struct nand_chip *this, const u_char *buf, int len)
  87 {
  88         int i;
  89 
  90         for (i = 0; i < len; i++) {
  91                 writeb(buf[i], this->legacy.IO_ADDR_W);
  92                 wmb(); 
  93         }
  94 }
  95 
  96 
  97 
  98 
  99 
 100 
 101 
 102 
 103 
 104 static void au_read_buf(struct nand_chip *this, u_char *buf, int len)
 105 {
 106         int i;
 107 
 108         for (i = 0; i < len; i++) {
 109                 buf[i] = readb(this->legacy.IO_ADDR_R);
 110                 wmb(); 
 111         }
 112 }
 113 
 114 
 115 
 116 
 117 
 118 
 119 
 120 
 121 
 122 static void au_write_buf16(struct nand_chip *this, const u_char *buf, int len)
 123 {
 124         int i;
 125         u16 *p = (u16 *) buf;
 126         len >>= 1;
 127 
 128         for (i = 0; i < len; i++) {
 129                 writew(p[i], this->legacy.IO_ADDR_W);
 130                 wmb(); 
 131         }
 132 
 133 }
 134 
 135 
 136 
 137 
 138 
 139 
 140 
 141 
 142 
 143 static void au_read_buf16(struct nand_chip *this, u_char *buf, int len)
 144 {
 145         int i;
 146         u16 *p = (u16 *) buf;
 147         len >>= 1;
 148 
 149         for (i = 0; i < len; i++) {
 150                 p[i] = readw(this->legacy.IO_ADDR_R);
 151                 wmb(); 
 152         }
 153 }
 154 
 155 
 156 #define NAND_CTL_SETNCE         1
 157 
 158 #define NAND_CTL_CLRNCE         2
 159 
 160 #define NAND_CTL_SETCLE         3
 161 
 162 #define NAND_CTL_CLRCLE         4
 163 
 164 #define NAND_CTL_SETALE         5
 165 
 166 #define NAND_CTL_CLRALE         6
 167 
 168 static void au1550_hwcontrol(struct mtd_info *mtd, int cmd)
 169 {
 170         struct nand_chip *this = mtd_to_nand(mtd);
 171         struct au1550nd_ctx *ctx = container_of(this, struct au1550nd_ctx,
 172                                                 chip);
 173 
 174         switch (cmd) {
 175 
 176         case NAND_CTL_SETCLE:
 177                 this->legacy.IO_ADDR_W = ctx->base + MEM_STNAND_CMD;
 178                 break;
 179 
 180         case NAND_CTL_CLRCLE:
 181                 this->legacy.IO_ADDR_W = ctx->base + MEM_STNAND_DATA;
 182                 break;
 183 
 184         case NAND_CTL_SETALE:
 185                 this->legacy.IO_ADDR_W = ctx->base + MEM_STNAND_ADDR;
 186                 break;
 187 
 188         case NAND_CTL_CLRALE:
 189                 this->legacy.IO_ADDR_W = ctx->base + MEM_STNAND_DATA;
 190                 
 191 
 192                 udelay(1);
 193                 break;
 194 
 195         case NAND_CTL_SETNCE:
 196                 
 197                 alchemy_wrsmem((1 << (4 + ctx->cs)), AU1000_MEM_STNDCTL);
 198                 break;
 199 
 200         case NAND_CTL_CLRNCE:
 201                 
 202                 alchemy_wrsmem(0, AU1000_MEM_STNDCTL);
 203                 break;
 204         }
 205 
 206         this->legacy.IO_ADDR_R = this->legacy.IO_ADDR_W;
 207 
 208         wmb(); 
 209 }
 210 
 211 int au1550_device_ready(struct nand_chip *this)
 212 {
 213         return (alchemy_rdsmem(AU1000_MEM_STSTAT) & 0x1) ? 1 : 0;
 214 }
 215 
 216 
 217 
 218 
 219 
 220 
 221 
 222 
 223 
 224 
 225 
 226 
 227 
 228 static void au1550_select_chip(struct nand_chip *this, int chip)
 229 {
 230 }
 231 
 232 
 233 
 234 
 235 
 236 
 237 
 238 
 239 static void au1550_command(struct nand_chip *this, unsigned command,
 240                            int column, int page_addr)
 241 {
 242         struct mtd_info *mtd = nand_to_mtd(this);
 243         struct au1550nd_ctx *ctx = container_of(this, struct au1550nd_ctx,
 244                                                 chip);
 245         int ce_override = 0, i;
 246         unsigned long flags = 0;
 247 
 248         
 249         au1550_hwcontrol(mtd, NAND_CTL_SETCLE);
 250         
 251 
 252 
 253         if (command == NAND_CMD_SEQIN) {
 254                 int readcmd;
 255 
 256                 if (column >= mtd->writesize) {
 257                         
 258                         column -= mtd->writesize;
 259                         readcmd = NAND_CMD_READOOB;
 260                 } else if (column < 256) {
 261                         
 262                         readcmd = NAND_CMD_READ0;
 263                 } else {
 264                         column -= 256;
 265                         readcmd = NAND_CMD_READ1;
 266                 }
 267                 ctx->write_byte(this, readcmd);
 268         }
 269         ctx->write_byte(this, command);
 270 
 271         
 272         au1550_hwcontrol(mtd, NAND_CTL_CLRCLE);
 273 
 274         if (column != -1 || page_addr != -1) {
 275                 au1550_hwcontrol(mtd, NAND_CTL_SETALE);
 276 
 277                 
 278                 if (column != -1) {
 279                         
 280                         if (this->options & NAND_BUSWIDTH_16 &&
 281                                         !nand_opcode_8bits(command))
 282                                 column >>= 1;
 283                         ctx->write_byte(this, column);
 284                 }
 285                 if (page_addr != -1) {
 286                         ctx->write_byte(this, (u8)(page_addr & 0xff));
 287 
 288                         if (command == NAND_CMD_READ0 ||
 289                             command == NAND_CMD_READ1 ||
 290                             command == NAND_CMD_READOOB) {
 291                                 
 292 
 293 
 294 
 295 
 296 
 297 
 298 
 299                                 ce_override = 1;
 300                                 local_irq_save(flags);
 301                                 au1550_hwcontrol(mtd, NAND_CTL_SETNCE);
 302                         }
 303 
 304                         ctx->write_byte(this, (u8)(page_addr >> 8));
 305 
 306                         if (this->options & NAND_ROW_ADDR_3)
 307                                 ctx->write_byte(this,
 308                                                 ((page_addr >> 16) & 0x0f));
 309                 }
 310                 
 311                 au1550_hwcontrol(mtd, NAND_CTL_CLRALE);
 312         }
 313 
 314         
 315 
 316 
 317 
 318         switch (command) {
 319 
 320         case NAND_CMD_PAGEPROG:
 321         case NAND_CMD_ERASE1:
 322         case NAND_CMD_ERASE2:
 323         case NAND_CMD_SEQIN:
 324         case NAND_CMD_STATUS:
 325                 return;
 326 
 327         case NAND_CMD_RESET:
 328                 break;
 329 
 330         case NAND_CMD_READ0:
 331         case NAND_CMD_READ1:
 332         case NAND_CMD_READOOB:
 333                 
 334                 if (unlikely(!ce_override))
 335                         break;
 336 
 337                 
 338                 ndelay(100);
 339                 
 340                 for (i = this->legacy.chip_delay;
 341                      !this->legacy.dev_ready(this) && i > 0; --i)
 342                         udelay(1);
 343 
 344                 
 345                 au1550_hwcontrol(mtd, NAND_CTL_CLRNCE);
 346                 local_irq_restore(flags);
 347                 return;
 348         }
 349         
 350         ndelay(100);
 351 
 352         while(!this->legacy.dev_ready(this));
 353 }
 354 
 355 static int find_nand_cs(unsigned long nand_base)
 356 {
 357         void __iomem *base =
 358                         (void __iomem *)KSEG1ADDR(AU1000_STATIC_MEM_PHYS_ADDR);
 359         unsigned long addr, staddr, start, mask, end;
 360         int i;
 361 
 362         for (i = 0; i < 4; i++) {
 363                 addr = 0x1000 + (i * 0x10);                     
 364                 staddr = __raw_readl(base + addr + 0x08);       
 365                 
 366                 start = (staddr << 4) & 0xfffc0000;
 367                 mask = (staddr << 18) & 0xfffc0000;
 368                 end = (start | (start - 1)) & ~(start ^ mask);
 369                 if ((nand_base >= start) && (nand_base < end))
 370                         return i;
 371         }
 372 
 373         return -ENODEV;
 374 }
 375 
 376 static int au1550nd_probe(struct platform_device *pdev)
 377 {
 378         struct au1550nd_platdata *pd;
 379         struct au1550nd_ctx *ctx;
 380         struct nand_chip *this;
 381         struct mtd_info *mtd;
 382         struct resource *r;
 383         int ret, cs;
 384 
 385         pd = dev_get_platdata(&pdev->dev);
 386         if (!pd) {
 387                 dev_err(&pdev->dev, "missing platform data\n");
 388                 return -ENODEV;
 389         }
 390 
 391         ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
 392         if (!ctx)
 393                 return -ENOMEM;
 394 
 395         r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 396         if (!r) {
 397                 dev_err(&pdev->dev, "no NAND memory resource\n");
 398                 ret = -ENODEV;
 399                 goto out1;
 400         }
 401         if (request_mem_region(r->start, resource_size(r), "au1550-nand")) {
 402                 dev_err(&pdev->dev, "cannot claim NAND memory area\n");
 403                 ret = -ENOMEM;
 404                 goto out1;
 405         }
 406 
 407         ctx->base = ioremap_nocache(r->start, 0x1000);
 408         if (!ctx->base) {
 409                 dev_err(&pdev->dev, "cannot remap NAND memory area\n");
 410                 ret = -ENODEV;
 411                 goto out2;
 412         }
 413 
 414         this = &ctx->chip;
 415         mtd = nand_to_mtd(this);
 416         mtd->dev.parent = &pdev->dev;
 417 
 418         
 419         cs = find_nand_cs(r->start);
 420         if (cs < 0) {
 421                 dev_err(&pdev->dev, "cannot detect NAND chipselect\n");
 422                 ret = -ENODEV;
 423                 goto out3;
 424         }
 425         ctx->cs = cs;
 426 
 427         this->legacy.dev_ready = au1550_device_ready;
 428         this->legacy.select_chip = au1550_select_chip;
 429         this->legacy.cmdfunc = au1550_command;
 430 
 431         
 432         this->legacy.chip_delay = 30;
 433         this->ecc.mode = NAND_ECC_SOFT;
 434         this->ecc.algo = NAND_ECC_HAMMING;
 435 
 436         if (pd->devwidth)
 437                 this->options |= NAND_BUSWIDTH_16;
 438 
 439         this->legacy.read_byte = (pd->devwidth) ? au_read_byte16 : au_read_byte;
 440         ctx->write_byte = (pd->devwidth) ? au_write_byte16 : au_write_byte;
 441         this->legacy.write_buf = (pd->devwidth) ? au_write_buf16 : au_write_buf;
 442         this->legacy.read_buf = (pd->devwidth) ? au_read_buf16 : au_read_buf;
 443 
 444         ret = nand_scan(this, 1);
 445         if (ret) {
 446                 dev_err(&pdev->dev, "NAND scan failed with %d\n", ret);
 447                 goto out3;
 448         }
 449 
 450         mtd_device_register(mtd, pd->parts, pd->num_parts);
 451 
 452         platform_set_drvdata(pdev, ctx);
 453 
 454         return 0;
 455 
 456 out3:
 457         iounmap(ctx->base);
 458 out2:
 459         release_mem_region(r->start, resource_size(r));
 460 out1:
 461         kfree(ctx);
 462         return ret;
 463 }
 464 
 465 static int au1550nd_remove(struct platform_device *pdev)
 466 {
 467         struct au1550nd_ctx *ctx = platform_get_drvdata(pdev);
 468         struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 469 
 470         nand_release(&ctx->chip);
 471         iounmap(ctx->base);
 472         release_mem_region(r->start, 0x1000);
 473         kfree(ctx);
 474         return 0;
 475 }
 476 
 477 static struct platform_driver au1550nd_driver = {
 478         .driver = {
 479                 .name   = "au1550-nand",
 480         },
 481         .probe          = au1550nd_probe,
 482         .remove         = au1550nd_remove,
 483 };
 484 
 485 module_platform_driver(au1550nd_driver);
 486 
 487 MODULE_LICENSE("GPL");
 488 MODULE_AUTHOR("Embedded Edge, LLC");
 489 MODULE_DESCRIPTION("Board-specific glue layer for NAND flash on Pb1550 board");