4b815a433e1f8dd80a156a11957a659218cd6c0b
[oweals/u-boot.git] / drivers / mtd / nand / raw / denali_spl.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2014       Panasonic Corporation
4  * Copyright (C) 2014-2015  Masahiro Yamada <yamada.masahiro@socionext.com>
5  */
6
7 #include <common.h>
8 #include <log.h>
9 #include <asm/io.h>
10 #include <asm/unaligned.h>
11 #include <linux/mtd/rawnand.h>
12 #include "denali.h"
13
14 #define DENALI_MAP01            (1 << 26)       /* read/write pages in PIO */
15 #define DENALI_MAP10            (2 << 26)       /* high-level control plane */
16
17 #define INDEX_CTRL_REG          0x0
18 #define INDEX_DATA_REG          0x10
19
20 #define SPARE_ACCESS            0x41
21 #define MAIN_ACCESS             0x42
22 #define PIPELINE_ACCESS         0x2000
23
24 #define BANK(x) ((x) << 24)
25
26 static void __iomem *denali_flash_mem =
27                         (void __iomem *)CONFIG_SYS_NAND_DATA_BASE;
28 static void __iomem *denali_flash_reg =
29                         (void __iomem *)CONFIG_SYS_NAND_REGS_BASE;
30
31 static const int flash_bank;
32 static int page_size, oob_size, pages_per_block;
33
34 static void index_addr(uint32_t address, uint32_t data)
35 {
36         writel(address, denali_flash_mem + INDEX_CTRL_REG);
37         writel(data, denali_flash_mem + INDEX_DATA_REG);
38 }
39
40 static int wait_for_irq(uint32_t irq_mask)
41 {
42         unsigned long timeout = 1000000;
43         uint32_t intr_status;
44
45         do {
46                 intr_status = readl(denali_flash_reg + INTR_STATUS(flash_bank));
47
48                 if (intr_status & INTR__ECC_UNCOR_ERR) {
49                         debug("Uncorrected ECC detected\n");
50                         return -EBADMSG;
51                 }
52
53                 if (intr_status & irq_mask)
54                         break;
55
56                 udelay(1);
57                 timeout--;
58         } while (timeout);
59
60         if (!timeout) {
61                 debug("Timeout with interrupt status %08x\n", intr_status);
62                 return -EIO;
63         }
64
65         return 0;
66 }
67
68 static void read_data_from_flash_mem(uint8_t *buf, int len)
69 {
70         int i;
71         uint32_t *buf32;
72
73         /* transfer the data from the flash */
74         buf32 = (uint32_t *)buf;
75
76         /*
77          * Let's take care of unaligned access although it rarely happens.
78          * Avoid put_unaligned() for the normal use cases since it leads to
79          * a bit performance regression.
80          */
81         if ((unsigned long)buf32 % 4) {
82                 for (i = 0; i < len / 4; i++)
83                         put_unaligned(readl(denali_flash_mem + INDEX_DATA_REG),
84                                       buf32++);
85         } else {
86                 for (i = 0; i < len / 4; i++)
87                         *buf32++ = readl(denali_flash_mem + INDEX_DATA_REG);
88         }
89
90         if (len % 4) {
91                 u32 tmp;
92
93                 tmp = cpu_to_le32(readl(denali_flash_mem + INDEX_DATA_REG));
94                 buf = (uint8_t *)buf32;
95                 for (i = 0; i < len % 4; i++) {
96                         *buf++ = tmp;
97                         tmp >>= 8;
98                 }
99         }
100 }
101
102 int denali_send_pipeline_cmd(int page, int ecc_en, int access_type)
103 {
104         uint32_t addr, cmd;
105         static uint32_t page_count = 1;
106
107         writel(ecc_en, denali_flash_reg + ECC_ENABLE);
108
109         /* clear all bits of intr_status. */
110         writel(0xffff, denali_flash_reg + INTR_STATUS(flash_bank));
111
112         addr = BANK(flash_bank) | page;
113
114         /* setup the acccess type */
115         cmd = DENALI_MAP10 | addr;
116         index_addr(cmd, access_type);
117
118         /* setup the pipeline command */
119         index_addr(cmd, PIPELINE_ACCESS | page_count);
120
121         cmd = DENALI_MAP01 | addr;
122         writel(cmd, denali_flash_mem + INDEX_CTRL_REG);
123
124         return wait_for_irq(INTR__LOAD_COMP);
125 }
126
127 static int nand_read_oob(void *buf, int page)
128 {
129         int ret;
130
131         ret = denali_send_pipeline_cmd(page, 0, SPARE_ACCESS);
132         if (ret < 0)
133                 return ret;
134
135         read_data_from_flash_mem(buf, oob_size);
136
137         return 0;
138 }
139
140 static int nand_read_page(void *buf, int page)
141 {
142         int ret;
143
144         ret = denali_send_pipeline_cmd(page, 1, MAIN_ACCESS);
145         if (ret < 0)
146                 return ret;
147
148         read_data_from_flash_mem(buf, page_size);
149
150         return 0;
151 }
152
153 static int nand_block_isbad(void *buf, int block)
154 {
155         int ret;
156
157         ret = nand_read_oob(buf, block * pages_per_block);
158         if (ret < 0)
159                 return ret;
160
161         return *((uint8_t *)buf + CONFIG_SYS_NAND_BAD_BLOCK_POS) != 0xff;
162 }
163
164 /* nand_init() - initialize data to make nand usable by SPL */
165 void nand_init(void)
166 {
167         /* access to main area */
168         writel(0, denali_flash_reg + TRANSFER_SPARE_REG);
169
170         /*
171          * These registers are expected to be already set by the hardware
172          * or earlier boot code.  So we read these values out.
173          */
174         page_size = readl(denali_flash_reg + DEVICE_MAIN_AREA_SIZE);
175         oob_size = readl(denali_flash_reg + DEVICE_SPARE_AREA_SIZE);
176         pages_per_block = readl(denali_flash_reg + PAGES_PER_BLOCK);
177
178         /* Do as denali_hw_init() does. */
179         writel(CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES,
180                denali_flash_reg + SPARE_AREA_SKIP_BYTES);
181         writel(0x0F, denali_flash_reg + RB_PIN_ENABLED);
182         writel(CHIP_EN_DONT_CARE__FLAG, denali_flash_reg + CHIP_ENABLE_DONT_CARE);
183         writel(0xffff, denali_flash_reg + SPARE_AREA_MARKER);
184 }
185
186 int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
187 {
188         int block, page, column, readlen;
189         int ret;
190         int force_bad_block_check = 1;
191
192         page = offs / page_size;
193         column = offs % page_size;
194
195         block = page / pages_per_block;
196         page = page % pages_per_block;
197
198         while (size) {
199                 if (force_bad_block_check || page == 0) {
200                         ret = nand_block_isbad(dst, block);
201                         if (ret < 0)
202                                 return ret;
203
204                         if (ret) {
205                                 block++;
206                                 continue;
207                         }
208                 }
209
210                 force_bad_block_check = 0;
211
212                 ret = nand_read_page(dst, block * pages_per_block + page);
213                 if (ret < 0)
214                         return ret;
215
216                 readlen = min(page_size - column, (int)size);
217
218                 if (unlikely(column)) {
219                         /* Partial page read */
220                         memmove(dst, dst + column, readlen);
221                         column = 0;
222                 }
223
224                 size -= readlen;
225                 dst += readlen;
226                 page++;
227                 if (page == pages_per_block) {
228                         block++;
229                         page = 0;
230                 }
231         }
232
233         return 0;
234 }
235
236 void nand_deselect(void) {}