Implemented writing, not working yet.
authorMarkus Klotzbücher <Markus Klotzbümk@pollux.denx.de>
Fri, 3 Mar 2006 11:11:11 +0000 (12:11 +0100)
committerMarkus Klotzbücher <mk@pollux.denx.de>
Fri, 3 Mar 2006 11:11:11 +0000 (12:11 +0100)
board/delta/nand.c

index da6430d..ef78e30 100644 (file)
@@ -46,6 +46,48 @@ static int delta_device_ready(struct mtd_info *mtdinfo)
        return 0;
 }
 
+/*
+ * Write buf to the DFC Controller Data Buffer
+ */
+static void delta_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
+{
+       unsigned long bytes_multi = len & 0xfffffffc;
+       unsigned long rest = len & 0x3;
+       unsigned long *long_buf;
+       int i;
+
+       if(bytes_multi) {
+               for(i=0; i<bytes_multi; i+=4) {
+                       long_buf = (unsigned long*) &buf[i];
+                       NDDB = *long_buf;
+               }
+       }
+       if(rest) {
+               printf("delta_write_buf: ERROR, writing non 4-byte aligned data.\n");
+       }
+       return;
+}
+
+
+/* 
+ * These functions are quite problematic for the DFC. Luckily they are
+ * not used in the current nand code, except for nand_command, which
+ * we've defined our own anyway. The problem is, that we always need
+ * to write 4 bytes to the DFC Data Buffer, but in these functions we
+ * don't know if to buffer the bytes/half words until we've gathered 4
+ * bytes or if to send them straight away.
+ *
+ * Solution: Don't use these with Mona's DFC and complain loudly.
+ */
+static void delta_write_word(struct mtd_info *mtd, u16 word)
+{
+       printf("delta_write_word: WARNING, this function does not work with the Monahans DFC!\n");
+}
+static void delta_write_byte(struct mtd_info *mtd, u_char byte)
+{
+       printf("delta_write_byte: WARNING, this function does not work with the Monahans DFC!\n");
+}
+
 /* The original:
  * static void delta_read_buf(struct mtd_info *mtd, const u_char *buf, int len)
  *
@@ -57,14 +99,14 @@ static void delta_read_buf(struct mtd_info *mtd, u_char* const buf, int len)
 
        /* we have to be carefull not to overflow the buffer if len is
         * not a multiple of 4 */
-       unsigned long num_words = len & 0xfffffffc;
+       unsigned long bytes_multi = len & 0xfffffffc;
        unsigned long rest = len & 0x3;
+       unsigned long *long_buf;
 
        /* if there are any, first copy multiple of 4 bytes */
-       if(num_words) {
-               for(i=0; i<num_words; i+=4) {
-                       unsigned long *long_buf = &buf[i];
-/*                     ((unsigned long *) &buf[i]) = NDDB; */
+       if(bytes_multi) {
+               for(i=0; i<bytes_multi; i+=4) {
+                       long_buf = (unsigned long*) &buf[i];
                        *long_buf = NDDB;
                }
        }
@@ -72,30 +114,22 @@ static void delta_read_buf(struct mtd_info *mtd, u_char* const buf, int len)
        /* ...then the rest */
        if(rest) {
                unsigned long rest_data = NDDB;
-               for(j=0;j<rest;j++)
+               for(j=0;j<rest; j++)
                        buf[i+j] = (u_char) ((rest_data>>j) & 0xff);
        }
 
        return;
 }
 
-/* global var, too bad */
+static void delta_read_word(struct mtd_info *mtd, u_char byte)
+{
+       printf("delta_write_byte: UNIMPLEMENTED.\n");
+}
+
+/* global var, too bad: mk@tbd: move to ->priv pointer */
 static unsigned long read_buf = 0;
 static unsigned char bytes_read = 0;
 
-/* wait for read request */
-static void delta_wait_event(unsigned long event)
-{
-       if(!event)
-               return;
-       
-       while(1) {
-               if(NDSR & event) {
-                       NDSR |= event;
-                       break;
-               }
-       }
-}
 static u_char delta_read_byte(struct mtd_info *mtd)
 {
 /*     struct nand_chip *this = mtd->priv; */
@@ -113,16 +147,50 @@ static u_char delta_read_byte(struct mtd_info *mtd)
        return byte;
 }
 
+/* delay function */
+static void wait(unsigned long us)
+{
+#define OSCR_CLK_FREQ 3.250 /* kHz */
+
+       unsigned long start = OSCR;
+       unsigned long delta = 0, cur;
+       us *= OSCR_CLK_FREQ;
+
+       while (delta < us) {
+               cur = OSCR;
+               if(cur < start) /* OSCR overflowed */
+                       delta = cur + (start^0xffffffff);
+               else
+                       delta = cur - start;
+       }
+}
+
+/* poll the NAND Controller Status Register for event */
+static void delta_wait_event(unsigned long event)
+{
+       if(!event)
+               return;
+       
+       while(1) {
+               if(NDSR & event) {
+                       NDSR |= event;
+                       break;
+               }
+       }
+}
+
 /* this is really monahans, not board specific ... */
 static void delta_cmdfunc(struct mtd_info *mtd, unsigned command, 
                          int column, int page_addr)
 {
        /* register struct nand_chip *this = mtd->priv; */
        unsigned long ndcb0=0, ndcb1=0, ndcb2=0, event=0;
+       unsigned long what_the_hack;
 
        /* clear the ugly byte read buffer */
        bytes_read = 0;
        read_buf = 0;
+
        
        /* Clear NDSR */
        NDSR = 0xFFF;
@@ -160,29 +228,76 @@ static void delta_cmdfunc(struct mtd_info *mtd, unsigned command,
                event = NDSR_RDDREQ;
                break;
        case NAND_CMD_PAGEPROG:
+               printk("delta_cmdfunc: NAND_CMD_PAGEPROG.\n");
+               ndcb0 = (NAND_CMD_PAGEPROG | (1 << 21));
                break;
        case NAND_CMD_ERASE1:
        case NAND_CMD_ERASE2:
+               printf("delta_cmdfunc: NAND_CMD_ERASEx unimplemented.\n");
                break;
        case NAND_CMD_SEQIN:
-               ndcb0 = (NAND_CMD_SEQIN<<8) | (1<<19) | (4<<16);
-               if(column >= mtd->oobblock) {
-                       /* OOB area */
-                       column -= mtd->oobblock;
-                       ndcb0 |= NAND_CMD_READOOB;
-               } else if (column < 256) {
-                       /* First 256 bytes --> READ0 */
-                       ndcb0 |= NAND_CMD_READ0;
-               } else {
-                       /* Only for 8 bit devices - not delta!!! */
-                       column -= 256;
-                       ndcb0 |= NAND_CMD_READ1;
-               }
+               /* send PAGE_PROG command(0x80) */
+               printf("delta_cmdfunc: NAND_CMD_SEQIN/PAGE_PROG.\n");
+               ndcb0 = (NAND_CMD_SEQIN | (1<<21) | (3<<16));
+               column >>= 1; /* adjust for 16 bit bus */
+               ndcb1 = (((column>>1) & 0xff) |
+                        ((page_addr<<8) & 0xff00) |
+                        ((page_addr<<8) & 0xff0000) |
+                        ((page_addr<<8) & 0xff000000)); /* make this 0x01000000 ? */
+               event = NDSR_WRDREQ;
                break;
+/*     case NAND_CMD_SEQIN_pointer_operation: */
+
+/*             /\* This is confusing because the command names are */
+/*              * different compared to the ones in the K9K12Q0C */
+/*              * datasheet. Infact this has nothing to do with */
+/*              * reading, as the but with page programming */
+/*              * (writing). */
+/*              * Here we send the multibyte commands */
+/*              * cmd1=0x00, cmd2=0x80 (for programming main area) or */
+/*              * cmd1=0x50, cmd2=0x80 (for spare area) */
+/*              * */
+/*              * When all data is written to the buffer, the page */
+/*              * program command (0x10) is sent to actually write */
+/*              * the data. */
+/*              *\/ */
+
+/*             printf("delta_cmdfunc: NAND_CMD_SEQIN pointer op called.\n"); */
+
+/*             ndcb0 = (NAND_CMD_SEQIN<<8) | (1<<21) | (1<<19) | (4<<16); */
+/*             if(column >= mtd->oobblock) { */
+/*                     /\* OOB area *\/ */
+/*                     column -= mtd->oobblock; */
+/*                     ndcb0 |= NAND_CMD_READOOB; */
+/*             } else if (column < 256) { */
+/*                     /\* First 256 bytes --> READ0 *\/ */
+/*                     ndcb0 |= NAND_CMD_READ0; */
+/*             } else { */
+/*                     /\* Only for 8 bit devices - not delta!!! *\/ */
+/*                     column -= 256; */
+/*                     ndcb0 |= NAND_CMD_READ1; */
+/*             } */
+/*             event = NDSR_WRDREQ; */
+/*             break; */
        case NAND_CMD_STATUS:
-               return;
+               /* oh, this is not nice. for some reason the real
+                * status byte is in the second read from the data
+                * buffer. The hack is to read the first byte right
+                * here, so the next read access by the nand code
+                * yields the right one.
+                */
+               ndcb0 = (NAND_CMD_STATUS | (4<<21));
+               event = NDSR_RDDREQ;
+               NDCB0 = ndcb0;
+               NDCB0 = ndcb1;
+               NDCB0 = ndcb2;
+               delta_wait_event(event);
+               what_the_hack = NDDB;
+               goto end;
+               break;
        case NAND_CMD_RESET:
-               return;
+               printf("delta_cmdfunc: NAND_CMD_RESET unimplemented.\n");
+               break;
        default:
                printk("delta_cmdfunc: error, unsupported command.\n");
                return;
@@ -194,6 +309,8 @@ static void delta_cmdfunc(struct mtd_info *mtd, unsigned command,
 
        /* wait for event */
        delta_wait_event(event);
+ end:
+       return;
 }
 
 static void delta_dfc_gpio_init()
@@ -251,23 +368,6 @@ static void delta_dfc_gpio_init()
  * Members with a "?" were not set in the merged testing-NAND branch,
  * so they are not set here either.
  */
-void wait(unsigned long us)
-{
-#define OSCR_CLK_FREQ 3.250 /* kHz */
-
-       unsigned long start = OSCR;
-       unsigned long delta = 0, cur;
-       us *= OSCR_CLK_FREQ;
-
-       while (delta < us) {
-               cur = OSCR;
-               if(cur < start) /* OSCR overflowed */
-                       delta = cur + (start^0xffffffff);
-               else
-                       delta = cur - start;
-       }
-}
-
 void board_nand_init(struct nand_chip *nand)
 {
        unsigned long tCH, tCS, tWH, tWP, tRH, tRP, tRP_high, tR, tWHR, tAR;
@@ -402,13 +502,17 @@ void board_nand_init(struct nand_chip *nand)
        nand->eccmode = NAND_ECC_SOFT;
        nand->chip_delay = NAND_DELAY_US;
        nand->options = NAND_BUSWIDTH_16;
+
        nand->read_byte = delta_read_byte;
+       nand->write_byte = delta_write_byte;
+       nand->read_word = delta_read_word;
+       nand->write_word = delta_write_word;
        nand->read_buf = delta_read_buf;
+       nand->write_buf = delta_write_buf;
        nand->cmdfunc = delta_cmdfunc;
-       /*      nand->options = NAND_SAMSUNG_LP_OPTIONS; */
 }
 
 #else
-#error "U-Boot legacy NAND support not available for delta board."
+ #error "U-Boot legacy NAND support not available for delta board."
 #endif
 #endif