1d8701fe8SMiquel Raynal // SPDX-License-Identifier: GPL-2.0
2d8701fe8SMiquel Raynal /*
3d8701fe8SMiquel Raynal  * Evatronix/Renesas R-Car Gen3, RZ/N1D, RZ/N1S, RZ/N1L NAND controller driver
4d8701fe8SMiquel Raynal  *
5d8701fe8SMiquel Raynal  * Copyright (C) 2021 Schneider Electric
6d8701fe8SMiquel Raynal  * Author: Miquel RAYNAL <miquel.raynal@bootlin.com>
7d8701fe8SMiquel Raynal  */
8d8701fe8SMiquel Raynal 
9d8701fe8SMiquel Raynal #include <linux/bitfield.h>
10d8701fe8SMiquel Raynal #include <linux/clk.h>
11d8701fe8SMiquel Raynal #include <linux/dma-mapping.h>
12d8701fe8SMiquel Raynal #include <linux/interrupt.h>
13d8701fe8SMiquel Raynal #include <linux/iopoll.h>
14d8701fe8SMiquel Raynal #include <linux/module.h>
15d8701fe8SMiquel Raynal #include <linux/mtd/mtd.h>
16d8701fe8SMiquel Raynal #include <linux/mtd/rawnand.h>
17d8701fe8SMiquel Raynal #include <linux/of.h>
18d8701fe8SMiquel Raynal #include <linux/platform_device.h>
196a2277a0SMiquel Raynal #include <linux/pm_runtime.h>
20d8701fe8SMiquel Raynal #include <linux/slab.h>
21d8701fe8SMiquel Raynal 
22d8701fe8SMiquel Raynal #define COMMAND_REG 0x00
23d8701fe8SMiquel Raynal #define   COMMAND_SEQ(x) FIELD_PREP(GENMASK(5, 0), (x))
24d8701fe8SMiquel Raynal #define     COMMAND_SEQ_10 COMMAND_SEQ(0x2A)
25d8701fe8SMiquel Raynal #define     COMMAND_SEQ_12 COMMAND_SEQ(0x0C)
26d8701fe8SMiquel Raynal #define     COMMAND_SEQ_18 COMMAND_SEQ(0x32)
27d8701fe8SMiquel Raynal #define     COMMAND_SEQ_19 COMMAND_SEQ(0x13)
28d8701fe8SMiquel Raynal #define     COMMAND_SEQ_GEN_IN COMMAND_SEQ_18
29d8701fe8SMiquel Raynal #define     COMMAND_SEQ_GEN_OUT COMMAND_SEQ_19
30d8701fe8SMiquel Raynal #define     COMMAND_SEQ_READ_PAGE COMMAND_SEQ_10
31d8701fe8SMiquel Raynal #define     COMMAND_SEQ_WRITE_PAGE COMMAND_SEQ_12
32d8701fe8SMiquel Raynal #define   COMMAND_INPUT_SEL_AHBS 0
33d8701fe8SMiquel Raynal #define   COMMAND_INPUT_SEL_DMA BIT(6)
34d8701fe8SMiquel Raynal #define   COMMAND_FIFO_SEL 0
35d8701fe8SMiquel Raynal #define   COMMAND_DATA_SEL BIT(7)
36d8701fe8SMiquel Raynal #define   COMMAND_0(x) FIELD_PREP(GENMASK(15, 8), (x))
37d8701fe8SMiquel Raynal #define   COMMAND_1(x) FIELD_PREP(GENMASK(23, 16), (x))
38d8701fe8SMiquel Raynal #define   COMMAND_2(x) FIELD_PREP(GENMASK(31, 24), (x))
39d8701fe8SMiquel Raynal 
40d8701fe8SMiquel Raynal #define CONTROL_REG 0x04
41d8701fe8SMiquel Raynal #define   CONTROL_CHECK_RB_LINE 0
42d8701fe8SMiquel Raynal #define   CONTROL_ECC_BLOCK_SIZE(x) FIELD_PREP(GENMASK(2, 1), (x))
43d8701fe8SMiquel Raynal #define     CONTROL_ECC_BLOCK_SIZE_256 CONTROL_ECC_BLOCK_SIZE(0)
44d8701fe8SMiquel Raynal #define     CONTROL_ECC_BLOCK_SIZE_512 CONTROL_ECC_BLOCK_SIZE(1)
45d8701fe8SMiquel Raynal #define     CONTROL_ECC_BLOCK_SIZE_1024 CONTROL_ECC_BLOCK_SIZE(2)
46d8701fe8SMiquel Raynal #define   CONTROL_INT_EN BIT(4)
47d8701fe8SMiquel Raynal #define   CONTROL_ECC_EN BIT(5)
48d8701fe8SMiquel Raynal #define   CONTROL_BLOCK_SIZE(x) FIELD_PREP(GENMASK(7, 6), (x))
49d8701fe8SMiquel Raynal #define     CONTROL_BLOCK_SIZE_32P CONTROL_BLOCK_SIZE(0)
50d8701fe8SMiquel Raynal #define     CONTROL_BLOCK_SIZE_64P CONTROL_BLOCK_SIZE(1)
51d8701fe8SMiquel Raynal #define     CONTROL_BLOCK_SIZE_128P CONTROL_BLOCK_SIZE(2)
52d8701fe8SMiquel Raynal #define     CONTROL_BLOCK_SIZE_256P CONTROL_BLOCK_SIZE(3)
53d8701fe8SMiquel Raynal 
54d8701fe8SMiquel Raynal #define STATUS_REG 0x8
55d8701fe8SMiquel Raynal #define   MEM_RDY(cs, reg) (FIELD_GET(GENMASK(3, 0), (reg)) & BIT(cs))
56d8701fe8SMiquel Raynal #define   CTRL_RDY(reg) (FIELD_GET(BIT(8), (reg)) == 0)
57d8701fe8SMiquel Raynal 
58d8701fe8SMiquel Raynal #define ECC_CTRL_REG 0x18
59d8701fe8SMiquel Raynal #define   ECC_CTRL_CAP(x) FIELD_PREP(GENMASK(2, 0), (x))
60d8701fe8SMiquel Raynal #define     ECC_CTRL_CAP_2B ECC_CTRL_CAP(0)
61d8701fe8SMiquel Raynal #define     ECC_CTRL_CAP_4B ECC_CTRL_CAP(1)
62d8701fe8SMiquel Raynal #define     ECC_CTRL_CAP_8B ECC_CTRL_CAP(2)
63d8701fe8SMiquel Raynal #define     ECC_CTRL_CAP_16B ECC_CTRL_CAP(3)
64d8701fe8SMiquel Raynal #define     ECC_CTRL_CAP_24B ECC_CTRL_CAP(4)
65d8701fe8SMiquel Raynal #define     ECC_CTRL_CAP_32B ECC_CTRL_CAP(5)
66d8701fe8SMiquel Raynal #define   ECC_CTRL_ERR_THRESHOLD(x) FIELD_PREP(GENMASK(13, 8), (x))
67d8701fe8SMiquel Raynal 
68d8701fe8SMiquel Raynal #define INT_MASK_REG 0x10
69d8701fe8SMiquel Raynal #define INT_STATUS_REG 0x14
70d8701fe8SMiquel Raynal #define   INT_CMD_END BIT(1)
71d8701fe8SMiquel Raynal #define   INT_DMA_END BIT(3)
72d8701fe8SMiquel Raynal #define   INT_MEM_RDY(cs) FIELD_PREP(GENMASK(11, 8), BIT(cs))
73d8701fe8SMiquel Raynal #define   INT_DMA_ENDED BIT(3)
74d8701fe8SMiquel Raynal #define   MEM_IS_RDY(cs, reg) (FIELD_GET(GENMASK(11, 8), (reg)) & BIT(cs))
75d8701fe8SMiquel Raynal #define   DMA_HAS_ENDED(reg) FIELD_GET(BIT(3), (reg))
76d8701fe8SMiquel Raynal 
77d8701fe8SMiquel Raynal #define ECC_OFFSET_REG 0x1C
78d8701fe8SMiquel Raynal #define   ECC_OFFSET(x) FIELD_PREP(GENMASK(15, 0), (x))
79d8701fe8SMiquel Raynal 
80d8701fe8SMiquel Raynal #define ECC_STAT_REG 0x20
81d8701fe8SMiquel Raynal #define   ECC_STAT_CORRECTABLE(cs, reg) (FIELD_GET(GENMASK(3, 0), (reg)) & BIT(cs))
82d8701fe8SMiquel Raynal #define   ECC_STAT_UNCORRECTABLE(cs, reg) (FIELD_GET(GENMASK(11, 8), (reg)) & BIT(cs))
83d8701fe8SMiquel Raynal 
84d8701fe8SMiquel Raynal #define ADDR0_COL_REG 0x24
85d8701fe8SMiquel Raynal #define   ADDR0_COL(x) FIELD_PREP(GENMASK(15, 0), (x))
86d8701fe8SMiquel Raynal 
87d8701fe8SMiquel Raynal #define ADDR0_ROW_REG 0x28
88d8701fe8SMiquel Raynal #define   ADDR0_ROW(x) FIELD_PREP(GENMASK(23, 0), (x))
89d8701fe8SMiquel Raynal 
90d8701fe8SMiquel Raynal #define ADDR1_COL_REG 0x2C
91d8701fe8SMiquel Raynal #define   ADDR1_COL(x) FIELD_PREP(GENMASK(15, 0), (x))
92d8701fe8SMiquel Raynal 
93d8701fe8SMiquel Raynal #define ADDR1_ROW_REG 0x30
94d8701fe8SMiquel Raynal #define   ADDR1_ROW(x) FIELD_PREP(GENMASK(23, 0), (x))
95d8701fe8SMiquel Raynal 
96d8701fe8SMiquel Raynal #define FIFO_DATA_REG 0x38
97d8701fe8SMiquel Raynal 
98d8701fe8SMiquel Raynal #define DATA_REG 0x3C
99d8701fe8SMiquel Raynal 
100d8701fe8SMiquel Raynal #define DATA_REG_SIZE_REG 0x40
101d8701fe8SMiquel Raynal 
102d8701fe8SMiquel Raynal #define DMA_ADDR_LOW_REG 0x64
103d8701fe8SMiquel Raynal 
104d8701fe8SMiquel Raynal #define DMA_ADDR_HIGH_REG 0x68
105d8701fe8SMiquel Raynal 
106d8701fe8SMiquel Raynal #define DMA_CNT_REG 0x6C
107d8701fe8SMiquel Raynal 
108d8701fe8SMiquel Raynal #define DMA_CTRL_REG 0x70
109d8701fe8SMiquel Raynal #define   DMA_CTRL_INCREMENT_BURST_4 0
110d8701fe8SMiquel Raynal #define   DMA_CTRL_REGISTER_MANAGED_MODE 0
111d8701fe8SMiquel Raynal #define   DMA_CTRL_START BIT(7)
112d8701fe8SMiquel Raynal 
113d8701fe8SMiquel Raynal #define MEM_CTRL_REG 0x80
114d8701fe8SMiquel Raynal #define   MEM_CTRL_CS(cs) FIELD_PREP(GENMASK(1, 0), (cs))
115d8701fe8SMiquel Raynal #define   MEM_CTRL_DIS_WP(cs) FIELD_PREP(GENMASK(11, 8), BIT((cs)))
116d8701fe8SMiquel Raynal 
117d8701fe8SMiquel Raynal #define DATA_SIZE_REG 0x84
118d8701fe8SMiquel Raynal #define   DATA_SIZE(x) FIELD_PREP(GENMASK(14, 0), (x))
119d8701fe8SMiquel Raynal 
120d8701fe8SMiquel Raynal #define TIMINGS_ASYN_REG 0x88
121d8701fe8SMiquel Raynal #define   TIMINGS_ASYN_TRWP(x) FIELD_PREP(GENMASK(3, 0), max((x), 1U) - 1)
122d8701fe8SMiquel Raynal #define   TIMINGS_ASYN_TRWH(x) FIELD_PREP(GENMASK(7, 4), max((x), 1U) - 1)
123d8701fe8SMiquel Raynal 
124d8701fe8SMiquel Raynal #define TIM_SEQ0_REG 0x90
125d8701fe8SMiquel Raynal #define   TIM_SEQ0_TCCS(x) FIELD_PREP(GENMASK(5, 0), max((x), 1U) - 1)
126d8701fe8SMiquel Raynal #define   TIM_SEQ0_TADL(x) FIELD_PREP(GENMASK(13, 8), max((x), 1U) - 1)
127d8701fe8SMiquel Raynal #define   TIM_SEQ0_TRHW(x) FIELD_PREP(GENMASK(21, 16), max((x), 1U) - 1)
128d8701fe8SMiquel Raynal #define   TIM_SEQ0_TWHR(x) FIELD_PREP(GENMASK(29, 24), max((x), 1U) - 1)
129d8701fe8SMiquel Raynal 
130d8701fe8SMiquel Raynal #define TIM_SEQ1_REG 0x94
131d8701fe8SMiquel Raynal #define   TIM_SEQ1_TWB(x) FIELD_PREP(GENMASK(5, 0), max((x), 1U) - 1)
132d8701fe8SMiquel Raynal #define   TIM_SEQ1_TRR(x) FIELD_PREP(GENMASK(13, 8), max((x), 1U) - 1)
133d8701fe8SMiquel Raynal #define   TIM_SEQ1_TWW(x) FIELD_PREP(GENMASK(21, 16), max((x), 1U) - 1)
134d8701fe8SMiquel Raynal 
135d8701fe8SMiquel Raynal #define TIM_GEN_SEQ0_REG 0x98
136d8701fe8SMiquel Raynal #define   TIM_GEN_SEQ0_D0(x) FIELD_PREP(GENMASK(5, 0), max((x), 1U) - 1)
137d8701fe8SMiquel Raynal #define   TIM_GEN_SEQ0_D1(x) FIELD_PREP(GENMASK(13, 8), max((x), 1U) - 1)
138d8701fe8SMiquel Raynal #define   TIM_GEN_SEQ0_D2(x) FIELD_PREP(GENMASK(21, 16), max((x), 1U) - 1)
139d8701fe8SMiquel Raynal #define   TIM_GEN_SEQ0_D3(x) FIELD_PREP(GENMASK(29, 24), max((x), 1U) - 1)
140d8701fe8SMiquel Raynal 
141d8701fe8SMiquel Raynal #define TIM_GEN_SEQ1_REG 0x9c
142d8701fe8SMiquel Raynal #define   TIM_GEN_SEQ1_D4(x) FIELD_PREP(GENMASK(5, 0), max((x), 1U) - 1)
143d8701fe8SMiquel Raynal #define   TIM_GEN_SEQ1_D5(x) FIELD_PREP(GENMASK(13, 8), max((x), 1U) - 1)
144d8701fe8SMiquel Raynal #define   TIM_GEN_SEQ1_D6(x) FIELD_PREP(GENMASK(21, 16), max((x), 1U) - 1)
145d8701fe8SMiquel Raynal #define   TIM_GEN_SEQ1_D7(x) FIELD_PREP(GENMASK(29, 24), max((x), 1U) - 1)
146d8701fe8SMiquel Raynal 
147d8701fe8SMiquel Raynal #define TIM_GEN_SEQ2_REG 0xA0
148d8701fe8SMiquel Raynal #define   TIM_GEN_SEQ2_D8(x) FIELD_PREP(GENMASK(5, 0), max((x), 1U) - 1)
149d8701fe8SMiquel Raynal #define   TIM_GEN_SEQ2_D9(x) FIELD_PREP(GENMASK(13, 8), max((x), 1U) - 1)
150d8701fe8SMiquel Raynal #define   TIM_GEN_SEQ2_D10(x) FIELD_PREP(GENMASK(21, 16), max((x), 1U) - 1)
151d8701fe8SMiquel Raynal #define   TIM_GEN_SEQ2_D11(x) FIELD_PREP(GENMASK(29, 24), max((x), 1U) - 1)
152d8701fe8SMiquel Raynal 
153d8701fe8SMiquel Raynal #define FIFO_INIT_REG 0xB4
154d8701fe8SMiquel Raynal #define   FIFO_INIT BIT(0)
155d8701fe8SMiquel Raynal 
156d8701fe8SMiquel Raynal #define FIFO_STATE_REG 0xB4
157d8701fe8SMiquel Raynal #define   FIFO_STATE_R_EMPTY(reg) FIELD_GET(BIT(0), (reg))
158d8701fe8SMiquel Raynal #define   FIFO_STATE_W_FULL(reg) FIELD_GET(BIT(1), (reg))
159d8701fe8SMiquel Raynal #define   FIFO_STATE_C_EMPTY(reg) FIELD_GET(BIT(2), (reg))
160d8701fe8SMiquel Raynal #define   FIFO_STATE_R_FULL(reg) FIELD_GET(BIT(6), (reg))
161d8701fe8SMiquel Raynal #define   FIFO_STATE_W_EMPTY(reg) FIELD_GET(BIT(7), (reg))
162d8701fe8SMiquel Raynal 
163d8701fe8SMiquel Raynal #define GEN_SEQ_CTRL_REG 0xB8
164d8701fe8SMiquel Raynal #define   GEN_SEQ_CMD0_EN BIT(0)
165d8701fe8SMiquel Raynal #define   GEN_SEQ_CMD1_EN BIT(1)
166d8701fe8SMiquel Raynal #define   GEN_SEQ_CMD2_EN BIT(2)
167d8701fe8SMiquel Raynal #define   GEN_SEQ_CMD3_EN BIT(3)
168d8701fe8SMiquel Raynal #define   GEN_SEQ_COL_A0(x) FIELD_PREP(GENMASK(5, 4), min((x), 2U))
169d8701fe8SMiquel Raynal #define   GEN_SEQ_COL_A1(x) FIELD_PREP(GENMASK(7, 6), min((x), 2U))
170d8701fe8SMiquel Raynal #define   GEN_SEQ_ROW_A0(x) FIELD_PREP(GENMASK(9, 8), min((x), 3U))
171d8701fe8SMiquel Raynal #define   GEN_SEQ_ROW_A1(x) FIELD_PREP(GENMASK(11, 10), min((x), 3U))
172d8701fe8SMiquel Raynal #define   GEN_SEQ_DATA_EN BIT(12)
173d8701fe8SMiquel Raynal #define   GEN_SEQ_DELAY_EN(x) FIELD_PREP(GENMASK(14, 13), (x))
174d8701fe8SMiquel Raynal #define     GEN_SEQ_DELAY0_EN GEN_SEQ_DELAY_EN(1)
175d8701fe8SMiquel Raynal #define     GEN_SEQ_DELAY1_EN GEN_SEQ_DELAY_EN(2)
176d8701fe8SMiquel Raynal #define   GEN_SEQ_IMD_SEQ BIT(15)
177d8701fe8SMiquel Raynal #define   GEN_SEQ_COMMAND_3(x) FIELD_PREP(GENMASK(26, 16), (x))
178d8701fe8SMiquel Raynal 
179d8701fe8SMiquel Raynal #define DMA_TLVL_REG 0x114
180d8701fe8SMiquel Raynal #define   DMA_TLVL(x) FIELD_PREP(GENMASK(7, 0), (x))
181d8701fe8SMiquel Raynal #define   DMA_TLVL_MAX DMA_TLVL(0xFF)
182d8701fe8SMiquel Raynal 
183d8701fe8SMiquel Raynal #define TIM_GEN_SEQ3_REG 0x134
184d8701fe8SMiquel Raynal #define   TIM_GEN_SEQ3_D12(x) FIELD_PREP(GENMASK(5, 0), max((x), 1U) - 1)
185d8701fe8SMiquel Raynal 
186d8701fe8SMiquel Raynal #define ECC_CNT_REG 0x14C
187d8701fe8SMiquel Raynal #define   ECC_CNT(cs, reg) FIELD_GET(GENMASK(5, 0), (reg) >> ((cs) * 8))
188d8701fe8SMiquel Raynal 
189d8701fe8SMiquel Raynal #define RNANDC_CS_NUM 4
190d8701fe8SMiquel Raynal 
191d8701fe8SMiquel Raynal #define TO_CYCLES64(ps, period_ns) ((unsigned int)DIV_ROUND_UP_ULL(div_u64(ps, 1000), \
192d8701fe8SMiquel Raynal 								   period_ns))
193d8701fe8SMiquel Raynal 
194d8701fe8SMiquel Raynal struct rnand_chip_sel {
195d8701fe8SMiquel Raynal 	unsigned int cs;
196d8701fe8SMiquel Raynal };
197d8701fe8SMiquel Raynal 
198d8701fe8SMiquel Raynal struct rnand_chip {
199d8701fe8SMiquel Raynal 	struct nand_chip chip;
200d8701fe8SMiquel Raynal 	struct list_head node;
201d8701fe8SMiquel Raynal 	int selected_die;
202d8701fe8SMiquel Raynal 	u32 ctrl;
203d8701fe8SMiquel Raynal 	unsigned int nsels;
204d8701fe8SMiquel Raynal 	u32 control;
205d8701fe8SMiquel Raynal 	u32 ecc_ctrl;
206d8701fe8SMiquel Raynal 	u32 timings_asyn;
207d8701fe8SMiquel Raynal 	u32 tim_seq0;
208d8701fe8SMiquel Raynal 	u32 tim_seq1;
209d8701fe8SMiquel Raynal 	u32 tim_gen_seq0;
210d8701fe8SMiquel Raynal 	u32 tim_gen_seq1;
211d8701fe8SMiquel Raynal 	u32 tim_gen_seq2;
212d8701fe8SMiquel Raynal 	u32 tim_gen_seq3;
213*cb5fce7dSKees Cook 	struct rnand_chip_sel sels[] __counted_by(nsels);
214d8701fe8SMiquel Raynal };
215d8701fe8SMiquel Raynal 
216d8701fe8SMiquel Raynal struct rnandc {
217d8701fe8SMiquel Raynal 	struct nand_controller controller;
218d8701fe8SMiquel Raynal 	struct device *dev;
219d8701fe8SMiquel Raynal 	void __iomem *regs;
2206a2277a0SMiquel Raynal 	unsigned long ext_clk_rate;
221d8701fe8SMiquel Raynal 	unsigned long assigned_cs;
222d8701fe8SMiquel Raynal 	struct list_head chips;
223d8701fe8SMiquel Raynal 	struct nand_chip *selected_chip;
224d8701fe8SMiquel Raynal 	struct completion complete;
225d8701fe8SMiquel Raynal 	bool use_polling;
226d8701fe8SMiquel Raynal 	u8 *buf;
227d8701fe8SMiquel Raynal 	unsigned int buf_sz;
228d8701fe8SMiquel Raynal };
229d8701fe8SMiquel Raynal 
230d8701fe8SMiquel Raynal struct rnandc_op {
231d8701fe8SMiquel Raynal 	u32 command;
232d8701fe8SMiquel Raynal 	u32 addr0_col;
233d8701fe8SMiquel Raynal 	u32 addr0_row;
234d8701fe8SMiquel Raynal 	u32 addr1_col;
235d8701fe8SMiquel Raynal 	u32 addr1_row;
236d8701fe8SMiquel Raynal 	u32 data_size;
237d8701fe8SMiquel Raynal 	u32 ecc_offset;
238d8701fe8SMiquel Raynal 	u32 gen_seq_ctrl;
239d8701fe8SMiquel Raynal 	u8 *buf;
240d8701fe8SMiquel Raynal 	bool read;
241d8701fe8SMiquel Raynal 	unsigned int len;
242d8701fe8SMiquel Raynal };
243d8701fe8SMiquel Raynal 
to_rnandc(struct nand_controller * ctrl)244d8701fe8SMiquel Raynal static inline struct rnandc *to_rnandc(struct nand_controller *ctrl)
245d8701fe8SMiquel Raynal {
246d8701fe8SMiquel Raynal 	return container_of(ctrl, struct rnandc, controller);
247d8701fe8SMiquel Raynal }
248d8701fe8SMiquel Raynal 
to_rnand(struct nand_chip * chip)249d8701fe8SMiquel Raynal static inline struct rnand_chip *to_rnand(struct nand_chip *chip)
250d8701fe8SMiquel Raynal {
251d8701fe8SMiquel Raynal 	return container_of(chip, struct rnand_chip, chip);
252d8701fe8SMiquel Raynal }
253d8701fe8SMiquel Raynal 
to_rnandc_cs(struct rnand_chip * nand)254d8701fe8SMiquel Raynal static inline unsigned int to_rnandc_cs(struct rnand_chip *nand)
255d8701fe8SMiquel Raynal {
256d8701fe8SMiquel Raynal 	return nand->sels[nand->selected_die].cs;
257d8701fe8SMiquel Raynal }
258d8701fe8SMiquel Raynal 
rnandc_dis_correction(struct rnandc * rnandc)259d8701fe8SMiquel Raynal static void rnandc_dis_correction(struct rnandc *rnandc)
260d8701fe8SMiquel Raynal {
261d8701fe8SMiquel Raynal 	u32 control;
262d8701fe8SMiquel Raynal 
263d8701fe8SMiquel Raynal 	control = readl_relaxed(rnandc->regs + CONTROL_REG);
264d8701fe8SMiquel Raynal 	control &= ~CONTROL_ECC_EN;
265d8701fe8SMiquel Raynal 	writel_relaxed(control, rnandc->regs + CONTROL_REG);
266d8701fe8SMiquel Raynal }
267d8701fe8SMiquel Raynal 
rnandc_en_correction(struct rnandc * rnandc)268d8701fe8SMiquel Raynal static void rnandc_en_correction(struct rnandc *rnandc)
269d8701fe8SMiquel Raynal {
270d8701fe8SMiquel Raynal 	u32 control;
271d8701fe8SMiquel Raynal 
272d8701fe8SMiquel Raynal 	control = readl_relaxed(rnandc->regs + CONTROL_REG);
273d8701fe8SMiquel Raynal 	control |= CONTROL_ECC_EN;
274d8701fe8SMiquel Raynal 	writel_relaxed(control, rnandc->regs + CONTROL_REG);
275d8701fe8SMiquel Raynal }
276d8701fe8SMiquel Raynal 
rnandc_clear_status(struct rnandc * rnandc)277d8701fe8SMiquel Raynal static void rnandc_clear_status(struct rnandc *rnandc)
278d8701fe8SMiquel Raynal {
279d8701fe8SMiquel Raynal 	writel_relaxed(0, rnandc->regs + INT_STATUS_REG);
280d8701fe8SMiquel Raynal 	writel_relaxed(0, rnandc->regs + ECC_STAT_REG);
281d8701fe8SMiquel Raynal 	writel_relaxed(0, rnandc->regs + ECC_CNT_REG);
282d8701fe8SMiquel Raynal }
283d8701fe8SMiquel Raynal 
rnandc_dis_interrupts(struct rnandc * rnandc)284d8701fe8SMiquel Raynal static void rnandc_dis_interrupts(struct rnandc *rnandc)
285d8701fe8SMiquel Raynal {
286d8701fe8SMiquel Raynal 	writel_relaxed(0, rnandc->regs + INT_MASK_REG);
287d8701fe8SMiquel Raynal }
288d8701fe8SMiquel Raynal 
rnandc_en_interrupts(struct rnandc * rnandc,u32 val)289d8701fe8SMiquel Raynal static void rnandc_en_interrupts(struct rnandc *rnandc, u32 val)
290d8701fe8SMiquel Raynal {
291d8701fe8SMiquel Raynal 	if (!rnandc->use_polling)
292d8701fe8SMiquel Raynal 		writel_relaxed(val, rnandc->regs + INT_MASK_REG);
293d8701fe8SMiquel Raynal }
294d8701fe8SMiquel Raynal 
rnandc_clear_fifo(struct rnandc * rnandc)295d8701fe8SMiquel Raynal static void rnandc_clear_fifo(struct rnandc *rnandc)
296d8701fe8SMiquel Raynal {
297d8701fe8SMiquel Raynal 	writel_relaxed(FIFO_INIT, rnandc->regs + FIFO_INIT_REG);
298d8701fe8SMiquel Raynal }
299d8701fe8SMiquel Raynal 
rnandc_select_target(struct nand_chip * chip,int die_nr)300d8701fe8SMiquel Raynal static void rnandc_select_target(struct nand_chip *chip, int die_nr)
301d8701fe8SMiquel Raynal {
302d8701fe8SMiquel Raynal 	struct rnand_chip *rnand = to_rnand(chip);
303d8701fe8SMiquel Raynal 	struct rnandc *rnandc = to_rnandc(chip->controller);
304d8701fe8SMiquel Raynal 	unsigned int cs = rnand->sels[die_nr].cs;
305d8701fe8SMiquel Raynal 
306d8701fe8SMiquel Raynal 	if (chip == rnandc->selected_chip && die_nr == rnand->selected_die)
307d8701fe8SMiquel Raynal 		return;
308d8701fe8SMiquel Raynal 
309d8701fe8SMiquel Raynal 	rnandc_clear_status(rnandc);
310d8701fe8SMiquel Raynal 	writel_relaxed(MEM_CTRL_CS(cs) | MEM_CTRL_DIS_WP(cs), rnandc->regs + MEM_CTRL_REG);
311d8701fe8SMiquel Raynal 	writel_relaxed(rnand->control, rnandc->regs + CONTROL_REG);
312d8701fe8SMiquel Raynal 	writel_relaxed(rnand->ecc_ctrl, rnandc->regs + ECC_CTRL_REG);
313d8701fe8SMiquel Raynal 	writel_relaxed(rnand->timings_asyn, rnandc->regs + TIMINGS_ASYN_REG);
314d8701fe8SMiquel Raynal 	writel_relaxed(rnand->tim_seq0, rnandc->regs + TIM_SEQ0_REG);
315d8701fe8SMiquel Raynal 	writel_relaxed(rnand->tim_seq1, rnandc->regs + TIM_SEQ1_REG);
316d8701fe8SMiquel Raynal 	writel_relaxed(rnand->tim_gen_seq0, rnandc->regs + TIM_GEN_SEQ0_REG);
317d8701fe8SMiquel Raynal 	writel_relaxed(rnand->tim_gen_seq1, rnandc->regs + TIM_GEN_SEQ1_REG);
318d8701fe8SMiquel Raynal 	writel_relaxed(rnand->tim_gen_seq2, rnandc->regs + TIM_GEN_SEQ2_REG);
319d8701fe8SMiquel Raynal 	writel_relaxed(rnand->tim_gen_seq3, rnandc->regs + TIM_GEN_SEQ3_REG);
320d8701fe8SMiquel Raynal 
321d8701fe8SMiquel Raynal 	rnandc->selected_chip = chip;
322d8701fe8SMiquel Raynal 	rnand->selected_die = die_nr;
323d8701fe8SMiquel Raynal }
324d8701fe8SMiquel Raynal 
rnandc_trigger_op(struct rnandc * rnandc,struct rnandc_op * rop)325d8701fe8SMiquel Raynal static void rnandc_trigger_op(struct rnandc *rnandc, struct rnandc_op *rop)
326d8701fe8SMiquel Raynal {
327d8701fe8SMiquel Raynal 	writel_relaxed(rop->addr0_col, rnandc->regs + ADDR0_COL_REG);
328d8701fe8SMiquel Raynal 	writel_relaxed(rop->addr0_row, rnandc->regs + ADDR0_ROW_REG);
329d8701fe8SMiquel Raynal 	writel_relaxed(rop->addr1_col, rnandc->regs + ADDR1_COL_REG);
330d8701fe8SMiquel Raynal 	writel_relaxed(rop->addr1_row, rnandc->regs + ADDR1_ROW_REG);
331d8701fe8SMiquel Raynal 	writel_relaxed(rop->ecc_offset, rnandc->regs + ECC_OFFSET_REG);
332d8701fe8SMiquel Raynal 	writel_relaxed(rop->gen_seq_ctrl, rnandc->regs + GEN_SEQ_CTRL_REG);
333d8701fe8SMiquel Raynal 	writel_relaxed(DATA_SIZE(rop->len), rnandc->regs + DATA_SIZE_REG);
334d8701fe8SMiquel Raynal 	writel_relaxed(rop->command, rnandc->regs + COMMAND_REG);
335d8701fe8SMiquel Raynal }
336d8701fe8SMiquel Raynal 
rnandc_trigger_dma(struct rnandc * rnandc)337d8701fe8SMiquel Raynal static void rnandc_trigger_dma(struct rnandc *rnandc)
338d8701fe8SMiquel Raynal {
339d8701fe8SMiquel Raynal 	writel_relaxed(DMA_CTRL_INCREMENT_BURST_4 |
340d8701fe8SMiquel Raynal 		       DMA_CTRL_REGISTER_MANAGED_MODE |
341d8701fe8SMiquel Raynal 		       DMA_CTRL_START, rnandc->regs + DMA_CTRL_REG);
342d8701fe8SMiquel Raynal }
343d8701fe8SMiquel Raynal 
rnandc_irq_handler(int irq,void * private)344d8701fe8SMiquel Raynal static irqreturn_t rnandc_irq_handler(int irq, void *private)
345d8701fe8SMiquel Raynal {
346d8701fe8SMiquel Raynal 	struct rnandc *rnandc = private;
347d8701fe8SMiquel Raynal 
348d8701fe8SMiquel Raynal 	rnandc_dis_interrupts(rnandc);
349d8701fe8SMiquel Raynal 	complete(&rnandc->complete);
350d8701fe8SMiquel Raynal 
351d8701fe8SMiquel Raynal 	return IRQ_HANDLED;
352d8701fe8SMiquel Raynal }
353d8701fe8SMiquel Raynal 
rnandc_wait_end_of_op(struct rnandc * rnandc,struct nand_chip * chip)354d8701fe8SMiquel Raynal static int rnandc_wait_end_of_op(struct rnandc *rnandc,
355d8701fe8SMiquel Raynal 				 struct nand_chip *chip)
356d8701fe8SMiquel Raynal {
357d8701fe8SMiquel Raynal 	struct rnand_chip *rnand = to_rnand(chip);
358d8701fe8SMiquel Raynal 	unsigned int cs = to_rnandc_cs(rnand);
359d8701fe8SMiquel Raynal 	u32 status;
360d8701fe8SMiquel Raynal 	int ret;
361d8701fe8SMiquel Raynal 
362d8701fe8SMiquel Raynal 	ret = readl_poll_timeout(rnandc->regs + STATUS_REG, status,
363d8701fe8SMiquel Raynal 				 MEM_RDY(cs, status) && CTRL_RDY(status),
364d8701fe8SMiquel Raynal 				 1, 100000);
365d8701fe8SMiquel Raynal 	if (ret)
366d8701fe8SMiquel Raynal 		dev_err(rnandc->dev, "Operation timed out, status: 0x%08x\n",
367d8701fe8SMiquel Raynal 			status);
368d8701fe8SMiquel Raynal 
369d8701fe8SMiquel Raynal 	return ret;
370d8701fe8SMiquel Raynal }
371d8701fe8SMiquel Raynal 
rnandc_wait_end_of_io(struct rnandc * rnandc,struct nand_chip * chip)372d8701fe8SMiquel Raynal static int rnandc_wait_end_of_io(struct rnandc *rnandc,
373d8701fe8SMiquel Raynal 				 struct nand_chip *chip)
374d8701fe8SMiquel Raynal {
375d8701fe8SMiquel Raynal 	int timeout_ms = 1000;
376d8701fe8SMiquel Raynal 	int ret;
377d8701fe8SMiquel Raynal 
378d8701fe8SMiquel Raynal 	if (rnandc->use_polling) {
379d8701fe8SMiquel Raynal 		struct rnand_chip *rnand = to_rnand(chip);
380d8701fe8SMiquel Raynal 		unsigned int cs = to_rnandc_cs(rnand);
381d8701fe8SMiquel Raynal 		u32 status;
382d8701fe8SMiquel Raynal 
383d8701fe8SMiquel Raynal 		ret = readl_poll_timeout(rnandc->regs + INT_STATUS_REG, status,
384d8701fe8SMiquel Raynal 					 MEM_IS_RDY(cs, status) &
385d8701fe8SMiquel Raynal 					 DMA_HAS_ENDED(status),
386d8701fe8SMiquel Raynal 					 0, timeout_ms * 1000);
387d8701fe8SMiquel Raynal 	} else {
388d8701fe8SMiquel Raynal 		ret = wait_for_completion_timeout(&rnandc->complete,
389d8701fe8SMiquel Raynal 						  msecs_to_jiffies(timeout_ms));
390d8701fe8SMiquel Raynal 		if (!ret)
391d8701fe8SMiquel Raynal 			ret = -ETIMEDOUT;
392d8701fe8SMiquel Raynal 		else
393d8701fe8SMiquel Raynal 			ret = 0;
394d8701fe8SMiquel Raynal 	}
395d8701fe8SMiquel Raynal 
396d8701fe8SMiquel Raynal 	return ret;
397d8701fe8SMiquel Raynal }
398d8701fe8SMiquel Raynal 
rnandc_read_page_hw_ecc(struct nand_chip * chip,u8 * buf,int oob_required,int page)399d8701fe8SMiquel Raynal static int rnandc_read_page_hw_ecc(struct nand_chip *chip, u8 *buf,
400d8701fe8SMiquel Raynal 				   int oob_required, int page)
401d8701fe8SMiquel Raynal {
402d8701fe8SMiquel Raynal 	struct rnandc *rnandc = to_rnandc(chip->controller);
403d8701fe8SMiquel Raynal 	struct mtd_info *mtd = nand_to_mtd(chip);
404d8701fe8SMiquel Raynal 	struct rnand_chip *rnand = to_rnand(chip);
405d8701fe8SMiquel Raynal 	unsigned int cs = to_rnandc_cs(rnand);
406d8701fe8SMiquel Raynal 	struct rnandc_op rop = {
407d8701fe8SMiquel Raynal 		.command = COMMAND_INPUT_SEL_DMA | COMMAND_0(NAND_CMD_READ0) |
408d8701fe8SMiquel Raynal 			   COMMAND_2(NAND_CMD_READSTART) | COMMAND_FIFO_SEL |
409d8701fe8SMiquel Raynal 			   COMMAND_SEQ_READ_PAGE,
410d8701fe8SMiquel Raynal 		.addr0_row = page,
411d8701fe8SMiquel Raynal 		.len = mtd->writesize,
412d8701fe8SMiquel Raynal 		.ecc_offset = ECC_OFFSET(mtd->writesize + 2),
413d8701fe8SMiquel Raynal 	};
414d8701fe8SMiquel Raynal 	unsigned int max_bitflips = 0;
415d8701fe8SMiquel Raynal 	dma_addr_t dma_addr;
416d8701fe8SMiquel Raynal 	u32 ecc_stat;
417d8701fe8SMiquel Raynal 	int bf, ret, i;
418d8701fe8SMiquel Raynal 
419d8701fe8SMiquel Raynal 	/* Prepare controller */
420d8701fe8SMiquel Raynal 	rnandc_select_target(chip, chip->cur_cs);
421d8701fe8SMiquel Raynal 	rnandc_clear_status(rnandc);
422d8701fe8SMiquel Raynal 	reinit_completion(&rnandc->complete);
423d8701fe8SMiquel Raynal 	rnandc_en_interrupts(rnandc, INT_DMA_ENDED);
424d8701fe8SMiquel Raynal 	rnandc_en_correction(rnandc);
425d8701fe8SMiquel Raynal 
426d8701fe8SMiquel Raynal 	/* Configure DMA */
427d8701fe8SMiquel Raynal 	dma_addr = dma_map_single(rnandc->dev, rnandc->buf, mtd->writesize,
428d8701fe8SMiquel Raynal 				  DMA_FROM_DEVICE);
429d8701fe8SMiquel Raynal 	writel(dma_addr, rnandc->regs + DMA_ADDR_LOW_REG);
430d8701fe8SMiquel Raynal 	writel(mtd->writesize, rnandc->regs + DMA_CNT_REG);
431d8701fe8SMiquel Raynal 	writel(DMA_TLVL_MAX, rnandc->regs + DMA_TLVL_REG);
432d8701fe8SMiquel Raynal 
433d8701fe8SMiquel Raynal 	rnandc_trigger_op(rnandc, &rop);
434d8701fe8SMiquel Raynal 	rnandc_trigger_dma(rnandc);
435d8701fe8SMiquel Raynal 
436d8701fe8SMiquel Raynal 	ret = rnandc_wait_end_of_io(rnandc, chip);
437d8701fe8SMiquel Raynal 	dma_unmap_single(rnandc->dev, dma_addr, mtd->writesize, DMA_FROM_DEVICE);
438d8701fe8SMiquel Raynal 	rnandc_dis_correction(rnandc);
439d8701fe8SMiquel Raynal 	if (ret) {
440d8701fe8SMiquel Raynal 		dev_err(rnandc->dev, "Read page operation never ending\n");
441d8701fe8SMiquel Raynal 		return ret;
442d8701fe8SMiquel Raynal 	}
443d8701fe8SMiquel Raynal 
444d8701fe8SMiquel Raynal 	ecc_stat = readl_relaxed(rnandc->regs + ECC_STAT_REG);
445d8701fe8SMiquel Raynal 
446d8701fe8SMiquel Raynal 	if (oob_required || ECC_STAT_UNCORRECTABLE(cs, ecc_stat)) {
447d8701fe8SMiquel Raynal 		ret = nand_change_read_column_op(chip, mtd->writesize,
448d8701fe8SMiquel Raynal 						 chip->oob_poi, mtd->oobsize,
449d8701fe8SMiquel Raynal 						 false);
450d8701fe8SMiquel Raynal 		if (ret)
451d8701fe8SMiquel Raynal 			return ret;
452d8701fe8SMiquel Raynal 	}
453d8701fe8SMiquel Raynal 
454d8701fe8SMiquel Raynal 	if (ECC_STAT_UNCORRECTABLE(cs, ecc_stat)) {
455d8701fe8SMiquel Raynal 		for (i = 0; i < chip->ecc.steps; i++) {
456d8701fe8SMiquel Raynal 			unsigned int off = i * chip->ecc.size;
457d8701fe8SMiquel Raynal 			unsigned int eccoff = i * chip->ecc.bytes;
458d8701fe8SMiquel Raynal 
459d8701fe8SMiquel Raynal 			bf = nand_check_erased_ecc_chunk(rnandc->buf + off,
460d8701fe8SMiquel Raynal 							 chip->ecc.size,
461d8701fe8SMiquel Raynal 							 chip->oob_poi + 2 + eccoff,
462d8701fe8SMiquel Raynal 							 chip->ecc.bytes,
463d8701fe8SMiquel Raynal 							 NULL, 0,
464d8701fe8SMiquel Raynal 							 chip->ecc.strength);
465d8701fe8SMiquel Raynal 			if (bf < 0) {
466d8701fe8SMiquel Raynal 				mtd->ecc_stats.failed++;
467d8701fe8SMiquel Raynal 			} else {
468d8701fe8SMiquel Raynal 				mtd->ecc_stats.corrected += bf;
469d8701fe8SMiquel Raynal 				max_bitflips = max_t(unsigned int, max_bitflips, bf);
470d8701fe8SMiquel Raynal 			}
471d8701fe8SMiquel Raynal 		}
472d8701fe8SMiquel Raynal 	} else if (ECC_STAT_CORRECTABLE(cs, ecc_stat)) {
473d8701fe8SMiquel Raynal 		bf = ECC_CNT(cs, readl_relaxed(rnandc->regs + ECC_CNT_REG));
474d8701fe8SMiquel Raynal 		/*
475d8701fe8SMiquel Raynal 		 * The number of bitflips is an approximation given the fact
476d8701fe8SMiquel Raynal 		 * that this controller does not provide per-chunk details but
477d8701fe8SMiquel Raynal 		 * only gives statistics on the entire page.
478d8701fe8SMiquel Raynal 		 */
479d8701fe8SMiquel Raynal 		mtd->ecc_stats.corrected += bf;
480d8701fe8SMiquel Raynal 	}
481d8701fe8SMiquel Raynal 
482d8701fe8SMiquel Raynal 	memcpy(buf, rnandc->buf, mtd->writesize);
483d8701fe8SMiquel Raynal 
484d8701fe8SMiquel Raynal 	return 0;
485d8701fe8SMiquel Raynal }
486d8701fe8SMiquel Raynal 
rnandc_read_subpage_hw_ecc(struct nand_chip * chip,u32 req_offset,u32 req_len,u8 * bufpoi,int page)487d8701fe8SMiquel Raynal static int rnandc_read_subpage_hw_ecc(struct nand_chip *chip, u32 req_offset,
488d8701fe8SMiquel Raynal 				      u32 req_len, u8 *bufpoi, int page)
489d8701fe8SMiquel Raynal {
490d8701fe8SMiquel Raynal 	struct rnandc *rnandc = to_rnandc(chip->controller);
491d8701fe8SMiquel Raynal 	struct mtd_info *mtd = nand_to_mtd(chip);
492d8701fe8SMiquel Raynal 	struct rnand_chip *rnand = to_rnand(chip);
493d8701fe8SMiquel Raynal 	unsigned int cs = to_rnandc_cs(rnand);
494d8701fe8SMiquel Raynal 	unsigned int page_off = round_down(req_offset, chip->ecc.size);
495d8701fe8SMiquel Raynal 	unsigned int real_len = round_up(req_offset + req_len - page_off,
496d8701fe8SMiquel Raynal 					 chip->ecc.size);
497d8701fe8SMiquel Raynal 	unsigned int start_chunk = page_off / chip->ecc.size;
498d8701fe8SMiquel Raynal 	unsigned int nchunks = real_len / chip->ecc.size;
499d8701fe8SMiquel Raynal 	unsigned int ecc_off = 2 + (start_chunk * chip->ecc.bytes);
500d8701fe8SMiquel Raynal 	struct rnandc_op rop = {
501d8701fe8SMiquel Raynal 		.command = COMMAND_INPUT_SEL_AHBS | COMMAND_0(NAND_CMD_READ0) |
502d8701fe8SMiquel Raynal 			   COMMAND_2(NAND_CMD_READSTART) | COMMAND_FIFO_SEL |
503d8701fe8SMiquel Raynal 			   COMMAND_SEQ_READ_PAGE,
504d8701fe8SMiquel Raynal 		.addr0_row = page,
505d8701fe8SMiquel Raynal 		.addr0_col = page_off,
506d8701fe8SMiquel Raynal 		.len = real_len,
507d8701fe8SMiquel Raynal 		.ecc_offset = ECC_OFFSET(mtd->writesize + ecc_off),
508d8701fe8SMiquel Raynal 	};
509d8701fe8SMiquel Raynal 	unsigned int max_bitflips = 0, i;
510d8701fe8SMiquel Raynal 	u32 ecc_stat;
511d8701fe8SMiquel Raynal 	int bf, ret;
512d8701fe8SMiquel Raynal 
513d8701fe8SMiquel Raynal 	/* Prepare controller */
514d8701fe8SMiquel Raynal 	rnandc_select_target(chip, chip->cur_cs);
515d8701fe8SMiquel Raynal 	rnandc_clear_status(rnandc);
516d8701fe8SMiquel Raynal 	rnandc_en_correction(rnandc);
517d8701fe8SMiquel Raynal 	rnandc_trigger_op(rnandc, &rop);
518d8701fe8SMiquel Raynal 
519d8701fe8SMiquel Raynal 	while (!FIFO_STATE_C_EMPTY(readl(rnandc->regs + FIFO_STATE_REG)))
520d8701fe8SMiquel Raynal 		cpu_relax();
521d8701fe8SMiquel Raynal 
522d8701fe8SMiquel Raynal 	while (FIFO_STATE_R_EMPTY(readl(rnandc->regs + FIFO_STATE_REG)))
523d8701fe8SMiquel Raynal 		cpu_relax();
524d8701fe8SMiquel Raynal 
525d8701fe8SMiquel Raynal 	ioread32_rep(rnandc->regs + FIFO_DATA_REG, bufpoi + page_off,
526d8701fe8SMiquel Raynal 		     real_len / 4);
527d8701fe8SMiquel Raynal 
528d8701fe8SMiquel Raynal 	if (!FIFO_STATE_R_EMPTY(readl(rnandc->regs + FIFO_STATE_REG))) {
529d8701fe8SMiquel Raynal 		dev_err(rnandc->dev, "Clearing residual data in the read FIFO\n");
530d8701fe8SMiquel Raynal 		rnandc_clear_fifo(rnandc);
531d8701fe8SMiquel Raynal 	}
532d8701fe8SMiquel Raynal 
533d8701fe8SMiquel Raynal 	ret = rnandc_wait_end_of_op(rnandc, chip);
534d8701fe8SMiquel Raynal 	rnandc_dis_correction(rnandc);
535d8701fe8SMiquel Raynal 	if (ret) {
536d8701fe8SMiquel Raynal 		dev_err(rnandc->dev, "Read subpage operation never ending\n");
537d8701fe8SMiquel Raynal 		return ret;
538d8701fe8SMiquel Raynal 	}
539d8701fe8SMiquel Raynal 
540d8701fe8SMiquel Raynal 	ecc_stat = readl_relaxed(rnandc->regs + ECC_STAT_REG);
541d8701fe8SMiquel Raynal 
542d8701fe8SMiquel Raynal 	if (ECC_STAT_UNCORRECTABLE(cs, ecc_stat)) {
543d8701fe8SMiquel Raynal 		ret = nand_change_read_column_op(chip, mtd->writesize,
544d8701fe8SMiquel Raynal 						 chip->oob_poi, mtd->oobsize,
545d8701fe8SMiquel Raynal 						 false);
546d8701fe8SMiquel Raynal 		if (ret)
547d8701fe8SMiquel Raynal 			return ret;
548d8701fe8SMiquel Raynal 
549d8701fe8SMiquel Raynal 		for (i = start_chunk; i < nchunks; i++) {
550d8701fe8SMiquel Raynal 			unsigned int dataoff = i * chip->ecc.size;
551d8701fe8SMiquel Raynal 			unsigned int eccoff = 2 + (i * chip->ecc.bytes);
552d8701fe8SMiquel Raynal 
553d8701fe8SMiquel Raynal 			bf = nand_check_erased_ecc_chunk(bufpoi + dataoff,
554d8701fe8SMiquel Raynal 							 chip->ecc.size,
555d8701fe8SMiquel Raynal 							 chip->oob_poi + eccoff,
556d8701fe8SMiquel Raynal 							 chip->ecc.bytes,
557d8701fe8SMiquel Raynal 							 NULL, 0,
558d8701fe8SMiquel Raynal 							 chip->ecc.strength);
559d8701fe8SMiquel Raynal 			if (bf < 0) {
560d8701fe8SMiquel Raynal 				mtd->ecc_stats.failed++;
561d8701fe8SMiquel Raynal 			} else {
562d8701fe8SMiquel Raynal 				mtd->ecc_stats.corrected += bf;
563d8701fe8SMiquel Raynal 				max_bitflips = max_t(unsigned int, max_bitflips, bf);
564d8701fe8SMiquel Raynal 			}
565d8701fe8SMiquel Raynal 		}
566d8701fe8SMiquel Raynal 	} else if (ECC_STAT_CORRECTABLE(cs, ecc_stat)) {
567d8701fe8SMiquel Raynal 		bf = ECC_CNT(cs, readl_relaxed(rnandc->regs + ECC_CNT_REG));
568d8701fe8SMiquel Raynal 		/*
569d8701fe8SMiquel Raynal 		 * The number of bitflips is an approximation given the fact
570d8701fe8SMiquel Raynal 		 * that this controller does not provide per-chunk details but
571d8701fe8SMiquel Raynal 		 * only gives statistics on the entire page.
572d8701fe8SMiquel Raynal 		 */
573d8701fe8SMiquel Raynal 		mtd->ecc_stats.corrected += bf;
574d8701fe8SMiquel Raynal 	}
575d8701fe8SMiquel Raynal 
576d8701fe8SMiquel Raynal 	return 0;
577d8701fe8SMiquel Raynal }
578d8701fe8SMiquel Raynal 
rnandc_write_page_hw_ecc(struct nand_chip * chip,const u8 * buf,int oob_required,int page)579d8701fe8SMiquel Raynal static int rnandc_write_page_hw_ecc(struct nand_chip *chip, const u8 *buf,
580d8701fe8SMiquel Raynal 				    int oob_required, int page)
581d8701fe8SMiquel Raynal {
582d8701fe8SMiquel Raynal 	struct rnandc *rnandc = to_rnandc(chip->controller);
583d8701fe8SMiquel Raynal 	struct mtd_info *mtd = nand_to_mtd(chip);
584d8701fe8SMiquel Raynal 	struct rnand_chip *rnand = to_rnand(chip);
585d8701fe8SMiquel Raynal 	unsigned int cs = to_rnandc_cs(rnand);
586d8701fe8SMiquel Raynal 	struct rnandc_op rop = {
587d8701fe8SMiquel Raynal 		.command = COMMAND_INPUT_SEL_DMA | COMMAND_0(NAND_CMD_SEQIN) |
588d8701fe8SMiquel Raynal 			   COMMAND_1(NAND_CMD_PAGEPROG) | COMMAND_FIFO_SEL |
589d8701fe8SMiquel Raynal 			   COMMAND_SEQ_WRITE_PAGE,
590d8701fe8SMiquel Raynal 		.addr0_row = page,
591d8701fe8SMiquel Raynal 		.len = mtd->writesize,
592d8701fe8SMiquel Raynal 		.ecc_offset = ECC_OFFSET(mtd->writesize + 2),
593d8701fe8SMiquel Raynal 	};
594d8701fe8SMiquel Raynal 	dma_addr_t dma_addr;
595d8701fe8SMiquel Raynal 	int ret;
596d8701fe8SMiquel Raynal 
597d8701fe8SMiquel Raynal 	memcpy(rnandc->buf, buf, mtd->writesize);
598d8701fe8SMiquel Raynal 
599d8701fe8SMiquel Raynal 	/* Prepare controller */
600d8701fe8SMiquel Raynal 	rnandc_select_target(chip, chip->cur_cs);
601d8701fe8SMiquel Raynal 	rnandc_clear_status(rnandc);
602d8701fe8SMiquel Raynal 	reinit_completion(&rnandc->complete);
603d8701fe8SMiquel Raynal 	rnandc_en_interrupts(rnandc, INT_MEM_RDY(cs));
604d8701fe8SMiquel Raynal 	rnandc_en_correction(rnandc);
605d8701fe8SMiquel Raynal 
606d8701fe8SMiquel Raynal 	/* Configure DMA */
607d8701fe8SMiquel Raynal 	dma_addr = dma_map_single(rnandc->dev, (void *)rnandc->buf, mtd->writesize,
608d8701fe8SMiquel Raynal 				  DMA_TO_DEVICE);
609d8701fe8SMiquel Raynal 	writel(dma_addr, rnandc->regs + DMA_ADDR_LOW_REG);
610d8701fe8SMiquel Raynal 	writel(mtd->writesize, rnandc->regs + DMA_CNT_REG);
611d8701fe8SMiquel Raynal 	writel(DMA_TLVL_MAX, rnandc->regs + DMA_TLVL_REG);
612d8701fe8SMiquel Raynal 
613d8701fe8SMiquel Raynal 	rnandc_trigger_op(rnandc, &rop);
614d8701fe8SMiquel Raynal 	rnandc_trigger_dma(rnandc);
615d8701fe8SMiquel Raynal 
616d8701fe8SMiquel Raynal 	ret = rnandc_wait_end_of_io(rnandc, chip);
617d8701fe8SMiquel Raynal 	dma_unmap_single(rnandc->dev, dma_addr, mtd->writesize, DMA_TO_DEVICE);
618d8701fe8SMiquel Raynal 	rnandc_dis_correction(rnandc);
619d8701fe8SMiquel Raynal 	if (ret) {
620d8701fe8SMiquel Raynal 		dev_err(rnandc->dev, "Write page operation never ending\n");
621d8701fe8SMiquel Raynal 		return ret;
622d8701fe8SMiquel Raynal 	}
623d8701fe8SMiquel Raynal 
624d8701fe8SMiquel Raynal 	if (!oob_required)
625d8701fe8SMiquel Raynal 		return 0;
626d8701fe8SMiquel Raynal 
627d8701fe8SMiquel Raynal 	return nand_change_write_column_op(chip, mtd->writesize, chip->oob_poi,
628d8701fe8SMiquel Raynal 					   mtd->oobsize, false);
629d8701fe8SMiquel Raynal }
630d8701fe8SMiquel Raynal 
rnandc_write_subpage_hw_ecc(struct nand_chip * chip,u32 req_offset,u32 req_len,const u8 * bufpoi,int oob_required,int page)631d8701fe8SMiquel Raynal static int rnandc_write_subpage_hw_ecc(struct nand_chip *chip, u32 req_offset,
632d8701fe8SMiquel Raynal 				       u32 req_len, const u8 *bufpoi,
633d8701fe8SMiquel Raynal 				       int oob_required, int page)
634d8701fe8SMiquel Raynal {
635d8701fe8SMiquel Raynal 	struct rnandc *rnandc = to_rnandc(chip->controller);
636d8701fe8SMiquel Raynal 	struct mtd_info *mtd = nand_to_mtd(chip);
637d8701fe8SMiquel Raynal 	unsigned int page_off = round_down(req_offset, chip->ecc.size);
638d8701fe8SMiquel Raynal 	unsigned int real_len = round_up(req_offset + req_len - page_off,
639d8701fe8SMiquel Raynal 					 chip->ecc.size);
640d8701fe8SMiquel Raynal 	unsigned int start_chunk = page_off / chip->ecc.size;
641d8701fe8SMiquel Raynal 	unsigned int ecc_off = 2 + (start_chunk * chip->ecc.bytes);
642d8701fe8SMiquel Raynal 	struct rnandc_op rop = {
643d8701fe8SMiquel Raynal 		.command = COMMAND_INPUT_SEL_AHBS | COMMAND_0(NAND_CMD_SEQIN) |
644d8701fe8SMiquel Raynal 			   COMMAND_1(NAND_CMD_PAGEPROG) | COMMAND_FIFO_SEL |
645d8701fe8SMiquel Raynal 			   COMMAND_SEQ_WRITE_PAGE,
646d8701fe8SMiquel Raynal 		.addr0_row = page,
647d8701fe8SMiquel Raynal 		.addr0_col = page_off,
648d8701fe8SMiquel Raynal 		.len = real_len,
649d8701fe8SMiquel Raynal 		.ecc_offset = ECC_OFFSET(mtd->writesize + ecc_off),
650d8701fe8SMiquel Raynal 	};
651d8701fe8SMiquel Raynal 	int ret;
652d8701fe8SMiquel Raynal 
653d8701fe8SMiquel Raynal 	/* Prepare controller */
654d8701fe8SMiquel Raynal 	rnandc_select_target(chip, chip->cur_cs);
655d8701fe8SMiquel Raynal 	rnandc_clear_status(rnandc);
656d8701fe8SMiquel Raynal 	rnandc_en_correction(rnandc);
657d8701fe8SMiquel Raynal 	rnandc_trigger_op(rnandc, &rop);
658d8701fe8SMiquel Raynal 
659d8701fe8SMiquel Raynal 	while (FIFO_STATE_W_FULL(readl(rnandc->regs + FIFO_STATE_REG)))
660d8701fe8SMiquel Raynal 		cpu_relax();
661d8701fe8SMiquel Raynal 
662d8701fe8SMiquel Raynal 	iowrite32_rep(rnandc->regs + FIFO_DATA_REG, bufpoi + page_off,
663d8701fe8SMiquel Raynal 		      real_len / 4);
664d8701fe8SMiquel Raynal 
665d8701fe8SMiquel Raynal 	while (!FIFO_STATE_W_EMPTY(readl(rnandc->regs + FIFO_STATE_REG)))
666d8701fe8SMiquel Raynal 		cpu_relax();
667d8701fe8SMiquel Raynal 
668d8701fe8SMiquel Raynal 	ret = rnandc_wait_end_of_op(rnandc, chip);
669d8701fe8SMiquel Raynal 	rnandc_dis_correction(rnandc);
670d8701fe8SMiquel Raynal 	if (ret) {
671d8701fe8SMiquel Raynal 		dev_err(rnandc->dev, "Write subpage operation never ending\n");
672d8701fe8SMiquel Raynal 		return ret;
673d8701fe8SMiquel Raynal 	}
674d8701fe8SMiquel Raynal 
675d8701fe8SMiquel Raynal 	return 0;
676d8701fe8SMiquel Raynal }
677d8701fe8SMiquel Raynal 
678d8701fe8SMiquel Raynal /*
679d8701fe8SMiquel Raynal  * This controller is simple enough and thus does not need to use the parser
680d8701fe8SMiquel Raynal  * provided by the core, instead, handle every situation here.
681d8701fe8SMiquel Raynal  */
rnandc_exec_op(struct nand_chip * chip,const struct nand_operation * op,bool check_only)682d8701fe8SMiquel Raynal static int rnandc_exec_op(struct nand_chip *chip,
683d8701fe8SMiquel Raynal 			  const struct nand_operation *op, bool check_only)
684d8701fe8SMiquel Raynal {
685d8701fe8SMiquel Raynal 	struct rnandc *rnandc = to_rnandc(chip->controller);
686d8701fe8SMiquel Raynal 	const struct nand_op_instr *instr = NULL;
687d8701fe8SMiquel Raynal 	struct rnandc_op rop = {
688d8701fe8SMiquel Raynal 		.command = COMMAND_INPUT_SEL_AHBS,
689d8701fe8SMiquel Raynal 		.gen_seq_ctrl = GEN_SEQ_IMD_SEQ,
690d8701fe8SMiquel Raynal 	};
691d8701fe8SMiquel Raynal 	unsigned int cmd_phase = 0, addr_phase = 0, data_phase = 0,
692d8701fe8SMiquel Raynal 		delay_phase = 0, delays = 0;
693d8701fe8SMiquel Raynal 	unsigned int op_id, col_addrs, row_addrs, naddrs, remainder, words, i;
694d8701fe8SMiquel Raynal 	const u8 *addrs;
695d8701fe8SMiquel Raynal 	u32 last_bytes;
696d8701fe8SMiquel Raynal 	int ret;
697d8701fe8SMiquel Raynal 
698d8701fe8SMiquel Raynal 	if (!check_only)
699d8701fe8SMiquel Raynal 		rnandc_select_target(chip, op->cs);
700d8701fe8SMiquel Raynal 
701d8701fe8SMiquel Raynal 	for (op_id = 0; op_id < op->ninstrs; op_id++) {
702d8701fe8SMiquel Raynal 		instr = &op->instrs[op_id];
703d8701fe8SMiquel Raynal 
704d8701fe8SMiquel Raynal 		nand_op_trace("  ", instr);
705d8701fe8SMiquel Raynal 
706d8701fe8SMiquel Raynal 		switch (instr->type) {
707d8701fe8SMiquel Raynal 		case NAND_OP_CMD_INSTR:
708d8701fe8SMiquel Raynal 			switch (cmd_phase++) {
709d8701fe8SMiquel Raynal 			case 0:
710d8701fe8SMiquel Raynal 				rop.command |= COMMAND_0(instr->ctx.cmd.opcode);
711d8701fe8SMiquel Raynal 				rop.gen_seq_ctrl |= GEN_SEQ_CMD0_EN;
712d8701fe8SMiquel Raynal 				break;
713d8701fe8SMiquel Raynal 			case 1:
714d8701fe8SMiquel Raynal 				rop.gen_seq_ctrl |= GEN_SEQ_COMMAND_3(instr->ctx.cmd.opcode);
715d8701fe8SMiquel Raynal 				rop.gen_seq_ctrl |= GEN_SEQ_CMD3_EN;
716d8701fe8SMiquel Raynal 				if (addr_phase == 0)
717d8701fe8SMiquel Raynal 					addr_phase = 1;
718d8701fe8SMiquel Raynal 				break;
719d8701fe8SMiquel Raynal 			case 2:
720d8701fe8SMiquel Raynal 				rop.command |= COMMAND_2(instr->ctx.cmd.opcode);
721d8701fe8SMiquel Raynal 				rop.gen_seq_ctrl |= GEN_SEQ_CMD2_EN;
722d8701fe8SMiquel Raynal 				if (addr_phase <= 1)
723d8701fe8SMiquel Raynal 					addr_phase = 2;
724d8701fe8SMiquel Raynal 				break;
725d8701fe8SMiquel Raynal 			case 3:
726d8701fe8SMiquel Raynal 				rop.command |= COMMAND_1(instr->ctx.cmd.opcode);
727d8701fe8SMiquel Raynal 				rop.gen_seq_ctrl |= GEN_SEQ_CMD1_EN;
728d8701fe8SMiquel Raynal 				if (addr_phase <= 1)
729d8701fe8SMiquel Raynal 					addr_phase = 2;
730d8701fe8SMiquel Raynal 				if (delay_phase == 0)
731d8701fe8SMiquel Raynal 					delay_phase = 1;
732d8701fe8SMiquel Raynal 				if (data_phase == 0)
733d8701fe8SMiquel Raynal 					data_phase = 1;
734d8701fe8SMiquel Raynal 				break;
735d8701fe8SMiquel Raynal 			default:
736d8701fe8SMiquel Raynal 				return -EOPNOTSUPP;
737d8701fe8SMiquel Raynal 			}
738d8701fe8SMiquel Raynal 			break;
739d8701fe8SMiquel Raynal 
740d8701fe8SMiquel Raynal 		case NAND_OP_ADDR_INSTR:
741d8701fe8SMiquel Raynal 			addrs = instr->ctx.addr.addrs;
742d8701fe8SMiquel Raynal 			naddrs = instr->ctx.addr.naddrs;
743d8701fe8SMiquel Raynal 			if (naddrs > 5)
744d8701fe8SMiquel Raynal 				return -EOPNOTSUPP;
745d8701fe8SMiquel Raynal 
746d8701fe8SMiquel Raynal 			col_addrs = min(2U, naddrs);
747d8701fe8SMiquel Raynal 			row_addrs = naddrs > 2 ? naddrs - col_addrs : 0;
748d8701fe8SMiquel Raynal 
749d8701fe8SMiquel Raynal 			switch (addr_phase++) {
750d8701fe8SMiquel Raynal 			case 0:
751d8701fe8SMiquel Raynal 				for (i = 0; i < col_addrs; i++)
752d8701fe8SMiquel Raynal 					rop.addr0_col |= addrs[i] << (i * 8);
753d8701fe8SMiquel Raynal 				rop.gen_seq_ctrl |= GEN_SEQ_COL_A0(col_addrs);
754d8701fe8SMiquel Raynal 
755d8701fe8SMiquel Raynal 				for (i = 0; i < row_addrs; i++)
756d8701fe8SMiquel Raynal 					rop.addr0_row |= addrs[2 + i] << (i * 8);
757d8701fe8SMiquel Raynal 				rop.gen_seq_ctrl |= GEN_SEQ_ROW_A0(row_addrs);
758d8701fe8SMiquel Raynal 
759d8701fe8SMiquel Raynal 				if (cmd_phase == 0)
760d8701fe8SMiquel Raynal 					cmd_phase = 1;
761d8701fe8SMiquel Raynal 				break;
762d8701fe8SMiquel Raynal 			case 1:
763d8701fe8SMiquel Raynal 				for (i = 0; i < col_addrs; i++)
764d8701fe8SMiquel Raynal 					rop.addr1_col |= addrs[i] << (i * 8);
765d8701fe8SMiquel Raynal 				rop.gen_seq_ctrl |= GEN_SEQ_COL_A1(col_addrs);
766d8701fe8SMiquel Raynal 
767d8701fe8SMiquel Raynal 				for (i = 0; i < row_addrs; i++)
768d8701fe8SMiquel Raynal 					rop.addr1_row |= addrs[2 + i] << (i * 8);
769d8701fe8SMiquel Raynal 				rop.gen_seq_ctrl |= GEN_SEQ_ROW_A1(row_addrs);
770d8701fe8SMiquel Raynal 
771d8701fe8SMiquel Raynal 				if (cmd_phase <= 1)
772d8701fe8SMiquel Raynal 					cmd_phase = 2;
773d8701fe8SMiquel Raynal 				break;
774d8701fe8SMiquel Raynal 			default:
775d8701fe8SMiquel Raynal 				return -EOPNOTSUPP;
776d8701fe8SMiquel Raynal 			}
777d8701fe8SMiquel Raynal 			break;
778d8701fe8SMiquel Raynal 
779d8701fe8SMiquel Raynal 		case NAND_OP_DATA_IN_INSTR:
780d8701fe8SMiquel Raynal 			rop.read = true;
781d8701fe8SMiquel Raynal 			fallthrough;
782d8701fe8SMiquel Raynal 		case NAND_OP_DATA_OUT_INSTR:
783d8701fe8SMiquel Raynal 			rop.gen_seq_ctrl |= GEN_SEQ_DATA_EN;
784d8701fe8SMiquel Raynal 			rop.buf = instr->ctx.data.buf.in;
785d8701fe8SMiquel Raynal 			rop.len = instr->ctx.data.len;
786d8701fe8SMiquel Raynal 			rop.command |= COMMAND_FIFO_SEL;
787d8701fe8SMiquel Raynal 
788d8701fe8SMiquel Raynal 			switch (data_phase++) {
789d8701fe8SMiquel Raynal 			case 0:
790d8701fe8SMiquel Raynal 				if (cmd_phase <= 2)
791d8701fe8SMiquel Raynal 					cmd_phase = 3;
792d8701fe8SMiquel Raynal 				if (addr_phase <= 1)
793d8701fe8SMiquel Raynal 					addr_phase = 2;
794d8701fe8SMiquel Raynal 				if (delay_phase == 0)
795d8701fe8SMiquel Raynal 					delay_phase = 1;
796d8701fe8SMiquel Raynal 				break;
797d8701fe8SMiquel Raynal 			default:
798d8701fe8SMiquel Raynal 				return -EOPNOTSUPP;
799d8701fe8SMiquel Raynal 			}
800d8701fe8SMiquel Raynal 			break;
801d8701fe8SMiquel Raynal 
802d8701fe8SMiquel Raynal 		case NAND_OP_WAITRDY_INSTR:
803d8701fe8SMiquel Raynal 			switch (delay_phase++) {
804d8701fe8SMiquel Raynal 			case 0:
805d8701fe8SMiquel Raynal 				rop.gen_seq_ctrl |= GEN_SEQ_DELAY0_EN;
806d8701fe8SMiquel Raynal 
807d8701fe8SMiquel Raynal 				if (cmd_phase <= 2)
808d8701fe8SMiquel Raynal 					cmd_phase = 3;
809d8701fe8SMiquel Raynal 				break;
810d8701fe8SMiquel Raynal 			case 1:
811d8701fe8SMiquel Raynal 				rop.gen_seq_ctrl |= GEN_SEQ_DELAY1_EN;
812d8701fe8SMiquel Raynal 
813d8701fe8SMiquel Raynal 				if (cmd_phase <= 3)
814d8701fe8SMiquel Raynal 					cmd_phase = 4;
815d8701fe8SMiquel Raynal 				if (data_phase == 0)
816d8701fe8SMiquel Raynal 					data_phase = 1;
817d8701fe8SMiquel Raynal 				break;
818d8701fe8SMiquel Raynal 			default:
819d8701fe8SMiquel Raynal 				return -EOPNOTSUPP;
820d8701fe8SMiquel Raynal 			}
821d8701fe8SMiquel Raynal 			break;
822d8701fe8SMiquel Raynal 		}
823d8701fe8SMiquel Raynal 	}
824d8701fe8SMiquel Raynal 
825d8701fe8SMiquel Raynal 	/*
826d8701fe8SMiquel Raynal 	 * Sequence 19 is generic and dedicated to write operations.
827d8701fe8SMiquel Raynal 	 * Sequence 18 is also generic and works for all other operations.
828d8701fe8SMiquel Raynal 	 */
829d8701fe8SMiquel Raynal 	if (rop.buf && !rop.read)
830d8701fe8SMiquel Raynal 		rop.command |= COMMAND_SEQ_GEN_OUT;
831d8701fe8SMiquel Raynal 	else
832d8701fe8SMiquel Raynal 		rop.command |= COMMAND_SEQ_GEN_IN;
833d8701fe8SMiquel Raynal 
834d8701fe8SMiquel Raynal 	if (delays > 1) {
835d8701fe8SMiquel Raynal 		dev_err(rnandc->dev, "Cannot handle more than one wait delay\n");
836d8701fe8SMiquel Raynal 		return -EOPNOTSUPP;
837d8701fe8SMiquel Raynal 	}
838d8701fe8SMiquel Raynal 
839d8701fe8SMiquel Raynal 	if (check_only)
840d8701fe8SMiquel Raynal 		return 0;
841d8701fe8SMiquel Raynal 
842d8701fe8SMiquel Raynal 	rnandc_trigger_op(rnandc, &rop);
843d8701fe8SMiquel Raynal 
844d8701fe8SMiquel Raynal 	words = rop.len / sizeof(u32);
845d8701fe8SMiquel Raynal 	remainder = rop.len % sizeof(u32);
846d8701fe8SMiquel Raynal 	if (rop.buf && rop.read) {
847d8701fe8SMiquel Raynal 		while (!FIFO_STATE_C_EMPTY(readl(rnandc->regs + FIFO_STATE_REG)))
848d8701fe8SMiquel Raynal 			cpu_relax();
849d8701fe8SMiquel Raynal 
850d8701fe8SMiquel Raynal 		while (FIFO_STATE_R_EMPTY(readl(rnandc->regs + FIFO_STATE_REG)))
851d8701fe8SMiquel Raynal 			cpu_relax();
852d8701fe8SMiquel Raynal 
853d8701fe8SMiquel Raynal 		ioread32_rep(rnandc->regs + FIFO_DATA_REG, rop.buf, words);
854d8701fe8SMiquel Raynal 		if (remainder) {
855d8701fe8SMiquel Raynal 			last_bytes = readl_relaxed(rnandc->regs + FIFO_DATA_REG);
856d8701fe8SMiquel Raynal 			memcpy(rop.buf + (words * sizeof(u32)), &last_bytes,
857d8701fe8SMiquel Raynal 			       remainder);
858d8701fe8SMiquel Raynal 		}
859d8701fe8SMiquel Raynal 
860d8701fe8SMiquel Raynal 		if (!FIFO_STATE_R_EMPTY(readl(rnandc->regs + FIFO_STATE_REG))) {
861d8701fe8SMiquel Raynal 			dev_warn(rnandc->dev,
862d8701fe8SMiquel Raynal 				 "Clearing residual data in the read FIFO\n");
863d8701fe8SMiquel Raynal 			rnandc_clear_fifo(rnandc);
864d8701fe8SMiquel Raynal 		}
865d8701fe8SMiquel Raynal 	} else if (rop.len && !rop.read) {
866d8701fe8SMiquel Raynal 		while (FIFO_STATE_W_FULL(readl(rnandc->regs + FIFO_STATE_REG)))
867d8701fe8SMiquel Raynal 			cpu_relax();
868d8701fe8SMiquel Raynal 
869d8701fe8SMiquel Raynal 		iowrite32_rep(rnandc->regs + FIFO_DATA_REG, rop.buf,
870d8701fe8SMiquel Raynal 			      DIV_ROUND_UP(rop.len, 4));
871d8701fe8SMiquel Raynal 
872d8701fe8SMiquel Raynal 		if (remainder) {
873d8701fe8SMiquel Raynal 			last_bytes = 0;
874d8701fe8SMiquel Raynal 			memcpy(&last_bytes, rop.buf + (words * sizeof(u32)), remainder);
875d8701fe8SMiquel Raynal 			writel_relaxed(last_bytes, rnandc->regs + FIFO_DATA_REG);
876d8701fe8SMiquel Raynal 		}
877d8701fe8SMiquel Raynal 
878d8701fe8SMiquel Raynal 		while (!FIFO_STATE_W_EMPTY(readl(rnandc->regs + FIFO_STATE_REG)))
879d8701fe8SMiquel Raynal 			cpu_relax();
880d8701fe8SMiquel Raynal 	}
881d8701fe8SMiquel Raynal 
882d8701fe8SMiquel Raynal 	ret = rnandc_wait_end_of_op(rnandc, chip);
883d8701fe8SMiquel Raynal 	if (ret)
884d8701fe8SMiquel Raynal 		return ret;
885d8701fe8SMiquel Raynal 
886d8701fe8SMiquel Raynal 	return 0;
887d8701fe8SMiquel Raynal }
888d8701fe8SMiquel Raynal 
rnandc_setup_interface(struct nand_chip * chip,int chipnr,const struct nand_interface_config * conf)889d8701fe8SMiquel Raynal static int rnandc_setup_interface(struct nand_chip *chip, int chipnr,
890d8701fe8SMiquel Raynal 				  const struct nand_interface_config *conf)
891d8701fe8SMiquel Raynal {
892d8701fe8SMiquel Raynal 	struct rnand_chip *rnand = to_rnand(chip);
893d8701fe8SMiquel Raynal 	struct rnandc *rnandc = to_rnandc(chip->controller);
8946a2277a0SMiquel Raynal 	unsigned int period_ns = 1000000000 / rnandc->ext_clk_rate;
895d8701fe8SMiquel Raynal 	const struct nand_sdr_timings *sdr;
896d8701fe8SMiquel Raynal 	unsigned int cyc, cle, ale, bef_dly, ca_to_data;
897d8701fe8SMiquel Raynal 
898d8701fe8SMiquel Raynal 	sdr = nand_get_sdr_timings(conf);
899d8701fe8SMiquel Raynal 	if (IS_ERR(sdr))
900d8701fe8SMiquel Raynal 		return PTR_ERR(sdr);
901d8701fe8SMiquel Raynal 
902d8701fe8SMiquel Raynal 	if (sdr->tRP_min != sdr->tWP_min || sdr->tREH_min != sdr->tWH_min) {
903d8701fe8SMiquel Raynal 		dev_err(rnandc->dev, "Read and write hold times must be identical\n");
904d8701fe8SMiquel Raynal 		return -EINVAL;
905d8701fe8SMiquel Raynal 	}
906d8701fe8SMiquel Raynal 
907d8701fe8SMiquel Raynal 	if (chipnr < 0)
908d8701fe8SMiquel Raynal 		return 0;
909d8701fe8SMiquel Raynal 
910d8701fe8SMiquel Raynal 	rnand->timings_asyn =
911d8701fe8SMiquel Raynal 		TIMINGS_ASYN_TRWP(TO_CYCLES64(sdr->tRP_min, period_ns)) |
912d8701fe8SMiquel Raynal 		TIMINGS_ASYN_TRWH(TO_CYCLES64(sdr->tREH_min, period_ns));
913d8701fe8SMiquel Raynal 	rnand->tim_seq0 =
914d8701fe8SMiquel Raynal 		TIM_SEQ0_TCCS(TO_CYCLES64(sdr->tCCS_min, period_ns)) |
915d8701fe8SMiquel Raynal 		TIM_SEQ0_TADL(TO_CYCLES64(sdr->tADL_min, period_ns)) |
916d8701fe8SMiquel Raynal 		TIM_SEQ0_TRHW(TO_CYCLES64(sdr->tRHW_min, period_ns)) |
917d8701fe8SMiquel Raynal 		TIM_SEQ0_TWHR(TO_CYCLES64(sdr->tWHR_min, period_ns));
918d8701fe8SMiquel Raynal 	rnand->tim_seq1 =
919d8701fe8SMiquel Raynal 		TIM_SEQ1_TWB(TO_CYCLES64(sdr->tWB_max, period_ns)) |
920d8701fe8SMiquel Raynal 		TIM_SEQ1_TRR(TO_CYCLES64(sdr->tRR_min, period_ns)) |
921d8701fe8SMiquel Raynal 		TIM_SEQ1_TWW(TO_CYCLES64(sdr->tWW_min, period_ns));
922d8701fe8SMiquel Raynal 
923d8701fe8SMiquel Raynal 	cyc = sdr->tDS_min + sdr->tDH_min;
924d8701fe8SMiquel Raynal 	cle = sdr->tCLH_min + sdr->tCLS_min;
925d8701fe8SMiquel Raynal 	ale = sdr->tALH_min + sdr->tALS_min;
926d8701fe8SMiquel Raynal 	bef_dly = sdr->tWB_max - sdr->tDH_min;
927d8701fe8SMiquel Raynal 	ca_to_data = sdr->tWHR_min + sdr->tREA_max - sdr->tDH_min;
928d8701fe8SMiquel Raynal 
929d8701fe8SMiquel Raynal 	/*
930d8701fe8SMiquel Raynal 	 * D0 = CMD -> ADDR = tCLH + tCLS - 1 cycle
931d8701fe8SMiquel Raynal 	 * D1 = CMD -> CMD = tCLH + tCLS - 1 cycle
932d8701fe8SMiquel Raynal 	 * D2 = CMD -> DLY = tWB - tDH
933d8701fe8SMiquel Raynal 	 * D3 = CMD -> DATA = tWHR + tREA - tDH
934d8701fe8SMiquel Raynal 	 */
935d8701fe8SMiquel Raynal 	rnand->tim_gen_seq0 =
936d8701fe8SMiquel Raynal 		TIM_GEN_SEQ0_D0(TO_CYCLES64(cle - cyc, period_ns)) |
937d8701fe8SMiquel Raynal 		TIM_GEN_SEQ0_D1(TO_CYCLES64(cle - cyc, period_ns)) |
938d8701fe8SMiquel Raynal 		TIM_GEN_SEQ0_D2(TO_CYCLES64(bef_dly, period_ns)) |
939d8701fe8SMiquel Raynal 		TIM_GEN_SEQ0_D3(TO_CYCLES64(ca_to_data, period_ns));
940d8701fe8SMiquel Raynal 
941d8701fe8SMiquel Raynal 	/*
942d8701fe8SMiquel Raynal 	 * D4 = ADDR -> CMD = tALH + tALS - 1 cyle
943d8701fe8SMiquel Raynal 	 * D5 = ADDR -> ADDR = tALH + tALS - 1 cyle
944d8701fe8SMiquel Raynal 	 * D6 = ADDR -> DLY = tWB - tDH
945d8701fe8SMiquel Raynal 	 * D7 = ADDR -> DATA = tWHR + tREA - tDH
946d8701fe8SMiquel Raynal 	 */
947d8701fe8SMiquel Raynal 	rnand->tim_gen_seq1 =
948d8701fe8SMiquel Raynal 		TIM_GEN_SEQ1_D4(TO_CYCLES64(ale - cyc, period_ns)) |
949d8701fe8SMiquel Raynal 		TIM_GEN_SEQ1_D5(TO_CYCLES64(ale - cyc, period_ns)) |
950d8701fe8SMiquel Raynal 		TIM_GEN_SEQ1_D6(TO_CYCLES64(bef_dly, period_ns)) |
951d8701fe8SMiquel Raynal 		TIM_GEN_SEQ1_D7(TO_CYCLES64(ca_to_data, period_ns));
952d8701fe8SMiquel Raynal 
953d8701fe8SMiquel Raynal 	/*
954d8701fe8SMiquel Raynal 	 * D8 = DLY -> DATA = tRR + tREA
955d8701fe8SMiquel Raynal 	 * D9 = DLY -> CMD = tRR
956d8701fe8SMiquel Raynal 	 * D10 = DATA -> CMD = tCLH + tCLS - 1 cycle
957d8701fe8SMiquel Raynal 	 * D11 = DATA -> DLY = tWB - tDH
958d8701fe8SMiquel Raynal 	 */
959d8701fe8SMiquel Raynal 	rnand->tim_gen_seq2 =
960d8701fe8SMiquel Raynal 		TIM_GEN_SEQ2_D8(TO_CYCLES64(sdr->tRR_min + sdr->tREA_max, period_ns)) |
961d8701fe8SMiquel Raynal 		TIM_GEN_SEQ2_D9(TO_CYCLES64(sdr->tRR_min, period_ns)) |
962d8701fe8SMiquel Raynal 		TIM_GEN_SEQ2_D10(TO_CYCLES64(cle - cyc, period_ns)) |
963d8701fe8SMiquel Raynal 		TIM_GEN_SEQ2_D11(TO_CYCLES64(bef_dly, period_ns));
964d8701fe8SMiquel Raynal 
965d8701fe8SMiquel Raynal 	/* D12 = DATA -> END = tCLH - tDH */
966d8701fe8SMiquel Raynal 	rnand->tim_gen_seq3 =
967d8701fe8SMiquel Raynal 		TIM_GEN_SEQ3_D12(TO_CYCLES64(sdr->tCLH_min - sdr->tDH_min, period_ns));
968d8701fe8SMiquel Raynal 
969d8701fe8SMiquel Raynal 	return 0;
970d8701fe8SMiquel Raynal }
971d8701fe8SMiquel Raynal 
rnandc_ooblayout_ecc(struct mtd_info * mtd,int section,struct mtd_oob_region * oobregion)972d8701fe8SMiquel Raynal static int rnandc_ooblayout_ecc(struct mtd_info *mtd, int section,
973d8701fe8SMiquel Raynal 				struct mtd_oob_region *oobregion)
974d8701fe8SMiquel Raynal {
975d8701fe8SMiquel Raynal 	struct nand_chip *chip = mtd_to_nand(mtd);
976d8701fe8SMiquel Raynal 	unsigned int eccbytes = round_up(chip->ecc.bytes, 4) * chip->ecc.steps;
977d8701fe8SMiquel Raynal 
978d8701fe8SMiquel Raynal 	if (section)
979d8701fe8SMiquel Raynal 		return -ERANGE;
980d8701fe8SMiquel Raynal 
981d8701fe8SMiquel Raynal 	oobregion->offset = 2;
982d8701fe8SMiquel Raynal 	oobregion->length = eccbytes;
983d8701fe8SMiquel Raynal 
984d8701fe8SMiquel Raynal 	return 0;
985d8701fe8SMiquel Raynal }
986d8701fe8SMiquel Raynal 
rnandc_ooblayout_free(struct mtd_info * mtd,int section,struct mtd_oob_region * oobregion)987d8701fe8SMiquel Raynal static int rnandc_ooblayout_free(struct mtd_info *mtd, int section,
988d8701fe8SMiquel Raynal 				 struct mtd_oob_region *oobregion)
989d8701fe8SMiquel Raynal {
990d8701fe8SMiquel Raynal 	struct nand_chip *chip = mtd_to_nand(mtd);
991d8701fe8SMiquel Raynal 	unsigned int eccbytes = round_up(chip->ecc.bytes, 4) * chip->ecc.steps;
992d8701fe8SMiquel Raynal 
993d8701fe8SMiquel Raynal 	if (section)
994d8701fe8SMiquel Raynal 		return -ERANGE;
995d8701fe8SMiquel Raynal 
996d8701fe8SMiquel Raynal 	oobregion->offset = 2 + eccbytes;
997d8701fe8SMiquel Raynal 	oobregion->length = mtd->oobsize - oobregion->offset;
998d8701fe8SMiquel Raynal 
999d8701fe8SMiquel Raynal 	return 0;
1000d8701fe8SMiquel Raynal }
1001d8701fe8SMiquel Raynal 
1002d8701fe8SMiquel Raynal static const struct mtd_ooblayout_ops rnandc_ooblayout_ops = {
1003d8701fe8SMiquel Raynal 	.ecc = rnandc_ooblayout_ecc,
1004d8701fe8SMiquel Raynal 	.free = rnandc_ooblayout_free,
1005d8701fe8SMiquel Raynal };
1006d8701fe8SMiquel Raynal 
rnandc_hw_ecc_controller_init(struct nand_chip * chip)1007d8701fe8SMiquel Raynal static int rnandc_hw_ecc_controller_init(struct nand_chip *chip)
1008d8701fe8SMiquel Raynal {
1009d8701fe8SMiquel Raynal 	struct rnand_chip *rnand = to_rnand(chip);
1010d8701fe8SMiquel Raynal 	struct mtd_info *mtd = nand_to_mtd(chip);
1011d8701fe8SMiquel Raynal 	struct rnandc *rnandc = to_rnandc(chip->controller);
1012d8701fe8SMiquel Raynal 
1013d8701fe8SMiquel Raynal 	if (mtd->writesize > SZ_16K) {
1014d8701fe8SMiquel Raynal 		dev_err(rnandc->dev, "Unsupported page size\n");
1015d8701fe8SMiquel Raynal 		return -EINVAL;
1016d8701fe8SMiquel Raynal 	}
1017d8701fe8SMiquel Raynal 
1018d8701fe8SMiquel Raynal 	switch (chip->ecc.size) {
1019d8701fe8SMiquel Raynal 	case SZ_256:
1020d8701fe8SMiquel Raynal 		rnand->control |= CONTROL_ECC_BLOCK_SIZE_256;
1021d8701fe8SMiquel Raynal 		break;
1022d8701fe8SMiquel Raynal 	case SZ_512:
1023d8701fe8SMiquel Raynal 		rnand->control |= CONTROL_ECC_BLOCK_SIZE_512;
1024d8701fe8SMiquel Raynal 		break;
1025d8701fe8SMiquel Raynal 	case SZ_1K:
1026d8701fe8SMiquel Raynal 		rnand->control |= CONTROL_ECC_BLOCK_SIZE_1024;
1027d8701fe8SMiquel Raynal 		break;
1028d8701fe8SMiquel Raynal 	default:
1029d8701fe8SMiquel Raynal 		dev_err(rnandc->dev, "Unsupported ECC chunk size\n");
1030d8701fe8SMiquel Raynal 		return -EINVAL;
1031d8701fe8SMiquel Raynal 	}
1032d8701fe8SMiquel Raynal 
1033d8701fe8SMiquel Raynal 	switch (chip->ecc.strength) {
1034d8701fe8SMiquel Raynal 	case 2:
1035d8701fe8SMiquel Raynal 		chip->ecc.bytes = 4;
1036d8701fe8SMiquel Raynal 		rnand->ecc_ctrl |= ECC_CTRL_CAP_2B;
1037d8701fe8SMiquel Raynal 		break;
1038d8701fe8SMiquel Raynal 	case 4:
1039d8701fe8SMiquel Raynal 		chip->ecc.bytes = 7;
1040d8701fe8SMiquel Raynal 		rnand->ecc_ctrl |= ECC_CTRL_CAP_4B;
1041d8701fe8SMiquel Raynal 		break;
1042d8701fe8SMiquel Raynal 	case 8:
1043d8701fe8SMiquel Raynal 		chip->ecc.bytes = 14;
1044d8701fe8SMiquel Raynal 		rnand->ecc_ctrl |= ECC_CTRL_CAP_8B;
1045d8701fe8SMiquel Raynal 		break;
1046d8701fe8SMiquel Raynal 	case 16:
1047d8701fe8SMiquel Raynal 		chip->ecc.bytes = 28;
1048d8701fe8SMiquel Raynal 		rnand->ecc_ctrl |= ECC_CTRL_CAP_16B;
1049d8701fe8SMiquel Raynal 		break;
1050d8701fe8SMiquel Raynal 	case 24:
1051d8701fe8SMiquel Raynal 		chip->ecc.bytes = 42;
1052d8701fe8SMiquel Raynal 		rnand->ecc_ctrl |= ECC_CTRL_CAP_24B;
1053d8701fe8SMiquel Raynal 		break;
1054d8701fe8SMiquel Raynal 	case 32:
1055d8701fe8SMiquel Raynal 		chip->ecc.bytes = 56;
1056d8701fe8SMiquel Raynal 		rnand->ecc_ctrl |= ECC_CTRL_CAP_32B;
1057d8701fe8SMiquel Raynal 		break;
1058d8701fe8SMiquel Raynal 	default:
1059d8701fe8SMiquel Raynal 		dev_err(rnandc->dev, "Unsupported ECC strength\n");
1060d8701fe8SMiquel Raynal 		return -EINVAL;
1061d8701fe8SMiquel Raynal 	}
1062d8701fe8SMiquel Raynal 
1063d8701fe8SMiquel Raynal 	rnand->ecc_ctrl |= ECC_CTRL_ERR_THRESHOLD(chip->ecc.strength);
1064d8701fe8SMiquel Raynal 
1065d8701fe8SMiquel Raynal 	mtd_set_ooblayout(mtd, &rnandc_ooblayout_ops);
1066d8701fe8SMiquel Raynal 	chip->ecc.steps = mtd->writesize / chip->ecc.size;
1067d8701fe8SMiquel Raynal 	chip->ecc.read_page = rnandc_read_page_hw_ecc;
1068d8701fe8SMiquel Raynal 	chip->ecc.read_subpage = rnandc_read_subpage_hw_ecc;
1069d8701fe8SMiquel Raynal 	chip->ecc.write_page = rnandc_write_page_hw_ecc;
1070d8701fe8SMiquel Raynal 	chip->ecc.write_subpage = rnandc_write_subpage_hw_ecc;
1071d8701fe8SMiquel Raynal 
1072d8701fe8SMiquel Raynal 	return 0;
1073d8701fe8SMiquel Raynal }
1074d8701fe8SMiquel Raynal 
rnandc_ecc_init(struct nand_chip * chip)1075d8701fe8SMiquel Raynal static int rnandc_ecc_init(struct nand_chip *chip)
1076d8701fe8SMiquel Raynal {
1077d8701fe8SMiquel Raynal 	struct nand_ecc_ctrl *ecc = &chip->ecc;
1078d8701fe8SMiquel Raynal 	const struct nand_ecc_props *requirements =
1079d8701fe8SMiquel Raynal 		nanddev_get_ecc_requirements(&chip->base);
1080d8701fe8SMiquel Raynal 	struct rnandc *rnandc = to_rnandc(chip->controller);
1081d8701fe8SMiquel Raynal 	int ret;
1082d8701fe8SMiquel Raynal 
1083d8701fe8SMiquel Raynal 	if (ecc->engine_type != NAND_ECC_ENGINE_TYPE_NONE &&
1084d8701fe8SMiquel Raynal 	    (!ecc->size || !ecc->strength)) {
1085d8701fe8SMiquel Raynal 		if (requirements->step_size && requirements->strength) {
1086d8701fe8SMiquel Raynal 			ecc->size = requirements->step_size;
1087d8701fe8SMiquel Raynal 			ecc->strength = requirements->strength;
1088d8701fe8SMiquel Raynal 		} else {
1089d8701fe8SMiquel Raynal 			dev_err(rnandc->dev, "No minimum ECC strength\n");
1090d8701fe8SMiquel Raynal 			return -EINVAL;
1091d8701fe8SMiquel Raynal 		}
1092d8701fe8SMiquel Raynal 	}
1093d8701fe8SMiquel Raynal 
1094d8701fe8SMiquel Raynal 	switch (ecc->engine_type) {
1095d8701fe8SMiquel Raynal 	case NAND_ECC_ENGINE_TYPE_ON_HOST:
1096d8701fe8SMiquel Raynal 		ret = rnandc_hw_ecc_controller_init(chip);
1097d8701fe8SMiquel Raynal 		if (ret)
1098d8701fe8SMiquel Raynal 			return ret;
1099d8701fe8SMiquel Raynal 		break;
1100d8701fe8SMiquel Raynal 	case NAND_ECC_ENGINE_TYPE_NONE:
1101d8701fe8SMiquel Raynal 	case NAND_ECC_ENGINE_TYPE_SOFT:
1102d8701fe8SMiquel Raynal 	case NAND_ECC_ENGINE_TYPE_ON_DIE:
1103d8701fe8SMiquel Raynal 		break;
1104d8701fe8SMiquel Raynal 	default:
1105d8701fe8SMiquel Raynal 		return -EINVAL;
1106d8701fe8SMiquel Raynal 	}
1107d8701fe8SMiquel Raynal 
1108d8701fe8SMiquel Raynal 	return 0;
1109d8701fe8SMiquel Raynal }
1110d8701fe8SMiquel Raynal 
rnandc_attach_chip(struct nand_chip * chip)1111d8701fe8SMiquel Raynal static int rnandc_attach_chip(struct nand_chip *chip)
1112d8701fe8SMiquel Raynal {
1113d8701fe8SMiquel Raynal 	struct rnand_chip *rnand = to_rnand(chip);
1114d8701fe8SMiquel Raynal 	struct rnandc *rnandc = to_rnandc(chip->controller);
1115d8701fe8SMiquel Raynal 	struct mtd_info *mtd = nand_to_mtd(chip);
1116d8701fe8SMiquel Raynal 	struct nand_memory_organization *memorg = nanddev_get_memorg(&chip->base);
1117d8701fe8SMiquel Raynal 	int ret;
1118d8701fe8SMiquel Raynal 
1119d8701fe8SMiquel Raynal 	/* Do not store BBT bits in the OOB section as it is not protected */
1120d8701fe8SMiquel Raynal 	if (chip->bbt_options & NAND_BBT_USE_FLASH)
1121d8701fe8SMiquel Raynal 		chip->bbt_options |= NAND_BBT_NO_OOB;
1122d8701fe8SMiquel Raynal 
1123d8701fe8SMiquel Raynal 	if (mtd->writesize <= 512) {
1124d8701fe8SMiquel Raynal 		dev_err(rnandc->dev, "Small page devices not supported\n");
1125d8701fe8SMiquel Raynal 		return -EINVAL;
1126d8701fe8SMiquel Raynal 	}
1127d8701fe8SMiquel Raynal 
1128d8701fe8SMiquel Raynal 	rnand->control |= CONTROL_CHECK_RB_LINE | CONTROL_INT_EN;
1129d8701fe8SMiquel Raynal 
1130d8701fe8SMiquel Raynal 	switch (memorg->pages_per_eraseblock) {
1131d8701fe8SMiquel Raynal 	case 32:
1132d8701fe8SMiquel Raynal 		rnand->control |= CONTROL_BLOCK_SIZE_32P;
1133d8701fe8SMiquel Raynal 		break;
1134d8701fe8SMiquel Raynal 	case 64:
1135d8701fe8SMiquel Raynal 		rnand->control |= CONTROL_BLOCK_SIZE_64P;
1136d8701fe8SMiquel Raynal 		break;
1137d8701fe8SMiquel Raynal 	case 128:
1138d8701fe8SMiquel Raynal 		rnand->control |= CONTROL_BLOCK_SIZE_128P;
1139d8701fe8SMiquel Raynal 		break;
1140d8701fe8SMiquel Raynal 	case 256:
1141d8701fe8SMiquel Raynal 		rnand->control |= CONTROL_BLOCK_SIZE_256P;
1142d8701fe8SMiquel Raynal 		break;
1143d8701fe8SMiquel Raynal 	default:
1144d8701fe8SMiquel Raynal 		dev_err(rnandc->dev, "Unsupported memory organization\n");
1145d8701fe8SMiquel Raynal 		return -EINVAL;
1146d8701fe8SMiquel Raynal 	}
1147d8701fe8SMiquel Raynal 
1148d8701fe8SMiquel Raynal 	chip->options |= NAND_SUBPAGE_READ;
1149d8701fe8SMiquel Raynal 
1150d8701fe8SMiquel Raynal 	ret = rnandc_ecc_init(chip);
1151d8701fe8SMiquel Raynal 	if (ret) {
1152d8701fe8SMiquel Raynal 		dev_err(rnandc->dev, "ECC initialization failed (%d)\n", ret);
1153d8701fe8SMiquel Raynal 		return ret;
1154d8701fe8SMiquel Raynal 	}
1155d8701fe8SMiquel Raynal 
1156d8701fe8SMiquel Raynal 	/* Force an update of the configuration registers */
1157d8701fe8SMiquel Raynal 	rnand->selected_die = -1;
1158d8701fe8SMiquel Raynal 
1159d8701fe8SMiquel Raynal 	return 0;
1160d8701fe8SMiquel Raynal }
1161d8701fe8SMiquel Raynal 
1162d8701fe8SMiquel Raynal static const struct nand_controller_ops rnandc_ops = {
1163d8701fe8SMiquel Raynal 	.attach_chip = rnandc_attach_chip,
1164d8701fe8SMiquel Raynal 	.exec_op = rnandc_exec_op,
1165d8701fe8SMiquel Raynal 	.setup_interface = rnandc_setup_interface,
1166d8701fe8SMiquel Raynal };
1167d8701fe8SMiquel Raynal 
rnandc_alloc_dma_buf(struct rnandc * rnandc,struct mtd_info * new_mtd)1168d8701fe8SMiquel Raynal static int rnandc_alloc_dma_buf(struct rnandc *rnandc,
1169d8701fe8SMiquel Raynal 				struct mtd_info *new_mtd)
1170d8701fe8SMiquel Raynal {
1171d8701fe8SMiquel Raynal 	unsigned int max_len = new_mtd->writesize + new_mtd->oobsize;
1172d8701fe8SMiquel Raynal 	struct rnand_chip *entry, *temp;
1173d8701fe8SMiquel Raynal 	struct nand_chip *chip;
1174d8701fe8SMiquel Raynal 	struct mtd_info *mtd;
1175d8701fe8SMiquel Raynal 
1176d8701fe8SMiquel Raynal 	list_for_each_entry_safe(entry, temp, &rnandc->chips, node) {
1177d8701fe8SMiquel Raynal 		chip = &entry->chip;
1178d8701fe8SMiquel Raynal 		mtd = nand_to_mtd(chip);
1179d8701fe8SMiquel Raynal 		max_len = max(max_len, mtd->writesize + mtd->oobsize);
1180d8701fe8SMiquel Raynal 	}
1181d8701fe8SMiquel Raynal 
1182d8701fe8SMiquel Raynal 	if (rnandc->buf && rnandc->buf_sz < max_len) {
1183d8701fe8SMiquel Raynal 		devm_kfree(rnandc->dev, rnandc->buf);
1184d8701fe8SMiquel Raynal 		rnandc->buf = NULL;
1185d8701fe8SMiquel Raynal 	}
1186d8701fe8SMiquel Raynal 
1187d8701fe8SMiquel Raynal 	if (!rnandc->buf) {
1188d8701fe8SMiquel Raynal 		rnandc->buf_sz = max_len;
1189d8701fe8SMiquel Raynal 		rnandc->buf = devm_kmalloc(rnandc->dev, max_len,
1190d8701fe8SMiquel Raynal 					   GFP_KERNEL | GFP_DMA);
1191d8701fe8SMiquel Raynal 		if (!rnandc->buf)
1192d8701fe8SMiquel Raynal 			return -ENOMEM;
1193d8701fe8SMiquel Raynal 	}
1194d8701fe8SMiquel Raynal 
1195d8701fe8SMiquel Raynal 	return 0;
1196d8701fe8SMiquel Raynal }
1197d8701fe8SMiquel Raynal 
rnandc_chip_init(struct rnandc * rnandc,struct device_node * np)1198d8701fe8SMiquel Raynal static int rnandc_chip_init(struct rnandc *rnandc, struct device_node *np)
1199d8701fe8SMiquel Raynal {
1200d8701fe8SMiquel Raynal 	struct rnand_chip *rnand;
1201d8701fe8SMiquel Raynal 	struct mtd_info *mtd;
1202d8701fe8SMiquel Raynal 	struct nand_chip *chip;
1203d8701fe8SMiquel Raynal 	int nsels, ret, i;
1204d8701fe8SMiquel Raynal 	u32 cs;
1205d8701fe8SMiquel Raynal 
1206d8701fe8SMiquel Raynal 	nsels = of_property_count_elems_of_size(np, "reg", sizeof(u32));
1207d8701fe8SMiquel Raynal 	if (nsels <= 0) {
1208d8701fe8SMiquel Raynal 		ret = (nsels < 0) ? nsels : -EINVAL;
1209d8701fe8SMiquel Raynal 		dev_err(rnandc->dev, "Invalid reg property (%d)\n", ret);
1210d8701fe8SMiquel Raynal 		return ret;
1211d8701fe8SMiquel Raynal 	}
1212d8701fe8SMiquel Raynal 
1213d8701fe8SMiquel Raynal 	/* Alloc the driver's NAND chip structure */
1214d8701fe8SMiquel Raynal 	rnand = devm_kzalloc(rnandc->dev, struct_size(rnand, sels, nsels),
1215d8701fe8SMiquel Raynal 			     GFP_KERNEL);
1216d8701fe8SMiquel Raynal 	if (!rnand)
1217d8701fe8SMiquel Raynal 		return -ENOMEM;
1218d8701fe8SMiquel Raynal 
1219d8701fe8SMiquel Raynal 	rnand->nsels = nsels;
1220d8701fe8SMiquel Raynal 	rnand->selected_die = -1;
1221d8701fe8SMiquel Raynal 
1222d8701fe8SMiquel Raynal 	for (i = 0; i < nsels; i++) {
1223d8701fe8SMiquel Raynal 		ret = of_property_read_u32_index(np, "reg", i, &cs);
1224d8701fe8SMiquel Raynal 		if (ret) {
1225d8701fe8SMiquel Raynal 			dev_err(rnandc->dev, "Incomplete reg property (%d)\n", ret);
1226d8701fe8SMiquel Raynal 			return ret;
1227d8701fe8SMiquel Raynal 		}
1228d8701fe8SMiquel Raynal 
1229d8701fe8SMiquel Raynal 		if (cs >= RNANDC_CS_NUM) {
1230d8701fe8SMiquel Raynal 			dev_err(rnandc->dev, "Invalid reg property (%d)\n", cs);
1231d8701fe8SMiquel Raynal 			return -EINVAL;
1232d8701fe8SMiquel Raynal 		}
1233d8701fe8SMiquel Raynal 
1234d8701fe8SMiquel Raynal 		if (test_and_set_bit(cs, &rnandc->assigned_cs)) {
1235d8701fe8SMiquel Raynal 			dev_err(rnandc->dev, "CS %d already assigned\n", cs);
1236d8701fe8SMiquel Raynal 			return -EINVAL;
1237d8701fe8SMiquel Raynal 		}
1238d8701fe8SMiquel Raynal 
1239d8701fe8SMiquel Raynal 		/*
1240d8701fe8SMiquel Raynal 		 * No need to check for RB or WP properties, there is a 1:1
1241d8701fe8SMiquel Raynal 		 * mandatory mapping with the CS.
1242d8701fe8SMiquel Raynal 		 */
1243d8701fe8SMiquel Raynal 		rnand->sels[i].cs = cs;
1244d8701fe8SMiquel Raynal 	}
1245d8701fe8SMiquel Raynal 
1246d8701fe8SMiquel Raynal 	chip = &rnand->chip;
1247d8701fe8SMiquel Raynal 	chip->controller = &rnandc->controller;
1248d8701fe8SMiquel Raynal 	nand_set_flash_node(chip, np);
1249d8701fe8SMiquel Raynal 
1250d8701fe8SMiquel Raynal 	mtd = nand_to_mtd(chip);
1251d8701fe8SMiquel Raynal 	mtd->dev.parent = rnandc->dev;
1252d8701fe8SMiquel Raynal 	if (!mtd->name) {
1253d8701fe8SMiquel Raynal 		dev_err(rnandc->dev, "Missing MTD label\n");
1254d8701fe8SMiquel Raynal 		return -EINVAL;
1255d8701fe8SMiquel Raynal 	}
1256d8701fe8SMiquel Raynal 
1257d8701fe8SMiquel Raynal 	ret = nand_scan(chip, rnand->nsels);
1258d8701fe8SMiquel Raynal 	if (ret) {
1259d8701fe8SMiquel Raynal 		dev_err(rnandc->dev, "Failed to scan the NAND chip (%d)\n", ret);
1260d8701fe8SMiquel Raynal 		return ret;
1261d8701fe8SMiquel Raynal 	}
1262d8701fe8SMiquel Raynal 
1263d8701fe8SMiquel Raynal 	ret = rnandc_alloc_dma_buf(rnandc, mtd);
1264d8701fe8SMiquel Raynal 	if (ret)
1265d8701fe8SMiquel Raynal 		goto cleanup_nand;
1266d8701fe8SMiquel Raynal 
1267d8701fe8SMiquel Raynal 	ret = mtd_device_register(mtd, NULL, 0);
1268d8701fe8SMiquel Raynal 	if (ret) {
1269d8701fe8SMiquel Raynal 		dev_err(rnandc->dev, "Failed to register MTD device (%d)\n", ret);
1270d8701fe8SMiquel Raynal 		goto cleanup_nand;
1271d8701fe8SMiquel Raynal 	}
1272d8701fe8SMiquel Raynal 
1273d8701fe8SMiquel Raynal 	list_add_tail(&rnand->node, &rnandc->chips);
1274d8701fe8SMiquel Raynal 
1275d8701fe8SMiquel Raynal 	return 0;
1276d8701fe8SMiquel Raynal 
1277d8701fe8SMiquel Raynal cleanup_nand:
1278d8701fe8SMiquel Raynal 	nand_cleanup(chip);
1279d8701fe8SMiquel Raynal 
1280d8701fe8SMiquel Raynal 	return ret;
1281d8701fe8SMiquel Raynal }
1282d8701fe8SMiquel Raynal 
rnandc_chips_cleanup(struct rnandc * rnandc)1283d8701fe8SMiquel Raynal static void rnandc_chips_cleanup(struct rnandc *rnandc)
1284d8701fe8SMiquel Raynal {
1285d8701fe8SMiquel Raynal 	struct rnand_chip *entry, *temp;
1286d8701fe8SMiquel Raynal 	struct nand_chip *chip;
1287d8701fe8SMiquel Raynal 	int ret;
1288d8701fe8SMiquel Raynal 
1289d8701fe8SMiquel Raynal 	list_for_each_entry_safe(entry, temp, &rnandc->chips, node) {
1290d8701fe8SMiquel Raynal 		chip = &entry->chip;
1291d8701fe8SMiquel Raynal 		ret = mtd_device_unregister(nand_to_mtd(chip));
1292d8701fe8SMiquel Raynal 		WARN_ON(ret);
1293d8701fe8SMiquel Raynal 		nand_cleanup(chip);
1294d8701fe8SMiquel Raynal 		list_del(&entry->node);
1295d8701fe8SMiquel Raynal 	}
1296d8701fe8SMiquel Raynal }
1297d8701fe8SMiquel Raynal 
rnandc_chips_init(struct rnandc * rnandc)1298d8701fe8SMiquel Raynal static int rnandc_chips_init(struct rnandc *rnandc)
1299d8701fe8SMiquel Raynal {
1300d8701fe8SMiquel Raynal 	struct device_node *np;
1301d8701fe8SMiquel Raynal 	int ret;
1302d8701fe8SMiquel Raynal 
1303d8701fe8SMiquel Raynal 	for_each_child_of_node(rnandc->dev->of_node, np) {
1304d8701fe8SMiquel Raynal 		ret = rnandc_chip_init(rnandc, np);
1305d8701fe8SMiquel Raynal 		if (ret) {
1306d8701fe8SMiquel Raynal 			of_node_put(np);
1307d8701fe8SMiquel Raynal 			goto cleanup_chips;
1308d8701fe8SMiquel Raynal 		}
1309d8701fe8SMiquel Raynal 	}
1310d8701fe8SMiquel Raynal 
1311d8701fe8SMiquel Raynal 	return 0;
1312d8701fe8SMiquel Raynal 
1313d8701fe8SMiquel Raynal cleanup_chips:
1314d8701fe8SMiquel Raynal 	rnandc_chips_cleanup(rnandc);
1315d8701fe8SMiquel Raynal 
1316d8701fe8SMiquel Raynal 	return ret;
1317d8701fe8SMiquel Raynal }
1318d8701fe8SMiquel Raynal 
rnandc_probe(struct platform_device * pdev)1319d8701fe8SMiquel Raynal static int rnandc_probe(struct platform_device *pdev)
1320d8701fe8SMiquel Raynal {
1321d8701fe8SMiquel Raynal 	struct rnandc *rnandc;
13226a2277a0SMiquel Raynal 	struct clk *eclk;
1323d8701fe8SMiquel Raynal 	int irq, ret;
1324d8701fe8SMiquel Raynal 
1325d8701fe8SMiquel Raynal 	rnandc = devm_kzalloc(&pdev->dev, sizeof(*rnandc), GFP_KERNEL);
1326d8701fe8SMiquel Raynal 	if (!rnandc)
1327d8701fe8SMiquel Raynal 		return -ENOMEM;
1328d8701fe8SMiquel Raynal 
1329d8701fe8SMiquel Raynal 	rnandc->dev = &pdev->dev;
1330d8701fe8SMiquel Raynal 	nand_controller_init(&rnandc->controller);
1331d8701fe8SMiquel Raynal 	rnandc->controller.ops = &rnandc_ops;
1332d8701fe8SMiquel Raynal 	INIT_LIST_HEAD(&rnandc->chips);
1333d8701fe8SMiquel Raynal 	init_completion(&rnandc->complete);
1334d8701fe8SMiquel Raynal 
1335d8701fe8SMiquel Raynal 	rnandc->regs = devm_platform_ioremap_resource(pdev, 0);
1336d8701fe8SMiquel Raynal 	if (IS_ERR(rnandc->regs))
1337d8701fe8SMiquel Raynal 		return PTR_ERR(rnandc->regs);
1338d8701fe8SMiquel Raynal 
13396a2277a0SMiquel Raynal 	devm_pm_runtime_enable(&pdev->dev);
13406a2277a0SMiquel Raynal 	ret = pm_runtime_resume_and_get(&pdev->dev);
13416a2277a0SMiquel Raynal 	if (ret < 0)
1342d8701fe8SMiquel Raynal 		return ret;
1343d8701fe8SMiquel Raynal 
13446a2277a0SMiquel Raynal 	/* The external NAND bus clock rate is needed for computing timings */
13456a2277a0SMiquel Raynal 	eclk = clk_get(&pdev->dev, "eclk");
13466a2277a0SMiquel Raynal 	if (IS_ERR(eclk)) {
13476a2277a0SMiquel Raynal 		ret = PTR_ERR(eclk);
13486a2277a0SMiquel Raynal 		goto dis_runtime_pm;
13496a2277a0SMiquel Raynal 	}
13506a2277a0SMiquel Raynal 
13516a2277a0SMiquel Raynal 	rnandc->ext_clk_rate = clk_get_rate(eclk);
13526a2277a0SMiquel Raynal 	clk_put(eclk);
1353d8701fe8SMiquel Raynal 
1354d8701fe8SMiquel Raynal 	rnandc_dis_interrupts(rnandc);
1355d8701fe8SMiquel Raynal 	irq = platform_get_irq_optional(pdev, 0);
1356d8701fe8SMiquel Raynal 	if (irq == -EPROBE_DEFER) {
1357d8701fe8SMiquel Raynal 		ret = irq;
13586a2277a0SMiquel Raynal 		goto dis_runtime_pm;
1359d8701fe8SMiquel Raynal 	} else if (irq < 0) {
1360d8701fe8SMiquel Raynal 		dev_info(&pdev->dev, "No IRQ found, fallback to polling\n");
1361d8701fe8SMiquel Raynal 		rnandc->use_polling = true;
1362d8701fe8SMiquel Raynal 	} else {
1363d8701fe8SMiquel Raynal 		ret = devm_request_irq(&pdev->dev, irq, rnandc_irq_handler, 0,
1364d8701fe8SMiquel Raynal 				       "renesas-nand-controller", rnandc);
1365d8701fe8SMiquel Raynal 		if (ret < 0)
13666a2277a0SMiquel Raynal 			goto dis_runtime_pm;
1367d8701fe8SMiquel Raynal 	}
1368d8701fe8SMiquel Raynal 
1369d8701fe8SMiquel Raynal 	ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
1370d8701fe8SMiquel Raynal 	if (ret)
13716a2277a0SMiquel Raynal 		goto dis_runtime_pm;
1372d8701fe8SMiquel Raynal 
1373d8701fe8SMiquel Raynal 	rnandc_clear_fifo(rnandc);
1374d8701fe8SMiquel Raynal 
1375d8701fe8SMiquel Raynal 	platform_set_drvdata(pdev, rnandc);
1376d8701fe8SMiquel Raynal 
1377d8701fe8SMiquel Raynal 	ret = rnandc_chips_init(rnandc);
1378d8701fe8SMiquel Raynal 	if (ret)
13796a2277a0SMiquel Raynal 		goto dis_runtime_pm;
1380d8701fe8SMiquel Raynal 
1381d8701fe8SMiquel Raynal 	return 0;
1382d8701fe8SMiquel Raynal 
13836a2277a0SMiquel Raynal dis_runtime_pm:
13846a2277a0SMiquel Raynal 	pm_runtime_put(&pdev->dev);
1385d8701fe8SMiquel Raynal 
1386d8701fe8SMiquel Raynal 	return ret;
1387d8701fe8SMiquel Raynal }
1388d8701fe8SMiquel Raynal 
rnandc_remove(struct platform_device * pdev)1389ec185b18SUwe Kleine-König static void rnandc_remove(struct platform_device *pdev)
1390d8701fe8SMiquel Raynal {
1391d8701fe8SMiquel Raynal 	struct rnandc *rnandc = platform_get_drvdata(pdev);
1392d8701fe8SMiquel Raynal 
1393d8701fe8SMiquel Raynal 	rnandc_chips_cleanup(rnandc);
1394d8701fe8SMiquel Raynal 
13956a2277a0SMiquel Raynal 	pm_runtime_put(&pdev->dev);
1396d8701fe8SMiquel Raynal }
1397d8701fe8SMiquel Raynal 
1398d8701fe8SMiquel Raynal static const struct of_device_id rnandc_id_table[] = {
1399d8701fe8SMiquel Raynal 	{ .compatible = "renesas,rcar-gen3-nandc" },
1400d8701fe8SMiquel Raynal 	{ .compatible = "renesas,rzn1-nandc" },
1401d8701fe8SMiquel Raynal 	{} /* sentinel */
1402d8701fe8SMiquel Raynal };
1403d8701fe8SMiquel Raynal MODULE_DEVICE_TABLE(of, rnandc_id_table);
1404d8701fe8SMiquel Raynal 
1405d8701fe8SMiquel Raynal static struct platform_driver rnandc_driver = {
1406d8701fe8SMiquel Raynal 	.driver = {
1407d8701fe8SMiquel Raynal 		.name = "renesas-nandc",
14083f26d1bfSMiquel Raynal 		.of_match_table = rnandc_id_table,
1409d8701fe8SMiquel Raynal 	},
1410d8701fe8SMiquel Raynal 	.probe = rnandc_probe,
1411ec185b18SUwe Kleine-König 	.remove_new = rnandc_remove,
1412d8701fe8SMiquel Raynal };
1413d8701fe8SMiquel Raynal module_platform_driver(rnandc_driver);
1414d8701fe8SMiquel Raynal 
1415d8701fe8SMiquel Raynal MODULE_AUTHOR("Miquel Raynal <miquel.raynal@bootlin.com>");
1416d8701fe8SMiquel Raynal MODULE_DESCRIPTION("Renesas R-Car Gen3 & RZ/N1 NAND controller driver");
1417d8701fe8SMiquel Raynal MODULE_LICENSE("GPL v2");
1418