]> git.sur5r.net Git - u-boot/blob - board/prodrive/pdnb3/nand.c
Merge git://git.denx.de/u-boot-arm
[u-boot] / board / prodrive / pdnb3 / nand.c
1 /*
2  * (C) Copyright 2006
3  * Stefan Roese, DENX Software Engineering, sr@denx.de.
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 #include <common.h>
9
10 #if defined(CONFIG_CMD_NAND)
11
12 #include <nand.h>
13
14 struct pdnb3_ndfc_regs {
15         uchar cmd;
16         uchar wait;
17         uchar addr;
18         uchar term;
19         uchar data;
20 };
21
22 static u8 hwctl;
23 static struct pdnb3_ndfc_regs *pdnb3_ndfc;
24
25 #define readb(addr)     *(volatile u_char *)(addr)
26 #define readl(addr)     *(volatile u_long *)(addr)
27 #define writeb(d,addr)  *(volatile u_char *)(addr) = (d)
28
29 /*
30  * The PDNB3 has a NAND Flash Controller (NDFC) that handles all accesses to
31  * the NAND devices.  The NDFC has command, address and data registers that
32  * when accessed will set up the NAND flash pins appropriately.  We'll use the
33  * hwcontrol function to save the configuration in a global variable.
34  * We can then use this information in the read and write functions to
35  * determine which NDFC register to access.
36  *
37  * There is one NAND devices on the board, a Hynix HY27US08561A (32 MByte).
38  */
39 static void pdnb3_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
40 {
41         struct nand_chip *this = mtd->priv;
42
43         if (ctrl & NAND_CTRL_CHANGE) {
44                 if ( ctrl & NAND_CLE )
45                         hwctl |= 0x1;
46                 else
47                         hwctl &= ~0x1;
48                 if ( ctrl & NAND_ALE )
49                         hwctl |= 0x2;
50                 else
51                         hwctl &= ~0x2;
52                 if ( (ctrl & NAND_NCE) != NAND_NCE)
53                         writeb(0x00, &(pdnb3_ndfc->term));
54         }
55         if (cmd != NAND_CMD_NONE)
56                 writeb(cmd, this->IO_ADDR_W);
57 }
58
59
60 static u_char pdnb3_nand_read_byte(struct mtd_info *mtd)
61 {
62         return readb(&(pdnb3_ndfc->data));
63 }
64
65 static void pdnb3_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
66 {
67         int i;
68
69         for (i = 0; i < len; i++) {
70                 if (hwctl & 0x1)
71                         writeb(buf[i], &(pdnb3_ndfc->cmd));
72                 else if (hwctl & 0x2)
73                         writeb(buf[i], &(pdnb3_ndfc->addr));
74                 else
75                         writeb(buf[i], &(pdnb3_ndfc->data));
76         }
77 }
78
79 static void pdnb3_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
80 {
81         int i;
82
83         for (i = 0; i < len; i++)
84                 buf[i] = readb(&(pdnb3_ndfc->data));
85 }
86
87 static int pdnb3_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
88 {
89         int i;
90
91         for (i = 0; i < len; i++)
92                 if (buf[i] != readb(&(pdnb3_ndfc->data)))
93                         return i;
94
95         return 0;
96 }
97
98 static int pdnb3_nand_dev_ready(struct mtd_info *mtd)
99 {
100         /*
101          * Blocking read to wait for NAND to be ready
102          */
103         readb(&(pdnb3_ndfc->wait));
104
105         /*
106          * Return always true
107          */
108         return 1;
109 }
110
111 int board_nand_init(struct nand_chip *nand)
112 {
113         pdnb3_ndfc = (struct pdnb3_ndfc_regs *)CONFIG_SYS_NAND_BASE;
114
115         nand->ecc.mode = NAND_ECC_SOFT;
116
117         /* Set address of NAND IO lines (Using Linear Data Access Region) */
118         nand->IO_ADDR_R = (void __iomem *) ((ulong) pdnb3_ndfc + 0x4);
119         nand->IO_ADDR_W = (void __iomem *) ((ulong) pdnb3_ndfc + 0x4);
120         /* Reference hardware control function */
121         nand->cmd_ctrl   = pdnb3_nand_hwcontrol;
122         nand->read_byte  = pdnb3_nand_read_byte;
123         nand->write_buf  = pdnb3_nand_write_buf;
124         nand->read_buf   = pdnb3_nand_read_buf;
125         nand->verify_buf = pdnb3_nand_verify_buf;
126         nand->dev_ready  = pdnb3_nand_dev_ready;
127         return 0;
128 }
129 #endif