1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2014 Panasonic Corporation
10 #include <asm/unaligned.h>
11 #include <linux/delay.h>
12 #include <linux/mtd/rawnand.h>
15 #define DENALI_MAP01 (1 << 26) /* read/write pages in PIO */
16 #define DENALI_MAP10 (2 << 26) /* high-level control plane */
18 #define INDEX_CTRL_REG 0x0
19 #define INDEX_DATA_REG 0x10
21 #define SPARE_ACCESS 0x41
22 #define MAIN_ACCESS 0x42
23 #define PIPELINE_ACCESS 0x2000
25 #define BANK(x) ((x) << 24)
27 static void __iomem *denali_flash_mem =
28 (void __iomem *)CONFIG_SYS_NAND_DATA_BASE;
29 static void __iomem *denali_flash_reg =
30 (void __iomem *)CONFIG_SYS_NAND_REGS_BASE;
32 static const int flash_bank;
33 static int page_size, oob_size, pages_per_block;
35 static void index_addr(uint32_t address, uint32_t data)
37 writel(address, denali_flash_mem + INDEX_CTRL_REG);
38 writel(data, denali_flash_mem + INDEX_DATA_REG);
41 static int wait_for_irq(uint32_t irq_mask)
43 unsigned long timeout = 1000000;
47 intr_status = readl(denali_flash_reg + INTR_STATUS(flash_bank));
49 if (intr_status & INTR__ECC_UNCOR_ERR) {
50 debug("Uncorrected ECC detected\n");
54 if (intr_status & irq_mask)
62 debug("Timeout with interrupt status %08x\n", intr_status);
69 static void read_data_from_flash_mem(uint8_t *buf, int len)
74 /* transfer the data from the flash */
75 buf32 = (uint32_t *)buf;
78 * Let's take care of unaligned access although it rarely happens.
79 * Avoid put_unaligned() for the normal use cases since it leads to
80 * a bit performance regression.
82 if ((unsigned long)buf32 % 4) {
83 for (i = 0; i < len / 4; i++)
84 put_unaligned(readl(denali_flash_mem + INDEX_DATA_REG),
87 for (i = 0; i < len / 4; i++)
88 *buf32++ = readl(denali_flash_mem + INDEX_DATA_REG);
94 tmp = cpu_to_le32(readl(denali_flash_mem + INDEX_DATA_REG));
95 buf = (uint8_t *)buf32;
96 for (i = 0; i < len % 4; i++) {
103 int denali_send_pipeline_cmd(int page, int ecc_en, int access_type)
106 static uint32_t page_count = 1;
108 writel(ecc_en, denali_flash_reg + ECC_ENABLE);
110 /* clear all bits of intr_status. */
111 writel(0xffff, denali_flash_reg + INTR_STATUS(flash_bank));
113 addr = BANK(flash_bank) | page;
115 /* setup the acccess type */
116 cmd = DENALI_MAP10 | addr;
117 index_addr(cmd, access_type);
119 /* setup the pipeline command */
120 index_addr(cmd, PIPELINE_ACCESS | page_count);
122 cmd = DENALI_MAP01 | addr;
123 writel(cmd, denali_flash_mem + INDEX_CTRL_REG);
125 return wait_for_irq(INTR__LOAD_COMP);
128 static int nand_read_oob(void *buf, int page)
132 ret = denali_send_pipeline_cmd(page, 0, SPARE_ACCESS);
136 read_data_from_flash_mem(buf, oob_size);
141 static int nand_read_page(void *buf, int page)
145 ret = denali_send_pipeline_cmd(page, 1, MAIN_ACCESS);
149 read_data_from_flash_mem(buf, page_size);
154 static int nand_block_isbad(void *buf, int block)
158 ret = nand_read_oob(buf, block * pages_per_block);
162 return *((uint8_t *)buf + CONFIG_SYS_NAND_BAD_BLOCK_POS) != 0xff;
165 /* nand_init() - initialize data to make nand usable by SPL */
168 /* access to main area */
169 writel(0, denali_flash_reg + TRANSFER_SPARE_REG);
172 * These registers are expected to be already set by the hardware
173 * or earlier boot code. So we read these values out.
175 page_size = readl(denali_flash_reg + DEVICE_MAIN_AREA_SIZE);
176 oob_size = readl(denali_flash_reg + DEVICE_SPARE_AREA_SIZE);
177 pages_per_block = readl(denali_flash_reg + PAGES_PER_BLOCK);
179 /* Do as denali_hw_init() does. */
180 writel(CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES,
181 denali_flash_reg + SPARE_AREA_SKIP_BYTES);
182 writel(0x0F, denali_flash_reg + RB_PIN_ENABLED);
183 writel(CHIP_EN_DONT_CARE__FLAG, denali_flash_reg + CHIP_ENABLE_DONT_CARE);
184 writel(0xffff, denali_flash_reg + SPARE_AREA_MARKER);
187 int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
189 int block, page, column, readlen;
191 int force_bad_block_check = 1;
193 page = offs / page_size;
194 column = offs % page_size;
196 block = page / pages_per_block;
197 page = page % pages_per_block;
200 if (force_bad_block_check || page == 0) {
201 ret = nand_block_isbad(dst, block);
211 force_bad_block_check = 0;
213 ret = nand_read_page(dst, block * pages_per_block + page);
217 readlen = min(page_size - column, (int)size);
219 if (unlikely(column)) {
220 /* Partial page read */
221 memmove(dst, dst + column, readlen);
228 if (page == pages_per_block) {
237 void nand_deselect(void) {}