Merge tag 'xilinx-for-v2020.07-rc2' of https://gitlab.denx.de/u-boot/custodians/u...
[oweals/u-boot.git] / board / socrates / nand.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2008
4  * Sergei Poselenov, Emcraft Systems, sposelenov@emcraft.com.
5  */
6
7 #include <common.h>
8
9 #if defined(CONFIG_SYS_NAND_BASE)
10 #include <nand.h>
11 #include <linux/errno.h>
12 #include <asm/io.h>
13
14 static int state;
15 static void sc_nand_write_byte(struct mtd_info *mtd, u_char byte);
16 static void sc_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len);
17 static u_char sc_nand_read_byte(struct mtd_info *mtd);
18 static u16 sc_nand_read_word(struct mtd_info *mtd);
19 static void sc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len);
20 static int sc_nand_device_ready(struct mtd_info *mtdinfo);
21
22 #define FPGA_NAND_CMD_MASK              (0x7 << 28)
23 #define FPGA_NAND_CMD_COMMAND           (0x0 << 28)
24 #define FPGA_NAND_CMD_ADDR              (0x1 << 28)
25 #define FPGA_NAND_CMD_READ              (0x2 << 28)
26 #define FPGA_NAND_CMD_WRITE             (0x3 << 28)
27 #define FPGA_NAND_BUSY                  (0x1 << 15)
28 #define FPGA_NAND_ENABLE                (0x1 << 31)
29 #define FPGA_NAND_DATA_SHIFT            16
30
31 /**
32  * sc_nand_write_byte -  write one byte to the chip
33  * @mtd:        MTD device structure
34  * @byte:       pointer to data byte to write
35  */
36 static void sc_nand_write_byte(struct mtd_info *mtd, u_char byte)
37 {
38         sc_nand_write_buf(mtd, (const uchar *)&byte, sizeof(byte));
39 }
40
41 /**
42  * sc_nand_write_buf -  write buffer to chip
43  * @mtd:        MTD device structure
44  * @buf:        data buffer
45  * @len:        number of bytes to write
46  */
47 static void sc_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
48 {
49         int i;
50         struct nand_chip *this = mtd_to_nand(mtd);
51
52         for (i = 0; i < len; i++) {
53                 out_be32(this->IO_ADDR_W,
54                          state | (buf[i] << FPGA_NAND_DATA_SHIFT));
55         }
56 }
57
58
59 /**
60  * sc_nand_read_byte -  read one byte from the chip
61  * @mtd:        MTD device structure
62  */
63 static u_char sc_nand_read_byte(struct mtd_info *mtd)
64 {
65         u8 byte;
66         sc_nand_read_buf(mtd, (uchar *)&byte, sizeof(byte));
67         return byte;
68 }
69
70 /**
71  * sc_nand_read_word -  read one word from the chip
72  * @mtd:        MTD device structure
73  */
74 static u16 sc_nand_read_word(struct mtd_info *mtd)
75 {
76         u16 word;
77         sc_nand_read_buf(mtd, (uchar *)&word, sizeof(word));
78         return word;
79 }
80
81 /**
82  * sc_nand_read_buf -  read chip data into buffer
83  * @mtd:        MTD device structure
84  * @buf:        buffer to store date
85  * @len:        number of bytes to read
86  */
87 static void sc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
88 {
89         int i;
90         struct nand_chip *this = mtd_to_nand(mtd);
91         int val;
92
93         val = (state & FPGA_NAND_ENABLE) | FPGA_NAND_CMD_READ;
94
95         out_be32(this->IO_ADDR_W, val);
96         for (i = 0; i < len; i++) {
97                 buf[i] = (in_be32(this->IO_ADDR_R) >> FPGA_NAND_DATA_SHIFT) & 0xff;
98         }
99 }
100
101 /**
102  * sc_nand_device_ready - Check the NAND device is ready for next command.
103  * @mtd:        MTD device structure
104  */
105 static int sc_nand_device_ready(struct mtd_info *mtdinfo)
106 {
107         struct nand_chip *this = mtd_to_nand(mtdinfo);
108
109         if (in_be32(this->IO_ADDR_W) & FPGA_NAND_BUSY)
110                 return 0; /* busy */
111         return 1;
112 }
113
114 /**
115  * sc_nand_hwcontrol - NAND control functions wrapper.
116  * @mtd:        MTD device structure
117  * @cmd:        Command
118  */
119 static void sc_nand_hwcontrol(struct mtd_info *mtdinfo, int cmd, unsigned int ctrl)
120 {
121         if (ctrl & NAND_CTRL_CHANGE) {
122                 state &= ~(FPGA_NAND_CMD_MASK | FPGA_NAND_ENABLE);
123
124                 switch (ctrl & (NAND_ALE | NAND_CLE)) {
125                 case 0:
126                         state |= FPGA_NAND_CMD_WRITE;
127                         break;
128
129                 case NAND_ALE:
130                         state |= FPGA_NAND_CMD_ADDR;
131                         break;
132
133                 case NAND_CLE:
134                         state |= FPGA_NAND_CMD_COMMAND;
135                         break;
136
137                 default:
138                         printf("%s: unknown ctrl %#x\n", __FUNCTION__, ctrl);
139                 }
140
141                 if (ctrl & NAND_NCE)
142                         state |= FPGA_NAND_ENABLE;
143         }
144
145         if (cmd != NAND_CMD_NONE)
146                 sc_nand_write_byte(mtdinfo, cmd);
147 }
148
149 int board_nand_init(struct nand_chip *nand)
150 {
151         nand->cmd_ctrl = sc_nand_hwcontrol;
152         nand->ecc.mode = NAND_ECC_SOFT;
153         nand->dev_ready = sc_nand_device_ready;
154         nand->read_byte = sc_nand_read_byte;
155         nand->read_word = sc_nand_read_word;
156         nand->write_buf = sc_nand_write_buf;
157         nand->read_buf = sc_nand_read_buf;
158
159         return 0;
160 }
161
162 #endif