blob: 719a74d2f688641b3d86f65c271b4294289388aa [file] [log] [blame]
Vladimir Zapolskiy78f04f02015-07-18 03:07:52 +03001/*
2 * LPC32xx SLC NAND flash controller driver
3 *
4 * (C) Copyright 2015 Vladimir Zapolskiy <vz@mleia.com>
5 *
6 * SPDX-License-Identifier: GPL-2.0+
7 */
8
9#include <common.h>
10#include <nand.h>
11#include <asm/errno.h>
12#include <asm/io.h>
13#include <asm/arch/clk.h>
14#include <asm/arch/sys_proto.h>
15
16struct lpc32xx_nand_slc_regs {
17 u32 data;
18 u32 addr;
19 u32 cmd;
20 u32 stop;
21 u32 ctrl;
22 u32 cfg;
23 u32 stat;
24 u32 int_stat;
25 u32 ien;
26 u32 isr;
27 u32 icr;
28 u32 tac;
29 u32 tc;
30 u32 ecc;
31 u32 dma_data;
32};
33
34/* CFG register */
35#define CFG_CE_LOW (1 << 5)
36
37/* CTRL register */
38#define CTRL_SW_RESET (1 << 2)
39
40/* STAT register */
41#define STAT_NAND_READY (1 << 0)
42
43/* INT_STAT register */
44#define INT_STAT_TC (1 << 1)
45#define INT_STAT_RDY (1 << 0)
46
47/* TAC register bits, be aware of overflows */
48#define TAC_W_RDY(n) (max_t(uint32_t, (n), 0xF) << 28)
49#define TAC_W_WIDTH(n) (max_t(uint32_t, (n), 0xF) << 24)
50#define TAC_W_HOLD(n) (max_t(uint32_t, (n), 0xF) << 20)
51#define TAC_W_SETUP(n) (max_t(uint32_t, (n), 0xF) << 16)
52#define TAC_R_RDY(n) (max_t(uint32_t, (n), 0xF) << 12)
53#define TAC_R_WIDTH(n) (max_t(uint32_t, (n), 0xF) << 8)
54#define TAC_R_HOLD(n) (max_t(uint32_t, (n), 0xF) << 4)
55#define TAC_R_SETUP(n) (max_t(uint32_t, (n), 0xF) << 0)
56
57static struct lpc32xx_nand_slc_regs __iomem *lpc32xx_nand_slc_regs
58 = (struct lpc32xx_nand_slc_regs __iomem *)SLC_NAND_BASE;
59
60static void lpc32xx_nand_init(void)
61{
62 uint32_t hclk = get_hclk_clk_rate();
63
64 /* Reset SLC NAND controller */
65 writel(CTRL_SW_RESET, &lpc32xx_nand_slc_regs->ctrl);
66
67 /* 8-bit bus, no DMA, no ECC, ordinary CE signal */
68 writel(0, &lpc32xx_nand_slc_regs->cfg);
69
70 /* Interrupts disabled and cleared */
71 writel(0, &lpc32xx_nand_slc_regs->ien);
72 writel(INT_STAT_TC | INT_STAT_RDY,
73 &lpc32xx_nand_slc_regs->icr);
74
75 /* Configure NAND flash timings */
76 writel(TAC_W_RDY(CONFIG_LPC32XX_NAND_SLC_WDR_CLKS) |
77 TAC_W_WIDTH(hclk / CONFIG_LPC32XX_NAND_SLC_WWIDTH) |
78 TAC_W_HOLD(hclk / CONFIG_LPC32XX_NAND_SLC_WHOLD) |
79 TAC_W_SETUP(hclk / CONFIG_LPC32XX_NAND_SLC_WSETUP) |
80 TAC_R_RDY(CONFIG_LPC32XX_NAND_SLC_RDR_CLKS) |
81 TAC_R_WIDTH(hclk / CONFIG_LPC32XX_NAND_SLC_RWIDTH) |
82 TAC_R_HOLD(hclk / CONFIG_LPC32XX_NAND_SLC_RHOLD) |
83 TAC_R_SETUP(hclk / CONFIG_LPC32XX_NAND_SLC_RSETUP),
84 &lpc32xx_nand_slc_regs->tac);
85}
86
87static void lpc32xx_nand_cmd_ctrl(struct mtd_info *mtd,
88 int cmd, unsigned int ctrl)
89{
90 debug("ctrl: 0x%08x, cmd: 0x%08x\n", ctrl, cmd);
91
92 if (ctrl & NAND_NCE)
93 setbits_le32(&lpc32xx_nand_slc_regs->cfg, CFG_CE_LOW);
94 else
95 clrbits_le32(&lpc32xx_nand_slc_regs->cfg, CFG_CE_LOW);
96
97 if (cmd == NAND_CMD_NONE)
98 return;
99
100 if (ctrl & NAND_CLE)
101 writel(cmd & 0xFF, &lpc32xx_nand_slc_regs->cmd);
102 else if (ctrl & NAND_ALE)
103 writel(cmd & 0xFF, &lpc32xx_nand_slc_regs->addr);
104}
105
106static int lpc32xx_nand_dev_ready(struct mtd_info *mtd)
107{
108 return readl(&lpc32xx_nand_slc_regs->stat) & STAT_NAND_READY;
109}
110
111static void lpc32xx_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
112{
113 while (len-- > 0)
114 *buf++ = readl(&lpc32xx_nand_slc_regs->data);
115}
116
117static uint8_t lpc32xx_read_byte(struct mtd_info *mtd)
118{
119 return readl(&lpc32xx_nand_slc_regs->data);
120}
121
122static void lpc32xx_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
123{
124 while (len-- > 0)
125 writel(*buf++, &lpc32xx_nand_slc_regs->data);
126}
127
128static void lpc32xx_write_byte(struct mtd_info *mtd, uint8_t byte)
129{
130 writel(byte, &lpc32xx_nand_slc_regs->data);
131}
132
133/*
134 * LPC32xx has only one SLC NAND controller, don't utilize
135 * CONFIG_SYS_NAND_SELF_INIT to be able to reuse this function
136 * both in SPL NAND and U-boot images.
137 */
138int board_nand_init(struct nand_chip *lpc32xx_chip)
139{
140 lpc32xx_chip->cmd_ctrl = lpc32xx_nand_cmd_ctrl;
141 lpc32xx_chip->dev_ready = lpc32xx_nand_dev_ready;
142
143 /*
144 * Hardware ECC calculation is not supported by the driver,
145 * because it requires DMA support, see LPC32x0 User Manual,
146 * note after SLC_ECC register description (UM10326, p.198)
147 */
148 lpc32xx_chip->ecc.mode = NAND_ECC_SOFT;
149
150 /*
151 * The implementation of these functions is quite common, but
152 * they MUST be defined, because access to data register
153 * is strictly 32-bit aligned.
154 */
155 lpc32xx_chip->read_buf = lpc32xx_read_buf;
156 lpc32xx_chip->read_byte = lpc32xx_read_byte;
157 lpc32xx_chip->write_buf = lpc32xx_write_buf;
158 lpc32xx_chip->write_byte = lpc32xx_write_byte;
159
160 /*
161 * Use default ECC layout, but these values are predefined
162 * for both small and large page NAND flash devices.
163 */
164 lpc32xx_chip->ecc.size = 256;
165 lpc32xx_chip->ecc.bytes = 3;
166 lpc32xx_chip->ecc.strength = 1;
167
168#if defined(CONFIG_SYS_NAND_USE_FLASH_BBT)
169 lpc32xx_chip->bbt_options |= NAND_BBT_USE_FLASH;
170#endif
171
172 /* Initialize NAND interface */
173 lpc32xx_nand_init();
174
175 return 0;
176}