]> git.sur5r.net Git - u-boot/blob - board/synopsys/axs10x/nand.c
SPDX: Convert all of our single license tags to Linux Kernel style
[u-boot] / board / synopsys / axs10x / nand.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
4  */
5
6 #include <bouncebuf.h>
7 #include <common.h>
8 #include <malloc.h>
9 #include <nand.h>
10 #include <asm/io.h>
11 #include "axs10x.h"
12
13 DECLARE_GLOBAL_DATA_PTR;
14
15 #define BUS_WIDTH       8               /* AXI data bus width in bytes  */
16
17 /* DMA buffer descriptor bits & masks */
18 #define BD_STAT_OWN                     (1 << 31)
19 #define BD_STAT_BD_FIRST                (1 << 3)
20 #define BD_STAT_BD_LAST                 (1 << 2)
21 #define BD_SIZES_BUFFER1_MASK           0xfff
22
23 #define BD_STAT_BD_COMPLETE     (BD_STAT_BD_FIRST | BD_STAT_BD_LAST)
24
25 /* Controller command flags */
26 #define B_WFR           (1 << 19)       /* 1b - Wait for ready          */
27 #define B_LC            (1 << 18)       /* 1b - Last cycle              */
28 #define B_IWC           (1 << 13)       /* 1b - Interrupt when complete */
29
30 /* NAND cycle types */
31 #define B_CT_ADDRESS    (0x0 << 16)     /* Address operation            */
32 #define B_CT_COMMAND    (0x1 << 16)     /* Command operation            */
33 #define B_CT_WRITE      (0x2 << 16)     /* Write operation              */
34 #define B_CT_READ       (0x3 << 16)     /* Write operation              */
35
36 enum nand_isr_t {
37         NAND_ISR_DATAREQUIRED = 0,
38         NAND_ISR_TXUNDERFLOW,
39         NAND_ISR_TXOVERFLOW,
40         NAND_ISR_DATAAVAILABLE,
41         NAND_ISR_RXUNDERFLOW,
42         NAND_ISR_RXOVERFLOW,
43         NAND_ISR_TXDMACOMPLETE,
44         NAND_ISR_RXDMACOMPLETE,
45         NAND_ISR_DESCRIPTORUNAVAILABLE,
46         NAND_ISR_CMDDONE,
47         NAND_ISR_CMDAVAILABLE,
48         NAND_ISR_CMDERROR,
49         NAND_ISR_DATATRANSFEROVER,
50         NAND_ISR_NONE
51 };
52
53 enum nand_regs_t {
54         AC_FIFO = 0,            /* address and command fifo */
55         IDMAC_BDADDR = 0x18,    /* idmac descriptor list base address */
56         INT_STATUS = 0x118,     /* interrupt status register */
57         INT_CLR_STATUS = 0x120, /* interrupt clear status register */
58 };
59
60 struct nand_bd {
61         uint32_t status;        /* DES0 */
62         uint32_t sizes;         /* DES1 */
63         uint32_t buffer_ptr0;   /* DES2 */
64         uint32_t buffer_ptr1;   /* DES3 */
65 };
66
67 #define NAND_REG_WRITE(r, v)    \
68         writel(v, (volatile void __iomem *)(CONFIG_SYS_NAND_BASE + r))
69 #define NAND_REG_READ(r)                \
70         readl((const volatile void __iomem *)(CONFIG_SYS_NAND_BASE + r))
71
72 static struct nand_bd *bd;      /* DMA buffer descriptors       */
73
74 /**
75  * axs101_nand_write_buf -  write buffer to chip
76  * @mtd:        MTD device structure
77  * @buf:        data buffer
78  * @len:        number of bytes to write
79  */
80 static uint32_t nand_flag_is_set(uint32_t flag)
81 {
82         uint32_t reg = NAND_REG_READ(INT_STATUS);
83
84         if (reg & (1 << NAND_ISR_CMDERROR))
85                 return 0;
86
87         if (reg & (1 << flag)) {
88                 NAND_REG_WRITE(INT_CLR_STATUS, 1 << flag);
89                 return 1;
90         }
91
92         return 0;
93 }
94
95 /**
96  * axs101_nand_write_buf -  write buffer to chip
97  * @mtd:        MTD device structure
98  * @buf:        data buffer
99  * @len:        number of bytes to write
100  */
101 static void axs101_nand_write_buf(struct mtd_info *mtd, const u_char *buf,
102                                    int len)
103 {
104         struct bounce_buffer bbstate;
105
106         bounce_buffer_start(&bbstate, (void *)buf, len, GEN_BB_READ);
107
108         /* Setup buffer descriptor */
109         writel(BD_STAT_OWN | BD_STAT_BD_COMPLETE, &bd->status);
110         writel(ALIGN(len, BUS_WIDTH) & BD_SIZES_BUFFER1_MASK, &bd->sizes);
111         writel(bbstate.bounce_buffer, &bd->buffer_ptr0);
112         writel(0, &bd->buffer_ptr1);
113
114         /* Flush modified buffer descriptor */
115         flush_dcache_range((unsigned long)bd,
116                            (unsigned long)bd + sizeof(struct nand_bd));
117
118         /* Issue "write" command */
119         NAND_REG_WRITE(AC_FIFO, B_CT_WRITE | B_WFR | B_IWC | B_LC | (len-1));
120
121         /* Wait for NAND command and DMA to complete */
122         while (!nand_flag_is_set(NAND_ISR_CMDDONE))
123                 ;
124         while (!nand_flag_is_set(NAND_ISR_TXDMACOMPLETE))
125                 ;
126
127         bounce_buffer_stop(&bbstate);
128 }
129
130 /**
131  * axs101_nand_read_buf -  read chip data into buffer
132  * @mtd:        MTD device structure
133  * @buf:        buffer to store data
134  * @len:        number of bytes to read
135  */
136 static void axs101_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
137 {
138         struct bounce_buffer bbstate;
139
140         bounce_buffer_start(&bbstate, buf, len, GEN_BB_WRITE);
141
142         /* Setup buffer descriptor */
143         writel(BD_STAT_OWN | BD_STAT_BD_COMPLETE, &bd->status);
144         writel(ALIGN(len, BUS_WIDTH) & BD_SIZES_BUFFER1_MASK, &bd->sizes);
145         writel(bbstate.bounce_buffer, &bd->buffer_ptr0);
146         writel(0, &bd->buffer_ptr1);
147
148         /* Flush modified buffer descriptor */
149         flush_dcache_range((unsigned long)bd,
150                            (unsigned long)bd + sizeof(struct nand_bd));
151
152         /* Issue "read" command */
153         NAND_REG_WRITE(AC_FIFO, B_CT_READ | B_WFR | B_IWC | B_LC | (len - 1));
154
155         /* Wait for NAND command and DMA to complete */
156         while (!nand_flag_is_set(NAND_ISR_CMDDONE))
157                 ;
158         while (!nand_flag_is_set(NAND_ISR_RXDMACOMPLETE))
159                 ;
160
161         bounce_buffer_stop(&bbstate);
162 }
163
164 /**
165  * axs101_nand_read_byte -  read one byte from the chip
166  * @mtd:        MTD device structure
167  */
168 static u_char axs101_nand_read_byte(struct mtd_info *mtd)
169 {
170         u8 byte;
171
172         axs101_nand_read_buf(mtd, (uchar *)&byte, sizeof(byte));
173         return byte;
174 }
175
176 /**
177  * axs101_nand_read_word -  read one word from the chip
178  * @mtd:        MTD device structure
179  */
180 static u16 axs101_nand_read_word(struct mtd_info *mtd)
181 {
182         u16 word;
183
184         axs101_nand_read_buf(mtd, (uchar *)&word, sizeof(word));
185         return word;
186 }
187
188 /**
189  * axs101_nand_hwcontrol - NAND control functions wrapper.
190  * @mtd:        MTD device structure
191  * @cmd:        Command
192  */
193 static void axs101_nand_hwcontrol(struct mtd_info *mtdinfo, int cmd,
194                                    unsigned int ctrl)
195 {
196         if (cmd == NAND_CMD_NONE)
197                 return;
198
199         cmd = cmd & 0xff;
200
201         switch (ctrl & (NAND_ALE | NAND_CLE)) {
202         /* Address */
203         case NAND_ALE:
204                 cmd |= B_CT_ADDRESS;
205                 break;
206
207         /* Command */
208         case NAND_CLE:
209                 cmd |= B_CT_COMMAND | B_WFR;
210
211                 break;
212
213         default:
214                 debug("%s: unknown ctrl %#x\n", __func__, ctrl);
215         }
216
217         NAND_REG_WRITE(AC_FIFO, cmd | B_LC);
218         while (!nand_flag_is_set(NAND_ISR_CMDDONE))
219                 ;
220 }
221
222 int board_nand_init(struct nand_chip *nand)
223 {
224         bd = (struct nand_bd *)memalign(ARCH_DMA_MINALIGN,
225                                         sizeof(struct nand_bd));
226
227         /* Set buffer descriptor address in IDMAC */
228         NAND_REG_WRITE(IDMAC_BDADDR, bd);
229
230         nand->ecc.mode = NAND_ECC_SOFT;
231         nand->cmd_ctrl = axs101_nand_hwcontrol;
232         nand->read_byte = axs101_nand_read_byte;
233         nand->read_word = axs101_nand_read_word;
234         nand->write_buf = axs101_nand_write_buf;
235         nand->read_buf = axs101_nand_read_buf;
236
237         /* MBv3 has NAND IC with 16-bit data bus */
238         if (gd->board_type == AXS_MB_V3)
239                 nand->options |= NAND_BUSWIDTH_16;
240
241         return 0;
242 }