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