blob: 86421597b703abf057e5d8f0beae5cc26b491984 [file] [log] [blame]
developer23f9f0f2023-06-15 13:06:25 +08001diff --git a/package/boot/uboot-mediatek/patches/002-nand-add-spi-nand-driver.patch b/package/boot/uboot-mediatek/patches/002-nand-add-spi-nand-driver.patch
2deleted file mode 100644
3index dc3ebaf..0000000
4--- a/package/boot/uboot-mediatek/patches/002-nand-add-spi-nand-driver.patch
5+++ /dev/null
6@@ -1,8659 +0,0 @@
7-From de8b6cf615be20b25d0f3c817866de2c0d46a704 Mon Sep 17 00:00:00 2001
8-From: Sam Shih <sam.shih@mediatek.com>
9-Date: Mon, 20 Apr 2020 17:10:05 +0800
10-Subject: [PATCH 1/3] nand: add spi nand driver
11-
12-Add spi nand driver support for mt7622 based on nfi controller
13-
14-Signed-off-by: Xiangsheng Hou <xiangsheng.hou@mediatek.com>
15----
16- drivers/mtd/Kconfig | 7 +
17- drivers/mtd/Makefile | 4 +
18- drivers/mtd/nand/raw/nand.c | 2 +
19- drivers/mtd/nandx/NOTICE | 52 +
20- drivers/mtd/nandx/Nandx.config | 17 +
21- drivers/mtd/nandx/Nandx.mk | 91 ++
22- drivers/mtd/nandx/README | 31 +
23- drivers/mtd/nandx/core/Nandx.mk | 38 +
24- drivers/mtd/nandx/core/core_io.c | 735 +++++++++
25- drivers/mtd/nandx/core/core_io.h | 39 +
26- drivers/mtd/nandx/core/nand/device_spi.c | 200 +++
27- drivers/mtd/nandx/core/nand/device_spi.h | 132 ++
28- drivers/mtd/nandx/core/nand/nand_spi.c | 526 +++++++
29- drivers/mtd/nandx/core/nand/nand_spi.h | 35 +
30- drivers/mtd/nandx/core/nand_base.c | 304 ++++
31- drivers/mtd/nandx/core/nand_base.h | 71 +
32- drivers/mtd/nandx/core/nand_chip.c | 272 ++++
33- drivers/mtd/nandx/core/nand_chip.h | 103 ++
34- drivers/mtd/nandx/core/nand_device.c | 285 ++++
35- drivers/mtd/nandx/core/nand_device.h | 608 ++++++++
36- drivers/mtd/nandx/core/nfi.h | 51 +
37- drivers/mtd/nandx/core/nfi/nfi_base.c | 1357 +++++++++++++++++
38- drivers/mtd/nandx/core/nfi/nfi_base.h | 95 ++
39- drivers/mtd/nandx/core/nfi/nfi_regs.h | 114 ++
40- drivers/mtd/nandx/core/nfi/nfi_spi.c | 689 +++++++++
41- drivers/mtd/nandx/core/nfi/nfi_spi.h | 44 +
42- drivers/mtd/nandx/core/nfi/nfi_spi_regs.h | 64 +
43- drivers/mtd/nandx/core/nfi/nfiecc.c | 510 +++++++
44- drivers/mtd/nandx/core/nfi/nfiecc.h | 90 ++
45- drivers/mtd/nandx/core/nfi/nfiecc_regs.h | 51 +
46- drivers/mtd/nandx/driver/Nandx.mk | 18 +
47- drivers/mtd/nandx/driver/bbt/bbt.c | 408 +++++
48- drivers/mtd/nandx/driver/uboot/driver.c | 574 +++++++
49- drivers/mtd/nandx/include/Nandx.mk | 16 +
50- drivers/mtd/nandx/include/internal/bbt.h | 62 +
51- .../mtd/nandx/include/internal/nandx_core.h | 250 +++
52- .../mtd/nandx/include/internal/nandx_errno.h | 40 +
53- .../mtd/nandx/include/internal/nandx_util.h | 221 +++
54- drivers/mtd/nandx/include/uboot/nandx_os.h | 78 +
55- include/configs/mt7622.h | 25 +
56- 40 files changed, 8309 insertions(+)
57- create mode 100644 drivers/mtd/nandx/NOTICE
58- create mode 100644 drivers/mtd/nandx/Nandx.config
59- create mode 100644 drivers/mtd/nandx/Nandx.mk
60- create mode 100644 drivers/mtd/nandx/README
61- create mode 100644 drivers/mtd/nandx/core/Nandx.mk
62- create mode 100644 drivers/mtd/nandx/core/core_io.c
63- create mode 100644 drivers/mtd/nandx/core/core_io.h
64- create mode 100644 drivers/mtd/nandx/core/nand/device_spi.c
65- create mode 100644 drivers/mtd/nandx/core/nand/device_spi.h
66- create mode 100644 drivers/mtd/nandx/core/nand/nand_spi.c
67- create mode 100644 drivers/mtd/nandx/core/nand/nand_spi.h
68- create mode 100644 drivers/mtd/nandx/core/nand_base.c
69- create mode 100644 drivers/mtd/nandx/core/nand_base.h
70- create mode 100644 drivers/mtd/nandx/core/nand_chip.c
71- create mode 100644 drivers/mtd/nandx/core/nand_chip.h
72- create mode 100644 drivers/mtd/nandx/core/nand_device.c
73- create mode 100644 drivers/mtd/nandx/core/nand_device.h
74- create mode 100644 drivers/mtd/nandx/core/nfi.h
75- create mode 100644 drivers/mtd/nandx/core/nfi/nfi_base.c
76- create mode 100644 drivers/mtd/nandx/core/nfi/nfi_base.h
77- create mode 100644 drivers/mtd/nandx/core/nfi/nfi_regs.h
78- create mode 100644 drivers/mtd/nandx/core/nfi/nfi_spi.c
79- create mode 100644 drivers/mtd/nandx/core/nfi/nfi_spi.h
80- create mode 100644 drivers/mtd/nandx/core/nfi/nfi_spi_regs.h
81- create mode 100644 drivers/mtd/nandx/core/nfi/nfiecc.c
82- create mode 100644 drivers/mtd/nandx/core/nfi/nfiecc.h
83- create mode 100644 drivers/mtd/nandx/core/nfi/nfiecc_regs.h
84- create mode 100644 drivers/mtd/nandx/driver/Nandx.mk
85- create mode 100644 drivers/mtd/nandx/driver/bbt/bbt.c
86- create mode 100644 drivers/mtd/nandx/driver/uboot/driver.c
87- create mode 100644 drivers/mtd/nandx/include/Nandx.mk
88- create mode 100644 drivers/mtd/nandx/include/internal/bbt.h
89- create mode 100644 drivers/mtd/nandx/include/internal/nandx_core.h
90- create mode 100644 drivers/mtd/nandx/include/internal/nandx_errno.h
91- create mode 100644 drivers/mtd/nandx/include/internal/nandx_util.h
92- create mode 100644 drivers/mtd/nandx/include/uboot/nandx_os.h
93-
94-diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
95-index 5e7571cf3d..34a59b44b9 100644
96---- a/drivers/mtd/Kconfig
97-+++ b/drivers/mtd/Kconfig
98-@@ -101,6 +101,13 @@ config HBMC_AM654
99- This is the driver for HyperBus controller on TI's AM65x and
100- other SoCs
101-
102-+config MTK_SPI_NAND
103-+ tristate "Mediatek SPI Nand"
104-+ depends on DM_MTD
105-+ help
106-+ This option will support SPI Nand device via Mediatek
107-+ NFI controller.
108-+
109- source "drivers/mtd/nand/Kconfig"
110-
111- source "drivers/mtd/spi/Kconfig"
112-diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
113-index 318788c5e2..1df1031b23 100644
114---- a/drivers/mtd/Makefile
115-+++ b/drivers/mtd/Makefile
116-@@ -41,3 +41,7 @@ obj-$(CONFIG_$(SPL_TPL_)SPI_FLASH_SUPPORT) += spi/
117- obj-$(CONFIG_SPL_UBI) += ubispl/
118-
119- endif
120-+
121-+ifeq ($(CONFIG_MTK_SPI_NAND), y)
122-+include $(srctree)/drivers/mtd/nandx/Nandx.mk
123-+endif
124-diff --git a/drivers/mtd/nand/raw/nand.c b/drivers/mtd/nand/raw/nand.c
125-index 026419e4e6..4be0c7d8f3 100644
126---- a/drivers/mtd/nand/raw/nand.c
127-+++ b/drivers/mtd/nand/raw/nand.c
128-@@ -91,8 +91,10 @@ static void nand_init_chip(int i)
129- if (board_nand_init(nand))
130- return;
131-
132-+#ifndef CONFIG_MTK_SPI_NAND
133- if (nand_scan(mtd, maxchips))
134- return;
135-+#endif
136-
137- nand_register(i, mtd);
138- }
139-diff --git a/drivers/mtd/nandx/NOTICE b/drivers/mtd/nandx/NOTICE
140-new file mode 100644
141-index 0000000000..1a06ca3867
142---- /dev/null
143-+++ b/drivers/mtd/nandx/NOTICE
144-@@ -0,0 +1,52 @@
145-+
146-+/*
147-+ * Nandx - Mediatek Common Nand Driver
148-+ * Copyright (C) 2017 MediaTek Inc.
149-+ *
150-+ * Nandx is dual licensed: you can use it either under the terms of
151-+ * the GPL, or the BSD license, at your option.
152-+ *
153-+ * a) This program is free software; you can redistribute it and/or modify
154-+ * it under the terms of the GNU General Public License version 2 as
155-+ * published by the Free Software Foundation.
156-+ *
157-+ * This library is distributed in the hope that it will be useful,
158-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
159-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
160-+ * GNU General Public License for more details.
161-+ *
162-+ * This program is distributed in the hope that it will be useful,
163-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
164-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
165-+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
166-+ *
167-+ * Alternatively,
168-+ *
169-+ * b) Redistribution and use in source and binary forms, with or
170-+ * without modification, are permitted provided that the following
171-+ * conditions are met:
172-+ *
173-+ * 1. Redistributions of source code must retain the above
174-+ * copyright notice, this list of conditions and the following
175-+ * disclaimer.
176-+ * 2. Redistributions in binary form must reproduce the above
177-+ * copyright notice, this list of conditions and the following
178-+ * disclaimer in the documentation and/or other materials
179-+ * provided with the distribution.
180-+ *
181-+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
182-+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
183-+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
184-+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
185-+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
186-+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
187-+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
188-+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
189-+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
190-+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
191-+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
192-+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
193-+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
194-+ */
195-+
196-+####################################################################################################
197-\ No newline at end of file
198-diff --git a/drivers/mtd/nandx/Nandx.config b/drivers/mtd/nandx/Nandx.config
199-new file mode 100644
200-index 0000000000..35705ee28d
201---- /dev/null
202-+++ b/drivers/mtd/nandx/Nandx.config
203-@@ -0,0 +1,17 @@
204-+NANDX_SIMULATOR_SUPPORT := n
205-+NANDX_CTP_SUPPORT := n
206-+NANDX_DA_SUPPORT := n
207-+NANDX_PRELOADER_SUPPORT := n
208-+NANDX_LK_SUPPORT := n
209-+NANDX_KERNEL_SUPPORT := n
210-+NANDX_BROM_SUPPORT := n
211-+NANDX_UBOOT_SUPPORT := y
212-+NANDX_BBT_SUPPORT := y
213-+
214-+NANDX_NAND_SPI := y
215-+NANDX_NAND_SLC := n
216-+NANDX_NAND_MLC := n
217-+NANDX_NAND_TLC := n
218-+NANDX_NFI_BASE := y
219-+NANDX_NFI_ECC := y
220-+NANDX_NFI_SPI := y
221-diff --git a/drivers/mtd/nandx/Nandx.mk b/drivers/mtd/nandx/Nandx.mk
222-new file mode 100644
223-index 0000000000..f5a6f2a628
224---- /dev/null
225-+++ b/drivers/mtd/nandx/Nandx.mk
226-@@ -0,0 +1,91 @@
227-+#
228-+# Copyright (C) 2017 MediaTek Inc.
229-+# Licensed under either
230-+# BSD Licence, (see NOTICE for more details)
231-+# GNU General Public License, version 2.0, (see NOTICE for more details)
232-+#
233-+
234-+nandx_dir := $(shell dirname $(lastword $(MAKEFILE_LIST)))
235-+include $(nandx_dir)/Nandx.config
236-+
237-+ifeq ($(NANDX_SIMULATOR_SUPPORT), y)
238-+sim-obj :=
239-+sim-inc :=
240-+nandx-obj := sim-obj
241-+nandx-prefix := .
242-+nandx-postfix := %.o
243-+sim-inc += -I$(nandx-prefix)/include/internal
244-+sim-inc += -I$(nandx-prefix)/include/simulator
245-+endif
246-+
247-+ifeq ($(NANDX_CTP_SUPPORT), y)
248-+nandx-obj := C_SRC_FILES
249-+nandx-prefix := $(nandx_dir)
250-+nandx-postfix := %.c
251-+INC_DIRS += $(nandx_dir)/include/internal
252-+INC_DIRS += $(nandx_dir)/include/ctp
253-+endif
254-+
255-+ifeq ($(NANDX_DA_SUPPORT), y)
256-+nandx-obj := obj-y
257-+nandx-prefix := $(nandx_dir)
258-+nandx-postfix := %.o
259-+INCLUDE_PATH += $(TOPDIR)/platform/$(CODE_BASE)/dev/nand/nandx/include/internal
260-+INCLUDE_PATH += $(TOPDIR)/platform/$(CODE_BASE)/dev/nand/nandx/include/da
261-+endif
262-+
263-+ifeq ($(NANDX_PRELOADER_SUPPORT), y)
264-+nandx-obj := MOD_SRC
265-+nandx-prefix := $(nandx_dir)
266-+nandx-postfix := %.c
267-+C_OPTION += -I$(MTK_PATH_PLATFORM)/src/drivers/nandx/include/internal
268-+C_OPTION += -I$(MTK_PATH_PLATFORM)/src/drivers/nandx/include/preloader
269-+endif
270-+
271-+ifeq ($(NANDX_LK_SUPPORT), y)
272-+nandx-obj := MODULE_SRCS
273-+nandx-prefix := $(nandx_dir)
274-+nandx-postfix := %.c
275-+GLOBAL_INCLUDES += $(nandx_dir)/include/internal
276-+GLOBAL_INCLUDES += $(nandx_dir)/include/lk
277-+endif
278-+
279-+ifeq ($(NANDX_KERNEL_SUPPORT), y)
280-+nandx-obj := obj-y
281-+nandx-prefix := nandx
282-+nandx-postfix := %.o
283-+ccflags-y += -I$(nandx_dir)/include/internal
284-+ccflags-y += -I$(nandx_dir)/include/kernel
285-+endif
286-+
287-+ifeq ($(NANDX_UBOOT_SUPPORT), y)
288-+nandx-obj := obj-y
289-+nandx-prefix := nandx
290-+nandx-postfix := %.o
291-+ccflags-y += -I$(nandx_dir)/include/internal
292-+ccflags-y += -I$(nandx_dir)/include/uboot
293-+endif
294-+
295-+nandx-y :=
296-+include $(nandx_dir)/core/Nandx.mk
297-+nandx-target := $(nandx-prefix)/core/$(nandx-postfix)
298-+$(nandx-obj) += $(patsubst %.c, $(nandx-target), $(nandx-y))
299-+
300-+
301-+nandx-y :=
302-+include $(nandx_dir)/driver/Nandx.mk
303-+nandx-target := $(nandx-prefix)/driver/$(nandx-postfix)
304-+$(nandx-obj) += $(patsubst %.c, $(nandx-target), $(nandx-y))
305-+
306-+ifeq ($(NANDX_SIMULATOR_SUPPORT), y)
307-+cc := gcc
308-+CFLAGS += $(sim-inc)
309-+
310-+.PHONY:nandx
311-+nandx: $(sim-obj)
312-+ $(cc) $(sim-obj) -o nandx
313-+
314-+.PHONY:clean
315-+clean:
316-+ rm -rf $(sim-obj) nandx
317-+endif
318-diff --git a/drivers/mtd/nandx/README b/drivers/mtd/nandx/README
319-new file mode 100644
320-index 0000000000..0feaeaeb88
321---- /dev/null
322-+++ b/drivers/mtd/nandx/README
323-@@ -0,0 +1,31 @@
324-+
325-+ NAND2.0
326-+ ===============================
327-+
328-+ NAND2.0 is a common nand driver which designed for accessing
329-+different type of NANDs(SLC, SPI-NAND, MLC, TLC) on various OS. This
330-+driver can work on mostly SoCs of Mediatek.
331-+
332-+ Although there already has a common nand driver, it doesn't cover
333-+SPI-NAND, and not match our IC-Verification's reqirement. We need
334-+a driver that can be exten or cut easily.
335-+
336-+ This driver is base on NANDX & SLC. We try to refactor structures,
337-+and make them inheritable. We also refactor some operations' flow
338-+principally for adding SPI-NAND support.
339-+
340-+ This driver's architecture is like:
341-+
342-+ Driver @LK/Uboot/DA... |IC verify/other purposes
343-+ ----------------------------------------------------------------
344-+ partition | BBM |
345-+ -------------------------------------- | extend_core
346-+ nandx_core/core_io |
347-+ ----------------------------------------------------------------
348-+ nand_chip/nand_base |
349-+ -------------------------------------- | extend_nfi
350-+ nand_device | nfi/nfi_base |
351-+
352-+ Any block of above graph can be extended at your will, if you
353-+want add new feature into this code, please make sure that your code
354-+would follow the framework, and we will be appreciated about it.
355-diff --git a/drivers/mtd/nandx/core/Nandx.mk b/drivers/mtd/nandx/core/Nandx.mk
356-new file mode 100644
357-index 0000000000..7a5661c044
358---- /dev/null
359-+++ b/drivers/mtd/nandx/core/Nandx.mk
360-@@ -0,0 +1,38 @@
361-+#
362-+# Copyright (C) 2017 MediaTek Inc.
363-+# Licensed under either
364-+# BSD Licence, (see NOTICE for more details)
365-+# GNU General Public License, version 2.0, (see NOTICE for more details)
366-+#
367-+
368-+nandx-y += nand_device.c
369-+nandx-y += nand_base.c
370-+nandx-y += nand_chip.c
371-+nandx-y += core_io.c
372-+
373-+nandx-header-y += nand_device.h
374-+nandx-header-y += nand_base.h
375-+nandx-header-y += nand_chip.h
376-+nandx-header-y += core_io.h
377-+nandx-header-y += nfi.h
378-+
379-+nandx-$(NANDX_NAND_SPI) += nand/device_spi.c
380-+nandx-$(NANDX_NAND_SPI) += nand/nand_spi.c
381-+nandx-$(NANDX_NAND_SLC) += nand/device_slc.c
382-+nandx-$(NANDX_NAND_SLC) += nand/nand_slc.c
383-+
384-+nandx-header-$(NANDX_NAND_SPI) += nand/device_spi.h
385-+nandx-header-$(NANDX_NAND_SPI) += nand/nand_spi.h
386-+nandx-header-$(NANDX_NAND_SLC) += nand/device_slc.h
387-+nandx-header-$(NANDX_NAND_SLC) += nand/nand_slc.h
388-+
389-+nandx-$(NANDX_NFI_BASE) += nfi/nfi_base.c
390-+nandx-$(NANDX_NFI_ECC) += nfi/nfiecc.c
391-+nandx-$(NANDX_NFI_SPI) += nfi/nfi_spi.c
392-+
393-+nandx-header-$(NANDX_NFI_BASE) += nfi/nfi_base.h
394-+nandx-header-$(NANDX_NFI_BASE) += nfi/nfi_regs.h
395-+nandx-header-$(NANDX_NFI_ECC) += nfi/nfiecc.h
396-+nandx-header-$(NANDX_NFI_ECC) += nfi/nfiecc_regs.h
397-+nandx-header-$(NANDX_NFI_SPI) += nfi/nfi_spi.h
398-+nandx-header-$(NANDX_NFI_SPI) += nfi/nfi_spi_regs.h
399-diff --git a/drivers/mtd/nandx/core/core_io.c b/drivers/mtd/nandx/core/core_io.c
400-new file mode 100644
401-index 0000000000..716eeed38d
402---- /dev/null
403-+++ b/drivers/mtd/nandx/core/core_io.c
404-@@ -0,0 +1,735 @@
405-+/*
406-+ * Copyright (C) 2017 MediaTek Inc.
407-+ * Licensed under either
408-+ * BSD Licence, (see NOTICE for more details)
409-+ * GNU General Public License, version 2.0, (see NOTICE for more details)
410-+ */
411-+
412-+/*NOTE: switch cache/multi*/
413-+#include "nandx_util.h"
414-+#include "nandx_core.h"
415-+#include "nand_chip.h"
416-+#include "core_io.h"
417-+
418-+static struct nandx_desc *g_nandx;
419-+
420-+static inline bool is_sector_align(u64 val)
421-+{
422-+ return reminder(val, g_nandx->chip->sector_size) ? false : true;
423-+}
424-+
425-+static inline bool is_page_align(u64 val)
426-+{
427-+ return reminder(val, g_nandx->chip->page_size) ? false : true;
428-+}
429-+
430-+static inline bool is_block_align(u64 val)
431-+{
432-+ return reminder(val, g_nandx->chip->block_size) ? false : true;
433-+}
434-+
435-+static inline u32 page_sectors(void)
436-+{
437-+ return div_down(g_nandx->chip->page_size, g_nandx->chip->sector_size);
438-+}
439-+
440-+static inline u32 sector_oob(void)
441-+{
442-+ return div_down(g_nandx->chip->oob_size, page_sectors());
443-+}
444-+
445-+static inline u32 sector_padded_size(void)
446-+{
447-+ return g_nandx->chip->sector_size + g_nandx->chip->sector_spare_size;
448-+}
449-+
450-+static inline u32 page_padded_size(void)
451-+{
452-+ return page_sectors() * sector_padded_size();
453-+}
454-+
455-+static inline u32 offset_to_padded_col(u64 offset)
456-+{
457-+ struct nandx_desc *nandx = g_nandx;
458-+ u32 col, sectors;
459-+
460-+ col = reminder(offset, nandx->chip->page_size);
461-+ sectors = div_down(col, nandx->chip->sector_size);
462-+
463-+ return col + sectors * nandx->chip->sector_spare_size;
464-+}
465-+
466-+static inline u32 offset_to_row(u64 offset)
467-+{
468-+ return div_down(offset, g_nandx->chip->page_size);
469-+}
470-+
471-+static inline u32 offset_to_col(u64 offset)
472-+{
473-+ return reminder(offset, g_nandx->chip->page_size);
474-+}
475-+
476-+static inline u32 oob_upper_size(void)
477-+{
478-+ return g_nandx->ecc_en ? g_nandx->chip->oob_size :
479-+ g_nandx->chip->sector_spare_size * page_sectors();
480-+}
481-+
482-+static inline bool is_upper_oob_align(u64 val)
483-+{
484-+ return reminder(val, oob_upper_size()) ? false : true;
485-+}
486-+
487-+#define prepare_op(_op, _row, _col, _len, _data, _oob) \
488-+ do { \
489-+ (_op).row = (_row); \
490-+ (_op).col = (_col); \
491-+ (_op).len = (_len); \
492-+ (_op).data = (_data); \
493-+ (_op).oob = (_oob); \
494-+ } while (0)
495-+
496-+static int operation_multi(enum nandx_op_mode mode, u8 *data, u8 *oob,
497-+ u64 offset, size_t len)
498-+{
499-+ struct nandx_desc *nandx = g_nandx;
500-+ u32 row = offset_to_row(offset);
501-+ u32 col = offset_to_padded_col(offset);
502-+
503-+ if (nandx->mode == NANDX_IDLE) {
504-+ nandx->mode = mode;
505-+ nandx->ops_current = 0;
506-+ } else if (nandx->mode != mode) {
507-+ pr_info("forbid mixed operations.\n");
508-+ return -EOPNOTSUPP;
509-+ }
510-+
511-+ prepare_op(nandx->ops[nandx->ops_current], row, col, len, data, oob);
512-+ nandx->ops_current++;
513-+
514-+ if (nandx->ops_current == nandx->ops_multi_len)
515-+ return nandx_sync();
516-+
517-+ return nandx->ops_multi_len - nandx->ops_current;
518-+}
519-+
520-+static int operation_sequent(enum nandx_op_mode mode, u8 *data, u8 *oob,
521-+ u64 offset, size_t len)
522-+{
523-+ struct nandx_desc *nandx = g_nandx;
524-+ struct nand_chip *chip = nandx->chip;
525-+ u32 row = offset_to_row(offset);
526-+ func_chip_ops chip_ops;
527-+ u8 *ref_data = data, *ref_oob = oob;
528-+ int align, ops, row_step;
529-+ int i, rem;
530-+
531-+ align = data ? chip->page_size : oob_upper_size();
532-+ ops = data ? div_down(len, align) : div_down(len, oob_upper_size());
533-+ row_step = 1;
534-+
535-+ switch (mode) {
536-+ case NANDX_ERASE:
537-+ chip_ops = chip->erase_block;
538-+ align = chip->block_size;
539-+ ops = div_down(len, align);
540-+ row_step = chip->block_pages;
541-+ break;
542-+
543-+ case NANDX_READ:
544-+ chip_ops = chip->read_page;
545-+ break;
546-+
547-+ case NANDX_WRITE:
548-+ chip_ops = chip->write_page;
549-+ break;
550-+
551-+ default:
552-+ return -EINVAL;
553-+ }
554-+
555-+ if (!data) {
556-+ ref_data = nandx->head_buf;
557-+ memset(ref_data, 0xff, chip->page_size);
558-+ }
559-+
560-+ if (!oob) {
561-+ ref_oob = nandx->head_buf + chip->page_size;
562-+ memset(ref_oob, 0xff, oob_upper_size());
563-+ }
564-+
565-+ for (i = 0; i < ops; i++) {
566-+ prepare_op(nandx->ops[nandx->ops_current],
567-+ row + i * row_step, 0, align, ref_data, ref_oob);
568-+ nandx->ops_current++;
569-+ /* if data or oob is null, nandx->head_buf or
570-+ * nandx->head_buf + chip->page_size should not been used
571-+ * so, here it is safe to use the buf.
572-+ */
573-+ ref_data = data ? ref_data + chip->page_size : nandx->head_buf;
574-+ ref_oob = oob ? ref_oob + oob_upper_size() :
575-+ nandx->head_buf + chip->page_size;
576-+ }
577-+
578-+ if (nandx->mode == NANDX_WRITE) {
579-+ rem = reminder(nandx->ops_current, nandx->min_write_pages);
580-+ if (rem)
581-+ return nandx->min_write_pages - rem;
582-+ }
583-+
584-+ nandx->ops_current = 0;
585-+ return chip_ops(chip, nandx->ops, ops);
586-+}
587-+
588-+static int read_pages(u8 *data, u8 *oob, u64 offset, size_t len)
589-+{
590-+ struct nandx_desc *nandx = g_nandx;
591-+ struct nand_chip *chip = nandx->chip;
592-+ struct nandx_split64 split = {0};
593-+ u8 *ref_data = data, *ref_oob;
594-+ u32 row, col;
595-+ int ret = 0, i, ops;
596-+ u32 head_offset = 0;
597-+ u64 val;
598-+
599-+ if (!data)
600-+ return operation_sequent(NANDX_READ, NULL, oob, offset, len);
601-+
602-+ ref_oob = oob ? oob : nandx->head_buf + chip->page_size;
603-+
604-+ nandx_split(&split, offset, len, val, chip->page_size);
605-+
606-+ if (split.head_len) {
607-+ row = offset_to_row(split.head);
608-+ col = offset_to_col(split.head);
609-+ prepare_op(nandx->ops[nandx->ops_current], row, 0,
610-+ chip->page_size,
611-+ nandx->head_buf, ref_oob);
612-+ nandx->ops_current++;
613-+
614-+ head_offset = col;
615-+
616-+ ref_data += split.head_len;
617-+ ref_oob = oob ? ref_oob + oob_upper_size() :
618-+ nandx->head_buf + chip->page_size;
619-+ }
620-+
621-+ if (split.body_len) {
622-+ ops = div_down(split.body_len, chip->page_size);
623-+ row = offset_to_row(split.body);
624-+ for (i = 0; i < ops; i++) {
625-+ prepare_op(nandx->ops[nandx->ops_current],
626-+ row + i, 0, chip->page_size,
627-+ ref_data, ref_oob);
628-+ nandx->ops_current++;
629-+ ref_data += chip->page_size;
630-+ ref_oob = oob ? ref_oob + oob_upper_size() :
631-+ nandx->head_buf + chip->page_size;
632-+ }
633-+ }
634-+
635-+ if (split.tail_len) {
636-+ row = offset_to_row(split.tail);
637-+ prepare_op(nandx->ops[nandx->ops_current], row, 0,
638-+ chip->page_size, nandx->tail_buf, ref_oob);
639-+ nandx->ops_current++;
640-+ }
641-+
642-+ ret = chip->read_page(chip, nandx->ops, nandx->ops_current);
643-+
644-+ if (split.head_len)
645-+ memcpy(data, nandx->head_buf + head_offset, split.head_len);
646-+ if (split.tail_len)
647-+ memcpy(ref_data, nandx->tail_buf, split.tail_len);
648-+
649-+ nandx->ops_current = 0;
650-+ return ret;
651-+}
652-+
653-+int nandx_read(u8 *data, u8 *oob, u64 offset, size_t len)
654-+{
655-+ struct nandx_desc *nandx = g_nandx;
656-+
657-+ if (!len || len > nandx->info.total_size)
658-+ return -EINVAL;
659-+ if (div_up(len, nandx->chip->page_size) > nandx->ops_len)
660-+ return -EINVAL;
661-+ if (!data && !oob)
662-+ return -EINVAL;
663-+ /**
664-+ * as design, oob not support partial read
665-+ * and, the length of oob buf should be oob size aligned
666-+ */
667-+ if (!data && !is_upper_oob_align(len))
668-+ return -EINVAL;
669-+
670-+ if (g_nandx->multi_en) {
671-+ /* as design, there only 2 buf for partial read,
672-+ * if partial read allowed for multi read,
673-+ * there are not enough buf
674-+ */
675-+ if (!is_sector_align(offset))
676-+ return -EINVAL;
677-+ if (data && !is_sector_align(len))
678-+ return -EINVAL;
679-+ return operation_multi(NANDX_READ, data, oob, offset, len);
680-+ }
681-+
682-+ nandx->ops_current = 0;
683-+ nandx->mode = NANDX_IDLE;
684-+ return read_pages(data, oob, offset, len);
685-+}
686-+
687-+static int write_pages(u8 *data, u8 *oob, u64 offset, size_t len)
688-+{
689-+ struct nandx_desc *nandx = g_nandx;
690-+ struct nand_chip *chip = nandx->chip;
691-+ struct nandx_split64 split = {0};
692-+ int ret, rem, i, ops;
693-+ u32 row, col;
694-+ u8 *ref_oob = oob;
695-+ u64 val;
696-+
697-+ nandx->mode = NANDX_WRITE;
698-+
699-+ if (!data)
700-+ return operation_sequent(NANDX_WRITE, NULL, oob, offset, len);
701-+
702-+ if (!oob) {
703-+ ref_oob = nandx->head_buf + chip->page_size;
704-+ memset(ref_oob, 0xff, oob_upper_size());
705-+ }
706-+
707-+ nandx_split(&split, offset, len, val, chip->page_size);
708-+
709-+ /*NOTE: slc can support sector write, here copy too many data.*/
710-+ if (split.head_len) {
711-+ row = offset_to_row(split.head);
712-+ col = offset_to_col(split.head);
713-+ memset(nandx->head_buf, 0xff, page_padded_size());
714-+ memcpy(nandx->head_buf + col, data, split.head_len);
715-+ prepare_op(nandx->ops[nandx->ops_current], row, 0,
716-+ chip->page_size, nandx->head_buf, ref_oob);
717-+ nandx->ops_current++;
718-+
719-+ data += split.head_len;
720-+ ref_oob = oob ? ref_oob + oob_upper_size() :
721-+ nandx->head_buf + chip->page_size;
722-+ }
723-+
724-+ if (split.body_len) {
725-+ row = offset_to_row(split.body);
726-+ ops = div_down(split.body_len, chip->page_size);
727-+ for (i = 0; i < ops; i++) {
728-+ prepare_op(nandx->ops[nandx->ops_current],
729-+ row + i, 0, chip->page_size, data, ref_oob);
730-+ nandx->ops_current++;
731-+ data += chip->page_size;
732-+ ref_oob = oob ? ref_oob + oob_upper_size() :
733-+ nandx->head_buf + chip->page_size;
734-+ }
735-+ }
736-+
737-+ if (split.tail_len) {
738-+ row = offset_to_row(split.tail);
739-+ memset(nandx->tail_buf, 0xff, page_padded_size());
740-+ memcpy(nandx->tail_buf, data, split.tail_len);
741-+ prepare_op(nandx->ops[nandx->ops_current], row, 0,
742-+ chip->page_size, nandx->tail_buf, ref_oob);
743-+ nandx->ops_current++;
744-+ }
745-+
746-+ rem = reminder(nandx->ops_current, nandx->min_write_pages);
747-+ if (rem)
748-+ return nandx->min_write_pages - rem;
749-+
750-+ ret = chip->write_page(chip, nandx->ops, nandx->ops_current);
751-+
752-+ nandx->ops_current = 0;
753-+ nandx->mode = NANDX_IDLE;
754-+ return ret;
755-+}
756-+
757-+int nandx_write(u8 *data, u8 *oob, u64 offset, size_t len)
758-+{
759-+ struct nandx_desc *nandx = g_nandx;
760-+
761-+ if (!len || len > nandx->info.total_size)
762-+ return -EINVAL;
763-+ if (div_up(len, nandx->chip->page_size) > nandx->ops_len)
764-+ return -EINVAL;
765-+ if (!data && !oob)
766-+ return -EINVAL;
767-+ if (!data && !is_upper_oob_align(len))
768-+ return -EINVAL;
769-+
770-+ if (nandx->multi_en) {
771-+ if (!is_page_align(offset))
772-+ return -EINVAL;
773-+ if (data && !is_page_align(len))
774-+ return -EINVAL;
775-+
776-+ return operation_multi(NANDX_WRITE, data, oob, offset, len);
777-+ }
778-+
779-+ return write_pages(data, oob, offset, len);
780-+}
781-+
782-+int nandx_erase(u64 offset, size_t len)
783-+{
784-+ struct nandx_desc *nandx = g_nandx;
785-+
786-+ if (!len || len > nandx->info.total_size)
787-+ return -EINVAL;
788-+ if (div_down(len, nandx->chip->block_size) > nandx->ops_len)
789-+ return -EINVAL;
790-+ if (!is_block_align(offset) || !is_block_align(len))
791-+ return -EINVAL;
792-+
793-+ if (g_nandx->multi_en)
794-+ return operation_multi(NANDX_ERASE, NULL, NULL, offset, len);
795-+
796-+ nandx->ops_current = 0;
797-+ nandx->mode = NANDX_IDLE;
798-+ return operation_sequent(NANDX_ERASE, NULL, NULL, offset, len);
799-+}
800-+
801-+int nandx_sync(void)
802-+{
803-+ struct nandx_desc *nandx = g_nandx;
804-+ struct nand_chip *chip = nandx->chip;
805-+ func_chip_ops chip_ops;
806-+ int ret, i, rem;
807-+
808-+ if (!nandx->ops_current)
809-+ return 0;
810-+
811-+ rem = reminder(nandx->ops_current, nandx->ops_multi_len);
812-+ if (nandx->multi_en && rem) {
813-+ ret = -EIO;
814-+ goto error;
815-+ }
816-+
817-+ switch (nandx->mode) {
818-+ case NANDX_IDLE:
819-+ return 0;
820-+ case NANDX_ERASE:
821-+ chip_ops = chip->erase_block;
822-+ break;
823-+ case NANDX_READ:
824-+ chip_ops = chip->read_page;
825-+ break;
826-+ case NANDX_WRITE:
827-+ chip_ops = chip->write_page;
828-+ break;
829-+ default:
830-+ return -EINVAL;
831-+ }
832-+
833-+ rem = reminder(nandx->ops_current, nandx->min_write_pages);
834-+ if (!nandx->multi_en && nandx->mode == NANDX_WRITE && rem) {
835-+ /* in one process of program, only allow 2 pages to do partial
836-+ * write, here we supposed 1st buf would be used, and 2nd
837-+ * buf should be not used.
838-+ */
839-+ memset(nandx->tail_buf, 0xff,
840-+ chip->page_size + oob_upper_size());
841-+ for (i = 0; i < rem; i++) {
842-+ prepare_op(nandx->ops[nandx->ops_current],
843-+ nandx->ops[nandx->ops_current - 1].row + 1,
844-+ 0, chip->page_size, nandx->tail_buf,
845-+ nandx->tail_buf + chip->page_size);
846-+ nandx->ops_current++;
847-+ }
848-+ }
849-+
850-+ ret = chip_ops(nandx->chip, nandx->ops, nandx->ops_current);
851-+
852-+error:
853-+ nandx->mode = NANDX_IDLE;
854-+ nandx->ops_current = 0;
855-+
856-+ return ret;
857-+}
858-+
859-+int nandx_ioctl(int cmd, void *arg)
860-+{
861-+ struct nandx_desc *nandx = g_nandx;
862-+ struct nand_chip *chip = nandx->chip;
863-+ int ret = 0;
864-+
865-+ switch (cmd) {
866-+ case CORE_CTRL_NAND_INFO:
867-+ *(struct nandx_info *)arg = nandx->info;
868-+ break;
869-+
870-+ case CHIP_CTRL_OPS_MULTI:
871-+ ret = chip->chip_ctrl(chip, cmd, arg);
872-+ if (!ret)
873-+ nandx->multi_en = *(bool *)arg;
874-+ break;
875-+
876-+ case NFI_CTRL_ECC:
877-+ ret = chip->chip_ctrl(chip, cmd, arg);
878-+ if (!ret)
879-+ nandx->ecc_en = *(bool *)arg;
880-+ break;
881-+
882-+ default:
883-+ ret = chip->chip_ctrl(chip, cmd, arg);
884-+ break;
885-+ }
886-+
887-+ return ret;
888-+}
889-+
890-+bool nandx_is_bad_block(u64 offset)
891-+{
892-+ struct nandx_desc *nandx = g_nandx;
893-+
894-+ prepare_op(nandx->ops[0], offset_to_row(offset), 0,
895-+ nandx->chip->page_size, nandx->head_buf,
896-+ nandx->head_buf + nandx->chip->page_size);
897-+
898-+ return nandx->chip->is_bad_block(nandx->chip, nandx->ops, 1);
899-+}
900-+
901-+int nandx_suspend(void)
902-+{
903-+ return g_nandx->chip->suspend(g_nandx->chip);
904-+}
905-+
906-+int nandx_resume(void)
907-+{
908-+ return g_nandx->chip->resume(g_nandx->chip);
909-+}
910-+
911-+int nandx_init(struct nfi_resource *res)
912-+{
913-+ struct nand_chip *chip;
914-+ struct nandx_desc *nandx;
915-+ int ret = 0;
916-+
917-+ if (!res)
918-+ return -EINVAL;
919-+
920-+ chip = nand_chip_init(res);
921-+ if (!chip) {
922-+ pr_info("nand chip init fail.\n");
923-+ return -EFAULT;
924-+ }
925-+
926-+ nandx = (struct nandx_desc *)mem_alloc(1, sizeof(struct nandx_desc));
927-+ if (!nandx)
928-+ return -ENOMEM;
929-+
930-+ g_nandx = nandx;
931-+
932-+ nandx->chip = chip;
933-+ nandx->min_write_pages = chip->min_program_pages;
934-+ nandx->ops_multi_len = nandx->min_write_pages * chip->plane_num;
935-+ nandx->ops_len = chip->block_pages * chip->plane_num;
936-+ nandx->ops = mem_alloc(1, sizeof(struct nand_ops) * nandx->ops_len);
937-+ if (!nandx->ops) {
938-+ ret = -ENOMEM;
939-+ goto ops_error;
940-+ }
941-+
942-+#if NANDX_BULK_IO_USE_DRAM
943-+ nandx->head_buf = NANDX_CORE_BUF_ADDR;
944-+#else
945-+ nandx->head_buf = mem_alloc(2, page_padded_size());
946-+#endif
947-+ if (!nandx->head_buf) {
948-+ ret = -ENOMEM;
949-+ goto buf_error;
950-+ }
951-+ nandx->tail_buf = nandx->head_buf + page_padded_size();
952-+ memset(nandx->head_buf, 0xff, 2 * page_padded_size());
953-+ nandx->multi_en = false;
954-+ nandx->ecc_en = false;
955-+ nandx->ops_current = 0;
956-+ nandx->mode = NANDX_IDLE;
957-+
958-+ nandx->info.max_io_count = nandx->ops_len;
959-+ nandx->info.min_write_pages = nandx->min_write_pages;
960-+ nandx->info.plane_num = chip->plane_num;
961-+ nandx->info.oob_size = chip->oob_size;
962-+ nandx->info.page_parity_size = chip->sector_spare_size * page_sectors();
963-+ nandx->info.page_size = chip->page_size;
964-+ nandx->info.block_size = chip->block_size;
965-+ nandx->info.total_size = chip->block_size * chip->block_num;
966-+ nandx->info.fdm_ecc_size = chip->fdm_ecc_size;
967-+ nandx->info.fdm_reg_size = chip->fdm_reg_size;
968-+ nandx->info.ecc_strength = chip->ecc_strength;
969-+ nandx->info.sector_size = chip->sector_size;
970-+
971-+ return 0;
972-+
973-+buf_error:
974-+#if !NANDX_BULK_IO_USE_DRAM
975-+ mem_free(nandx->head_buf);
976-+#endif
977-+ops_error:
978-+ mem_free(nandx);
979-+
980-+ return ret;
981-+}
982-+
983-+void nandx_exit(void)
984-+{
985-+ nand_chip_exit(g_nandx->chip);
986-+#if !NANDX_BULK_IO_USE_DRAM
987-+ mem_free(g_nandx->head_buf);
988-+#endif
989-+ mem_free(g_nandx->ops);
990-+ mem_free(g_nandx);
991-+}
992-+
993-+#ifdef NANDX_UNIT_TEST
994-+static void dump_buf(u8 *buf, u32 len)
995-+{
996-+ u32 i;
997-+
998-+ pr_info("dump buf@0x%X start", (u32)buf);
999-+ for (i = 0; i < len; i++) {
1000-+ if (!reminder(i, 16))
1001-+ pr_info("\n0x");
1002-+ pr_info("%x ", buf[i]);
1003-+ }
1004-+ pr_info("\ndump buf done.\n");
1005-+}
1006-+
1007-+int nandx_unit_test(u64 offset, size_t len)
1008-+{
1009-+ u8 *src_buf, *dst_buf;
1010-+ u32 i, j;
1011-+ int ret;
1012-+
1013-+ if (!len || len > g_nandx->chip->block_size)
1014-+ return -EINVAL;
1015-+
1016-+#if NANDX_BULK_IO_USE_DRAM
1017-+ src_buf = NANDX_UT_SRC_ADDR;
1018-+ dst_buf = NANDX_UT_DST_ADDR;
1019-+
1020-+#else
1021-+ src_buf = mem_alloc(1, g_nandx->chip->page_size);
1022-+ if (!src_buf)
1023-+ return -ENOMEM;
1024-+ dst_buf = mem_alloc(1, g_nandx->chip->page_size);
1025-+ if (!dst_buf) {
1026-+ mem_free(src_buf);
1027-+ return -ENOMEM;
1028-+ }
1029-+#endif
1030-+
1031-+ pr_info("%s: src_buf address 0x%x, dst_buf address 0x%x\n",
1032-+ __func__, (int)((unsigned long)src_buf),
1033-+ (int)((unsigned long)dst_buf));
1034-+
1035-+ memset(dst_buf, 0, g_nandx->chip->page_size);
1036-+ pr_info("read page 0 data...!\n");
1037-+ ret = nandx_read(dst_buf, NULL, 0, g_nandx->chip->page_size);
1038-+ if (ret < 0) {
1039-+ pr_info("read fail with ret %d\n", ret);
1040-+ } else {
1041-+ pr_info("read page success!\n");
1042-+ }
1043-+
1044-+ for (i = 0; i < g_nandx->chip->page_size; i++) {
1045-+ src_buf[i] = 0x5a;
1046-+ }
1047-+
1048-+ ret = nandx_erase(offset, g_nandx->chip->block_size);
1049-+ if (ret < 0) {
1050-+ pr_info("erase fail with ret %d\n", ret);
1051-+ goto error;
1052-+ }
1053-+
1054-+ for (j = 0; j < g_nandx->chip->block_pages; j++) {
1055-+ memset(dst_buf, 0, g_nandx->chip->page_size);
1056-+ pr_info("check data after erase...!\n");
1057-+ ret = nandx_read(dst_buf, NULL, offset, g_nandx->chip->page_size);
1058-+ if (ret < 0) {
1059-+ pr_info("read fail with ret %d\n", ret);
1060-+ goto error;
1061-+ }
1062-+
1063-+ for (i = 0; i < g_nandx->chip->page_size; i++) {
1064-+ if (dst_buf[i] != 0xff) {
1065-+ pr_info("read after erase, check fail @%d\n", i);
1066-+ pr_info("all data should be 0xff\n");
1067-+ ret = -ENANDERASE;
1068-+ dump_buf(dst_buf, 128);
1069-+ //goto error;
1070-+ break;
1071-+ }
1072-+ }
1073-+
1074-+ pr_info("write data...!\n");
1075-+ ret = nandx_write(src_buf, NULL, offset, g_nandx->chip->page_size);
1076-+ if (ret < 0) {
1077-+ pr_info("write fail with ret %d\n", ret);
1078-+ goto error;
1079-+ }
1080-+
1081-+ memset(dst_buf, 0, g_nandx->chip->page_size);
1082-+ pr_info("read data...!\n");
1083-+ ret = nandx_read(dst_buf, NULL, offset, g_nandx->chip->page_size);
1084-+ if (ret < 0) {
1085-+ pr_info("read fail with ret %d\n", ret);
1086-+ goto error;
1087-+ }
1088-+
1089-+ for (i = 0; i < g_nandx->chip->page_size; i++) {
1090-+ if (dst_buf[i] != src_buf[i]) {
1091-+ pr_info("read after write, check fail @%d\n", i);
1092-+ pr_info("dst_buf should be same as src_buf\n");
1093-+ ret = -EIO;
1094-+ dump_buf(src_buf + i, 128);
1095-+ dump_buf(dst_buf + i, 128);
1096-+ break;
1097-+ }
1098-+ }
1099-+
1100-+ pr_err("%s %d %s@%d\n", __func__, __LINE__, ret?"Failed":"OK", j);
1101-+ if (ret)
1102-+ break;
1103-+
1104-+ offset += g_nandx->chip->page_size;
1105-+ }
1106-+
1107-+ ret = nandx_erase(offset, g_nandx->chip->block_size);
1108-+ if (ret < 0) {
1109-+ pr_info("erase fail with ret %d\n", ret);
1110-+ goto error;
1111-+ }
1112-+
1113-+ memset(dst_buf, 0, g_nandx->chip->page_size);
1114-+ ret = nandx_read(dst_buf, NULL, offset, g_nandx->chip->page_size);
1115-+ if (ret < 0) {
1116-+ pr_info("read fail with ret %d\n", ret);
1117-+ goto error;
1118-+ }
1119-+
1120-+ for (i = 0; i < g_nandx->chip->page_size; i++) {
1121-+ if (dst_buf[i] != 0xff) {
1122-+ pr_info("read after erase, check fail\n");
1123-+ pr_info("all data should be 0xff\n");
1124-+ ret = -ENANDERASE;
1125-+ dump_buf(dst_buf, 128);
1126-+ goto error;
1127-+ }
1128-+ }
1129-+
1130-+ return 0;
1131-+
1132-+error:
1133-+#if !NANDX_BULK_IO_USE_DRAM
1134-+ mem_free(src_buf);
1135-+ mem_free(dst_buf);
1136-+#endif
1137-+ return ret;
1138-+}
1139-+#endif
1140-diff --git a/drivers/mtd/nandx/core/core_io.h b/drivers/mtd/nandx/core/core_io.h
1141-new file mode 100644
1142-index 0000000000..edcb60908a
1143---- /dev/null
1144-+++ b/drivers/mtd/nandx/core/core_io.h
1145-@@ -0,0 +1,39 @@
1146-+/*
1147-+ * Copyright (C) 2017 MediaTek Inc.
1148-+ * Licensed under either
1149-+ * BSD Licence, (see NOTICE for more details)
1150-+ * GNU General Public License, version 2.0, (see NOTICE for more details)
1151-+ */
1152-+
1153-+#ifndef __CORE_IO_H__
1154-+#define __CORE_IO_H__
1155-+
1156-+typedef int (*func_chip_ops)(struct nand_chip *, struct nand_ops *,
1157-+ int);
1158-+
1159-+enum nandx_op_mode {
1160-+ NANDX_IDLE,
1161-+ NANDX_WRITE,
1162-+ NANDX_READ,
1163-+ NANDX_ERASE
1164-+};
1165-+
1166-+struct nandx_desc {
1167-+ struct nand_chip *chip;
1168-+ struct nandx_info info;
1169-+ enum nandx_op_mode mode;
1170-+
1171-+ bool multi_en;
1172-+ bool ecc_en;
1173-+
1174-+ struct nand_ops *ops;
1175-+ int ops_len;
1176-+ int ops_multi_len;
1177-+ int ops_current;
1178-+ int min_write_pages;
1179-+
1180-+ u8 *head_buf;
1181-+ u8 *tail_buf;
1182-+};
1183-+
1184-+#endif /* __CORE_IO_H__ */
1185-diff --git a/drivers/mtd/nandx/core/nand/device_spi.c b/drivers/mtd/nandx/core/nand/device_spi.c
1186-new file mode 100644
1187-index 0000000000..db338c28c2
1188---- /dev/null
1189-+++ b/drivers/mtd/nandx/core/nand/device_spi.c
1190-@@ -0,0 +1,200 @@
1191-+/*
1192-+ * Copyright (C) 2017 MediaTek Inc.
1193-+ * Licensed under either
1194-+ * BSD Licence, (see NOTICE for more details)
1195-+ * GNU General Public License, version 2.0, (see NOTICE for more details)
1196-+ */
1197-+
1198-+#include "nandx_util.h"
1199-+#include "../nand_device.h"
1200-+#include "device_spi.h"
1201-+
1202-+/* spi nand basic commands */
1203-+static struct nand_cmds spi_cmds = {
1204-+ .reset = 0xff,
1205-+ .read_id = 0x9f,
1206-+ .read_status = 0x0f,
1207-+ .read_param_page = 0x03,
1208-+ .set_feature = 0x1f,
1209-+ .get_feature = 0x0f,
1210-+ .read_1st = 0x13,
1211-+ .read_2nd = -1,
1212-+ .random_out_1st = 0x03,
1213-+ .random_out_2nd = -1,
1214-+ .program_1st = 0x02,
1215-+ .program_2nd = 0x10,
1216-+ .erase_1st = 0xd8,
1217-+ .erase_2nd = -1,
1218-+ .read_cache = 0x30,
1219-+ .read_cache_last = 0x3f,
1220-+ .program_cache = 0x02
1221-+};
1222-+
1223-+/* spi nand extend commands */
1224-+static struct spi_extend_cmds spi_extend_cmds = {
1225-+ .die_select = 0xc2,
1226-+ .write_enable = 0x06
1227-+};
1228-+
1229-+/* means the start bit of addressing type */
1230-+static struct nand_addressing spi_addressing = {
1231-+ .row_bit_start = 0,
1232-+ .block_bit_start = 0,
1233-+ .plane_bit_start = 12,
1234-+ .lun_bit_start = 0,
1235-+};
1236-+
1237-+/* spi nand endurance */
1238-+static struct nand_endurance spi_endurance = {
1239-+ .pe_cycle = 100000,
1240-+ .ecc_req = 1,
1241-+ .max_bitflips = 1
1242-+};
1243-+
1244-+/* array_busy, write_protect, erase_fail, program_fail */
1245-+static struct nand_status spi_status[] = {
1246-+ {.array_busy = BIT(0),
1247-+ .write_protect = BIT(1),
1248-+ .erase_fail = BIT(2),
1249-+ .program_fail = BIT(3)}
1250-+};
1251-+
1252-+/* measure time by the us */
1253-+static struct nand_array_timing spi_array_timing = {
1254-+ .tRST = 500,
1255-+ .tWHR = 1,
1256-+ .tR = 25,
1257-+ .tRCBSY = 25,
1258-+ .tFEAT = 1,
1259-+ .tPROG = 600,
1260-+ .tPCBSY = 600,
1261-+ .tBERS = 10000,
1262-+ .tDBSY = 1
1263-+};
1264-+
1265-+/* spi nand device table */
1266-+static struct device_spi spi_nand[] = {
1267-+ {
1268-+ NAND_DEVICE("W25N01GV",
1269-+ NAND_PACK_ID(0xef, 0xaa, 0x21, 0, 0, 0, 0, 0),
1270-+ 3, 0, 3, 3,
1271-+ 1, 1, 1, 1024, KB(128), KB(2), 64, 1,
1272-+ &spi_cmds, &spi_addressing, &spi_status[0],
1273-+ &spi_endurance, &spi_array_timing),
1274-+ {
1275-+ NAND_SPI_PROTECT(0xa0, 1, 2, 6),
1276-+ NAND_SPI_CONFIG(0xb0, 4, 6, 0),
1277-+ NAND_SPI_STATUS(0xc0, 4, 5),
1278-+ NAND_SPI_CHARACTER(0xff, 0xff, 0xff, 0xff)
1279-+ },
1280-+ &spi_extend_cmds, 0xff, 0xff
1281-+ },
1282-+ {
1283-+ NAND_DEVICE("MX35LF1G",
1284-+ NAND_PACK_ID(0xc2, 0x12, 0x21, 0, 0, 0, 0, 0),
1285-+ 2, 0, 3, 3,
1286-+ 1, 1, 1, 1024, KB(128), KB(2), 64, 1,
1287-+ &spi_cmds, &spi_addressing, &spi_status[0],
1288-+ &spi_endurance, &spi_array_timing),
1289-+ {
1290-+ NAND_SPI_PROTECT(0xa0, 1, 2, 6),
1291-+ NAND_SPI_CONFIG(0xb0, 4, 6, 1),
1292-+ NAND_SPI_STATUS(0xc0, 4, 5),
1293-+ NAND_SPI_CHARACTER(0xff, 0xff, 0xff, 0xff)
1294-+ },
1295-+ &spi_extend_cmds, 0xff, 0xff
1296-+ },
1297-+ {
1298-+ NAND_DEVICE("MT29F4G01ABAFDWB",
1299-+ NAND_PACK_ID(0x2c, 0x34, 0, 0, 0, 0, 0, 0),
1300-+ 2, 0, 3, 3,
1301-+ 1, 1, 1, 2048, KB(256), KB(4), 256, 1,
1302-+ &spi_cmds, &spi_addressing, &spi_status[0],
1303-+ &spi_endurance, &spi_array_timing),
1304-+ {
1305-+ NAND_SPI_PROTECT(0xa0, 1, 2, 6),
1306-+ NAND_SPI_CONFIG(0xb0, 4, 6, 1),
1307-+ NAND_SPI_STATUS(0xc0, 4, 5),
1308-+ NAND_SPI_CHARACTER(0xff, 0xff, 0xff, 0xff)
1309-+ },
1310-+ &spi_extend_cmds, 0xff, 0xff
1311-+ },
1312-+ {
1313-+ NAND_DEVICE("GD5F4GQ4UB",
1314-+ NAND_PACK_ID(0xc8, 0xd4, 0, 0, 0, 0, 0, 0),
1315-+ 2, 0, 3, 3,
1316-+ 1, 1, 1, 2048, KB(256), KB(4), 256, 1,
1317-+ &spi_cmds, &spi_addressing, &spi_status[0],
1318-+ &spi_endurance, &spi_array_timing),
1319-+ {
1320-+ NAND_SPI_PROTECT(0xa0, 1, 2, 6),
1321-+ NAND_SPI_CONFIG(0xb0, 4, 6, 1),
1322-+ NAND_SPI_STATUS(0xc0, 4, 5),
1323-+ NAND_SPI_CHARACTER(0xff, 0xff, 0xff, 0xff)
1324-+ },
1325-+ &spi_extend_cmds, 0xff, 0xff
1326-+ },
1327-+ {
1328-+ NAND_DEVICE("TC58CVG2S0HRAIJ",
1329-+ NAND_PACK_ID(0x98, 0xED, 0x51, 0, 0, 0, 0, 0),
1330-+ 3, 0, 3, 3,
1331-+ 1, 1, 1, 2048, KB(256), KB(4), 256, 1,
1332-+ &spi_cmds, &spi_addressing, &spi_status[0],
1333-+ &spi_endurance, &spi_array_timing),
1334-+ {
1335-+ NAND_SPI_PROTECT(0xa0, 1, 2, 6),
1336-+ NAND_SPI_CONFIG(0xb0, 4, 6, 1),
1337-+ NAND_SPI_STATUS(0xc0, 4, 5),
1338-+ NAND_SPI_CHARACTER(0xff, 0xff, 0xff, 0xff)
1339-+ },
1340-+ &spi_extend_cmds, 0xff, 0xff
1341-+ },
1342-+ {
1343-+ NAND_DEVICE("NO-DEVICE",
1344-+ NAND_PACK_ID(0, 0, 0, 0, 0, 0, 0, 0), 0, 0, 0, 0,
1345-+ 0, 0, 0, 0, 0, 0, 0, 1,
1346-+ &spi_cmds, &spi_addressing, &spi_status[0],
1347-+ &spi_endurance, &spi_array_timing),
1348-+ {
1349-+ NAND_SPI_PROTECT(0xa0, 1, 2, 6),
1350-+ NAND_SPI_CONFIG(0xb0, 4, 6, 0),
1351-+ NAND_SPI_STATUS(0xc0, 4, 5),
1352-+ NAND_SPI_CHARACTER(0xff, 0xff, 0xff, 0xff)
1353-+ },
1354-+ &spi_extend_cmds, 0xff, 0xff
1355-+ }
1356-+};
1357-+
1358-+u8 spi_replace_rx_cmds(u8 mode)
1359-+{
1360-+ u8 rx_replace_cmds[] = {0x03, 0x3b, 0x6b, 0xbb, 0xeb};
1361-+
1362-+ return rx_replace_cmds[mode];
1363-+}
1364-+
1365-+u8 spi_replace_tx_cmds(u8 mode)
1366-+{
1367-+ u8 tx_replace_cmds[] = {0x02, 0x32};
1368-+
1369-+ return tx_replace_cmds[mode];
1370-+}
1371-+
1372-+u8 spi_replace_rx_col_cycle(u8 mode)
1373-+{
1374-+ u8 rx_replace_col_cycle[] = {3, 3, 3, 3, 4};
1375-+
1376-+ return rx_replace_col_cycle[mode];
1377-+}
1378-+
1379-+u8 spi_replace_tx_col_cycle(u8 mode)
1380-+{
1381-+ u8 tx_replace_col_cycle[] = {2, 2};
1382-+
1383-+ return tx_replace_col_cycle[mode];
1384-+}
1385-+
1386-+struct nand_device *nand_get_device(int index)
1387-+{
1388-+ return &spi_nand[index].dev;
1389-+}
1390-+
1391-diff --git a/drivers/mtd/nandx/core/nand/device_spi.h b/drivers/mtd/nandx/core/nand/device_spi.h
1392-new file mode 100644
1393-index 0000000000..1676b61fc8
1394---- /dev/null
1395-+++ b/drivers/mtd/nandx/core/nand/device_spi.h
1396-@@ -0,0 +1,132 @@
1397-+/*
1398-+ * Copyright (C) 2017 MediaTek Inc.
1399-+ * Licensed under either
1400-+ * BSD Licence, (see NOTICE for more details)
1401-+ * GNU General Public License, version 2.0, (see NOTICE for more details)
1402-+ */
1403-+
1404-+#ifndef __DEVICE_SPI_H__
1405-+#define __DEVICE_SPI_H__
1406-+
1407-+/*
1408-+ * extend commands
1409-+ * @die_select: select nand device die command
1410-+ * @write_enable: enable write command before write data to spi nand
1411-+ * spi nand device will auto to be disable after write done
1412-+ */
1413-+struct spi_extend_cmds {
1414-+ short die_select;
1415-+ short write_enable;
1416-+};
1417-+
1418-+/*
1419-+ * protection feature register
1420-+ * @addr: register address
1421-+ * @wp_en_bit: write protection enable bit
1422-+ * @bp_start_bit: block protection mask start bit
1423-+ * @bp_end_bit: block protection mask end bit
1424-+ */
1425-+struct feature_protect {
1426-+ u8 addr;
1427-+ u8 wp_en_bit;
1428-+ u8 bp_start_bit;
1429-+ u8 bp_end_bit;
1430-+};
1431-+
1432-+/*
1433-+ * configuration feature register
1434-+ * @addr: register address
1435-+ * @ecc_en_bit: in-die ecc enable bit
1436-+ * @otp_en_bit: enter otp access mode bit
1437-+ * @need_qe: quad io enable bit
1438-+ */
1439-+struct feature_config {
1440-+ u8 addr;
1441-+ u8 ecc_en_bit;
1442-+ u8 otp_en_bit;
1443-+ u8 need_qe;
1444-+};
1445-+
1446-+/*
1447-+ * status feature register
1448-+ * @addr: register address
1449-+ * @ecc_start_bit: ecc status mask start bit for error bits number
1450-+ * @ecc_end_bit: ecc status mask end bit for error bits number
1451-+ * note that:
1452-+ * operations status (ex. array busy status) could see on struct nand_status
1453-+ */
1454-+struct feature_status {
1455-+ u8 addr;
1456-+ u8 ecc_start_bit;
1457-+ u8 ecc_end_bit;
1458-+};
1459-+
1460-+/*
1461-+ * character feature register
1462-+ * @addr: register address
1463-+ * @die_sel_bit: die select bit
1464-+ * @drive_start_bit: drive strength mask start bit
1465-+ * @drive_end_bit: drive strength mask end bit
1466-+ */
1467-+struct feature_character {
1468-+ u8 addr;
1469-+ u8 die_sel_bit;
1470-+ u8 drive_start_bit;
1471-+ u8 drive_end_bit;
1472-+};
1473-+
1474-+/*
1475-+ * spi features
1476-+ * @protect: protection feature register
1477-+ * @config: configuration feature register
1478-+ * @status: status feature register
1479-+ * @character: character feature register
1480-+ */
1481-+struct spi_features {
1482-+ struct feature_protect protect;
1483-+ struct feature_config config;
1484-+ struct feature_status status;
1485-+ struct feature_character character;
1486-+};
1487-+
1488-+/*
1489-+ * device_spi
1490-+ * configurations of spi nand device table
1491-+ * @dev: base information of nand device
1492-+ * @feature: feature information for spi nand
1493-+ * @extend_cmds: extended the nand base commands
1494-+ * @tx_mode_mask: tx mode mask for chip read
1495-+ * @rx_mode_mask: rx mode mask for chip write
1496-+ */
1497-+struct device_spi {
1498-+ struct nand_device dev;
1499-+ struct spi_features feature;
1500-+ struct spi_extend_cmds *extend_cmds;
1501-+
1502-+ u8 tx_mode_mask;
1503-+ u8 rx_mode_mask;
1504-+};
1505-+
1506-+#define NAND_SPI_PROTECT(addr, wp_en_bit, bp_start_bit, bp_end_bit) \
1507-+ {addr, wp_en_bit, bp_start_bit, bp_end_bit}
1508-+
1509-+#define NAND_SPI_CONFIG(addr, ecc_en_bit, otp_en_bit, need_qe) \
1510-+ {addr, ecc_en_bit, otp_en_bit, need_qe}
1511-+
1512-+#define NAND_SPI_STATUS(addr, ecc_start_bit, ecc_end_bit) \
1513-+ {addr, ecc_start_bit, ecc_end_bit}
1514-+
1515-+#define NAND_SPI_CHARACTER(addr, die_sel_bit, drive_start_bit, drive_end_bit) \
1516-+ {addr, die_sel_bit, drive_start_bit, drive_end_bit}
1517-+
1518-+static inline struct device_spi *device_to_spi(struct nand_device *dev)
1519-+{
1520-+ return container_of(dev, struct device_spi, dev);
1521-+}
1522-+
1523-+u8 spi_replace_rx_cmds(u8 mode);
1524-+u8 spi_replace_tx_cmds(u8 mode);
1525-+u8 spi_replace_rx_col_cycle(u8 mode);
1526-+u8 spi_replace_tx_col_cycle(u8 mode);
1527-+
1528-+#endif /* __DEVICE_SPI_H__ */
1529-diff --git a/drivers/mtd/nandx/core/nand/nand_spi.c b/drivers/mtd/nandx/core/nand/nand_spi.c
1530-new file mode 100644
1531-index 0000000000..2ae03e1cf4
1532---- /dev/null
1533-+++ b/drivers/mtd/nandx/core/nand/nand_spi.c
1534-@@ -0,0 +1,526 @@
1535-+/*
1536-+ * Copyright (C) 2017 MediaTek Inc.
1537-+ * Licensed under either
1538-+ * BSD Licence, (see NOTICE for more details)
1539-+ * GNU General Public License, version 2.0, (see NOTICE for more details)
1540-+ */
1541-+
1542-+#include "nandx_util.h"
1543-+#include "nandx_core.h"
1544-+#include "../nand_chip.h"
1545-+#include "../nand_device.h"
1546-+#include "../nfi.h"
1547-+#include "../nand_base.h"
1548-+#include "device_spi.h"
1549-+#include "nand_spi.h"
1550-+
1551-+#define READY_TIMEOUT 500000 /* us */
1552-+
1553-+static int nand_spi_read_status(struct nand_base *nand)
1554-+{
1555-+ struct device_spi *dev = device_to_spi(nand->dev);
1556-+ u8 status;
1557-+
1558-+ nand->get_feature(nand, dev->feature.status.addr, &status, 1);
1559-+
1560-+ return status;
1561-+}
1562-+
1563-+static int nand_spi_wait_ready(struct nand_base *nand, u32 timeout)
1564-+{
1565-+ u64 now, end;
1566-+ int status;
1567-+
1568-+ end = get_current_time_us() + timeout;
1569-+
1570-+ do {
1571-+ status = nand_spi_read_status(nand);
1572-+ status &= nand->dev->status->array_busy;
1573-+ now = get_current_time_us();
1574-+
1575-+ if (now > end)
1576-+ break;
1577-+ } while (status);
1578-+
1579-+ return status ? -EBUSY : 0;
1580-+}
1581-+
1582-+static int nand_spi_set_op_mode(struct nand_base *nand, u8 mode)
1583-+{
1584-+ struct nand_spi *spi_nand = base_to_spi(nand);
1585-+ struct nfi *nfi = nand->nfi;
1586-+ int ret = 0;
1587-+
1588-+ if (spi_nand->op_mode != mode) {
1589-+ ret = nfi->nfi_ctrl(nfi, SNFI_CTRL_OP_MODE, (void *)&mode);
1590-+ spi_nand->op_mode = mode;
1591-+ }
1592-+
1593-+ return ret;
1594-+}
1595-+
1596-+static int nand_spi_set_config(struct nand_base *nand, u8 addr, u8 mask,
1597-+ bool en)
1598-+{
1599-+ u8 configs = 0;
1600-+
1601-+ nand->get_feature(nand, addr, &configs, 1);
1602-+
1603-+ if (en)
1604-+ configs |= mask;
1605-+ else
1606-+ configs &= ~mask;
1607-+
1608-+ nand->set_feature(nand, addr, &configs, 1);
1609-+
1610-+ configs = 0;
1611-+ nand->get_feature(nand, addr, &configs, 1);
1612-+
1613-+ return (configs & mask) == en ? 0 : -EFAULT;
1614-+}
1615-+
1616-+static int nand_spi_die_select(struct nand_base *nand, int *row)
1617-+{
1618-+ struct device_spi *dev = device_to_spi(nand->dev);
1619-+ struct nfi *nfi = nand->nfi;
1620-+ int lun_blocks, block_pages, lun, blocks;
1621-+ int page = *row, ret = 0;
1622-+ u8 param = 0, die_sel;
1623-+
1624-+ if (nand->dev->lun_num < 2)
1625-+ return 0;
1626-+
1627-+ block_pages = nand_block_pages(nand->dev);
1628-+ lun_blocks = nand_lun_blocks(nand->dev);
1629-+ blocks = div_down(page, block_pages);
1630-+ lun = div_down(blocks, lun_blocks);
1631-+
1632-+ if (dev->extend_cmds->die_select == -1) {
1633-+ die_sel = (u8)(lun << dev->feature.character.die_sel_bit);
1634-+ nand->get_feature(nand, dev->feature.character.addr, &param, 1);
1635-+ param |= die_sel;
1636-+ nand->set_feature(nand, dev->feature.character.addr, &param, 1);
1637-+ param = 0;
1638-+ nand->get_feature(nand, dev->feature.character.addr, &param, 1);
1639-+ ret = (param & die_sel) ? 0 : -EFAULT;
1640-+ } else {
1641-+ nfi->reset(nfi);
1642-+ nfi->send_cmd(nfi, dev->extend_cmds->die_select);
1643-+ nfi->send_addr(nfi, lun, 0, 1, 0);
1644-+ nfi->trigger(nfi);
1645-+ }
1646-+
1647-+ *row = page - (lun_blocks * block_pages) * lun;
1648-+
1649-+ return ret;
1650-+}
1651-+
1652-+static int nand_spi_select_device(struct nand_base *nand, int cs)
1653-+{
1654-+ struct nand_spi *spi = base_to_spi(nand);
1655-+ struct nand_base *parent = spi->parent;
1656-+
1657-+ nand_spi_set_op_mode(nand, SNFI_MAC_MODE);
1658-+
1659-+ return parent->select_device(nand, cs);
1660-+}
1661-+
1662-+static int nand_spi_reset(struct nand_base *nand)
1663-+{
1664-+ struct nand_spi *spi = base_to_spi(nand);
1665-+ struct nand_base *parent = spi->parent;
1666-+
1667-+ nand_spi_set_op_mode(nand, SNFI_MAC_MODE);
1668-+
1669-+ parent->reset(nand);
1670-+
1671-+ return nand_spi_wait_ready(nand, READY_TIMEOUT);
1672-+}
1673-+
1674-+static int nand_spi_read_id(struct nand_base *nand, u8 *id, int count)
1675-+{
1676-+ struct nand_spi *spi = base_to_spi(nand);
1677-+ struct nand_base *parent = spi->parent;
1678-+
1679-+ nand_spi_set_op_mode(nand, SNFI_MAC_MODE);
1680-+
1681-+ return parent->read_id(nand, id, count);
1682-+}
1683-+
1684-+static int nand_spi_read_param_page(struct nand_base *nand, u8 *data,
1685-+ int count)
1686-+{
1687-+ struct device_spi *dev = device_to_spi(nand->dev);
1688-+ struct nand_spi *spi = base_to_spi(nand);
1689-+ struct nfi *nfi = nand->nfi;
1690-+ int sectors, value;
1691-+ u8 param = 0;
1692-+
1693-+ sectors = div_round_up(count, nfi->sector_size);
1694-+
1695-+ nand->get_feature(nand, dev->feature.config.addr, &param, 1);
1696-+ param |= BIT(dev->feature.config.otp_en_bit);
1697-+ nand->set_feature(nand, dev->feature.config.addr, &param, 1);
1698-+
1699-+ param = 0;
1700-+ nand->get_feature(nand, dev->feature.config.addr, &param, 1);
1701-+ if (param & BIT(dev->feature.config.otp_en_bit)) {
1702-+ value = 0;
1703-+ nfi->nfi_ctrl(nfi, NFI_CTRL_ECC, &value);
1704-+ nand->dev->col_cycle = spi_replace_rx_col_cycle(spi->rx_mode);
1705-+ nand->read_page(nand, 0x01);
1706-+ nand->read_data(nand, 0x01, 0, sectors, data, NULL);
1707-+ }
1708-+
1709-+ param &= ~BIT(dev->feature.config.otp_en_bit);
1710-+ nand->set_feature(nand, dev->feature.config.addr, &param, 1);
1711-+
1712-+ return 0;
1713-+}
1714-+
1715-+static int nand_spi_set_feature(struct nand_base *nand, u8 addr,
1716-+ u8 *param,
1717-+ int count)
1718-+{
1719-+ struct nand_spi *spi = base_to_spi(nand);
1720-+ struct nand_base *parent = spi->parent;
1721-+
1722-+ nand->write_enable(nand);
1723-+
1724-+ nand_spi_set_op_mode(nand, SNFI_MAC_MODE);
1725-+
1726-+ return parent->set_feature(nand, addr, param, count);
1727-+}
1728-+
1729-+static int nand_spi_get_feature(struct nand_base *nand, u8 addr,
1730-+ u8 *param,
1731-+ int count)
1732-+{
1733-+ struct nand_spi *spi = base_to_spi(nand);
1734-+ struct nand_base *parent = spi->parent;
1735-+
1736-+ nand_spi_set_op_mode(nand, SNFI_MAC_MODE);
1737-+
1738-+ return parent->get_feature(nand, addr, param, count);
1739-+}
1740-+
1741-+static int nand_spi_addressing(struct nand_base *nand, int *row,
1742-+ int *col)
1743-+{
1744-+ struct nand_device *dev = nand->dev;
1745-+ int plane, block, block_pages;
1746-+ int ret;
1747-+
1748-+ ret = nand_spi_die_select(nand, row);
1749-+ if (ret)
1750-+ return ret;
1751-+
1752-+ block_pages = nand_block_pages(dev);
1753-+ block = div_down(*row, block_pages);
1754-+
1755-+ plane = block % dev->plane_num;
1756-+ *col |= (plane << dev->addressing->plane_bit_start);
1757-+
1758-+ return 0;
1759-+}
1760-+
1761-+static int nand_spi_read_page(struct nand_base *nand, int row)
1762-+{
1763-+ struct nand_spi *spi = base_to_spi(nand);
1764-+ struct nand_base *parent = spi->parent;
1765-+
1766-+ if (spi->op_mode == SNFI_AUTO_MODE)
1767-+ nand_spi_set_op_mode(nand, SNFI_AUTO_MODE);
1768-+ else
1769-+ nand_spi_set_op_mode(nand, SNFI_MAC_MODE);
1770-+
1771-+ parent->read_page(nand, row);
1772-+
1773-+ return nand_spi_wait_ready(nand, READY_TIMEOUT);
1774-+}
1775-+
1776-+static int nand_spi_read_data(struct nand_base *nand, int row, int col,
1777-+ int sectors, u8 *data, u8 *oob)
1778-+{
1779-+ struct device_spi *dev = device_to_spi(nand->dev);
1780-+ struct nand_spi *spi = base_to_spi(nand);
1781-+ struct nand_base *parent = spi->parent;
1782-+ int ret;
1783-+
1784-+ if ((spi->rx_mode == SNFI_RX_114 || spi->rx_mode == SNFI_RX_144) &&
1785-+ dev->feature.config.need_qe)
1786-+ nand_spi_set_config(nand, dev->feature.config.addr,
1787-+ BIT(0), true);
1788-+
1789-+ nand->dev->col_cycle = spi_replace_rx_col_cycle(spi->rx_mode);
1790-+
1791-+ nand_spi_set_op_mode(nand, SNFI_CUSTOM_MODE);
1792-+
1793-+ ret = parent->read_data(nand, row, col, sectors, data, oob);
1794-+ if (ret)
1795-+ return -ENANDREAD;
1796-+
1797-+ if (spi->ondie_ecc) {
1798-+ ret = nand_spi_read_status(nand);
1799-+ ret &= GENMASK(dev->feature.status.ecc_end_bit,
1800-+ dev->feature.status.ecc_start_bit);
1801-+ ret >>= dev->feature.status.ecc_start_bit;
1802-+ if (ret > nand->dev->endurance->ecc_req)
1803-+ return -ENANDREAD;
1804-+ else if (ret > nand->dev->endurance->max_bitflips)
1805-+ return -ENANDFLIPS;
1806-+ }
1807-+
1808-+ return 0;
1809-+}
1810-+
1811-+static int nand_spi_write_enable(struct nand_base *nand)
1812-+{
1813-+ struct device_spi *dev = device_to_spi(nand->dev);
1814-+ struct nfi *nfi = nand->nfi;
1815-+ int status;
1816-+
1817-+ nand_spi_set_op_mode(nand, SNFI_MAC_MODE);
1818-+
1819-+ nfi->reset(nfi);
1820-+ nfi->send_cmd(nfi, dev->extend_cmds->write_enable);
1821-+
1822-+ nfi->trigger(nfi);
1823-+
1824-+ status = nand_spi_read_status(nand);
1825-+ status &= nand->dev->status->write_protect;
1826-+
1827-+ return !status;
1828-+}
1829-+
1830-+static int nand_spi_program_data(struct nand_base *nand, int row,
1831-+ int col,
1832-+ u8 *data, u8 *oob)
1833-+{
1834-+ struct device_spi *dev = device_to_spi(nand->dev);
1835-+ struct nand_spi *spi = base_to_spi(nand);
1836-+
1837-+ if (spi->tx_mode == SNFI_TX_114 && dev->feature.config.need_qe)
1838-+ nand_spi_set_config(nand, dev->feature.config.addr,
1839-+ BIT(0), true);
1840-+
1841-+ nand_spi_set_op_mode(nand, SNFI_CUSTOM_MODE);
1842-+
1843-+ nand->dev->col_cycle = spi_replace_tx_col_cycle(spi->tx_mode);
1844-+
1845-+ return spi->parent->program_data(nand, row, col, data, oob);
1846-+}
1847-+
1848-+static int nand_spi_program_page(struct nand_base *nand, int row)
1849-+{
1850-+ struct nand_spi *spi = base_to_spi(nand);
1851-+ struct nand_device *dev = nand->dev;
1852-+ struct nfi *nfi = nand->nfi;
1853-+
1854-+ if (spi->op_mode == SNFI_AUTO_MODE)
1855-+ nand_spi_set_op_mode(nand, SNFI_AUTO_MODE);
1856-+ else
1857-+ nand_spi_set_op_mode(nand, SNFI_MAC_MODE);
1858-+
1859-+ nfi->reset(nfi);
1860-+ nfi->send_cmd(nfi, dev->cmds->program_2nd);
1861-+ nfi->send_addr(nfi, 0, row, dev->col_cycle, dev->row_cycle);
1862-+ nfi->trigger(nfi);
1863-+
1864-+ return nand_spi_wait_ready(nand, READY_TIMEOUT);
1865-+}
1866-+
1867-+static int nand_spi_erase_block(struct nand_base *nand, int row)
1868-+{
1869-+ struct nand_spi *spi = base_to_spi(nand);
1870-+ struct nand_base *parent = spi->parent;
1871-+
1872-+ nand_spi_set_op_mode(nand, SNFI_MAC_MODE);
1873-+
1874-+ parent->erase_block(nand, row);
1875-+
1876-+ return nand_spi_wait_ready(nand, READY_TIMEOUT);
1877-+}
1878-+
1879-+static int nand_chip_spi_ctrl(struct nand_chip *chip, int cmd,
1880-+ void *args)
1881-+{
1882-+ struct nand_base *nand = chip->nand;
1883-+ struct device_spi *dev = device_to_spi(nand->dev);
1884-+ struct nand_spi *spi = base_to_spi(nand);
1885-+ struct nfi *nfi = nand->nfi;
1886-+ int ret = 0, value = *(int *)args;
1887-+
1888-+ switch (cmd) {
1889-+ case CHIP_CTRL_ONDIE_ECC:
1890-+ spi->ondie_ecc = (bool)value;
1891-+ ret = nand_spi_set_config(nand, dev->feature.config.addr,
1892-+ BIT(dev->feature.config.ecc_en_bit),
1893-+ spi->ondie_ecc);
1894-+ break;
1895-+
1896-+ case SNFI_CTRL_TX_MODE:
1897-+ if (value < 0 || value > SNFI_TX_114)
1898-+ return -EOPNOTSUPP;
1899-+
1900-+ if (dev->tx_mode_mask & BIT(value)) {
1901-+ spi->tx_mode = value;
1902-+ nand->dev->cmds->random_out_1st = spi_replace_tx_cmds(
1903-+ spi->tx_mode);
1904-+ ret = nfi->nfi_ctrl(nfi, cmd, args);
1905-+ }
1906-+
1907-+ break;
1908-+
1909-+ case SNFI_CTRL_RX_MODE:
1910-+ if (value < 0 || value > SNFI_RX_144)
1911-+ return -EOPNOTSUPP;
1912-+
1913-+ if (dev->rx_mode_mask & BIT(value)) {
1914-+ spi->rx_mode = value;
1915-+ nand->dev->cmds->program_1st = spi_replace_rx_cmds(
1916-+ spi->rx_mode);
1917-+ ret = nfi->nfi_ctrl(nfi, cmd, args);
1918-+ }
1919-+
1920-+ break;
1921-+
1922-+ case CHIP_CTRL_OPS_CACHE:
1923-+ case CHIP_CTRL_OPS_MULTI:
1924-+ case CHIP_CTRL_PSLC_MODE:
1925-+ case CHIP_CTRL_DDR_MODE:
1926-+ case CHIP_CTRL_DRIVE_STRENGTH:
1927-+ case CHIP_CTRL_TIMING_MODE:
1928-+ ret = -EOPNOTSUPP;
1929-+ break;
1930-+
1931-+ default:
1932-+ ret = nfi->nfi_ctrl(nfi, cmd, args);
1933-+ break;
1934-+ }
1935-+
1936-+ return ret;
1937-+}
1938-+
1939-+int nand_chip_spi_resume(struct nand_chip *chip)
1940-+{
1941-+ struct nand_base *nand = chip->nand;
1942-+ struct nand_spi *spi = base_to_spi(nand);
1943-+ struct device_spi *dev = device_to_spi(nand->dev);
1944-+ struct nfi *nfi = nand->nfi;
1945-+ struct nfi_format format;
1946-+ u8 mask;
1947-+
1948-+ nand->reset(nand);
1949-+
1950-+ mask = GENMASK(dev->feature.protect.bp_end_bit,
1951-+ dev->feature.protect.bp_start_bit);
1952-+ nand_spi_set_config(nand, dev->feature.config.addr, mask, false);
1953-+ mask = BIT(dev->feature.config.ecc_en_bit);
1954-+ nand_spi_set_config(nand, dev->feature.config.addr, mask,
1955-+ spi->ondie_ecc);
1956-+
1957-+ format.page_size = nand->dev->page_size;
1958-+ format.spare_size = nand->dev->spare_size;
1959-+ format.ecc_req = nand->dev->endurance->ecc_req;
1960-+
1961-+ return nfi->set_format(nfi, &format);
1962-+}
1963-+
1964-+static int nand_spi_set_format(struct nand_base *nand)
1965-+{
1966-+ struct nfi_format format = {
1967-+ nand->dev->page_size,
1968-+ nand->dev->spare_size,
1969-+ nand->dev->endurance->ecc_req
1970-+ };
1971-+
1972-+ return nand->nfi->set_format(nand->nfi, &format);
1973-+}
1974-+
1975-+struct nand_base *nand_device_init(struct nand_chip *chip)
1976-+{
1977-+ struct nand_base *nand;
1978-+ struct nand_spi *spi;
1979-+ struct device_spi *dev;
1980-+ int ret;
1981-+ u8 mask;
1982-+
1983-+ spi = mem_alloc(1, sizeof(struct nand_spi));
1984-+ if (!spi) {
1985-+ pr_info("alloc nand_spi fail\n");
1986-+ return NULL;
1987-+ }
1988-+
1989-+ spi->ondie_ecc = false;
1990-+ spi->op_mode = SNFI_CUSTOM_MODE;
1991-+ spi->rx_mode = SNFI_RX_114;
1992-+ spi->tx_mode = SNFI_TX_114;
1993-+
1994-+ spi->parent = chip->nand;
1995-+ nand = &spi->base;
1996-+ nand->dev = spi->parent->dev;
1997-+ nand->nfi = spi->parent->nfi;
1998-+
1999-+ nand->select_device = nand_spi_select_device;
2000-+ nand->reset = nand_spi_reset;
2001-+ nand->read_id = nand_spi_read_id;
2002-+ nand->read_param_page = nand_spi_read_param_page;
2003-+ nand->set_feature = nand_spi_set_feature;
2004-+ nand->get_feature = nand_spi_get_feature;
2005-+ nand->read_status = nand_spi_read_status;
2006-+ nand->addressing = nand_spi_addressing;
2007-+ nand->read_page = nand_spi_read_page;
2008-+ nand->read_data = nand_spi_read_data;
2009-+ nand->write_enable = nand_spi_write_enable;
2010-+ nand->program_data = nand_spi_program_data;
2011-+ nand->program_page = nand_spi_program_page;
2012-+ nand->erase_block = nand_spi_erase_block;
2013-+
2014-+ chip->chip_ctrl = nand_chip_spi_ctrl;
2015-+ chip->nand_type = NAND_SPI;
2016-+ chip->resume = nand_chip_spi_resume;
2017-+
2018-+ ret = nand_detect_device(nand);
2019-+ if (ret)
2020-+ goto err;
2021-+
2022-+ nand->select_device(nand, 0);
2023-+
2024-+ ret = nand_spi_set_format(nand);
2025-+ if (ret)
2026-+ goto err;
2027-+
2028-+ dev = (struct device_spi *)nand->dev;
2029-+
2030-+ nand->dev->cmds->random_out_1st =
2031-+ spi_replace_rx_cmds(spi->rx_mode);
2032-+ nand->dev->cmds->program_1st =
2033-+ spi_replace_tx_cmds(spi->tx_mode);
2034-+
2035-+ mask = GENMASK(dev->feature.protect.bp_end_bit,
2036-+ dev->feature.protect.bp_start_bit);
2037-+ ret = nand_spi_set_config(nand, dev->feature.protect.addr, mask, false);
2038-+ if (ret)
2039-+ goto err;
2040-+
2041-+ mask = BIT(dev->feature.config.ecc_en_bit);
2042-+ ret = nand_spi_set_config(nand, dev->feature.config.addr, mask,
2043-+ spi->ondie_ecc);
2044-+ if (ret)
2045-+ goto err;
2046-+
2047-+ return nand;
2048-+
2049-+err:
2050-+ mem_free(spi);
2051-+ return NULL;
2052-+}
2053-+
2054-+void nand_exit(struct nand_base *nand)
2055-+{
2056-+ struct nand_spi *spi = base_to_spi(nand);
2057-+
2058-+ nand_base_exit(spi->parent);
2059-+ mem_free(spi);
2060-+}
2061-diff --git a/drivers/mtd/nandx/core/nand/nand_spi.h b/drivers/mtd/nandx/core/nand/nand_spi.h
2062-new file mode 100644
2063-index 0000000000..e55e4de6f7
2064---- /dev/null
2065-+++ b/drivers/mtd/nandx/core/nand/nand_spi.h
2066-@@ -0,0 +1,35 @@
2067-+/*
2068-+ * Copyright (C) 2017 MediaTek Inc.
2069-+ * Licensed under either
2070-+ * BSD Licence, (see NOTICE for more details)
2071-+ * GNU General Public License, version 2.0, (see NOTICE for more details)
2072-+ */
2073-+
2074-+#ifndef __NAND_SPI_H__
2075-+#define __NAND_SPI_H__
2076-+
2077-+/*
2078-+ * spi nand handler
2079-+ * @base: spi nand base functions
2080-+ * @parent: common parent nand base functions
2081-+ * @tx_mode: spi bus width of transfer to device
2082-+ * @rx_mode: spi bus width of transfer from device
2083-+ * @op_mode: spi nand controller (NFI) operation mode
2084-+ * @ondie_ecc: spi nand on-die ecc flag
2085-+ */
2086-+
2087-+struct nand_spi {
2088-+ struct nand_base base;
2089-+ struct nand_base *parent;
2090-+ u8 tx_mode;
2091-+ u8 rx_mode;
2092-+ u8 op_mode;
2093-+ bool ondie_ecc;
2094-+};
2095-+
2096-+static inline struct nand_spi *base_to_spi(struct nand_base *base)
2097-+{
2098-+ return container_of(base, struct nand_spi, base);
2099-+}
2100-+
2101-+#endif /* __NAND_SPI_H__ */
2102-diff --git a/drivers/mtd/nandx/core/nand_base.c b/drivers/mtd/nandx/core/nand_base.c
2103-new file mode 100644
2104-index 0000000000..65998e5460
2105---- /dev/null
2106-+++ b/drivers/mtd/nandx/core/nand_base.c
2107-@@ -0,0 +1,304 @@
2108-+/*
2109-+ * Copyright (C) 2017 MediaTek Inc.
2110-+ * Licensed under either
2111-+ * BSD Licence, (see NOTICE for more details)
2112-+ * GNU General Public License, version 2.0, (see NOTICE for more details)
2113-+ */
2114-+
2115-+#include "nandx_util.h"
2116-+#include "nandx_core.h"
2117-+#include "nand_chip.h"
2118-+#include "nand_device.h"
2119-+#include "nfi.h"
2120-+#include "nand_base.h"
2121-+
2122-+static int nand_base_select_device(struct nand_base *nand, int cs)
2123-+{
2124-+ struct nfi *nfi = nand->nfi;
2125-+
2126-+ nfi->reset(nfi);
2127-+
2128-+ return nfi->select_chip(nfi, cs);
2129-+}
2130-+
2131-+static int nand_base_reset(struct nand_base *nand)
2132-+{
2133-+ struct nfi *nfi = nand->nfi;
2134-+ struct nand_device *dev = nand->dev;
2135-+
2136-+ nfi->reset(nfi);
2137-+ nfi->send_cmd(nfi, dev->cmds->reset);
2138-+ nfi->trigger(nfi);
2139-+
2140-+ return nfi->wait_ready(nfi, NAND_WAIT_POLLING, dev->array_timing->tRST);
2141-+}
2142-+
2143-+static int nand_base_read_id(struct nand_base *nand, u8 *id, int count)
2144-+{
2145-+ struct nfi *nfi = nand->nfi;
2146-+ struct nand_device *dev = nand->dev;
2147-+
2148-+ nfi->reset(nfi);
2149-+ nfi->send_cmd(nfi, dev->cmds->read_id);
2150-+ nfi->wait_ready(nfi, NAND_WAIT_POLLING, dev->array_timing->tWHR);
2151-+ nfi->send_addr(nfi, 0, 0, 1, 0);
2152-+
2153-+ return nfi->read_bytes(nfi, id, count);
2154-+}
2155-+
2156-+static int nand_base_read_param_page(struct nand_base *nand, u8 *data,
2157-+ int count)
2158-+{
2159-+ struct nfi *nfi = nand->nfi;
2160-+ struct nand_device *dev = nand->dev;
2161-+
2162-+ nfi->reset(nfi);
2163-+ nfi->send_cmd(nfi, dev->cmds->read_param_page);
2164-+ nfi->send_addr(nfi, 0, 0, 1, 0);
2165-+
2166-+ nfi->wait_ready(nfi, NAND_WAIT_POLLING, dev->array_timing->tR);
2167-+
2168-+ return nfi->read_bytes(nfi, data, count);
2169-+}
2170-+
2171-+static int nand_base_set_feature(struct nand_base *nand, u8 addr,
2172-+ u8 *param,
2173-+ int count)
2174-+{
2175-+ struct nfi *nfi = nand->nfi;
2176-+ struct nand_device *dev = nand->dev;
2177-+
2178-+ nfi->reset(nfi);
2179-+ nfi->send_cmd(nfi, dev->cmds->set_feature);
2180-+ nfi->send_addr(nfi, addr, 0, 1, 0);
2181-+
2182-+ nfi->write_bytes(nfi, param, count);
2183-+
2184-+ return nfi->wait_ready(nfi, NAND_WAIT_POLLING,
2185-+ dev->array_timing->tFEAT);
2186-+}
2187-+
2188-+static int nand_base_get_feature(struct nand_base *nand, u8 addr,
2189-+ u8 *param,
2190-+ int count)
2191-+{
2192-+ struct nfi *nfi = nand->nfi;
2193-+ struct nand_device *dev = nand->dev;
2194-+
2195-+ nfi->reset(nfi);
2196-+ nfi->send_cmd(nfi, dev->cmds->get_feature);
2197-+ nfi->send_addr(nfi, addr, 0, 1, 0);
2198-+ nfi->wait_ready(nfi, NAND_WAIT_POLLING, dev->array_timing->tFEAT);
2199-+
2200-+ return nfi->read_bytes(nfi, param, count);
2201-+}
2202-+
2203-+static int nand_base_read_status(struct nand_base *nand)
2204-+{
2205-+ struct nfi *nfi = nand->nfi;
2206-+ struct nand_device *dev = nand->dev;
2207-+ u8 status = 0;
2208-+
2209-+ nfi->reset(nfi);
2210-+ nfi->send_cmd(nfi, dev->cmds->read_status);
2211-+ nfi->wait_ready(nfi, NAND_WAIT_POLLING, dev->array_timing->tWHR);
2212-+ nfi->read_bytes(nfi, &status, 1);
2213-+
2214-+ return status;
2215-+}
2216-+
2217-+static int nand_base_addressing(struct nand_base *nand, int *row,
2218-+ int *col)
2219-+{
2220-+ struct nand_device *dev = nand->dev;
2221-+ int lun, plane, block, page, cs = 0;
2222-+ int block_pages, target_blocks, wl = 0;
2223-+ int icol = *col;
2224-+
2225-+ if (dev->target_num > 1) {
2226-+ block_pages = nand_block_pages(dev);
2227-+ target_blocks = nand_target_blocks(dev);
2228-+ cs = div_down(*row, block_pages * target_blocks);
2229-+ *row -= cs * block_pages * target_blocks;
2230-+ }
2231-+
2232-+ nand->select_device(nand, cs);
2233-+
2234-+ block_pages = nand_block_pages(dev);
2235-+ block = div_down(*row, block_pages);
2236-+ page = *row - block * block_pages;
2237-+ plane = reminder(block, dev->plane_num);
2238-+ lun = div_down(block, nand_lun_blocks(dev));
2239-+
2240-+ wl |= (page << dev->addressing->row_bit_start);
2241-+ wl |= (block << dev->addressing->block_bit_start);
2242-+ wl |= (plane << dev->addressing->plane_bit_start);
2243-+ wl |= (lun << dev->addressing->lun_bit_start);
2244-+
2245-+ *row = wl;
2246-+ *col = icol;
2247-+
2248-+ return 0;
2249-+}
2250-+
2251-+static int nand_base_read_page(struct nand_base *nand, int row)
2252-+{
2253-+ struct nfi *nfi = nand->nfi;
2254-+ struct nand_device *dev = nand->dev;
2255-+
2256-+ nfi->reset(nfi);
2257-+ nfi->send_cmd(nfi, dev->cmds->read_1st);
2258-+ nfi->send_addr(nfi, 0, row, dev->col_cycle, dev->row_cycle);
2259-+ nfi->send_cmd(nfi, dev->cmds->read_2nd);
2260-+ nfi->trigger(nfi);
2261-+
2262-+ return nfi->wait_ready(nfi, NAND_WAIT_POLLING, dev->array_timing->tR);
2263-+}
2264-+
2265-+static int nand_base_read_data(struct nand_base *nand, int row, int col,
2266-+ int sectors, u8 *data, u8 *oob)
2267-+{
2268-+ struct nfi *nfi = nand->nfi;
2269-+ struct nand_device *dev = nand->dev;
2270-+
2271-+ nfi->reset(nfi);
2272-+ nfi->send_cmd(nfi, dev->cmds->random_out_1st);
2273-+ nfi->send_addr(nfi, col, row, dev->col_cycle, dev->row_cycle);
2274-+ nfi->send_cmd(nfi, dev->cmds->random_out_2nd);
2275-+ nfi->wait_ready(nfi, NAND_WAIT_POLLING, dev->array_timing->tRCBSY);
2276-+
2277-+ return nfi->read_sectors(nfi, data, oob, sectors);
2278-+}
2279-+
2280-+static int nand_base_write_enable(struct nand_base *nand)
2281-+{
2282-+ struct nand_device *dev = nand->dev;
2283-+ int status;
2284-+
2285-+ status = nand_base_read_status(nand);
2286-+ if (status & dev->status->write_protect)
2287-+ return 0;
2288-+
2289-+ return -ENANDWP;
2290-+}
2291-+
2292-+static int nand_base_program_data(struct nand_base *nand, int row,
2293-+ int col,
2294-+ u8 *data, u8 *oob)
2295-+{
2296-+ struct nfi *nfi = nand->nfi;
2297-+ struct nand_device *dev = nand->dev;
2298-+
2299-+ nfi->reset(nfi);
2300-+ nfi->send_cmd(nfi, dev->cmds->program_1st);
2301-+ nfi->send_addr(nfi, 0, row, dev->col_cycle, dev->row_cycle);
2302-+
2303-+ return nfi->write_page(nfi, data, oob);
2304-+}
2305-+
2306-+static int nand_base_program_page(struct nand_base *nand, int row)
2307-+{
2308-+ struct nfi *nfi = nand->nfi;
2309-+ struct nand_device *dev = nand->dev;
2310-+
2311-+ nfi->reset(nfi);
2312-+ nfi->send_cmd(nfi, dev->cmds->program_2nd);
2313-+ nfi->trigger(nfi);
2314-+
2315-+ return nfi->wait_ready(nfi, NAND_WAIT_POLLING,
2316-+ dev->array_timing->tPROG);
2317-+}
2318-+
2319-+static int nand_base_erase_block(struct nand_base *nand, int row)
2320-+{
2321-+ struct nfi *nfi = nand->nfi;
2322-+ struct nand_device *dev = nand->dev;
2323-+
2324-+ nfi->reset(nfi);
2325-+ nfi->send_cmd(nfi, dev->cmds->erase_1st);
2326-+ nfi->send_addr(nfi, 0, row, 0, dev->row_cycle);
2327-+ nfi->send_cmd(nfi, dev->cmds->erase_2nd);
2328-+ nfi->trigger(nfi);
2329-+
2330-+ return nfi->wait_ready(nfi, NAND_WAIT_POLLING,
2331-+ dev->array_timing->tBERS);
2332-+}
2333-+
2334-+static int nand_base_read_cache(struct nand_base *nand, int row)
2335-+{
2336-+ struct nfi *nfi = nand->nfi;
2337-+ struct nand_device *dev = nand->dev;
2338-+
2339-+ nfi->reset(nfi);
2340-+ nfi->send_cmd(nfi, dev->cmds->read_1st);
2341-+ nfi->send_addr(nfi, 0, row, dev->col_cycle, dev->row_cycle);
2342-+ nfi->send_cmd(nfi, dev->cmds->read_cache);
2343-+ nfi->trigger(nfi);
2344-+
2345-+ return nfi->wait_ready(nfi, NAND_WAIT_POLLING,
2346-+ dev->array_timing->tRCBSY);
2347-+}
2348-+
2349-+static int nand_base_read_last(struct nand_base *nand)
2350-+{
2351-+ struct nfi *nfi = nand->nfi;
2352-+ struct nand_device *dev = nand->dev;
2353-+
2354-+ nfi->reset(nfi);
2355-+ nfi->send_cmd(nfi, dev->cmds->read_cache_last);
2356-+ nfi->trigger(nfi);
2357-+
2358-+ return nfi->wait_ready(nfi, NAND_WAIT_POLLING,
2359-+ dev->array_timing->tRCBSY);
2360-+}
2361-+
2362-+static int nand_base_program_cache(struct nand_base *nand)
2363-+{
2364-+ struct nfi *nfi = nand->nfi;
2365-+ struct nand_device *dev = nand->dev;
2366-+
2367-+ nfi->reset(nfi);
2368-+ nfi->send_cmd(nfi, dev->cmds->program_cache);
2369-+ nfi->trigger(nfi);
2370-+
2371-+ return nfi->wait_ready(nfi, NAND_WAIT_POLLING,
2372-+ dev->array_timing->tPCBSY);
2373-+}
2374-+
2375-+struct nand_base *nand_base_init(struct nand_device *dev,
2376-+ struct nfi *nfi)
2377-+{
2378-+ struct nand_base *nand;
2379-+
2380-+ nand = mem_alloc(1, sizeof(struct nand_base));
2381-+ if (!nand)
2382-+ return NULL;
2383-+
2384-+ nand->dev = dev;
2385-+ nand->nfi = nfi;
2386-+ nand->select_device = nand_base_select_device;
2387-+ nand->reset = nand_base_reset;
2388-+ nand->read_id = nand_base_read_id;
2389-+ nand->read_param_page = nand_base_read_param_page;
2390-+ nand->set_feature = nand_base_set_feature;
2391-+ nand->get_feature = nand_base_get_feature;
2392-+ nand->read_status = nand_base_read_status;
2393-+ nand->addressing = nand_base_addressing;
2394-+ nand->read_page = nand_base_read_page;
2395-+ nand->read_data = nand_base_read_data;
2396-+ nand->read_cache = nand_base_read_cache;
2397-+ nand->read_last = nand_base_read_last;
2398-+ nand->write_enable = nand_base_write_enable;
2399-+ nand->program_data = nand_base_program_data;
2400-+ nand->program_page = nand_base_program_page;
2401-+ nand->program_cache = nand_base_program_cache;
2402-+ nand->erase_block = nand_base_erase_block;
2403-+
2404-+ return nand;
2405-+}
2406-+
2407-+void nand_base_exit(struct nand_base *base)
2408-+{
2409-+ nfi_exit(base->nfi);
2410-+ mem_free(base);
2411-+}
2412-diff --git a/drivers/mtd/nandx/core/nand_base.h b/drivers/mtd/nandx/core/nand_base.h
2413-new file mode 100644
2414-index 0000000000..13217978e5
2415---- /dev/null
2416-+++ b/drivers/mtd/nandx/core/nand_base.h
2417-@@ -0,0 +1,71 @@
2418-+/*
2419-+ * Copyright (C) 2017 MediaTek Inc.
2420-+ * Licensed under either
2421-+ * BSD Licence, (see NOTICE for more details)
2422-+ * GNU General Public License, version 2.0, (see NOTICE for more details)
2423-+ */
2424-+
2425-+#ifndef __NAND_BASE_H__
2426-+#define __NAND_BASE_H__
2427-+
2428-+/*
2429-+ * nand base functions
2430-+ * @dev: nand device infomations
2431-+ * @nfi: nand host controller
2432-+ * @select_device: select one nand device of multi nand on chip
2433-+ * @reset: reset current nand device
2434-+ * @read_id: read current nand id
2435-+ * @read_param_page: read current nand parameters page
2436-+ * @set_feature: configurate the nand device feature
2437-+ * @get_feature: get the nand device feature
2438-+ * @read_status: read nand device status
2439-+ * @addressing: addressing the address to nand device physical address
2440-+ * @read_page: read page data to device cache register
2441-+ * @read_data: read data from device cache register by bus protocol
2442-+ * @read_cache: nand cache read operation for data output
2443-+ * @read_last: nand cache read operation for last page output
2444-+ * @write_enable: enable program/erase for nand, especially spi nand
2445-+ * @program_data: program data to nand device cache register
2446-+ * @program_page: program page data from nand device cache register to array
2447-+ * @program_cache: nand cache program operation for data input
2448-+ * @erase_block: erase nand block operation
2449-+ */
2450-+struct nand_base {
2451-+ struct nand_device *dev;
2452-+ struct nfi *nfi;
2453-+ int (*select_device)(struct nand_base *nand, int cs);
2454-+ int (*reset)(struct nand_base *nand);
2455-+ int (*read_id)(struct nand_base *nand, u8 *id, int count);
2456-+ int (*read_param_page)(struct nand_base *nand, u8 *data, int count);
2457-+ int (*set_feature)(struct nand_base *nand, u8 addr, u8 *param,
2458-+ int count);
2459-+ int (*get_feature)(struct nand_base *nand, u8 addr, u8 *param,
2460-+ int count);
2461-+ int (*read_status)(struct nand_base *nand);
2462-+ int (*addressing)(struct nand_base *nand, int *row, int *col);
2463-+
2464-+ int (*read_page)(struct nand_base *nand, int row);
2465-+ int (*read_data)(struct nand_base *nand, int row, int col, int sectors,
2466-+ u8 *data, u8 *oob);
2467-+ int (*read_cache)(struct nand_base *nand, int row);
2468-+ int (*read_last)(struct nand_base *nand);
2469-+
2470-+ int (*write_enable)(struct nand_base *nand);
2471-+ int (*program_data)(struct nand_base *nand, int row, int col, u8 *data,
2472-+ u8 *oob);
2473-+ int (*program_page)(struct nand_base *nand, int row);
2474-+ int (*program_cache)(struct nand_base *nand);
2475-+
2476-+ int (*erase_block)(struct nand_base *nand, int row);
2477-+};
2478-+
2479-+struct nand_base *nand_base_init(struct nand_device *device,
2480-+ struct nfi *nfi);
2481-+void nand_base_exit(struct nand_base *base);
2482-+
2483-+struct nand_base *nand_device_init(struct nand_chip *nand);
2484-+void nand_exit(struct nand_base *nand);
2485-+
2486-+int nand_detect_device(struct nand_base *nand);
2487-+
2488-+#endif /* __NAND_BASE_H__ */
2489-diff --git a/drivers/mtd/nandx/core/nand_chip.c b/drivers/mtd/nandx/core/nand_chip.c
2490-new file mode 100644
2491-index 0000000000..02adc6f52e
2492---- /dev/null
2493-+++ b/drivers/mtd/nandx/core/nand_chip.c
2494-@@ -0,0 +1,272 @@
2495-+/*
2496-+ * Copyright (C) 2017 MediaTek Inc.
2497-+ * Licensed under either
2498-+ * BSD Licence, (see NOTICE for more details)
2499-+ * GNU General Public License, version 2.0, (see NOTICE for more details)
2500-+ */
2501-+
2502-+#include "nandx_util.h"
2503-+#include "nandx_core.h"
2504-+#include "nand_chip.h"
2505-+#include "nand_device.h"
2506-+#include "nfi.h"
2507-+#include "nand_base.h"
2508-+
2509-+static int nand_chip_read_page(struct nand_chip *chip,
2510-+ struct nand_ops *ops,
2511-+ int count)
2512-+{
2513-+ struct nand_base *nand = chip->nand;
2514-+ struct nand_device *dev = nand->dev;
2515-+ int i, ret = 0;
2516-+ int row, col, sectors;
2517-+ u8 *data, *oob;
2518-+
2519-+ for (i = 0; i < count; i++) {
2520-+ row = ops[i].row;
2521-+ col = ops[i].col;
2522-+
2523-+ nand->addressing(nand, &row, &col);
2524-+ ops[i].status = nand->read_page(nand, row);
2525-+ if (ops[i].status < 0) {
2526-+ ret = ops[i].status;
2527-+ continue;
2528-+ }
2529-+
2530-+ data = ops[i].data;
2531-+ oob = ops[i].oob;
2532-+ sectors = ops[i].len / chip->sector_size;
2533-+ ops[i].status = nand->read_data(nand, row, col,
2534-+ sectors, data, oob);
2535-+ if (ops[i].status > 0)
2536-+ ops[i].status = ops[i].status >=
2537-+ dev->endurance->max_bitflips ?
2538-+ -ENANDFLIPS : 0;
2539-+
2540-+ ret = min_t(int, ret, ops[i].status);
2541-+ }
2542-+
2543-+ return ret;
2544-+}
2545-+
2546-+static int nand_chip_write_page(struct nand_chip *chip,
2547-+ struct nand_ops *ops,
2548-+ int count)
2549-+{
2550-+ struct nand_base *nand = chip->nand;
2551-+ struct nand_device *dev = nand->dev;
2552-+ int i, ret = 0;
2553-+ int row, col;
2554-+ u8 *data, *oob;
2555-+
2556-+ for (i = 0; i < count; i++) {
2557-+ row = ops[i].row;
2558-+ col = ops[i].col;
2559-+
2560-+ nand->addressing(nand, &row, &col);
2561-+
2562-+ ops[i].status = nand->write_enable(nand);
2563-+ if (ops[i].status) {
2564-+ pr_debug("Write Protect at %x!\n", row);
2565-+ ops[i].status = -ENANDWP;
2566-+ return -ENANDWP;
2567-+ }
2568-+
2569-+ data = ops[i].data;
2570-+ oob = ops[i].oob;
2571-+ ops[i].status = nand->program_data(nand, row, col, data, oob);
2572-+ if (ops[i].status < 0) {
2573-+ ret = ops[i].status;
2574-+ continue;
2575-+ }
2576-+
2577-+ ops[i].status = nand->program_page(nand, row);
2578-+ if (ops[i].status < 0) {
2579-+ ret = ops[i].status;
2580-+ continue;
2581-+ }
2582-+
2583-+ ops[i].status = nand->read_status(nand);
2584-+ if (ops[i].status & dev->status->program_fail)
2585-+ ops[i].status = -ENANDWRITE;
2586-+
2587-+ ret = min_t(int, ret, ops[i].status);
2588-+ }
2589-+
2590-+ return ret;
2591-+}
2592-+
2593-+static int nand_chip_erase_block(struct nand_chip *chip,
2594-+ struct nand_ops *ops,
2595-+ int count)
2596-+{
2597-+ struct nand_base *nand = chip->nand;
2598-+ struct nand_device *dev = nand->dev;
2599-+ int i, ret = 0;
2600-+ int row, col;
2601-+
2602-+ for (i = 0; i < count; i++) {
2603-+ row = ops[i].row;
2604-+ col = ops[i].col;
2605-+
2606-+ nand->addressing(nand, &row, &col);
2607-+
2608-+ ops[i].status = nand->write_enable(nand);
2609-+ if (ops[i].status) {
2610-+ pr_debug("Write Protect at %x!\n", row);
2611-+ ops[i].status = -ENANDWP;
2612-+ return -ENANDWP;
2613-+ }
2614-+
2615-+ ops[i].status = nand->erase_block(nand, row);
2616-+ if (ops[i].status < 0) {
2617-+ ret = ops[i].status;
2618-+ continue;
2619-+ }
2620-+
2621-+ ops[i].status = nand->read_status(nand);
2622-+ if (ops[i].status & dev->status->erase_fail)
2623-+ ops[i].status = -ENANDERASE;
2624-+
2625-+ ret = min_t(int, ret, ops[i].status);
2626-+ }
2627-+
2628-+ return ret;
2629-+}
2630-+
2631-+/* read first bad mark on spare */
2632-+static int nand_chip_is_bad_block(struct nand_chip *chip,
2633-+ struct nand_ops *ops,
2634-+ int count)
2635-+{
2636-+ int i, ret, value;
2637-+ int status = 0;
2638-+ u8 *data, *tmp_buf;
2639-+
2640-+ tmp_buf = mem_alloc(1, chip->page_size);
2641-+ if (!tmp_buf)
2642-+ return -ENOMEM;
2643-+
2644-+ memset(tmp_buf, 0x00, chip->page_size);
2645-+
2646-+ /* Disable ECC */
2647-+ value = 0;
2648-+ ret = chip->chip_ctrl(chip, NFI_CTRL_ECC, &value);
2649-+ if (ret)
2650-+ goto out;
2651-+
2652-+ ret = chip->read_page(chip, ops, count);
2653-+ if (ret)
2654-+ goto out;
2655-+
2656-+ for (i = 0; i < count; i++) {
2657-+ data = ops[i].data;
2658-+
2659-+ /* temp solution for mt7622, because of no bad mark swap */
2660-+ if (!memcmp(data, tmp_buf, chip->page_size)) {
2661-+ ops[i].status = -ENANDBAD;
2662-+ status = -ENANDBAD;
2663-+
2664-+ } else {
2665-+ ops[i].status = 0;
2666-+ }
2667-+ }
2668-+
2669-+ /* Enable ECC */
2670-+ value = 1;
2671-+ ret = chip->chip_ctrl(chip, NFI_CTRL_ECC, &value);
2672-+ if (ret)
2673-+ goto out;
2674-+
2675-+ mem_free(tmp_buf);
2676-+ return status;
2677-+
2678-+out:
2679-+ mem_free(tmp_buf);
2680-+ return ret;
2681-+}
2682-+
2683-+static int nand_chip_ctrl(struct nand_chip *chip, int cmd, void *args)
2684-+{
2685-+ return -EOPNOTSUPP;
2686-+}
2687-+
2688-+static int nand_chip_suspend(struct nand_chip *chip)
2689-+{
2690-+ return 0;
2691-+}
2692-+
2693-+static int nand_chip_resume(struct nand_chip *chip)
2694-+{
2695-+ return 0;
2696-+}
2697-+
2698-+struct nand_chip *nand_chip_init(struct nfi_resource *res)
2699-+{
2700-+ struct nand_chip *chip;
2701-+ struct nand_base *nand;
2702-+ struct nfi *nfi;
2703-+
2704-+ chip = mem_alloc(1, sizeof(struct nand_chip));
2705-+ if (!chip) {
2706-+ pr_info("nand chip alloc fail!\n");
2707-+ return NULL;
2708-+ }
2709-+
2710-+ nfi = nfi_init(res);
2711-+ if (!nfi) {
2712-+ pr_info("nfi init fail!\n");
2713-+ goto nfi_err;
2714-+ }
2715-+
2716-+ nand = nand_base_init(NULL, nfi);
2717-+ if (!nand) {
2718-+ pr_info("nand base init fail!\n");
2719-+ goto base_err;
2720-+ }
2721-+
2722-+ chip->nand = (void *)nand;
2723-+ chip->read_page = nand_chip_read_page;
2724-+ chip->write_page = nand_chip_write_page;
2725-+ chip->erase_block = nand_chip_erase_block;
2726-+ chip->is_bad_block = nand_chip_is_bad_block;
2727-+ chip->chip_ctrl = nand_chip_ctrl;
2728-+ chip->suspend = nand_chip_suspend;
2729-+ chip->resume = nand_chip_resume;
2730-+
2731-+ nand = nand_device_init(chip);
2732-+ if (!nand)
2733-+ goto nand_err;
2734-+
2735-+ chip->nand = (void *)nand;
2736-+ chip->plane_num = nand->dev->plane_num;
2737-+ chip->block_num = nand_total_blocks(nand->dev);
2738-+ chip->block_size = nand->dev->block_size;
2739-+ chip->block_pages = nand_block_pages(nand->dev);
2740-+ chip->page_size = nand->dev->page_size;
2741-+ chip->oob_size = nfi->fdm_size * div_down(chip->page_size,
2742-+ nfi->sector_size);
2743-+ chip->sector_size = nfi->sector_size;
2744-+ chip->sector_spare_size = nfi->sector_spare_size;
2745-+ chip->min_program_pages = nand->dev->min_program_pages;
2746-+ chip->ecc_strength = nfi->ecc_strength;
2747-+ chip->ecc_parity_size = nfi->ecc_parity_size;
2748-+ chip->fdm_ecc_size = nfi->fdm_ecc_size;
2749-+ chip->fdm_reg_size = nfi->fdm_size;
2750-+
2751-+ return chip;
2752-+
2753-+nand_err:
2754-+ mem_free(nand);
2755-+base_err:
2756-+ nfi_exit(nfi);
2757-+nfi_err:
2758-+ mem_free(chip);
2759-+ return NULL;
2760-+}
2761-+
2762-+void nand_chip_exit(struct nand_chip *chip)
2763-+{
2764-+ nand_exit(chip->nand);
2765-+ mem_free(chip);
2766-+}
2767-diff --git a/drivers/mtd/nandx/core/nand_chip.h b/drivers/mtd/nandx/core/nand_chip.h
2768-new file mode 100644
2769-index 0000000000..3e9c8e6ca3
2770---- /dev/null
2771-+++ b/drivers/mtd/nandx/core/nand_chip.h
2772-@@ -0,0 +1,103 @@
2773-+/*
2774-+ * Copyright (C) 2017 MediaTek Inc.
2775-+ * Licensed under either
2776-+ * BSD Licence, (see NOTICE for more details)
2777-+ * GNU General Public License, version 2.0, (see NOTICE for more details)
2778-+ */
2779-+
2780-+#ifndef __NAND_CHIP_H__
2781-+#define __NAND_CHIP_H__
2782-+
2783-+enum nand_type {
2784-+ NAND_SPI,
2785-+ NAND_SLC,
2786-+ NAND_MLC,
2787-+ NAND_TLC
2788-+};
2789-+
2790-+/*
2791-+ * nand chip operation unit
2792-+ * one nand_ops indicates one row operation
2793-+ * @row: nand chip row address, like as nand row
2794-+ * @col: nand chip column address, like as nand column
2795-+ * @len: operate data length, min is sector_size,
2796-+ * max is page_size and sector_size aligned
2797-+ * @status: one operation result status
2798-+ * @data: data buffer for operation
2799-+ * @oob: oob buffer for operation, like as nand spare area
2800-+ */
2801-+struct nand_ops {
2802-+ int row;
2803-+ int col;
2804-+ int len;
2805-+ int status;
2806-+ void *data;
2807-+ void *oob;
2808-+};
2809-+
2810-+/*
2811-+ * nand chip descriptions
2812-+ * nand chip includes nand controller and the several same nand devices
2813-+ * @nand_type: the nand type on this chip,
2814-+ * the chip maybe have several nand device and the type must be same
2815-+ * @plane_num: the whole plane number on the chip
2816-+ * @block_num: the whole block number on the chip
2817-+ * @block_size: nand device block size
2818-+ * @block_pages: nand device block has page number
2819-+ * @page_size: nand device page size
2820-+ * @oob_size: chip out of band size, like as nand spare szie,
2821-+ * but restricts this:
2822-+ * the size is provied by nand controller(NFI),
2823-+ * because NFI would use some nand spare size
2824-+ * @min_program_pages: chip needs min pages per program operations
2825-+ * one page as one nand_ops
2826-+ * @sector_size: chip min read size
2827-+ * @sector_spare_size: spare size for sector, is spare_size/page_sectors
2828-+ * @ecc_strength: ecc stregth per sector_size, it would be for calculated ecc
2829-+ * @ecc_parity_size: ecc parity size for one sector_size data
2830-+ * @nand: pointer to inherited struct nand_base
2831-+ * @read_page: read %count pages on chip
2832-+ * @write_page: write %count pages on chip
2833-+ * @erase_block: erase %count blocks on chip, one block is one nand_ops
2834-+ * it is better to set nand_ops.row to block start row
2835-+ * @is_bad_block: judge the %count blocks on chip if they are bad
2836-+ * by vendor specification
2837-+ * @chip_ctrl: control the chip features by nandx_ctrl_cmd
2838-+ * @suspend: suspend nand chip
2839-+ * @resume: resume nand chip
2840-+ */
2841-+struct nand_chip {
2842-+ int nand_type;
2843-+ int plane_num;
2844-+ int block_num;
2845-+ int block_size;
2846-+ int block_pages;
2847-+ int page_size;
2848-+ int oob_size;
2849-+
2850-+ int min_program_pages;
2851-+ int sector_size;
2852-+ int sector_spare_size;
2853-+ int ecc_strength;
2854-+ int ecc_parity_size;
2855-+ u32 fdm_ecc_size;
2856-+ u32 fdm_reg_size;
2857-+
2858-+ void *nand;
2859-+
2860-+ int (*read_page)(struct nand_chip *chip, struct nand_ops *ops,
2861-+ int count);
2862-+ int (*write_page)(struct nand_chip *chip, struct nand_ops *ops,
2863-+ int count);
2864-+ int (*erase_block)(struct nand_chip *chip, struct nand_ops *ops,
2865-+ int count);
2866-+ int (*is_bad_block)(struct nand_chip *chip, struct nand_ops *ops,
2867-+ int count);
2868-+ int (*chip_ctrl)(struct nand_chip *chip, int cmd, void *args);
2869-+ int (*suspend)(struct nand_chip *chip);
2870-+ int (*resume)(struct nand_chip *chip);
2871-+};
2872-+
2873-+struct nand_chip *nand_chip_init(struct nfi_resource *res);
2874-+void nand_chip_exit(struct nand_chip *chip);
2875-+#endif /* __NAND_CHIP_H__ */
2876-diff --git a/drivers/mtd/nandx/core/nand_device.c b/drivers/mtd/nandx/core/nand_device.c
2877-new file mode 100644
2878-index 0000000000..9f6764d1bc
2879---- /dev/null
2880-+++ b/drivers/mtd/nandx/core/nand_device.c
2881-@@ -0,0 +1,285 @@
2882-+/*
2883-+ * Copyright (C) 2017 MediaTek Inc.
2884-+ * Licensed under either
2885-+ * BSD Licence, (see NOTICE for more details)
2886-+ * GNU General Public License, version 2.0, (see NOTICE for more details)
2887-+ */
2888-+
2889-+#include "nandx_util.h"
2890-+#include "nandx_core.h"
2891-+#include "nand_chip.h"
2892-+#include "nand_device.h"
2893-+#include "nand_base.h"
2894-+
2895-+#define MAX_CHIP_DEVICE 4
2896-+#define PARAM_PAGE_LEN 2048
2897-+#define ONFI_CRC_BASE 0x4f4e
2898-+
2899-+static u16 nand_onfi_crc16(u16 crc, u8 const *p, size_t len)
2900-+{
2901-+ int i;
2902-+
2903-+ while (len--) {
2904-+ crc ^= *p++ << 8;
2905-+
2906-+ for (i = 0; i < 8; i++)
2907-+ crc = (crc << 1) ^ ((crc & 0x8000) ? 0x8005 : 0);
2908-+ }
2909-+
2910-+ return crc;
2911-+}
2912-+
2913-+static inline void decode_addr_cycle(u8 addr_cycle, u8 *row_cycle,
2914-+ u8 *col_cycle)
2915-+{
2916-+ *row_cycle = addr_cycle & 0xf;
2917-+ *col_cycle = (addr_cycle >> 4) & 0xf;
2918-+}
2919-+
2920-+static int detect_onfi(struct nand_device *dev,
2921-+ struct nand_onfi_params *onfi)
2922-+{
2923-+ struct nand_endurance *endurance = dev->endurance;
2924-+ u16 size, i, crc16;
2925-+ u8 *id;
2926-+
2927-+ size = sizeof(struct nand_onfi_params) - sizeof(u16);
2928-+
2929-+ for (i = 0; i < 3; i++) {
2930-+ crc16 = nand_onfi_crc16(ONFI_CRC_BASE, (u8 *)&onfi[i], size);
2931-+
2932-+ if (onfi[i].signature[0] == 'O' &&
2933-+ onfi[i].signature[1] == 'N' &&
2934-+ onfi[i].signature[2] == 'F' &&
2935-+ onfi[i].signature[3] == 'I' &&
2936-+ onfi[i].crc16 == crc16)
2937-+ break;
2938-+
2939-+ /* in some spi nand, onfi signature maybe "NAND" */
2940-+ if (onfi[i].signature[0] == 'N' &&
2941-+ onfi[i].signature[1] == 'A' &&
2942-+ onfi[i].signature[2] == 'N' &&
2943-+ onfi[i].signature[3] == 'D' &&
2944-+ onfi[i].crc16 == crc16)
2945-+ break;
2946-+ }
2947-+
2948-+ if (i == 3)
2949-+ return -ENODEV;
2950-+
2951-+ memcpy(dev->name, onfi[i].model, 20);
2952-+ id = onfi[i].manufacturer;
2953-+ dev->id = NAND_PACK_ID(id[0], id[1], id[2], id[3], id[4], id[5], id[6],
2954-+ id[7]);
2955-+ dev->id_len = MAX_ID_NUM;
2956-+ dev->io_width = (onfi[i].features & 1) ? NAND_IO16 : NAND_IO8;
2957-+ decode_addr_cycle(onfi[i].addr_cycle, &dev->row_cycle,
2958-+ &dev->col_cycle);
2959-+ dev->target_num = 1;
2960-+ dev->lun_num = onfi[i].lun_num;
2961-+ dev->plane_num = BIT(onfi[i].plane_address_bits);
2962-+ dev->block_num = onfi[i].lun_blocks / dev->plane_num;
2963-+ dev->block_size = onfi[i].block_pages * onfi[i].page_size;
2964-+ dev->page_size = onfi[i].page_size;
2965-+ dev->spare_size = onfi[i].spare_size;
2966-+
2967-+ endurance->ecc_req = onfi[i].ecc_req;
2968-+ endurance->pe_cycle = onfi[i].valid_block_endurance;
2969-+ endurance->max_bitflips = endurance->ecc_req >> 1;
2970-+
2971-+ return 0;
2972-+}
2973-+
2974-+static int detect_jedec(struct nand_device *dev,
2975-+ struct nand_jedec_params *jedec)
2976-+{
2977-+ struct nand_endurance *endurance = dev->endurance;
2978-+ u16 size, i, crc16;
2979-+ u8 *id;
2980-+
2981-+ size = sizeof(struct nand_jedec_params) - sizeof(u16);
2982-+
2983-+ for (i = 0; i < 3; i++) {
2984-+ crc16 = nand_onfi_crc16(ONFI_CRC_BASE, (u8 *)&jedec[i], size);
2985-+
2986-+ if (jedec[i].signature[0] == 'J' &&
2987-+ jedec[i].signature[1] == 'E' &&
2988-+ jedec[i].signature[2] == 'S' &&
2989-+ jedec[i].signature[3] == 'D' &&
2990-+ jedec[i].crc16 == crc16)
2991-+ break;
2992-+ }
2993-+
2994-+ if (i == 3)
2995-+ return -ENODEV;
2996-+
2997-+ memcpy(dev->name, jedec[i].model, 20);
2998-+ id = jedec[i].manufacturer;
2999-+ dev->id = NAND_PACK_ID(id[0], id[1], id[2], id[3], id[4], id[5], id[6],
3000-+ id[7]);
3001-+ dev->id_len = MAX_ID_NUM;
3002-+ dev->io_width = (jedec[i].features & 1) ? NAND_IO16 : NAND_IO8;
3003-+ decode_addr_cycle(jedec[i].addr_cycle, &dev->row_cycle,
3004-+ &dev->col_cycle);
3005-+ dev->target_num = 1;
3006-+ dev->lun_num = jedec[i].lun_num;
3007-+ dev->plane_num = BIT(jedec[i].plane_address_bits);
3008-+ dev->block_num = jedec[i].lun_blocks / dev->plane_num;
3009-+ dev->block_size = jedec[i].block_pages * jedec[i].page_size;
3010-+ dev->page_size = jedec[i].page_size;
3011-+ dev->spare_size = jedec[i].spare_size;
3012-+
3013-+ endurance->ecc_req = jedec[i].endurance_block0[0];
3014-+ endurance->pe_cycle = jedec[i].valid_block_endurance;
3015-+ endurance->max_bitflips = endurance->ecc_req >> 1;
3016-+
3017-+ return 0;
3018-+}
3019-+
3020-+static struct nand_device *detect_parameters_page(struct nand_base
3021-+ *nand)
3022-+{
3023-+ struct nand_device *dev = nand->dev;
3024-+ void *params;
3025-+ int ret;
3026-+
3027-+ params = mem_alloc(1, PARAM_PAGE_LEN);
3028-+ if (!params)
3029-+ return NULL;
3030-+
3031-+ memset(params, 0, PARAM_PAGE_LEN);
3032-+ ret = nand->read_param_page(nand, params, PARAM_PAGE_LEN);
3033-+ if (ret < 0) {
3034-+ pr_info("read parameters page fail!\n");
3035-+ goto error;
3036-+ }
3037-+
3038-+ ret = detect_onfi(dev, params);
3039-+ if (ret) {
3040-+ pr_info("detect onfi device fail! try to detect jedec\n");
3041-+ ret = detect_jedec(dev, params);
3042-+ if (ret) {
3043-+ pr_info("detect jedec device fail!\n");
3044-+ goto error;
3045-+ }
3046-+ }
3047-+
3048-+ mem_free(params);
3049-+ return dev;
3050-+
3051-+error:
3052-+ mem_free(params);
3053-+ return NULL;
3054-+}
3055-+
3056-+static int read_device_id(struct nand_base *nand, int cs, u8 *id)
3057-+{
3058-+ int i;
3059-+
3060-+ nand->select_device(nand, cs);
3061-+ nand->reset(nand);
3062-+ nand->read_id(nand, id, MAX_ID_NUM);
3063-+ pr_info("device %d ID: ", cs);
3064-+
3065-+ for (i = 0; i < MAX_ID_NUM; i++)
3066-+ pr_info("%x ", id[i]);
3067-+
3068-+ pr_info("\n");
3069-+
3070-+ return 0;
3071-+}
3072-+
3073-+static int detect_more_device(struct nand_base *nand, u8 *id)
3074-+{
3075-+ u8 id_ext[MAX_ID_NUM];
3076-+ int i, j, target_num = 0;
3077-+
3078-+ for (i = 1; i < MAX_CHIP_DEVICE; i++) {
3079-+ memset(id_ext, 0xff, MAX_ID_NUM);
3080-+ read_device_id(nand, i, id_ext);
3081-+
3082-+ for (j = 0; j < MAX_ID_NUM; j++) {
3083-+ if (id_ext[j] != id[j])
3084-+ goto out;
3085-+ }
3086-+
3087-+ target_num += 1;
3088-+ }
3089-+
3090-+out:
3091-+ return target_num;
3092-+}
3093-+
3094-+static struct nand_device *scan_device_table(const u8 *id, int id_len)
3095-+{
3096-+ struct nand_device *dev;
3097-+ int i = 0, j;
3098-+ u8 ids[MAX_ID_NUM] = {0};
3099-+
3100-+ while (1) {
3101-+ dev = nand_get_device(i);
3102-+
3103-+ if (!strcmp(dev->name, "NO-DEVICE"))
3104-+ break;
3105-+
3106-+ if (id_len < dev->id_len) {
3107-+ i += 1;
3108-+ continue;
3109-+ }
3110-+
3111-+ NAND_UNPACK_ID(dev->id, ids, MAX_ID_NUM);
3112-+ for (j = 0; j < dev->id_len; j++) {
3113-+ if (ids[j] != id[j])
3114-+ break;
3115-+ }
3116-+
3117-+ if (j == dev->id_len)
3118-+ break;
3119-+
3120-+ i += 1;
3121-+ }
3122-+
3123-+ return dev;
3124-+}
3125-+
3126-+int nand_detect_device(struct nand_base *nand)
3127-+{
3128-+ struct nand_device *dev;
3129-+ u8 id[MAX_ID_NUM] = { 0 };
3130-+ int target_num = 0;
3131-+
3132-+ /* Get nand device default setting for reset/read_id */
3133-+ nand->dev = scan_device_table(NULL, -1);
3134-+
3135-+ read_device_id(nand, 0, id);
3136-+ dev = scan_device_table(id, MAX_ID_NUM);
3137-+
3138-+ if (!strcmp(dev->name, "NO-DEVICE")) {
3139-+ pr_info("device scan fail\n");
3140-+ return -ENODEV;
3141-+ }
3142-+
3143-+ /* TobeFix: has null pointer issue in this funciton */
3144-+ if (!strcmp(dev->name, "NO-DEVICE")) {
3145-+ pr_info("device scan fail, detect parameters page\n");
3146-+ dev = detect_parameters_page(nand);
3147-+ if (!dev) {
3148-+ pr_info("detect parameters fail\n");
3149-+ return -ENODEV;
3150-+ }
3151-+ }
3152-+
3153-+ if (dev->target_num > 1)
3154-+ target_num = detect_more_device(nand, id);
3155-+
3156-+ target_num += 1;
3157-+ pr_debug("chip has target device num: %d\n", target_num);
3158-+
3159-+ if (dev->target_num != target_num)
3160-+ dev->target_num = target_num;
3161-+
3162-+ nand->dev = dev;
3163-+
3164-+ return 0;
3165-+}
3166-+
3167-diff --git a/drivers/mtd/nandx/core/nand_device.h b/drivers/mtd/nandx/core/nand_device.h
3168-new file mode 100644
3169-index 0000000000..e142cf529d
3170---- /dev/null
3171-+++ b/drivers/mtd/nandx/core/nand_device.h
3172-@@ -0,0 +1,608 @@
3173-+/*
3174-+ * Copyright (C) 2017 MediaTek Inc.
3175-+ * Licensed under either
3176-+ * BSD Licence, (see NOTICE for more details)
3177-+ * GNU General Public License, version 2.0, (see NOTICE for more details)
3178-+ */
3179-+
3180-+#ifndef __NAND_DEVICE_H__
3181-+#define __NAND_DEVICE_H__
3182-+
3183-+/* onfi 3.2 */
3184-+struct nand_onfi_params {
3185-+ /* Revision information and features block. 0 */
3186-+ /*
3187-+ * Byte 0: 4Fh,
3188-+ * Byte 1: 4Eh,
3189-+ * Byte 2: 46h,
3190-+ * Byte 3: 49h,
3191-+ */
3192-+ u8 signature[4];
3193-+ /*
3194-+ * 9-15 Reserved (0)
3195-+ * 8 1 = supports ONFI version 3.2
3196-+ * 7 1 = supports ONFI version 3.1
3197-+ * 6 1 = supports ONFI version 3.0
3198-+ * 5 1 = supports ONFI version 2.3
3199-+ * 4 1 = supports ONFI version 2.2
3200-+ * 3 1 = supports ONFI version 2.1
3201-+ * 2 1 = supports ONFI version 2.0
3202-+ * 1 1 = supports ONFI version 1.0
3203-+ * 0 Reserved (0)
3204-+ */
3205-+ u16 revision;
3206-+ /*
3207-+ * 13-15 Reserved (0)
3208-+ * 12 1 = supports external Vpp
3209-+ * 11 1 = supports Volume addressing
3210-+ * 10 1 = supports NV-DDR2
3211-+ * 9 1 = supports EZ NAND
3212-+ * 8 1 = supports program page register clear enhancement
3213-+ * 7 1 = supports extended parameter page
3214-+ * 6 1 = supports multi-plane read operations
3215-+ * 5 1 = supports NV-DDR
3216-+ * 4 1 = supports odd to even page Copyback
3217-+ * 3 1 = supports multi-plane program and erase operations
3218-+ * 2 1 = supports non-sequential page programming
3219-+ * 1 1 = supports multiple LUN operations
3220-+ * 0 1 = supports 16-bit data bus width
3221-+ */
3222-+ u16 features;
3223-+ /*
3224-+ * 13-15 Reserved (0)
3225-+ * 12 1 = supports LUN Get and LUN Set Features
3226-+ * 11 1 = supports ODT Configure
3227-+ * 10 1 = supports Volume Select
3228-+ * 9 1 = supports Reset LUN
3229-+ * 8 1 = supports Small Data Move
3230-+ * 7 1 = supports Change Row Address
3231-+ * 6 1 = supports Change Read Column Enhanced
3232-+ * 5 1 = supports Read Unique ID
3233-+ * 4 1 = supports Copyback
3234-+ * 3 1 = supports Read Status Enhanced
3235-+ * 2 1 = supports Get Features and Set Features
3236-+ * 1 1 = supports Read Cache commands
3237-+ * 0 1 = supports Page Cache Program command
3238-+ */
3239-+ u16 opt_cmds;
3240-+ /*
3241-+ * 4-7 Reserved (0)
3242-+ * 3 1 = supports Multi-plane Block Erase
3243-+ * 2 1 = supports Multi-plane Copyback Program
3244-+ * 1 1 = supports Multi-plane Page Program
3245-+ * 0 1 = supports Random Data Out
3246-+ */
3247-+ u8 advance_cmds;
3248-+ u8 reserved0[1];
3249-+ u16 extend_param_len;
3250-+ u8 param_page_num;
3251-+ u8 reserved1[17];
3252-+
3253-+ /* Manufacturer information block. 32 */
3254-+ u8 manufacturer[12];
3255-+ u8 model[20];
3256-+ u8 jedec_id;
3257-+ u16 data_code;
3258-+ u8 reserved2[13];
3259-+
3260-+ /* Memory organization block. 80 */
3261-+ u32 page_size;
3262-+ u16 spare_size;
3263-+ u32 partial_page_size; /* obsolete */
3264-+ u16 partial_spare_size; /* obsolete */
3265-+ u32 block_pages;
3266-+ u32 lun_blocks;
3267-+ u8 lun_num;
3268-+ /*
3269-+ * 4-7 Column address cycles
3270-+ * 0-3 Row address cycles
3271-+ */
3272-+ u8 addr_cycle;
3273-+ u8 cell_bits;
3274-+ u16 lun_max_bad_blocks;
3275-+ u16 block_endurance;
3276-+ u8 target_begin_valid_blocks;
3277-+ u16 valid_block_endurance;
3278-+ u8 page_program_num;
3279-+ u8 partial_program_attr; /* obsolete */
3280-+ u8 ecc_req;
3281-+ /*
3282-+ * 4-7 Reserved (0)
3283-+ * 0-3 Number of plane address bits
3284-+ */
3285-+ u8 plane_address_bits;
3286-+ /*
3287-+ * 6-7 Reserved (0)
3288-+ * 5 1 = lower bit XNOR block address restriction
3289-+ * 4 1 = read cache supported
3290-+ * 3 Address restrictions for cache operations
3291-+ * 2 1 = program cache supported
3292-+ * 1 1 = no block address restrictions
3293-+ * 0 Overlapped / concurrent multi-plane support
3294-+ */
3295-+ u8 multi_plane_attr;
3296-+ u8 ez_nand_support;
3297-+ u8 reserved3[12];
3298-+
3299-+ /* Electrical parameters block. 128 */
3300-+ u8 io_pin_max_capacitance;
3301-+ /*
3302-+ * 6-15 Reserved (0)
3303-+ * 5 1 = supports timing mode 5
3304-+ * 4 1 = supports timing mode 4
3305-+ * 3 1 = supports timing mode 3
3306-+ * 2 1 = supports timing mode 2
3307-+ * 1 1 = supports timing mode 1
3308-+ * 0 1 = supports timing mode 0, shall be 1
3309-+ */
3310-+ u16 sdr_timing_mode;
3311-+ u16 sdr_program_cache_timing_mode; /* obsolete */
3312-+ u16 tPROG;
3313-+ u16 tBERS;
3314-+ u16 tR;
3315-+ u16 tCCS;
3316-+ /*
3317-+ * 7 Reserved (0)
3318-+ * 6 1 = supports NV-DDR2 timing mode 8
3319-+ * 5 1 = supports NV-DDR timing mode 5
3320-+ * 4 1 = supports NV-DDR timing mode 4
3321-+ * 3 1 = supports NV-DDR timing mode 3
3322-+ * 2 1 = supports NV-DDR timing mode 2
3323-+ * 1 1 = supports NV-DDR timing mode 1
3324-+ * 0 1 = supports NV-DDR timing mode 0
3325-+ */
3326-+ u8 nvddr_timing_mode;
3327-+ /*
3328-+ * 7 1 = supports timing mode 7
3329-+ * 6 1 = supports timing mode 6
3330-+ * 5 1 = supports timing mode 5
3331-+ * 4 1 = supports timing mode 4
3332-+ * 3 1 = supports timing mode 3
3333-+ * 2 1 = supports timing mode 2
3334-+ * 1 1 = supports timing mode 1
3335-+ * 0 1 = supports timing mode 0
3336-+ */
3337-+ u8 nvddr2_timing_mode;
3338-+ /*
3339-+ * 4-7 Reserved (0)
3340-+ * 3 1 = device requires Vpp enablement sequence
3341-+ * 2 1 = device supports CLK stopped for data input
3342-+ * 1 1 = typical capacitance
3343-+ * 0 tCAD value to use
3344-+ */
3345-+ u8 nvddr_fetures;
3346-+ u16 clk_pin_capacitance;
3347-+ u16 io_pin_capacitance;
3348-+ u16 input_pin_capacitance;
3349-+ u8 input_pin_max_capacitance;
3350-+ /*
3351-+ * 3-7 Reserved (0)
3352-+ * 2 1 = supports 18 Ohm drive strength
3353-+ * 1 1 = supports 25 Ohm drive strength
3354-+ * 0 1 = supports driver strength settings
3355-+ */
3356-+ u8 drive_strength;
3357-+ u16 tR_multi_plane;
3358-+ u16 tADL;
3359-+ u16 tR_ez_nand;
3360-+ /*
3361-+ * 6-7 Reserved (0)
3362-+ * 5 1 = external VREFQ required for >= 200 MT/s
3363-+ * 4 1 = supports differential signaling for DQS
3364-+ * 3 1 = supports differential signaling for RE_n
3365-+ * 2 1 = supports ODT value of 30 Ohms
3366-+ * 1 1 = supports matrix termination ODT
3367-+ * 0 1 = supports self-termination ODT
3368-+ */
3369-+ u8 nvddr2_features;
3370-+ u8 nvddr2_warmup_cycles;
3371-+ u8 reserved4[4];
3372-+
3373-+ /* vendor block. 164 */
3374-+ u16 vendor_revision;
3375-+ u8 vendor_spec[88];
3376-+
3377-+ /* CRC for Parameter Page. 254 */
3378-+ u16 crc16;
3379-+} __packed;
3380-+
3381-+/* JESD230-B */
3382-+struct nand_jedec_params {
3383-+ /* Revision information and features block. 0 */
3384-+ /*
3385-+ * Byte 0:4Ah
3386-+ * Byte 1:45h
3387-+ * Byte 2:53h
3388-+ * Byte 3:44h
3389-+ */
3390-+ u8 signature[4];
3391-+ /*
3392-+ * 3-15: Reserved (0)
3393-+ * 2: 1 = supports parameter page revision 1.0 and standard revision 1.0
3394-+ * 1: 1 = supports vendor specific parameter page
3395-+ * 0: Reserved (0)
3396-+ */
3397-+ u16 revision;
3398-+ /*
3399-+ * 9-15 Reserved (0)
3400-+ * 8: 1 = supports program page register clear enhancement
3401-+ * 7: 1 = supports external Vpp
3402-+ * 6: 1 = supports Toggle Mode DDR
3403-+ * 5: 1 = supports Synchronous DDR
3404-+ * 4: 1 = supports multi-plane read operations
3405-+ * 3: 1 = supports multi-plane program and erase operations
3406-+ * 2: 1 = supports non-sequential page programming
3407-+ * 1: 1 = supports multiple LUN operations
3408-+ * 0: 1 = supports 16-bit data bus width
3409-+ */
3410-+ u16 features;
3411-+ /*
3412-+ * 11-23: Reserved (0)
3413-+ * 10: 1 = supports Synchronous Reset
3414-+ * 9: 1 = supports Reset LUN (Primary)
3415-+ * 8: 1 = supports Small Data Move
3416-+ * 7: 1 = supports Multi-plane Copyback Program (Primary)
3417-+ * 6: 1 = supports Random Data Out (Primary)
3418-+ * 5: 1 = supports Read Unique ID
3419-+ * 4: 1 = supports Copyback
3420-+ * 3: 1 = supports Read Status Enhanced (Primary)
3421-+ * 2: 1 = supports Get Features and Set Features
3422-+ * 1: 1 = supports Read Cache commands
3423-+ * 0: 1 = supports Page Cache Program command
3424-+ */
3425-+ u8 opt_cmds[3];
3426-+ /*
3427-+ * 8-15: Reserved (0)
3428-+ * 7: 1 = supports secondary Read Status Enhanced
3429-+ * 6: 1 = supports secondary Multi-plane Block Erase
3430-+ * 5: 1 = supports secondary Multi-plane Copyback Program
3431-+ * 4: 1 = supports secondary Multi-plane Program
3432-+ * 3: 1 = supports secondary Random Data Out
3433-+ * 2: 1 = supports secondary Multi-plane Copyback Read
3434-+ * 1: 1 = supports secondary Multi-plane Read Cache Random
3435-+ * 0: 1 = supports secondary Multi-plane Read
3436-+ */
3437-+ u16 secondary_cmds;
3438-+ u8 param_page_num;
3439-+ u8 reserved0[18];
3440-+
3441-+ /* Manufacturer information block. 32*/
3442-+ u8 manufacturer[12];
3443-+ u8 model[20];
3444-+ u8 jedec_id[6];
3445-+ u8 reserved1[10];
3446-+
3447-+ /* Memory organization block. 80 */
3448-+ u32 page_size;
3449-+ u16 spare_size;
3450-+ u8 reserved2[6];
3451-+ u32 block_pages;
3452-+ u32 lun_blocks;
3453-+ u8 lun_num;
3454-+ /*
3455-+ * 4-7 Column address cycles
3456-+ * 0-3 Row address cycles
3457-+ */
3458-+ u8 addr_cycle;
3459-+ u8 cell_bits;
3460-+ u8 page_program_num;
3461-+ /*
3462-+ * 4-7 Reserved (0)
3463-+ * 0-3 Number of plane address bits
3464-+ */
3465-+ u8 plane_address_bits;
3466-+ /*
3467-+ * 3-7: Reserved (0)
3468-+ * 2: 1= read cache supported
3469-+ * 1: 1 = program cache supported
3470-+ * 0: 1= No multi-plane block address restrictions
3471-+ */
3472-+ u8 multi_plane_attr;
3473-+ u8 reserved3[38];
3474-+
3475-+ /* Electrical parameters block. 144 */
3476-+ /*
3477-+ * 6-15: Reserved (0)
3478-+ * 5: 1 = supports 20 ns speed grade (50 MHz)
3479-+ * 4: 1 = supports 25 ns speed grade (40 MHz)
3480-+ * 3: 1 = supports 30 ns speed grade (~33 MHz)
3481-+ * 2: 1 = supports 35 ns speed grade (~28 MHz)
3482-+ * 1: 1 = supports 50 ns speed grade (20 MHz)
3483-+ * 0: 1 = supports 100 ns speed grade (10 MHz)
3484-+ */
3485-+ u16 sdr_speed;
3486-+ /*
3487-+ * 8-15: Reserved (0)
3488-+ * 7: 1 = supports 5 ns speed grade (200 MHz)
3489-+ * 6: 1 = supports 6 ns speed grade (~166 MHz)
3490-+ * 5: 1 = supports 7.5 ns speed grade (~133 MHz)
3491-+ * 4: 1 = supports 10 ns speed grade (100 MHz)
3492-+ * 3: 1 = supports 12 ns speed grade (~83 MHz)
3493-+ * 2: 1 = supports 15 ns speed grade (~66 MHz)
3494-+ * 1: 1 = supports 25 ns speed grade (40 MHz)
3495-+ * 0: 1 = supports 30 ns speed grade (~33 MHz)
3496-+ */
3497-+ u16 toggle_ddr_speed;
3498-+ /*
3499-+ * 6-15: Reserved (0)
3500-+ * 5: 1 = supports 10 ns speed grade (100 MHz)
3501-+ * 4: 1 = supports 12 ns speed grade (~83 MHz)
3502-+ * 3: 1 = supports 15 ns speed grade (~66 MHz)
3503-+ * 2: 1 = supports 20 ns speed grade (50 MHz)
3504-+ * 1: 1 = supports 30 ns speed grade (~33 MHz)
3505-+ * 0: 1 = supports 50 ns speed grade (20 MHz)
3506-+ */
3507-+ u16 sync_ddr_speed;
3508-+ u8 sdr_features;
3509-+ u8 toggle_ddr_features;
3510-+ /*
3511-+ * 2-7: Reserved (0)
3512-+ * 1: Device supports CK stopped for data input
3513-+ * 0: tCAD value to use
3514-+ */
3515-+ u8 sync_ddr_features;
3516-+ u16 tPROG;
3517-+ u16 tBERS;
3518-+ u16 tR;
3519-+ u16 tR_multi_plane;
3520-+ u16 tCCS;
3521-+ u16 io_pin_capacitance;
3522-+ u16 input_pin_capacitance;
3523-+ u16 ck_pin_capacitance;
3524-+ /*
3525-+ * 3-7: Reserved (0)
3526-+ * 2: 1 = supports 18 ohm drive strength
3527-+ * 1: 1 = supports 25 ohm drive strength
3528-+ * 0: 1 = supports 35ohm/50ohm drive strength
3529-+ */
3530-+ u8 drive_strength;
3531-+ u16 tADL;
3532-+ u8 reserved4[36];
3533-+
3534-+ /* ECC and endurance block. 208 */
3535-+ u8 target_begin_valid_blocks;
3536-+ u16 valid_block_endurance;
3537-+ /*
3538-+ * Byte 0: Number of bits ECC correctability
3539-+ * Byte 1: Codeword size
3540-+ * Byte 2-3: Bad blocks maximum per LUN
3541-+ * Byte 4-5: Block endurance
3542-+ * Byte 6-7: Reserved (0)
3543-+ */
3544-+ u8 endurance_block0[8];
3545-+ u8 endurance_block1[8];
3546-+ u8 endurance_block2[8];
3547-+ u8 endurance_block3[8];
3548-+ u8 reserved5[29];
3549-+
3550-+ /* Reserved. 272 */
3551-+ u8 reserved6[148];
3552-+
3553-+ /* Vendor specific block. 420 */
3554-+ u16 vendor_revision;
3555-+ u8 vendor_spec[88];
3556-+
3557-+ /* CRC for Parameter Page. 510 */
3558-+ u16 crc16;
3559-+} __packed;
3560-+
3561-+/* parallel nand io width */
3562-+enum nand_io_width {
3563-+ NAND_IO8,
3564-+ NAND_IO16
3565-+};
3566-+
3567-+/* all supported nand timming type */
3568-+enum nand_timing_type {
3569-+ NAND_TIMING_SDR,
3570-+ NAND_TIMING_SYNC_DDR,
3571-+ NAND_TIMING_TOGGLE_DDR,
3572-+ NAND_TIMING_NVDDR2
3573-+};
3574-+
3575-+/* nand basic commands */
3576-+struct nand_cmds {
3577-+ short reset;
3578-+ short read_id;
3579-+ short read_status;
3580-+ short read_param_page;
3581-+ short set_feature;
3582-+ short get_feature;
3583-+ short read_1st;
3584-+ short read_2nd;
3585-+ short random_out_1st;
3586-+ short random_out_2nd;
3587-+ short program_1st;
3588-+ short program_2nd;
3589-+ short erase_1st;
3590-+ short erase_2nd;
3591-+ short read_cache;
3592-+ short read_cache_last;
3593-+ short program_cache;
3594-+};
3595-+
3596-+/*
3597-+ * addressing for nand physical address
3598-+ * @row_bit_start: row address start bit
3599-+ * @block_bit_start: block address start bit
3600-+ * @plane_bit_start: plane address start bit
3601-+ * @lun_bit_start: lun address start bit
3602-+ */
3603-+struct nand_addressing {
3604-+ u8 row_bit_start;
3605-+ u8 block_bit_start;
3606-+ u8 plane_bit_start;
3607-+ u8 lun_bit_start;
3608-+};
3609-+
3610-+/*
3611-+ * nand operations status
3612-+ * @array_busy: indicates device array operation busy
3613-+ * @write_protect: indicates the device cannot be wrote or erased
3614-+ * @erase_fail: indicates erase operation fail
3615-+ * @program_fail: indicates program operation fail
3616-+ */
3617-+struct nand_status {
3618-+ u8 array_busy;
3619-+ u8 write_protect;
3620-+ u8 erase_fail;
3621-+ u8 program_fail;
3622-+};
3623-+
3624-+/*
3625-+ * nand endurance information
3626-+ * @pe_cycle: max program/erase cycle for nand stored data stability
3627-+ * @ecc_req: ecc strength required for the nand, measured per 1KB
3628-+ * @max_bitflips: bitflips is ecc corrected bits,
3629-+ * max_bitflips is the threshold for nand stored data stability
3630-+ * if corrected bits is over max_bitflips, stored data must be moved
3631-+ * to another good block
3632-+ */
3633-+struct nand_endurance {
3634-+ int pe_cycle;
3635-+ int ecc_req;
3636-+ int max_bitflips;
3637-+};
3638-+
3639-+/* wait for nand busy type */
3640-+enum nand_wait_type {
3641-+ NAND_WAIT_IRQ,
3642-+ NAND_WAIT_POLLING,
3643-+ NAND_WAIT_TWHR2,
3644-+};
3645-+
3646-+/* each nand array operations time */
3647-+struct nand_array_timing {
3648-+ u16 tRST;
3649-+ u16 tWHR;
3650-+ u16 tR;
3651-+ u16 tRCBSY;
3652-+ u16 tFEAT;
3653-+ u16 tPROG;
3654-+ u16 tPCBSY;
3655-+ u16 tBERS;
3656-+ u16 tDBSY;
3657-+};
3658-+
3659-+/* nand sdr interface timing required */
3660-+struct nand_sdr_timing {
3661-+ u16 tREA;
3662-+ u16 tREH;
3663-+ u16 tCR;
3664-+ u16 tRP;
3665-+ u16 tWP;
3666-+ u16 tWH;
3667-+ u16 tWHR;
3668-+ u16 tCLS;
3669-+ u16 tALS;
3670-+ u16 tCLH;
3671-+ u16 tALH;
3672-+ u16 tWC;
3673-+ u16 tRC;
3674-+};
3675-+
3676-+/* nand onfi ddr (nvddr) interface timing required */
3677-+struct nand_onfi_timing {
3678-+ u16 tCAD;
3679-+ u16 tWPRE;
3680-+ u16 tWPST;
3681-+ u16 tWRCK;
3682-+ u16 tDQSCK;
3683-+ u16 tWHR;
3684-+};
3685-+
3686-+/* nand toggle ddr (toggle 1.0) interface timing required */
3687-+struct nand_toggle_timing {
3688-+ u16 tCS;
3689-+ u16 tCH;
3690-+ u16 tCAS;
3691-+ u16 tCAH;
3692-+ u16 tCALS;
3693-+ u16 tCALH;
3694-+ u16 tWP;
3695-+ u16 tWPRE;
3696-+ u16 tWPST;
3697-+ u16 tWPSTH;
3698-+ u16 tCR;
3699-+ u16 tRPRE;
3700-+ u16 tRPST;
3701-+ u16 tRPSTH;
3702-+ u16 tCDQSS;
3703-+ u16 tWHR;
3704-+};
3705-+
3706-+/* nand basic device information */
3707-+struct nand_device {
3708-+ u8 *name;
3709-+ u64 id;
3710-+ u8 id_len;
3711-+ u8 io_width;
3712-+ u8 row_cycle;
3713-+ u8 col_cycle;
3714-+ u8 target_num;
3715-+ u8 lun_num;
3716-+ u8 plane_num;
3717-+ int block_num;
3718-+ int block_size;
3719-+ int page_size;
3720-+ int spare_size;
3721-+ int min_program_pages;
3722-+ struct nand_cmds *cmds;
3723-+ struct nand_addressing *addressing;
3724-+ struct nand_status *status;
3725-+ struct nand_endurance *endurance;
3726-+ struct nand_array_timing *array_timing;
3727-+};
3728-+
3729-+#define NAND_DEVICE(_name, _id, _id_len, _io_width, _row_cycle, \
3730-+ _col_cycle, _target_num, _lun_num, _plane_num, \
3731-+ _block_num, _block_size, _page_size, _spare_size, \
3732-+ _min_program_pages, _cmds, _addressing, _status, \
3733-+ _endurance, _array_timing) \
3734-+{ \
3735-+ _name, _id, _id_len, _io_width, _row_cycle, \
3736-+ _col_cycle, _target_num, _lun_num, _plane_num, \
3737-+ _block_num, _block_size, _page_size, _spare_size, \
3738-+ _min_program_pages, _cmds, _addressing, _status, \
3739-+ _endurance, _array_timing \
3740-+}
3741-+
3742-+#define MAX_ID_NUM sizeof(u64)
3743-+
3744-+#define NAND_PACK_ID(id0, id1, id2, id3, id4, id5, id6, id7) \
3745-+ ( \
3746-+ id0 | id1 << 8 | id2 << 16 | id3 << 24 | \
3747-+ (u64)id4 << 32 | (u64)id5 << 40 | \
3748-+ (u64)id6 << 48 | (u64)id7 << 56 \
3749-+ )
3750-+
3751-+#define NAND_UNPACK_ID(id, ids, len) \
3752-+ do { \
3753-+ int _i; \
3754-+ for (_i = 0; _i < len; _i++) \
3755-+ ids[_i] = id >> (_i << 3) & 0xff; \
3756-+ } while (0)
3757-+
3758-+static inline int nand_block_pages(struct nand_device *device)
3759-+{
3760-+ return div_down(device->block_size, device->page_size);
3761-+}
3762-+
3763-+static inline int nand_lun_blocks(struct nand_device *device)
3764-+{
3765-+ return device->plane_num * device->block_num;
3766-+}
3767-+
3768-+static inline int nand_target_blocks(struct nand_device *device)
3769-+{
3770-+ return device->lun_num * device->plane_num * device->block_num;
3771-+}
3772-+
3773-+static inline int nand_total_blocks(struct nand_device *device)
3774-+{
3775-+ return device->target_num * device->lun_num * device->plane_num *
3776-+ device->block_num;
3777-+}
3778-+
3779-+struct nand_device *nand_get_device(int index);
3780-+#endif /* __NAND_DEVICE_H__ */
3781-diff --git a/drivers/mtd/nandx/core/nfi.h b/drivers/mtd/nandx/core/nfi.h
3782-new file mode 100644
3783-index 0000000000..ba84e73ccc
3784---- /dev/null
3785-+++ b/drivers/mtd/nandx/core/nfi.h
3786-@@ -0,0 +1,51 @@
3787-+/*
3788-+ * Copyright (C) 2017 MediaTek Inc.
3789-+ * Licensed under either
3790-+ * BSD Licence, (see NOTICE for more details)
3791-+ * GNU General Public License, version 2.0, (see NOTICE for more details)
3792-+ */
3793-+
3794-+#ifndef __NFI_H__
3795-+#define __NFI_H__
3796-+
3797-+struct nfi_format {
3798-+ int page_size;
3799-+ int spare_size;
3800-+ int ecc_req;
3801-+};
3802-+
3803-+struct nfi {
3804-+ int sector_size;
3805-+ int sector_spare_size;
3806-+ int fdm_size; /*for sector*/
3807-+ int fdm_ecc_size;
3808-+ int ecc_strength;
3809-+ int ecc_parity_size; /*for sector*/
3810-+
3811-+ int (*select_chip)(struct nfi *nfi, int cs);
3812-+ int (*set_format)(struct nfi *nfi, struct nfi_format *format);
3813-+ int (*set_timing)(struct nfi *nfi, void *timing, int type);
3814-+ int (*nfi_ctrl)(struct nfi *nfi, int cmd, void *args);
3815-+
3816-+ int (*reset)(struct nfi *nfi);
3817-+ int (*send_cmd)(struct nfi *nfi, short cmd);
3818-+ int (*send_addr)(struct nfi *nfi, int col, int row,
3819-+ int col_cycle, int row_cycle);
3820-+ int (*trigger)(struct nfi *nfi);
3821-+
3822-+ int (*write_page)(struct nfi *nfi, u8 *data, u8 *fdm);
3823-+ int (*write_bytes)(struct nfi *nfi, u8 *data, int count);
3824-+ int (*read_sectors)(struct nfi *nfi, u8 *data, u8 *fdm,
3825-+ int sectors);
3826-+ int (*read_bytes)(struct nfi *nfi, u8 *data, int count);
3827-+
3828-+ int (*wait_ready)(struct nfi *nfi, int type, u32 timeout);
3829-+
3830-+ int (*enable_randomizer)(struct nfi *nfi, u32 row, bool encode);
3831-+ int (*disable_randomizer)(struct nfi *nfi);
3832-+};
3833-+
3834-+struct nfi *nfi_init(struct nfi_resource *res);
3835-+void nfi_exit(struct nfi *nfi);
3836-+
3837-+#endif /* __NFI_H__ */
3838-diff --git a/drivers/mtd/nandx/core/nfi/nfi_base.c b/drivers/mtd/nandx/core/nfi/nfi_base.c
3839-new file mode 100644
3840-index 0000000000..d8679d7aa3
3841---- /dev/null
3842-+++ b/drivers/mtd/nandx/core/nfi/nfi_base.c
3843-@@ -0,0 +1,1357 @@
3844-+/*
3845-+ * Copyright (C) 2017 MediaTek Inc.
3846-+ * Licensed under either
3847-+ * BSD Licence, (see NOTICE for more details)
3848-+ * GNU General Public License, version 2.0, (see NOTICE for more details)
3849-+ */
3850-+
3851-+/**
3852-+ * nfi_base.c - the base logic for nfi to access nand flash
3853-+ *
3854-+ * slc/mlc/tlc could use same code to access nand
3855-+ * of cause, there still some work need to do
3856-+ * even for spi nand, there should be a chance to integrate code together
3857-+ */
3858-+
3859-+#include "nandx_util.h"
3860-+#include "nandx_core.h"
3861-+#include "../nfi.h"
3862-+#include "../nand_device.h"
3863-+#include "nfi_regs.h"
3864-+#include "nfiecc.h"
3865-+#include "nfi_base.h"
3866-+
3867-+static const int spare_size_mt7622[] = {
3868-+ 16, 26, 27, 28
3869-+};
3870-+
3871-+#define RAND_SEED_SHIFT(op) \
3872-+ ((op) == RAND_ENCODE ? ENCODE_SEED_SHIFT : DECODE_SEED_SHIFT)
3873-+#define RAND_EN(op) \
3874-+ ((op) == RAND_ENCODE ? RAN_ENCODE_EN : RAN_DECODE_EN)
3875-+
3876-+#define SS_SEED_NUM 128
3877-+static u16 ss_randomizer_seed[SS_SEED_NUM] = {
3878-+ 0x576A, 0x05E8, 0x629D, 0x45A3, 0x649C, 0x4BF0, 0x2342, 0x272E,
3879-+ 0x7358, 0x4FF3, 0x73EC, 0x5F70, 0x7A60, 0x1AD8, 0x3472, 0x3612,
3880-+ 0x224F, 0x0454, 0x030E, 0x70A5, 0x7809, 0x2521, 0x484F, 0x5A2D,
3881-+ 0x492A, 0x043D, 0x7F61, 0x3969, 0x517A, 0x3B42, 0x769D, 0x0647,
3882-+ 0x7E2A, 0x1383, 0x49D9, 0x07B8, 0x2578, 0x4EEC, 0x4423, 0x352F,
3883-+ 0x5B22, 0x72B9, 0x367B, 0x24B6, 0x7E8E, 0x2318, 0x6BD0, 0x5519,
3884-+ 0x1783, 0x18A7, 0x7B6E, 0x7602, 0x4B7F, 0x3648, 0x2C53, 0x6B99,
3885-+ 0x0C23, 0x67CF, 0x7E0E, 0x4D8C, 0x5079, 0x209D, 0x244A, 0x747B,
3886-+ 0x350B, 0x0E4D, 0x7004, 0x6AC3, 0x7F3E, 0x21F5, 0x7A15, 0x2379,
3887-+ 0x1517, 0x1ABA, 0x4E77, 0x15A1, 0x04FA, 0x2D61, 0x253A, 0x1302,
3888-+ 0x1F63, 0x5AB3, 0x049A, 0x5AE8, 0x1CD7, 0x4A00, 0x30C8, 0x3247,
3889-+ 0x729C, 0x5034, 0x2B0E, 0x57F2, 0x00E4, 0x575B, 0x6192, 0x38F8,
3890-+ 0x2F6A, 0x0C14, 0x45FC, 0x41DF, 0x38DA, 0x7AE1, 0x7322, 0x62DF,
3891-+ 0x5E39, 0x0E64, 0x6D85, 0x5951, 0x5937, 0x6281, 0x33A1, 0x6A32,
3892-+ 0x3A5A, 0x2BAC, 0x743A, 0x5E74, 0x3B2E, 0x7EC7, 0x4FD2, 0x5D28,
3893-+ 0x751F, 0x3EF8, 0x39B1, 0x4E49, 0x746B, 0x6EF6, 0x44BE, 0x6DB7
3894-+};
3895-+
3896-+#if 0
3897-+static void dump_register(void *regs)
3898-+{
3899-+ int i;
3900-+
3901-+ pr_info("registers:\n");
3902-+ for (i = 0; i < 0x600; i += 0x10) {
3903-+ pr_info(" address 0x%X : %X %X %X %X\n",
3904-+ (u32)((unsigned long)regs + i),
3905-+ (u32)readl(regs + i),
3906-+ (u32)readl(regs + i + 0x4),
3907-+ (u32)readl(regs + i + 0x8),
3908-+ (u32)readl(regs + i + 0xC));
3909-+ }
3910-+}
3911-+#endif
3912-+
3913-+static int nfi_enable_randomizer(struct nfi *nfi, u32 row, bool encode)
3914-+{
3915-+ struct nfi_base *nb = nfi_to_base(nfi);
3916-+ enum randomizer_op op = RAND_ENCODE;
3917-+ void *regs = nb->res.nfi_regs;
3918-+ u32 val;
3919-+
3920-+ if (!encode)
3921-+ op = RAND_DECODE;
3922-+
3923-+ /* randomizer type and reseed type setup */
3924-+ val = readl(regs + NFI_CNFG);
3925-+ val |= CNFG_RAND_SEL | CNFG_RESEED_SEC_EN;
3926-+ writel(val, regs + NFI_CNFG);
3927-+
3928-+ /* randomizer seed and type setup */
3929-+ val = ss_randomizer_seed[row % SS_SEED_NUM] & RAN_SEED_MASK;
3930-+ val <<= RAND_SEED_SHIFT(op);
3931-+ val |= RAND_EN(op);
3932-+ writel(val, regs + NFI_RANDOM_CNFG);
3933-+
3934-+ return 0;
3935-+}
3936-+
3937-+static int nfi_disable_randomizer(struct nfi *nfi)
3938-+{
3939-+ struct nfi_base *nb = nfi_to_base(nfi);
3940-+
3941-+ writel(0, nb->res.nfi_regs + NFI_RANDOM_CNFG);
3942-+
3943-+ return 0;
3944-+}
3945-+
3946-+static int nfi_irq_handler(int irq, void *data)
3947-+{
3948-+ struct nfi_base *nb = (struct nfi_base *) data;
3949-+ void *regs = nb->res.nfi_regs;
3950-+ u16 status, en;
3951-+
3952-+ status = readw(regs + NFI_INTR_STA);
3953-+ en = readw(regs + NFI_INTR_EN);
3954-+
3955-+ if (!(status & en))
3956-+ return NAND_IRQ_NONE;
3957-+
3958-+ writew(~status & en, regs + NFI_INTR_EN);
3959-+
3960-+ nandx_event_complete(nb->done);
3961-+
3962-+ return NAND_IRQ_HANDLED;
3963-+}
3964-+
3965-+static int nfi_select_chip(struct nfi *nfi, int cs)
3966-+{
3967-+ struct nfi_base *nb = nfi_to_base(nfi);
3968-+
3969-+ writel(cs, nb->res.nfi_regs + NFI_CSEL);
3970-+
3971-+ return 0;
3972-+}
3973-+
3974-+static inline void set_op_mode(void *regs, u32 mode)
3975-+{
3976-+ u32 val = readl(regs + NFI_CNFG);
3977-+
3978-+ val &= ~CNFG_OP_MODE_MASK;
3979-+ val |= mode;
3980-+
3981-+ writel(val, regs + NFI_CNFG);
3982-+}
3983-+
3984-+static int nfi_reset(struct nfi *nfi)
3985-+{
3986-+ struct nfi_base *nb = nfi_to_base(nfi);
3987-+ void *regs = nb->res.nfi_regs;
3988-+ int ret, val;
3989-+
3990-+ /* The NFI reset to reset all registers and force the NFI
3991-+ * master be early terminated
3992-+ */
3993-+ writel(CON_FIFO_FLUSH | CON_NFI_RST, regs + NFI_CON);
3994-+
3995-+ /* check state of NFI internal FSM and NAND interface FSM */
3996-+ ret = readl_poll_timeout_atomic(regs + NFI_MASTER_STA, val,
3997-+ !(val & MASTER_BUS_BUSY),
3998-+ 10, NFI_TIMEOUT);
3999-+ if (ret)
4000-+ pr_info("nfi reset timeout...\n");
4001-+
4002-+ writel(CON_FIFO_FLUSH | CON_NFI_RST, regs + NFI_CON);
4003-+ writew(STAR_DE, regs + NFI_STRDATA);
4004-+
4005-+ return ret;
4006-+}
4007-+
4008-+static void bad_mark_swap(struct nfi *nfi, u8 *buf, u8 *fdm)
4009-+{
4010-+ struct nfi_base *nb = nfi_to_base(nfi);
4011-+ u32 start_sector = div_down(nb->col, nfi->sector_size);
4012-+ u32 data_mark_pos;
4013-+ u8 temp;
4014-+
4015-+ /* raw access, no need to do swap. */
4016-+ if (!nb->ecc_en)
4017-+ return;
4018-+
4019-+ if (!buf || !fdm)
4020-+ return;
4021-+
4022-+ if (nb->bad_mark_ctrl.sector < start_sector ||
4023-+ nb->bad_mark_ctrl.sector > start_sector + nb->rw_sectors)
4024-+ return;
4025-+
4026-+ data_mark_pos = nb->bad_mark_ctrl.position +
4027-+ (nb->bad_mark_ctrl.sector - start_sector) *
4028-+ nfi->sector_size;
4029-+
4030-+ temp = *fdm;
4031-+ *fdm = *(buf + data_mark_pos);
4032-+ *(buf + data_mark_pos) = temp;
4033-+}
4034-+
4035-+static u8 *fdm_shift(struct nfi *nfi, u8 *fdm, int sector)
4036-+{
4037-+ struct nfi_base *nb = nfi_to_base(nfi);
4038-+ u8 *pos;
4039-+
4040-+ if (!fdm)
4041-+ return NULL;
4042-+
4043-+ /* map the sector's FDM data to free oob:
4044-+ * the beginning of the oob area stores the FDM data of bad mark sectors
4045-+ */
4046-+ if (sector < nb->bad_mark_ctrl.sector)
4047-+ pos = fdm + (sector + 1) * nfi->fdm_size;
4048-+ else if (sector == nb->bad_mark_ctrl.sector)
4049-+ pos = fdm;
4050-+ else
4051-+ pos = fdm + sector * nfi->fdm_size;
4052-+
4053-+ return pos;
4054-+
4055-+}
4056-+
4057-+static void set_bad_mark_ctrl(struct nfi_base *nb)
4058-+{
4059-+ int temp, page_size = nb->format.page_size;
4060-+
4061-+ nb->bad_mark_ctrl.bad_mark_swap = bad_mark_swap;
4062-+ nb->bad_mark_ctrl.fdm_shift = fdm_shift;
4063-+
4064-+ temp = nb->nfi.sector_size + nb->nfi.sector_spare_size;
4065-+ nb->bad_mark_ctrl.sector = div_down(page_size, temp);
4066-+ nb->bad_mark_ctrl.position = reminder(page_size, temp);
4067-+}
4068-+
4069-+/* NOTE: check if page_size valid future */
4070-+static int setup_format(struct nfi_base *nb, int spare_idx)
4071-+{
4072-+ struct nfi *nfi = &nb->nfi;
4073-+ u32 page_size = nb->format.page_size;
4074-+ u32 val;
4075-+
4076-+ switch (page_size) {
4077-+ case 512:
4078-+ val = PAGEFMT_512_2K | PAGEFMT_SEC_SEL_512;
4079-+ break;
4080-+
4081-+ case KB(2):
4082-+ if (nfi->sector_size == 512)
4083-+ val = PAGEFMT_2K_4K | PAGEFMT_SEC_SEL_512;
4084-+ else
4085-+ val = PAGEFMT_512_2K;
4086-+
4087-+ break;
4088-+
4089-+ case KB(4):
4090-+ if (nfi->sector_size == 512)
4091-+ val = PAGEFMT_4K_8K | PAGEFMT_SEC_SEL_512;
4092-+ else
4093-+ val = PAGEFMT_2K_4K;
4094-+
4095-+ break;
4096-+
4097-+ case KB(8):
4098-+ if (nfi->sector_size == 512)
4099-+ val = PAGEFMT_8K_16K | PAGEFMT_SEC_SEL_512;
4100-+ else
4101-+ val = PAGEFMT_4K_8K;
4102-+
4103-+ break;
4104-+
4105-+ case KB(16):
4106-+ val = PAGEFMT_8K_16K;
4107-+ break;
4108-+
4109-+ default:
4110-+ pr_info("invalid page len: %d\n", page_size);
4111-+ return -EINVAL;
4112-+ }
4113-+
4114-+ val |= spare_idx << PAGEFMT_SPARE_SHIFT;
4115-+ val |= nfi->fdm_size << PAGEFMT_FDM_SHIFT;
4116-+ val |= nfi->fdm_ecc_size << PAGEFMT_FDM_ECC_SHIFT;
4117-+ writel(val, nb->res.nfi_regs + NFI_PAGEFMT);
4118-+
4119-+ if (nb->custom_sector_en) {
4120-+ val = nfi->sector_spare_size + nfi->sector_size;
4121-+ val |= SECCUS_SIZE_EN;
4122-+ writel(val, nb->res.nfi_regs + NFI_SECCUS_SIZE);
4123-+ }
4124-+
4125-+ return 0;
4126-+}
4127-+
4128-+static int adjust_spare(struct nfi_base *nb, int *spare)
4129-+{
4130-+ int multi = nb->nfi.sector_size == 512 ? 1 : 2;
4131-+ int i, count = nb->caps->spare_size_num;
4132-+
4133-+ if (*spare >= nb->caps->spare_size[count - 1] * multi) {
4134-+ *spare = nb->caps->spare_size[count - 1] * multi;
4135-+ return count - 1;
4136-+ }
4137-+
4138-+ if (*spare < nb->caps->spare_size[0] * multi)
4139-+ return -EINVAL;
4140-+
4141-+ for (i = 1; i < count; i++) {
4142-+ if (*spare < nb->caps->spare_size[i] * multi) {
4143-+ *spare = nb->caps->spare_size[i - 1] * multi;
4144-+ return i - 1;
4145-+ }
4146-+ }
4147-+
4148-+ return -EINVAL;
4149-+}
4150-+
4151-+static int nfi_set_format(struct nfi *nfi, struct nfi_format *format)
4152-+{
4153-+ struct nfi_base *nb = nfi_to_base(nfi);
4154-+ struct nfiecc *ecc = nb->ecc;
4155-+ int ecc_strength = format->ecc_req;
4156-+ int min_fdm, min_ecc, max_ecc;
4157-+ u32 temp, page_sectors;
4158-+ int spare_idx = 0;
4159-+
4160-+ if (!nb->buf) {
4161-+#if NANDX_BULK_IO_USE_DRAM
4162-+ nb->buf = NANDX_NFI_BUF_ADDR;
4163-+#else
4164-+ nb->buf = mem_alloc(1, format->page_size + format->spare_size);
4165-+#endif
4166-+ if (!nb->buf)
4167-+ return -ENOMEM;
4168-+ }
4169-+
4170-+ nb->format = *format;
4171-+
4172-+ /* ToBeFixed: for spi nand, now sector size is 512,
4173-+ * it should be same with slc.
4174-+ */
4175-+ nfi->sector_size = 512;
4176-+ /* format->ecc_req is the requirement per 1KB */
4177-+ ecc_strength >>= 1;
4178-+
4179-+ page_sectors = div_down(format->page_size, nfi->sector_size);
4180-+ nfi->sector_spare_size = div_down(format->spare_size, page_sectors);
4181-+
4182-+ if (!nb->custom_sector_en) {
4183-+ spare_idx = adjust_spare(nb, &nfi->sector_spare_size);
4184-+ if (spare_idx < 0)
4185-+ return -EINVAL;
4186-+ }
4187-+
4188-+ /* calculate ecc strength and fdm size */
4189-+ temp = (nfi->sector_spare_size - nb->caps->max_fdm_size) * 8;
4190-+ min_ecc = div_down(temp, nb->caps->ecc_parity_bits);
4191-+ min_ecc = ecc->adjust_strength(ecc, min_ecc);
4192-+ if (min_ecc < 0)
4193-+ return -EINVAL;
4194-+
4195-+ temp = div_up(nb->res.min_oob_req, page_sectors);
4196-+ temp = (nfi->sector_spare_size - temp) * 8;
4197-+ max_ecc = div_down(temp, nb->caps->ecc_parity_bits);
4198-+ max_ecc = ecc->adjust_strength(ecc, max_ecc);
4199-+ if (max_ecc < 0)
4200-+ return -EINVAL;
4201-+
4202-+ temp = div_up(temp * nb->caps->ecc_parity_bits, 8);
4203-+ temp = nfi->sector_spare_size - temp;
4204-+ min_fdm = min_t(u32, temp, (u32)nb->caps->max_fdm_size);
4205-+
4206-+ if (ecc_strength > max_ecc) {
4207-+ pr_info("required ecc strength %d, max supported %d\n",
4208-+ ecc_strength, max_ecc);
4209-+ nfi->ecc_strength = max_ecc;
4210-+ nfi->fdm_size = min_fdm;
4211-+ } else if (format->ecc_req < min_ecc) {
4212-+ nfi->ecc_strength = min_ecc;
4213-+ nfi->fdm_size = nb->caps->max_fdm_size;
4214-+ } else {
4215-+ ecc_strength = ecc->adjust_strength(ecc, ecc_strength);
4216-+ if (ecc_strength < 0)
4217-+ return -EINVAL;
4218-+
4219-+ nfi->ecc_strength = ecc_strength;
4220-+ temp = div_up(ecc_strength * nb->caps->ecc_parity_bits, 8);
4221-+ nfi->fdm_size = nfi->sector_spare_size - temp;
4222-+ }
4223-+
4224-+ nb->page_sectors = div_down(format->page_size, nfi->sector_size);
4225-+
4226-+ /* some IC has fixed fdm_ecc_size, if not assigend, set to fdm_size */
4227-+ nfi->fdm_ecc_size = nb->caps->fdm_ecc_size ? : nfi->fdm_size;
4228-+
4229-+ nfi->ecc_parity_size = div_up(nfi->ecc_strength *
4230-+ nb->caps->ecc_parity_bits,
4231-+ 8);
4232-+ set_bad_mark_ctrl(nb);
4233-+
4234-+ pr_debug("sector_size: %d\n", nfi->sector_size);
4235-+ pr_debug("sector_spare_size: %d\n", nfi->sector_spare_size);
4236-+ pr_debug("fdm_size: %d\n", nfi->fdm_size);
4237-+ pr_debug("fdm_ecc_size: %d\n", nfi->fdm_ecc_size);
4238-+ pr_debug("ecc_strength: %d\n", nfi->ecc_strength);
4239-+ pr_debug("ecc_parity_size: %d\n", nfi->ecc_parity_size);
4240-+
4241-+ return setup_format(nb, spare_idx);
4242-+}
4243-+
4244-+static int nfi_ctrl(struct nfi *nfi, int cmd, void *args)
4245-+{
4246-+ struct nfi_base *nb = nfi_to_base(nfi);
4247-+ int ret = 0;
4248-+
4249-+ switch (cmd) {
4250-+ case NFI_CTRL_DMA:
4251-+ nb->dma_en = *(bool *)args;
4252-+ break;
4253-+
4254-+ case NFI_CTRL_AUTOFORMAT:
4255-+ nb->auto_format = *(bool *)args;
4256-+ break;
4257-+
4258-+ case NFI_CTRL_NFI_IRQ:
4259-+ nb->nfi_irq_en = *(bool *)args;
4260-+ break;
4261-+
4262-+ case NFI_CTRL_PAGE_IRQ:
4263-+ nb->page_irq_en = *(bool *)args;
4264-+ break;
4265-+
4266-+ case NFI_CTRL_BAD_MARK_SWAP:
4267-+ nb->bad_mark_swap_en = *(bool *)args;
4268-+ break;
4269-+
4270-+ case NFI_CTRL_ECC:
4271-+ nb->ecc_en = *(bool *)args;
4272-+ break;
4273-+
4274-+ case NFI_CTRL_ECC_MODE:
4275-+ nb->ecc_mode = *(enum nfiecc_mode *)args;
4276-+ break;
4277-+
4278-+ case NFI_CTRL_ECC_CLOCK:
4279-+ /* NOTE: it seems that there's nothing need to do
4280-+ * if new IC need, just add tht logic
4281-+ */
4282-+ nb->ecc_clk_en = *(bool *)args;
4283-+ break;
4284-+
4285-+ case NFI_CTRL_ECC_IRQ:
4286-+ nb->ecc_irq_en = *(bool *)args;
4287-+ break;
4288-+
4289-+ case NFI_CTRL_ECC_DECODE_MODE:
4290-+ nb->ecc_deccon = *(enum nfiecc_deccon *)args;
4291-+ break;
4292-+
4293-+ default:
4294-+ pr_info("invalid arguments.\n");
4295-+ ret = -EOPNOTSUPP;
4296-+ break;
4297-+ }
4298-+
4299-+ pr_debug("%s: set cmd(%d) to %d\n", __func__, cmd, *(int *)args);
4300-+ return ret;
4301-+}
4302-+
4303-+static int nfi_send_cmd(struct nfi *nfi, short cmd)
4304-+{
4305-+ struct nfi_base *nb = nfi_to_base(nfi);
4306-+ void *regs = nb->res.nfi_regs;
4307-+ int ret;
4308-+ u32 val;
4309-+
4310-+ pr_debug("%s: cmd 0x%x\n", __func__, cmd);
4311-+
4312-+ if (cmd < 0)
4313-+ return -EINVAL;
4314-+
4315-+ set_op_mode(regs, nb->op_mode);
4316-+
4317-+ writel(cmd, regs + NFI_CMD);
4318-+
4319-+ ret = readl_poll_timeout_atomic(regs + NFI_STA,
4320-+ val, !(val & STA_CMD),
4321-+ 5, NFI_TIMEOUT);
4322-+ if (ret)
4323-+ pr_info("send cmd 0x%x timeout\n", cmd);
4324-+
4325-+ return ret;
4326-+}
4327-+
4328-+static int nfi_send_addr(struct nfi *nfi, int col, int row,
4329-+ int col_cycle, int row_cycle)
4330-+{
4331-+ struct nfi_base *nb = nfi_to_base(nfi);
4332-+ void *regs = nb->res.nfi_regs;
4333-+ int ret;
4334-+ u32 val;
4335-+
4336-+ pr_debug("%s: col 0x%x, row 0x%x, col_cycle 0x%x, row_cycle 0x%x\n",
4337-+ __func__, col, row, col_cycle, row_cycle);
4338-+
4339-+ nb->col = col;
4340-+ nb->row = row;
4341-+
4342-+ writel(col, regs + NFI_COLADDR);
4343-+ writel(row, regs + NFI_ROWADDR);
4344-+ writel(col_cycle | (row_cycle << ROW_SHIFT), regs + NFI_ADDRNOB);
4345-+
4346-+ ret = readl_poll_timeout_atomic(regs + NFI_STA,
4347-+ val, !(val & STA_ADDR),
4348-+ 5, NFI_TIMEOUT);
4349-+ if (ret)
4350-+ pr_info("send address timeout\n");
4351-+
4352-+ return ret;
4353-+}
4354-+
4355-+static int nfi_trigger(struct nfi *nfi)
4356-+{
4357-+ /* Nothing need to do. */
4358-+ return 0;
4359-+}
4360-+
4361-+static inline int wait_io_ready(void *regs)
4362-+{
4363-+ u32 val;
4364-+ int ret;
4365-+
4366-+ ret = readl_poll_timeout_atomic(regs + NFI_PIO_DIRDY,
4367-+ val, val & PIO_DI_RDY,
4368-+ 2, NFI_TIMEOUT);
4369-+ if (ret)
4370-+ pr_info("wait io ready timeout\n");
4371-+
4372-+ return ret;
4373-+}
4374-+
4375-+static int wait_ready_irq(struct nfi_base *nb, u32 timeout)
4376-+{
4377-+ void *regs = nb->res.nfi_regs;
4378-+ int ret;
4379-+ u32 val;
4380-+
4381-+ writel(0xf1, regs + NFI_CNRNB);
4382-+ nandx_event_init(nb->done);
4383-+
4384-+ writel(INTR_BUSY_RETURN_EN, (void *)(regs + NFI_INTR_EN));
4385-+
4386-+ /**
4387-+ * check if nand already bean ready,
4388-+ * avoid issue that casued by missing irq-event.
4389-+ */
4390-+ val = readl(regs + NFI_STA);
4391-+ if (val & STA_BUSY2READY) {
4392-+ readl(regs + NFI_INTR_STA);
4393-+ writel(0, (void *)(regs + NFI_INTR_EN));
4394-+ return 0;
4395-+ }
4396-+
4397-+ ret = nandx_event_wait_complete(nb->done, timeout);
4398-+
4399-+ writew(0, regs + NFI_CNRNB);
4400-+ return ret;
4401-+}
4402-+
4403-+static void wait_ready_twhr2(struct nfi_base *nb, u32 timeout)
4404-+{
4405-+ /* NOTE: this for tlc */
4406-+}
4407-+
4408-+static int wait_ready_poll(struct nfi_base *nb, u32 timeout)
4409-+{
4410-+ void *regs = nb->res.nfi_regs;
4411-+ int ret;
4412-+ u32 val;
4413-+
4414-+ writel(0x21, regs + NFI_CNRNB);
4415-+ ret = readl_poll_timeout_atomic(regs + NFI_STA, val,
4416-+ val & STA_BUSY2READY,
4417-+ 2, timeout);
4418-+ writew(0, regs + NFI_CNRNB);
4419-+
4420-+ return ret;
4421-+}
4422-+
4423-+static int nfi_wait_ready(struct nfi *nfi, int type, u32 timeout)
4424-+{
4425-+ struct nfi_base *nb = nfi_to_base(nfi);
4426-+ int ret;
4427-+
4428-+ switch (type) {
4429-+ case NAND_WAIT_IRQ:
4430-+ if (nb->nfi_irq_en)
4431-+ ret = wait_ready_irq(nb, timeout);
4432-+ else
4433-+ ret = -EINVAL;
4434-+
4435-+ break;
4436-+
4437-+ case NAND_WAIT_POLLING:
4438-+ ret = wait_ready_poll(nb, timeout);
4439-+ break;
4440-+
4441-+ case NAND_WAIT_TWHR2:
4442-+ wait_ready_twhr2(nb, timeout);
4443-+ ret = 0;
4444-+ break;
4445-+
4446-+ default:
4447-+ ret = -EINVAL;
4448-+ break;
4449-+ }
4450-+
4451-+ if (ret)
4452-+ pr_info("%s: type 0x%x, timeout 0x%x\n",
4453-+ __func__, type, timeout);
4454-+
4455-+ return ret;
4456-+}
4457-+
4458-+static int enable_ecc_decode(struct nfi_base *nb, int sectors)
4459-+{
4460-+ struct nfi *nfi = &nb->nfi;
4461-+ struct nfiecc *ecc = nb->ecc;
4462-+
4463-+ ecc->config.op = ECC_DECODE;
4464-+ ecc->config.mode = nb->ecc_mode;
4465-+ ecc->config.deccon = nb->ecc_deccon;
4466-+ ecc->config.sectors = sectors;
4467-+ ecc->config.len = nfi->sector_size + nfi->fdm_ecc_size;
4468-+ ecc->config.strength = nfi->ecc_strength;
4469-+
4470-+ return ecc->enable(ecc);
4471-+}
4472-+
4473-+static int enable_ecc_encode(struct nfi_base *nb)
4474-+{
4475-+ struct nfiecc *ecc = nb->ecc;
4476-+ struct nfi *nfi = &nb->nfi;
4477-+
4478-+ ecc->config.op = ECC_ENCODE;
4479-+ ecc->config.mode = nb->ecc_mode;
4480-+ ecc->config.len = nfi->sector_size + nfi->fdm_ecc_size;
4481-+ ecc->config.strength = nfi->ecc_strength;
4482-+
4483-+ return ecc->enable(ecc);
4484-+}
4485-+
4486-+static void read_fdm(struct nfi_base *nb, u8 *fdm, int start_sector,
4487-+ int sectors)
4488-+{
4489-+ void *regs = nb->res.nfi_regs;
4490-+ int j, i = start_sector;
4491-+ u32 vall, valm;
4492-+ u8 *buf = fdm;
4493-+
4494-+ for (; i < start_sector + sectors; i++) {
4495-+ if (nb->bad_mark_swap_en)
4496-+ buf = nb->bad_mark_ctrl.fdm_shift(&nb->nfi, fdm, i);
4497-+
4498-+ vall = readl(regs + NFI_FDML(i));
4499-+ valm = readl(regs + NFI_FDMM(i));
4500-+
4501-+ for (j = 0; j < nb->nfi.fdm_size; j++)
4502-+ *buf++ = (j >= 4 ? valm : vall) >> ((j & 3) << 3);
4503-+ }
4504-+}
4505-+
4506-+static void write_fdm(struct nfi_base *nb, u8 *fdm)
4507-+{
4508-+ struct nfi *nfi = &nb->nfi;
4509-+ void *regs = nb->res.nfi_regs;
4510-+ u32 vall, valm;
4511-+ int i, j;
4512-+ u8 *buf = fdm;
4513-+
4514-+ for (i = 0; i < nb->page_sectors; i++) {
4515-+ if (nb->bad_mark_swap_en)
4516-+ buf = nb->bad_mark_ctrl.fdm_shift(nfi, fdm, i);
4517-+
4518-+ vall = 0;
4519-+ for (j = 0; j < 4; j++)
4520-+ vall |= (j < nfi->fdm_size ? *buf++ : 0xff) << (j * 8);
4521-+ writel(vall, regs + NFI_FDML(i));
4522-+
4523-+ valm = 0;
4524-+ for (j = 0; j < 4; j++)
4525-+ valm |= (j < nfi->fdm_size ? *buf++ : 0xff) << (j * 8);
4526-+ writel(valm, regs + NFI_FDMM(i));
4527-+ }
4528-+}
4529-+
4530-+/* NOTE: pio not use auto format */
4531-+static int pio_rx_data(struct nfi_base *nb, u8 *data, u8 *fdm,
4532-+ int sectors)
4533-+{
4534-+ struct nfiecc_status ecc_status;
4535-+ struct nfi *nfi = &nb->nfi;
4536-+ void *regs = nb->res.nfi_regs;
4537-+ u32 val, bitflips = 0;
4538-+ int len, ret, i;
4539-+ u8 *buf;
4540-+
4541-+ val = readl(regs + NFI_CNFG) | CNFG_BYTE_RW;
4542-+ writel(val, regs + NFI_CNFG);
4543-+
4544-+ len = nfi->sector_size + nfi->sector_spare_size;
4545-+ len *= sectors;
4546-+
4547-+ for (i = 0; i < len; i++) {
4548-+ ret = wait_io_ready(regs);
4549-+ if (ret)
4550-+ return ret;
4551-+
4552-+ nb->buf[i] = readb(regs + NFI_DATAR);
4553-+ }
4554-+
4555-+ /* TODO: do error handle for autoformat setting of pio */
4556-+ if (nb->ecc_en) {
4557-+ for (i = 0; i < sectors; i++) {
4558-+ buf = nb->buf + i * (nfi->sector_size +
4559-+ nfi->sector_spare_size);
4560-+ ret = nb->ecc->correct_data(nb->ecc, &ecc_status,
4561-+ buf, i);
4562-+ if (data)
4563-+ memcpy(data + i * nfi->sector_size,
4564-+ buf, nfi->sector_size);
4565-+ if (fdm)
4566-+ memcpy(fdm + i * nfi->fdm_size,
4567-+ buf + nfi->sector_size, nfi->fdm_size);
4568-+ if (ret) {
4569-+ ret = nb->ecc->decode_status(nb->ecc, i, 1);
4570-+ if (ret < 0)
4571-+ return ret;
4572-+
4573-+ bitflips = max_t(int, (int)bitflips, ret);
4574-+ }
4575-+ }
4576-+
4577-+ return bitflips;
4578-+ }
4579-+
4580-+ /* raw read, only data not null, and its length should be $len */
4581-+ if (data)
4582-+ memcpy(data, nb->buf, len);
4583-+
4584-+ return 0;
4585-+}
4586-+
4587-+static int pio_tx_data(struct nfi_base *nb, u8 *data, u8 *fdm,
4588-+ int sectors)
4589-+{
4590-+ struct nfi *nfi = &nb->nfi;
4591-+ void *regs = nb->res.nfi_regs;
4592-+ u32 i, val;
4593-+ int len, ret;
4594-+
4595-+ val = readw(regs + NFI_CNFG) | CNFG_BYTE_RW;
4596-+ writew(val, regs + NFI_CNFG);
4597-+
4598-+ len = nb->ecc_en ? nfi->sector_size :
4599-+ nfi->sector_size + nfi->sector_spare_size;
4600-+ len *= sectors;
4601-+
4602-+ /* data shouldn't null,
4603-+ * and if ecc enable ,fdm been written in prepare process
4604-+ */
4605-+ for (i = 0; i < len; i++) {
4606-+ ret = wait_io_ready(regs);
4607-+ if (ret)
4608-+ return ret;
4609-+ writeb(data[i], regs + NFI_DATAW);
4610-+ }
4611-+
4612-+ return 0;
4613-+}
4614-+
4615-+static bool is_page_empty(struct nfi_base *nb, u8 *data, u8 *fdm,
4616-+ int sectors)
4617-+{
4618-+ u32 empty = readl(nb->res.nfi_regs + NFI_STA) & STA_EMP_PAGE;
4619-+
4620-+ if (empty) {
4621-+ pr_info("empty page!\n");
4622-+ return true;
4623-+ }
4624-+
4625-+ return false;
4626-+}
4627-+
4628-+static int rw_prepare(struct nfi_base *nb, int sectors, u8 *data,
4629-+ u8 *fdm, bool read)
4630-+{
4631-+ void *regs = nb->res.nfi_regs;
4632-+ u32 len = nb->nfi.sector_size * sectors;
4633-+ bool irq_en = nb->dma_en && nb->nfi_irq_en;
4634-+ void *dma_addr;
4635-+ u32 val;
4636-+ int ret;
4637-+
4638-+ nb->rw_sectors = sectors;
4639-+
4640-+ if (irq_en) {
4641-+ nandx_event_init(nb->done);
4642-+ writel(INTR_AHB_DONE_EN, regs + NFI_INTR_EN);
4643-+ }
4644-+
4645-+ val = readw(regs + NFI_CNFG);
4646-+ if (read)
4647-+ val |= CNFG_READ_EN;
4648-+ else
4649-+ val &= ~CNFG_READ_EN;
4650-+
4651-+ /* as design, now, auto format enabled when ecc enabled */
4652-+ if (nb->ecc_en) {
4653-+ val |= CNFG_HW_ECC_EN | CNFG_AUTO_FMT_EN;
4654-+
4655-+ if (read)
4656-+ ret = enable_ecc_decode(nb, sectors);
4657-+ else
4658-+ ret = enable_ecc_encode(nb);
4659-+
4660-+ if (ret) {
4661-+ pr_info("%s: ecc enable %s fail!\n", __func__,
4662-+ read ? "decode" : "encode");
4663-+ return ret;
4664-+ }
4665-+ } else {
4666-+ val &= ~(CNFG_HW_ECC_EN | CNFG_AUTO_FMT_EN);
4667-+ }
4668-+
4669-+ if (!read && nb->bad_mark_swap_en)
4670-+ nb->bad_mark_ctrl.bad_mark_swap(&nb->nfi, data, fdm);
4671-+
4672-+ if (!nb->ecc_en && read)
4673-+ len += sectors * nb->nfi.sector_spare_size;
4674-+
4675-+ if (nb->dma_en) {
4676-+ val |= CNFG_DMA_BURST_EN | CNFG_AHB;
4677-+
4678-+ if (read) {
4679-+ dma_addr = (void *)(unsigned long)nandx_dma_map(
4680-+ nb->res.dev, nb->buf,
4681-+ (u64)len, NDMA_FROM_DEV);
4682-+ } else {
4683-+ memcpy(nb->buf, data, len);
4684-+ dma_addr = (void *)(unsigned long)nandx_dma_map(
4685-+ nb->res.dev, nb->buf,
4686-+ (u64)len, NDMA_TO_DEV);
4687-+ }
4688-+
4689-+ writel((unsigned long)dma_addr, (void *)regs + NFI_STRADDR);
4690-+
4691-+ nb->access_len = len;
4692-+ nb->dma_addr = dma_addr;
4693-+ }
4694-+
4695-+ if (nb->ecc_en && !read && fdm)
4696-+ write_fdm(nb, fdm);
4697-+
4698-+ writew(val, regs + NFI_CNFG);
4699-+ /* setup R/W sector number */
4700-+ writel(sectors << CON_SEC_SHIFT, regs + NFI_CON);
4701-+
4702-+ return 0;
4703-+}
4704-+
4705-+static void rw_trigger(struct nfi_base *nb, bool read)
4706-+{
4707-+ void *regs = nb->res.nfi_regs;
4708-+ u32 val;
4709-+
4710-+ val = read ? CON_BRD : CON_BWR;
4711-+ val |= readl(regs + NFI_CON);
4712-+ writel(val, regs + NFI_CON);
4713-+
4714-+ writel(STAR_EN, regs + NFI_STRDATA);
4715-+}
4716-+
4717-+static int rw_wait_done(struct nfi_base *nb, int sectors, bool read)
4718-+{
4719-+ void *regs = nb->res.nfi_regs;
4720-+ bool irq_en = nb->dma_en && nb->nfi_irq_en;
4721-+ int ret;
4722-+ u32 val;
4723-+
4724-+ if (irq_en) {
4725-+ ret = nandx_event_wait_complete(nb->done, NFI_TIMEOUT);
4726-+ if (!ret) {
4727-+ writew(0, regs + NFI_INTR_EN);
4728-+ return ret;
4729-+ }
4730-+ }
4731-+
4732-+ if (read) {
4733-+ ret = readl_poll_timeout_atomic(regs + NFI_BYTELEN, val,
4734-+ ADDRCNTR_SEC(val) >=
4735-+ (u32)sectors,
4736-+ 2, NFI_TIMEOUT);
4737-+ /* HW issue: if not wait ahb done, need polling bus busy */
4738-+ if (!ret && !irq_en)
4739-+ ret = readl_poll_timeout_atomic(regs + NFI_MASTER_STA,
4740-+ val,
4741-+ !(val &
4742-+ MASTER_BUS_BUSY),
4743-+ 2, NFI_TIMEOUT);
4744-+ } else {
4745-+ ret = readl_poll_timeout_atomic(regs + NFI_ADDRCNTR, val,
4746-+ ADDRCNTR_SEC(val) >=
4747-+ (u32)sectors,
4748-+ 2, NFI_TIMEOUT);
4749-+ }
4750-+
4751-+ if (ret) {
4752-+ pr_info("do page %s timeout\n", read ? "read" : "write");
4753-+ return ret;
4754-+ }
4755-+
4756-+ if (read && nb->ecc_en) {
4757-+ ret = nb->ecc->wait_done(nb->ecc);
4758-+ if (ret)
4759-+ return ret;
4760-+
4761-+ return nb->ecc->decode_status(nb->ecc, 0, sectors);
4762-+ }
4763-+
4764-+ return 0;
4765-+}
4766-+
4767-+static int rw_data(struct nfi_base *nb, u8 *data, u8 *fdm, int sectors,
4768-+ bool read)
4769-+{
4770-+ if (read && nb->dma_en && nb->ecc_en && fdm)
4771-+ read_fdm(nb, fdm, 0, sectors);
4772-+
4773-+ if (!nb->dma_en) {
4774-+ if (read)
4775-+ return pio_rx_data(nb, data, fdm, sectors);
4776-+
4777-+ return pio_tx_data(nb, data, fdm, sectors);
4778-+ }
4779-+
4780-+ return 0;
4781-+}
4782-+
4783-+static void rw_complete(struct nfi_base *nb, u8 *data, u8 *fdm,
4784-+ bool read)
4785-+{
4786-+ int data_len = 0;
4787-+ bool is_empty;
4788-+
4789-+ if (nb->dma_en) {
4790-+ if (read) {
4791-+ nandx_dma_unmap(nb->res.dev, nb->buf, nb->dma_addr,
4792-+ (u64)nb->access_len, NDMA_FROM_DEV);
4793-+
4794-+ if (data) {
4795-+ data_len = nb->rw_sectors * nb->nfi.sector_size;
4796-+ memcpy(data, nb->buf, data_len);
4797-+ }
4798-+
4799-+ if (fdm)
4800-+ memcpy(fdm, nb->buf + data_len,
4801-+ nb->access_len - data_len);
4802-+
4803-+ if (nb->read_status == -ENANDREAD) {
4804-+ is_empty = nb->is_page_empty(nb, data, fdm,
4805-+ nb->rw_sectors);
4806-+ if (is_empty)
4807-+ nb->read_status = 0;
4808-+ }
4809-+ } else {
4810-+ nandx_dma_unmap(nb->res.dev, nb->buf, nb->dma_addr,
4811-+ (u64)nb->access_len, NDMA_TO_DEV);
4812-+ }
4813-+ }
4814-+
4815-+ /* whether it's reading or writing, we all check if nee swap
4816-+ * for write, we need to restore data
4817-+ */
4818-+ if (nb->bad_mark_swap_en)
4819-+ nb->bad_mark_ctrl.bad_mark_swap(&nb->nfi, data, fdm);
4820-+
4821-+ if (nb->ecc_en)
4822-+ nb->ecc->disable(nb->ecc);
4823-+
4824-+ writel(0, nb->res.nfi_regs + NFI_CNFG);
4825-+ writel(0, nb->res.nfi_regs + NFI_CON);
4826-+}
4827-+
4828-+static int nfi_read_sectors(struct nfi *nfi, u8 *data, u8 *fdm,
4829-+ int sectors)
4830-+{
4831-+ struct nfi_base *nb = nfi_to_base(nfi);
4832-+ int bitflips = 0, ret;
4833-+
4834-+ pr_debug("%s: read page#%d\n", __func__, nb->row);
4835-+ pr_debug("%s: data address 0x%x, fdm address 0x%x, sectors 0x%x\n",
4836-+ __func__, (u32)((unsigned long)data),
4837-+ (u32)((unsigned long)fdm), sectors);
4838-+
4839-+ nb->read_status = 0;
4840-+
4841-+ ret = nb->rw_prepare(nb, sectors, data, fdm, true);
4842-+ if (ret)
4843-+ return ret;
4844-+
4845-+ nb->rw_trigger(nb, true);
4846-+
4847-+ if (nb->dma_en) {
4848-+ ret = nb->rw_wait_done(nb, sectors, true);
4849-+ if (ret > 0)
4850-+ bitflips = ret;
4851-+ else if (ret == -ENANDREAD)
4852-+ nb->read_status = -ENANDREAD;
4853-+ else if (ret < 0)
4854-+ goto complete;
4855-+
4856-+ }
4857-+
4858-+ ret = nb->rw_data(nb, data, fdm, sectors, true);
4859-+ if (ret > 0)
4860-+ ret = max_t(int, ret, bitflips);
4861-+
4862-+complete:
4863-+ nb->rw_complete(nb, data, fdm, true);
4864-+
4865-+ if (nb->read_status == -ENANDREAD)
4866-+ return -ENANDREAD;
4867-+
4868-+ return ret;
4869-+}
4870-+
4871-+int nfi_write_page(struct nfi *nfi, u8 *data, u8 *fdm)
4872-+{
4873-+ struct nfi_base *nb = nfi_to_base(nfi);
4874-+ u32 sectors = div_down(nb->format.page_size, nfi->sector_size);
4875-+ int ret;
4876-+
4877-+ pr_debug("%s: data address 0x%x, fdm address 0x%x\n",
4878-+ __func__, (int)((unsigned long)data),
4879-+ (int)((unsigned long)fdm));
4880-+
4881-+ ret = nb->rw_prepare(nb, sectors, data, fdm, false);
4882-+ if (ret)
4883-+ return ret;
4884-+
4885-+ nb->rw_trigger(nb, false);
4886-+
4887-+ ret = nb->rw_data(nb, data, fdm, sectors, false);
4888-+ if (ret)
4889-+ return ret;
4890-+
4891-+ ret = nb->rw_wait_done(nb, sectors, false);
4892-+
4893-+ nb->rw_complete(nb, data, fdm, false);
4894-+
4895-+ return ret;
4896-+}
4897-+
4898-+static int nfi_rw_bytes(struct nfi *nfi, u8 *data, int count, bool read)
4899-+{
4900-+ struct nfi_base *nb = nfi_to_base(nfi);
4901-+ void *regs = nb->res.nfi_regs;
4902-+ int i, ret;
4903-+ u32 val;
4904-+
4905-+ for (i = 0; i < count; i++) {
4906-+ val = readl(regs + NFI_STA) & NFI_FSM_MASK;
4907-+ if (val != NFI_FSM_CUSTDATA) {
4908-+ val = readw(regs + NFI_CNFG) | CNFG_BYTE_RW;
4909-+ if (read)
4910-+ val |= CNFG_READ_EN;
4911-+ writew(val, regs + NFI_CNFG);
4912-+
4913-+ val = div_up(count, nfi->sector_size);
4914-+ val = (val << CON_SEC_SHIFT) | CON_BRD | CON_BWR;
4915-+ writel(val, regs + NFI_CON);
4916-+
4917-+ writew(STAR_EN, regs + NFI_STRDATA);
4918-+ }
4919-+
4920-+ ret = wait_io_ready(regs);
4921-+ if (ret)
4922-+ return ret;
4923-+
4924-+ if (read)
4925-+ data[i] = readb(regs + NFI_DATAR);
4926-+ else
4927-+ writeb(data[i], regs + NFI_DATAW);
4928-+ }
4929-+
4930-+ writel(0, nb->res.nfi_regs + NFI_CNFG);
4931-+
4932-+ return 0;
4933-+}
4934-+
4935-+static int nfi_read_bytes(struct nfi *nfi, u8 *data, int count)
4936-+{
4937-+ return nfi_rw_bytes(nfi, data, count, true);
4938-+}
4939-+
4940-+static int nfi_write_bytes(struct nfi *nfi, u8 *data, int count)
4941-+{
4942-+ return nfi_rw_bytes(nfi, data, count, false);
4943-+}
4944-+
4945-+/* As register map says, only when flash macro is idle,
4946-+ * sw reset or nand interface change can be issued
4947-+ */
4948-+static inline int wait_flash_macro_idle(void *regs)
4949-+{
4950-+ u32 val;
4951-+
4952-+ return readl_poll_timeout_atomic(regs + NFI_STA, val,
4953-+ val & FLASH_MACRO_IDLE, 2,
4954-+ NFI_TIMEOUT);
4955-+}
4956-+
4957-+#define ACCTIMING(tpoecs, tprecs, tc2r, tw2r, twh, twst, trlt) \
4958-+ ((tpoecs) << 28 | (tprecs) << 22 | (tc2r) << 16 | \
4959-+ (tw2r) << 12 | (twh) << 8 | (twst) << 4 | (trlt))
4960-+
4961-+static int nfi_set_sdr_timing(struct nfi *nfi, void *timing, u8 type)
4962-+{
4963-+ struct nand_sdr_timing *sdr = (struct nand_sdr_timing *) timing;
4964-+ struct nfi_base *nb = nfi_to_base(nfi);
4965-+ void *regs = nb->res.nfi_regs;
4966-+ u32 tpoecs, tprecs, tc2r, tw2r, twh, twst, trlt, tstrobe;
4967-+ u32 rate, val;
4968-+ int ret;
4969-+
4970-+ ret = wait_flash_macro_idle(regs);
4971-+ if (ret)
4972-+ return ret;
4973-+
4974-+ /* turn clock rate into KHZ */
4975-+ rate = nb->res.clock_1x / 1000;
4976-+
4977-+ tpoecs = max_t(u16, sdr->tALH, sdr->tCLH);
4978-+ tpoecs = div_up(tpoecs * rate, 1000000);
4979-+ tpoecs &= 0xf;
4980-+
4981-+ tprecs = max_t(u16, sdr->tCLS, sdr->tALS);
4982-+ tprecs = div_up(tprecs * rate, 1000000);
4983-+ tprecs &= 0x3f;
4984-+
4985-+ /* tc2r is in unit of 2T */
4986-+ tc2r = div_up(sdr->tCR * rate, 1000000);
4987-+ tc2r = div_down(tc2r, 2);
4988-+ tc2r &= 0x3f;
4989-+
4990-+ tw2r = div_up(sdr->tWHR * rate, 1000000);
4991-+ tw2r = div_down(tw2r, 2);
4992-+ tw2r &= 0xf;
4993-+
4994-+ twh = max_t(u16, sdr->tREH, sdr->tWH);
4995-+ twh = div_up(twh * rate, 1000000) - 1;
4996-+ twh &= 0xf;
4997-+
4998-+ twst = div_up(sdr->tWP * rate, 1000000) - 1;
4999-+ twst &= 0xf;
5000-+
5001-+ trlt = div_up(sdr->tRP * rate, 1000000) - 1;
5002-+ trlt &= 0xf;
5003-+
5004-+ /* If tREA is bigger than tRP, setup strobe sel here */
5005-+ if ((trlt + 1) * 1000000 / rate < sdr->tREA) {
5006-+ tstrobe = sdr->tREA - (trlt + 1) * 1000000 / rate;
5007-+ tstrobe = div_up(tstrobe * rate, 1000000);
5008-+ val = readl(regs + NFI_DEBUG_CON1);
5009-+ val &= ~STROBE_MASK;
5010-+ val |= tstrobe << STROBE_SHIFT;
5011-+ writel(val, regs + NFI_DEBUG_CON1);
5012-+ }
5013-+
5014-+ /*
5015-+ * ACCON: access timing control register
5016-+ * -------------------------------------
5017-+ * 31:28: tpoecs, minimum required time for CS post pulling down after
5018-+ * accessing the device
5019-+ * 27:22: tprecs, minimum required time for CS pre pulling down before
5020-+ * accessing the device
5021-+ * 21:16: tc2r, minimum required time from NCEB low to NREB low
5022-+ * 15:12: tw2r, minimum required time from NWEB high to NREB low.
5023-+ * 11:08: twh, write enable hold time
5024-+ * 07:04: twst, write wait states
5025-+ * 03:00: trlt, read wait states
5026-+ */
5027-+ val = ACCTIMING(tpoecs, tprecs, tc2r, tw2r, twh, twst, trlt);
5028-+ pr_info("acctiming: 0x%x\n", val);
5029-+ writel(val, regs + NFI_ACCCON);
5030-+
5031-+ /* set NAND type */
5032-+ writel(NAND_TYPE_ASYNC, regs + NFI_NAND_TYPE_CNFG);
5033-+
5034-+ return ret;
5035-+}
5036-+
5037-+static int nfi_set_timing(struct nfi *nfi, void *timing, int type)
5038-+{
5039-+ switch (type) {
5040-+ case NAND_TIMING_SDR:
5041-+ return nfi_set_sdr_timing(nfi, timing, type);
5042-+
5043-+ /* NOTE: for mlc/tlc */
5044-+ case NAND_TIMING_SYNC_DDR:
5045-+ case NAND_TIMING_TOGGLE_DDR:
5046-+ case NAND_TIMING_NVDDR2:
5047-+ default:
5048-+ return -EINVAL;
5049-+ }
5050-+
5051-+ return 0;
5052-+}
5053-+
5054-+static void set_nfi_funcs(struct nfi *nfi)
5055-+{
5056-+ nfi->select_chip = nfi_select_chip;
5057-+ nfi->set_format = nfi_set_format;
5058-+ nfi->nfi_ctrl = nfi_ctrl;
5059-+ nfi->set_timing = nfi_set_timing;
5060-+
5061-+ nfi->reset = nfi_reset;
5062-+ nfi->send_cmd = nfi_send_cmd;
5063-+ nfi->send_addr = nfi_send_addr;
5064-+ nfi->trigger = nfi_trigger;
5065-+
5066-+ nfi->write_page = nfi_write_page;
5067-+ nfi->write_bytes = nfi_write_bytes;
5068-+ nfi->read_sectors = nfi_read_sectors;
5069-+ nfi->read_bytes = nfi_read_bytes;
5070-+
5071-+ nfi->wait_ready = nfi_wait_ready;
5072-+
5073-+ nfi->enable_randomizer = nfi_enable_randomizer;
5074-+ nfi->disable_randomizer = nfi_disable_randomizer;
5075-+}
5076-+
5077-+static struct nfi_caps nfi_caps_mt7622 = {
5078-+ .max_fdm_size = 8,
5079-+ .fdm_ecc_size = 1,
5080-+ .ecc_parity_bits = 13,
5081-+ .spare_size = spare_size_mt7622,
5082-+ .spare_size_num = 4,
5083-+};
5084-+
5085-+static struct nfi_caps *nfi_get_match_data(enum mtk_ic_version ic)
5086-+{
5087-+ /* NOTE: add other IC's data */
5088-+ return &nfi_caps_mt7622;
5089-+}
5090-+
5091-+static void set_nfi_base_params(struct nfi_base *nb)
5092-+{
5093-+ nb->ecc_en = false;
5094-+ nb->dma_en = false;
5095-+ nb->nfi_irq_en = false;
5096-+ nb->ecc_irq_en = false;
5097-+ nb->page_irq_en = false;
5098-+ nb->ecc_clk_en = false;
5099-+ nb->randomize_en = false;
5100-+ nb->custom_sector_en = false;
5101-+ nb->bad_mark_swap_en = false;
5102-+
5103-+ nb->op_mode = CNFG_CUSTOM_MODE;
5104-+ nb->ecc_deccon = ECC_DEC_CORRECT;
5105-+ nb->ecc_mode = ECC_NFI_MODE;
5106-+
5107-+ nb->done = nandx_event_create();
5108-+ nb->caps = nfi_get_match_data(nb->res.ic_ver);
5109-+
5110-+ nb->set_op_mode = set_op_mode;
5111-+ nb->is_page_empty = is_page_empty;
5112-+
5113-+ nb->rw_prepare = rw_prepare;
5114-+ nb->rw_trigger = rw_trigger;
5115-+ nb->rw_wait_done = rw_wait_done;
5116-+ nb->rw_data = rw_data;
5117-+ nb->rw_complete = rw_complete;
5118-+}
5119-+
5120-+struct nfi *__weak nfi_extend_init(struct nfi_base *nb)
5121-+{
5122-+ return &nb->nfi;
5123-+}
5124-+
5125-+void __weak nfi_extend_exit(struct nfi_base *nb)
5126-+{
5127-+ mem_free(nb);
5128-+}
5129-+
5130-+struct nfi *nfi_init(struct nfi_resource *res)
5131-+{
5132-+ struct nfiecc_resource ecc_res;
5133-+ struct nfi_base *nb;
5134-+ struct nfiecc *ecc;
5135-+ struct nfi *nfi;
5136-+ int ret;
5137-+
5138-+ nb = mem_alloc(1, sizeof(struct nfi_base));
5139-+ if (!nb) {
5140-+ pr_info("nfi alloc memory fail @%s.\n", __func__);
5141-+ return NULL;
5142-+ }
5143-+
5144-+ nb->res = *res;
5145-+
5146-+ ret = nandx_irq_register(res->dev, res->nfi_irq_id, nfi_irq_handler,
5147-+ "mtk_nand", nb);
5148-+ if (ret) {
5149-+ pr_info("nfi irq register failed!\n");
5150-+ goto error;
5151-+ }
5152-+
5153-+ /* fill ecc paras and init ecc */
5154-+ ecc_res.ic_ver = nb->res.ic_ver;
5155-+ ecc_res.dev = nb->res.dev;
5156-+ ecc_res.irq_id = nb->res.ecc_irq_id;
5157-+ ecc_res.regs = nb->res.ecc_regs;
5158-+ ecc = nfiecc_init(&ecc_res);
5159-+ if (!ecc) {
5160-+ pr_info("nfiecc init fail.\n");
5161-+ return NULL;
5162-+ }
5163-+
5164-+ nb->ecc = ecc;
5165-+
5166-+ set_nfi_base_params(nb);
5167-+ set_nfi_funcs(&nb->nfi);
5168-+
5169-+ /* Assign a temp sector size for reading ID & para page.
5170-+ * We may assign new value later.
5171-+ */
5172-+ nb->nfi.sector_size = 512;
5173-+
5174-+ /* give a default timing, and as discuss
5175-+ * this is the only thing what we need do for nfi init
5176-+ * if need do more, then we can add a function
5177-+ */
5178-+ writel(0x30C77FFF, nb->res.nfi_regs + NFI_ACCCON);
5179-+
5180-+ nfi = nfi_extend_init(nb);
5181-+ if (nfi)
5182-+ return nfi;
5183-+
5184-+error:
5185-+ mem_free(nb);
5186-+ return NULL;
5187-+}
5188-+
5189-+void nfi_exit(struct nfi *nfi)
5190-+{
5191-+ struct nfi_base *nb = nfi_to_base(nfi);
5192-+
5193-+ nandx_event_destroy(nb->done);
5194-+ nfiecc_exit(nb->ecc);
5195-+#if !NANDX_BULK_IO_USE_DRAM
5196-+ mem_free(nb->buf);
5197-+#endif
5198-+ nfi_extend_exit(nb);
5199-+}
5200-+
5201-diff --git a/drivers/mtd/nandx/core/nfi/nfi_base.h b/drivers/mtd/nandx/core/nfi/nfi_base.h
5202-new file mode 100644
5203-index 0000000000..ae894eaa31
5204---- /dev/null
5205-+++ b/drivers/mtd/nandx/core/nfi/nfi_base.h
5206-@@ -0,0 +1,95 @@
5207-+/*
5208-+ * Copyright (C) 2017 MediaTek Inc.
5209-+ * Licensed under either
5210-+ * BSD Licence, (see NOTICE for more details)
5211-+ * GNU General Public License, version 2.0, (see NOTICE for more details)
5212-+ */
5213-+
5214-+#ifndef __NFI_BASE_H__
5215-+#define __NFI_BASE_H__
5216-+
5217-+#define NFI_TIMEOUT 1000000
5218-+
5219-+enum randomizer_op {
5220-+ RAND_ENCODE,
5221-+ RAND_DECODE
5222-+};
5223-+
5224-+struct bad_mark_ctrl {
5225-+ void (*bad_mark_swap)(struct nfi *nfi, u8 *buf, u8 *fdm);
5226-+ u8 *(*fdm_shift)(struct nfi *nfi, u8 *fdm, int sector);
5227-+ u32 sector;
5228-+ u32 position;
5229-+};
5230-+
5231-+struct nfi_caps {
5232-+ u8 max_fdm_size;
5233-+ u8 fdm_ecc_size;
5234-+ u8 ecc_parity_bits;
5235-+ const int *spare_size;
5236-+ u32 spare_size_num;
5237-+};
5238-+
5239-+struct nfi_base {
5240-+ struct nfi nfi;
5241-+ struct nfi_resource res;
5242-+ struct nfiecc *ecc;
5243-+ struct nfi_format format;
5244-+ struct nfi_caps *caps;
5245-+ struct bad_mark_ctrl bad_mark_ctrl;
5246-+
5247-+ /* page_size + spare_size */
5248-+ u8 *buf;
5249-+
5250-+ /* used for spi nand */
5251-+ u8 cmd_mode;
5252-+ u32 op_mode;
5253-+
5254-+ int page_sectors;
5255-+
5256-+ void *done;
5257-+
5258-+ /* for read/write */
5259-+ int col;
5260-+ int row;
5261-+ int access_len;
5262-+ int rw_sectors;
5263-+ void *dma_addr;
5264-+ int read_status;
5265-+
5266-+ bool dma_en;
5267-+ bool nfi_irq_en;
5268-+ bool page_irq_en;
5269-+ bool auto_format;
5270-+ bool ecc_en;
5271-+ bool ecc_irq_en;
5272-+ bool ecc_clk_en;
5273-+ bool randomize_en;
5274-+ bool custom_sector_en;
5275-+ bool bad_mark_swap_en;
5276-+
5277-+ enum nfiecc_deccon ecc_deccon;
5278-+ enum nfiecc_mode ecc_mode;
5279-+
5280-+ void (*set_op_mode)(void *regs, u32 mode);
5281-+ bool (*is_page_empty)(struct nfi_base *nb, u8 *data, u8 *fdm,
5282-+ int sectors);
5283-+
5284-+ int (*rw_prepare)(struct nfi_base *nb, int sectors, u8 *data, u8 *fdm,
5285-+ bool read);
5286-+ void (*rw_trigger)(struct nfi_base *nb, bool read);
5287-+ int (*rw_wait_done)(struct nfi_base *nb, int sectors, bool read);
5288-+ int (*rw_data)(struct nfi_base *nb, u8 *data, u8 *fdm, int sectors,
5289-+ bool read);
5290-+ void (*rw_complete)(struct nfi_base *nb, u8 *data, u8 *fdm, bool read);
5291-+};
5292-+
5293-+static inline struct nfi_base *nfi_to_base(struct nfi *nfi)
5294-+{
5295-+ return container_of(nfi, struct nfi_base, nfi);
5296-+}
5297-+
5298-+struct nfi *nfi_extend_init(struct nfi_base *nb);
5299-+void nfi_extend_exit(struct nfi_base *nb);
5300-+
5301-+#endif /* __NFI_BASE_H__ */
5302-diff --git a/drivers/mtd/nandx/core/nfi/nfi_regs.h b/drivers/mtd/nandx/core/nfi/nfi_regs.h
5303-new file mode 100644
5304-index 0000000000..ba4868acc8
5305---- /dev/null
5306-+++ b/drivers/mtd/nandx/core/nfi/nfi_regs.h
5307-@@ -0,0 +1,114 @@
5308-+/*
5309-+ * Copyright (C) 2017 MediaTek Inc.
5310-+ * Licensed under either
5311-+ * BSD Licence, (see NOTICE for more details)
5312-+ * GNU General Public License, version 2.0, (see NOTICE for more details)
5313-+ */
5314-+
5315-+#ifndef __NFI_REGS_H__
5316-+#define __NFI_REGS_H__
5317-+
5318-+#define NFI_CNFG 0x000
5319-+#define CNFG_AHB BIT(0)
5320-+#define CNFG_READ_EN BIT(1)
5321-+#define CNFG_DMA_BURST_EN BIT(2)
5322-+#define CNFG_RESEED_SEC_EN BIT(4)
5323-+#define CNFG_RAND_SEL BIT(5)
5324-+#define CNFG_BYTE_RW BIT(6)
5325-+#define CNFG_HW_ECC_EN BIT(8)
5326-+#define CNFG_AUTO_FMT_EN BIT(9)
5327-+#define CNFG_RAND_MASK GENMASK(5, 4)
5328-+#define CNFG_OP_MODE_MASK GENMASK(14, 12)
5329-+#define CNFG_IDLE_MOD 0
5330-+#define CNFG_READ_MODE (1 << 12)
5331-+#define CNFG_SINGLE_READ_MODE (2 << 12)
5332-+#define CNFG_PROGRAM_MODE (3 << 12)
5333-+#define CNFG_ERASE_MODE (4 << 12)
5334-+#define CNFG_RESET_MODE (5 << 12)
5335-+#define CNFG_CUSTOM_MODE (6 << 12)
5336-+#define NFI_PAGEFMT 0x004
5337-+#define PAGEFMT_SPARE_SHIFT 4
5338-+#define PAGEFMT_FDM_ECC_SHIFT 12
5339-+#define PAGEFMT_FDM_SHIFT 8
5340-+#define PAGEFMT_SEC_SEL_512 BIT(2)
5341-+#define PAGEFMT_512_2K 0
5342-+#define PAGEFMT_2K_4K 1
5343-+#define PAGEFMT_4K_8K 2
5344-+#define PAGEFMT_8K_16K 3
5345-+#define NFI_CON 0x008
5346-+#define CON_FIFO_FLUSH BIT(0)
5347-+#define CON_NFI_RST BIT(1)
5348-+#define CON_BRD BIT(8)
5349-+#define CON_BWR BIT(9)
5350-+#define CON_SEC_SHIFT 12
5351-+#define NFI_ACCCON 0x00c
5352-+#define NFI_INTR_EN 0x010
5353-+#define INTR_BUSY_RETURN_EN BIT(4)
5354-+#define INTR_AHB_DONE_EN BIT(6)
5355-+#define NFI_INTR_STA 0x014
5356-+#define NFI_CMD 0x020
5357-+#define NFI_ADDRNOB 0x030
5358-+#define ROW_SHIFT 4
5359-+#define NFI_COLADDR 0x034
5360-+#define NFI_ROWADDR 0x038
5361-+#define NFI_STRDATA 0x040
5362-+#define STAR_EN 1
5363-+#define STAR_DE 0
5364-+#define NFI_CNRNB 0x044
5365-+#define NFI_DATAW 0x050
5366-+#define NFI_DATAR 0x054
5367-+#define NFI_PIO_DIRDY 0x058
5368-+#define PIO_DI_RDY 1
5369-+#define NFI_STA 0x060
5370-+#define STA_CMD BIT(0)
5371-+#define STA_ADDR BIT(1)
5372-+#define FLASH_MACRO_IDLE BIT(5)
5373-+#define STA_BUSY BIT(8)
5374-+#define STA_BUSY2READY BIT(9)
5375-+#define STA_EMP_PAGE BIT(12)
5376-+#define NFI_FSM_CUSTDATA (0xe << 16)
5377-+#define NFI_FSM_MASK GENMASK(19, 16)
5378-+#define NAND_FSM_MASK GENMASK(29, 23)
5379-+#define NFI_ADDRCNTR 0x070
5380-+#define CNTR_VALID_MASK GENMASK(16, 0)
5381-+#define CNTR_MASK GENMASK(15, 12)
5382-+#define ADDRCNTR_SEC_SHIFT 12
5383-+#define ADDRCNTR_SEC(val) \
5384-+ (((val) & CNTR_MASK) >> ADDRCNTR_SEC_SHIFT)
5385-+#define NFI_STRADDR 0x080
5386-+#define NFI_BYTELEN 0x084
5387-+#define NFI_CSEL 0x090
5388-+#define NFI_FDML(x) (0x0a0 + (x) * 8)
5389-+#define NFI_FDMM(x) (0x0a4 + (x) * 8)
5390-+#define NFI_DEBUG_CON1 0x220
5391-+#define STROBE_MASK GENMASK(4, 3)
5392-+#define STROBE_SHIFT 3
5393-+#define ECC_CLK_EN BIT(11)
5394-+#define AUTOC_SRAM_MODE BIT(12)
5395-+#define BYPASS_MASTER_EN BIT(15)
5396-+#define NFI_MASTER_STA 0x224
5397-+#define MASTER_BUS_BUSY 0x3
5398-+#define NFI_SECCUS_SIZE 0x22c
5399-+#define SECCUS_SIZE_EN BIT(17)
5400-+#define NFI_RANDOM_CNFG 0x238
5401-+#define RAN_ENCODE_EN BIT(0)
5402-+#define ENCODE_SEED_SHIFT 1
5403-+#define RAN_DECODE_EN BIT(16)
5404-+#define DECODE_SEED_SHIFT 17
5405-+#define RAN_SEED_MASK 0x7fff
5406-+#define NFI_EMPTY_THRESH 0x23c
5407-+#define NFI_NAND_TYPE_CNFG 0x240
5408-+#define NAND_TYPE_ASYNC 0
5409-+#define NAND_TYPE_TOGGLE 1
5410-+#define NAND_TYPE_SYNC 2
5411-+#define NFI_ACCCON1 0x244
5412-+#define NFI_DELAY_CTRL 0x248
5413-+#define NFI_TLC_RD_WHR2 0x300
5414-+#define TLC_RD_WHR2_EN BIT(12)
5415-+#define TLC_RD_WHR2_MASK GENMASK(11, 0)
5416-+#define SNF_SNF_CNFG 0x55c
5417-+#define SPI_MODE_EN 1
5418-+#define SPI_MODE_DIS 0
5419-+
5420-+#endif /* __NFI_REGS_H__ */
5421-+
5422-diff --git a/drivers/mtd/nandx/core/nfi/nfi_spi.c b/drivers/mtd/nandx/core/nfi/nfi_spi.c
5423-new file mode 100644
5424-index 0000000000..67cd0aaad9
5425---- /dev/null
5426-+++ b/drivers/mtd/nandx/core/nfi/nfi_spi.c
5427-@@ -0,0 +1,689 @@
5428-+/*
5429-+ * Copyright (C) 2017 MediaTek Inc.
5430-+ * Licensed under either
5431-+ * BSD Licence, (see NOTICE for more details)
5432-+ * GNU General Public License, version 2.0, (see NOTICE for more details)
5433-+ */
5434-+
5435-+#include "nandx_util.h"
5436-+#include "nandx_core.h"
5437-+#include "../nfi.h"
5438-+#include "nfiecc.h"
5439-+#include "nfi_regs.h"
5440-+#include "nfi_base.h"
5441-+#include "nfi_spi_regs.h"
5442-+#include "nfi_spi.h"
5443-+
5444-+#define NFI_CMD_DUMMY_RD 0x00
5445-+#define NFI_CMD_DUMMY_WR 0x80
5446-+
5447-+static struct nfi_spi_delay spi_delay[SPI_NAND_MAX_DELAY] = {
5448-+ /*
5449-+ * tCLK_SAM_DLY, tCLK_OUT_DLY, tCS_DLY, tWR_EN_DLY,
5450-+ * tIO_IN_DLY[4], tIO_OUT_DLY[4], tREAD_LATCH_LATENCY
5451-+ */
5452-+ {0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0}, 0},
5453-+ {21, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0}, 0},
5454-+ {63, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0}, 0},
5455-+ {0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0}, 1},
5456-+ {21, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0}, 1},
5457-+ {63, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0}, 1}
5458-+};
5459-+
5460-+static inline struct nfi_spi *base_to_snfi(struct nfi_base *nb)
5461-+{
5462-+ return container_of(nb, struct nfi_spi, base);
5463-+}
5464-+
5465-+static void snfi_mac_enable(struct nfi_base *nb)
5466-+{
5467-+ void *regs = nb->res.nfi_regs;
5468-+ u32 val;
5469-+
5470-+ val = readl(regs + SNF_MAC_CTL);
5471-+ val &= ~MAC_XIO_SEL;
5472-+ val |= SF_MAC_EN;
5473-+
5474-+ writel(val, regs + SNF_MAC_CTL);
5475-+}
5476-+
5477-+static void snfi_mac_disable(struct nfi_base *nb)
5478-+{
5479-+ void *regs = nb->res.nfi_regs;
5480-+ u32 val;
5481-+
5482-+ val = readl(regs + SNF_MAC_CTL);
5483-+ val &= ~(SF_TRIG | SF_MAC_EN);
5484-+ writel(val, regs + SNF_MAC_CTL);
5485-+}
5486-+
5487-+static int snfi_mac_trigger(struct nfi_base *nb)
5488-+{
5489-+ void *regs = nb->res.nfi_regs;
5490-+ int ret;
5491-+ u32 val;
5492-+
5493-+ val = readl(regs + SNF_MAC_CTL);
5494-+ val |= SF_TRIG;
5495-+ writel(val, regs + SNF_MAC_CTL);
5496-+
5497-+ ret = readl_poll_timeout_atomic(regs + SNF_MAC_CTL, val,
5498-+ val & WIP_READY, 10,
5499-+ NFI_TIMEOUT);
5500-+ if (ret) {
5501-+ pr_info("polling wip ready for read timeout\n");
5502-+ return ret;
5503-+ }
5504-+
5505-+ return readl_poll_timeout_atomic(regs + SNF_MAC_CTL, val,
5506-+ !(val & WIP), 10,
5507-+ NFI_TIMEOUT);
5508-+}
5509-+
5510-+static int snfi_mac_op(struct nfi_base *nb)
5511-+{
5512-+ int ret;
5513-+
5514-+ snfi_mac_enable(nb);
5515-+ ret = snfi_mac_trigger(nb);
5516-+ snfi_mac_disable(nb);
5517-+
5518-+ return ret;
5519-+}
5520-+
5521-+static void snfi_write_mac(struct nfi_spi *nfi_spi, u8 *data, int count)
5522-+{
5523-+ struct nandx_split32 split = {0};
5524-+ u32 reg_offset = round_down(nfi_spi->tx_count, 4);
5525-+ void *regs = nfi_spi->base.res.nfi_regs;
5526-+ u32 data_offset = 0, i, val;
5527-+ u8 *p_val = (u8 *)(&val);
5528-+
5529-+ nandx_split(&split, nfi_spi->tx_count, count, val, 4);
5530-+
5531-+ if (split.head_len) {
5532-+ val = readl(regs + SPI_GPRAM_ADDR + reg_offset);
5533-+
5534-+ for (i = 0; i < split.head_len; i++)
5535-+ p_val[split.head + i] = data[i];
5536-+
5537-+ writel(val, regs + SPI_GPRAM_ADDR + reg_offset);
5538-+ }
5539-+
5540-+ if (split.body_len) {
5541-+ reg_offset = split.body;
5542-+ data_offset = split.head_len;
5543-+
5544-+ for (i = 0; i < split.body_len; i++) {
5545-+ p_val[i & 3] = data[data_offset + i];
5546-+
5547-+ if ((i & 3) == 3) {
5548-+ writel(val, regs + SPI_GPRAM_ADDR + reg_offset);
5549-+ reg_offset += 4;
5550-+ }
5551-+ }
5552-+ }
5553-+
5554-+ if (split.tail_len) {
5555-+ reg_offset = split.tail;
5556-+ data_offset += split.body_len;
5557-+
5558-+ for (i = 0; i < split.tail_len; i++) {
5559-+ p_val[i] = data[data_offset + i];
5560-+
5561-+ if (i == split.tail_len - 1)
5562-+ writel(val, regs + SPI_GPRAM_ADDR + reg_offset);
5563-+ }
5564-+ }
5565-+}
5566-+
5567-+static void snfi_read_mac(struct nfi_spi *nfi_spi, u8 *data, int count)
5568-+{
5569-+ void *regs = nfi_spi->base.res.nfi_regs;
5570-+ u32 reg_offset = round_down(nfi_spi->tx_count, 4);
5571-+ struct nandx_split32 split = {0};
5572-+ u32 data_offset = 0, i, val;
5573-+ u8 *p_val = (u8 *)&val;
5574-+
5575-+ nandx_split(&split, nfi_spi->tx_count, count, val, 4);
5576-+
5577-+ if (split.head_len) {
5578-+ val = readl(regs + SPI_GPRAM_ADDR + reg_offset);
5579-+
5580-+ for (i = 0; i < split.head_len; i++)
5581-+ data[data_offset + i] = p_val[split.head + i];
5582-+ }
5583-+
5584-+ if (split.body_len) {
5585-+ reg_offset = split.body;
5586-+ data_offset = split.head_len;
5587-+
5588-+ for (i = 0; i < split.body_len; i++) {
5589-+ if ((i & 3) == 0) {
5590-+ val = readl(regs + SPI_GPRAM_ADDR + reg_offset);
5591-+ reg_offset += 4;
5592-+ }
5593-+
5594-+ data[data_offset + i] = p_val[i % 4];
5595-+ }
5596-+ }
5597-+
5598-+ if (split.tail_len) {
5599-+ reg_offset = split.tail;
5600-+ data_offset += split.body_len;
5601-+ val = readl(regs + SPI_GPRAM_ADDR + reg_offset);
5602-+
5603-+ for (i = 0; i < split.tail_len; i++)
5604-+ data[data_offset + i] = p_val[i];
5605-+ }
5606-+}
5607-+
5608-+static int snfi_send_command(struct nfi *nfi, short cmd)
5609-+{
5610-+ struct nfi_base *nb = nfi_to_base(nfi);
5611-+ struct nfi_spi *nfi_spi = base_to_snfi(nb);
5612-+
5613-+ if (cmd == -1)
5614-+ return 0;
5615-+
5616-+ if (nfi_spi->snfi_mode == SNFI_MAC_MODE) {
5617-+ snfi_write_mac(nfi_spi, (u8 *)&cmd, 1);
5618-+ nfi_spi->tx_count++;
5619-+ return 0;
5620-+ }
5621-+
5622-+ nfi_spi->cmd[nfi_spi->cur_cmd_idx++] = cmd;
5623-+ return 0;
5624-+}
5625-+
5626-+static int snfi_send_address(struct nfi *nfi, int col, int row,
5627-+ int col_cycle,
5628-+ int row_cycle)
5629-+{
5630-+ struct nfi_base *nb = nfi_to_base(nfi);
5631-+ struct nfi_spi *nfi_spi = base_to_snfi(nb);
5632-+ u32 addr, cycle, temp;
5633-+
5634-+ nb->col = col;
5635-+ nb->row = row;
5636-+
5637-+ if (nfi_spi->snfi_mode == SNFI_MAC_MODE) {
5638-+ addr = row;
5639-+ cycle = row_cycle;
5640-+
5641-+ if (!row_cycle) {
5642-+ addr = col;
5643-+ cycle = col_cycle;
5644-+ }
5645-+
5646-+ temp = nandx_cpu_to_be32(addr) >> ((4 - cycle) << 3);
5647-+ snfi_write_mac(nfi_spi, (u8 *)&temp, cycle);
5648-+ nfi_spi->tx_count += cycle;
5649-+ } else {
5650-+ nfi_spi->row_addr[nfi_spi->cur_addr_idx++] = row;
5651-+ nfi_spi->col_addr[nfi_spi->cur_addr_idx++] = col;
5652-+ }
5653-+
5654-+ return 0;
5655-+}
5656-+
5657-+static int snfi_trigger(struct nfi *nfi)
5658-+{
5659-+ struct nfi_base *nb = nfi_to_base(nfi);
5660-+ struct nfi_spi *nfi_spi = base_to_snfi(nb);
5661-+ void *regs = nb->res.nfi_regs;
5662-+
5663-+ writel(nfi_spi->tx_count, regs + SNF_MAC_OUTL);
5664-+ writel(0, regs + SNF_MAC_INL);
5665-+
5666-+ nfi_spi->tx_count = 0;
5667-+ nfi_spi->cur_cmd_idx = 0;
5668-+ nfi_spi->cur_addr_idx = 0;
5669-+
5670-+ return snfi_mac_op(nb);
5671-+}
5672-+
5673-+static int snfi_select_chip(struct nfi *nfi, int cs)
5674-+{
5675-+ struct nfi_base *nb = nfi_to_base(nfi);
5676-+ void *regs = nb->res.nfi_regs;
5677-+ u32 val;
5678-+
5679-+ val = readl(regs + SNF_MISC_CTL);
5680-+
5681-+ if (cs == 0) {
5682-+ val &= ~SF2CS_SEL;
5683-+ val &= ~SF2CS_EN;
5684-+ } else if (cs == 1) {
5685-+ val |= SF2CS_SEL;
5686-+ val |= SF2CS_EN;
5687-+ } else {
5688-+ return -EIO;
5689-+ }
5690-+
5691-+ writel(val, regs + SNF_MISC_CTL);
5692-+
5693-+ return 0;
5694-+}
5695-+
5696-+static int snfi_set_delay(struct nfi_base *nb, u8 delay_mode)
5697-+{
5698-+ void *regs = nb->res.nfi_regs;
5699-+ struct nfi_spi_delay *delay;
5700-+ u32 val;
5701-+
5702-+ if (delay_mode < 0 || delay_mode > SPI_NAND_MAX_DELAY)
5703-+ return -EINVAL;
5704-+
5705-+ delay = &spi_delay[delay_mode];
5706-+
5707-+ val = delay->tIO_OUT_DLY[0] | delay->tIO_OUT_DLY[1] << 8 |
5708-+ delay->tIO_OUT_DLY[2] << 16 |
5709-+ delay->tIO_OUT_DLY[3] << 24;
5710-+ writel(val, regs + SNF_DLY_CTL1);
5711-+
5712-+ val = delay->tIO_IN_DLY[0] | (delay->tIO_IN_DLY[1] << 8) |
5713-+ delay->tIO_IN_DLY[2] << 16 |
5714-+ delay->tIO_IN_DLY[3] << 24;
5715-+ writel(val, regs + SNF_DLY_CTL2);
5716-+
5717-+ val = delay->tCLK_SAM_DLY | delay->tCLK_OUT_DLY << 8 |
5718-+ delay->tCS_DLY << 16 |
5719-+ delay->tWR_EN_DLY << 24;
5720-+ writel(val, regs + SNF_DLY_CTL3);
5721-+
5722-+ writel(delay->tCS_DLY, regs + SNF_DLY_CTL4);
5723-+
5724-+ val = readl(regs + SNF_MISC_CTL);
5725-+ val |= (delay->tREAD_LATCH_LATENCY) <<
5726-+ LATCH_LAT_SHIFT;
5727-+ writel(val, regs + SNF_MISC_CTL);
5728-+
5729-+ return 0;
5730-+}
5731-+
5732-+static int snfi_set_timing(struct nfi *nfi, void *timing, int type)
5733-+{
5734-+ /* Nothing need to do. */
5735-+ return 0;
5736-+}
5737-+
5738-+static int snfi_wait_ready(struct nfi *nfi, int type, u32 timeout)
5739-+{
5740-+ /* Nothing need to do. */
5741-+ return 0;
5742-+}
5743-+
5744-+static int snfi_ctrl(struct nfi *nfi, int cmd, void *args)
5745-+{
5746-+ struct nfi_base *nb = nfi_to_base(nfi);
5747-+ struct nfi_spi *nfi_spi = base_to_snfi(nb);
5748-+ int ret = 0;
5749-+
5750-+ if (!args)
5751-+ return -EINVAL;
5752-+
5753-+ switch (cmd) {
5754-+ case NFI_CTRL_DMA:
5755-+ nb->dma_en = *(bool *)args;
5756-+ break;
5757-+
5758-+ case NFI_CTRL_NFI_IRQ:
5759-+ nb->nfi_irq_en = *(bool *)args;
5760-+ break;
5761-+
5762-+ case NFI_CTRL_ECC_IRQ:
5763-+ nb->ecc_irq_en = *(bool *)args;
5764-+ break;
5765-+
5766-+ case NFI_CTRL_PAGE_IRQ:
5767-+ nb->page_irq_en = *(bool *)args;
5768-+ break;
5769-+
5770-+ case NFI_CTRL_ECC:
5771-+ nb->ecc_en = *(bool *)args;
5772-+ break;
5773-+
5774-+ case NFI_CTRL_BAD_MARK_SWAP:
5775-+ nb->bad_mark_swap_en = *(bool *)args;
5776-+ break;
5777-+
5778-+ case NFI_CTRL_ECC_CLOCK:
5779-+ nb->ecc_clk_en = *(bool *)args;
5780-+ break;
5781-+
5782-+ case SNFI_CTRL_OP_MODE:
5783-+ nfi_spi->snfi_mode = *(u8 *)args;
5784-+ break;
5785-+
5786-+ case SNFI_CTRL_RX_MODE:
5787-+ nfi_spi->read_cache_mode = *(u8 *)args;
5788-+ break;
5789-+
5790-+ case SNFI_CTRL_TX_MODE:
5791-+ nfi_spi->write_cache_mode = *(u8 *)args;
5792-+ break;
5793-+
5794-+ case SNFI_CTRL_DELAY_MODE:
5795-+ ret = snfi_set_delay(nb, *(u8 *)args);
5796-+ break;
5797-+
5798-+ default:
5799-+ pr_info("operation not support.\n");
5800-+ ret = -EOPNOTSUPP;
5801-+ break;
5802-+ }
5803-+
5804-+ return ret;
5805-+}
5806-+
5807-+static int snfi_read_bytes(struct nfi *nfi, u8 *data, int count)
5808-+{
5809-+ struct nfi_base *nb = nfi_to_base(nfi);
5810-+ struct nfi_spi *nfi_spi = base_to_snfi(nb);
5811-+ void *regs = nb->res.nfi_regs;
5812-+ int ret;
5813-+
5814-+ writel(nfi_spi->tx_count, regs + SNF_MAC_OUTL);
5815-+ writel(count, regs + SNF_MAC_INL);
5816-+
5817-+ ret = snfi_mac_op(nb);
5818-+ if (ret)
5819-+ return ret;
5820-+
5821-+ snfi_read_mac(nfi_spi, data, count);
5822-+
5823-+ nfi_spi->tx_count = 0;
5824-+
5825-+ return 0;
5826-+}
5827-+
5828-+static int snfi_write_bytes(struct nfi *nfi, u8 *data, int count)
5829-+{
5830-+ struct nfi_base *nb = nfi_to_base(nfi);
5831-+ struct nfi_spi *nfi_spi = base_to_snfi(nb);
5832-+ void *regs = nb->res.nfi_regs;
5833-+
5834-+ snfi_write_mac(nfi_spi, data, count);
5835-+ nfi_spi->tx_count += count;
5836-+
5837-+ writel(0, regs + SNF_MAC_INL);
5838-+ writel(nfi_spi->tx_count, regs + SNF_MAC_OUTL);
5839-+
5840-+ nfi_spi->tx_count = 0;
5841-+
5842-+ return snfi_mac_op(nb);
5843-+}
5844-+
5845-+static int snfi_reset(struct nfi *nfi)
5846-+{
5847-+ struct nfi_base *nb = nfi_to_base(nfi);
5848-+ struct nfi_spi *nfi_spi = base_to_snfi(nb);
5849-+ void *regs = nb->res.nfi_regs;
5850-+ u32 val;
5851-+ int ret;
5852-+
5853-+ ret = nfi_spi->parent->nfi.reset(nfi);
5854-+ if (ret)
5855-+ return ret;
5856-+
5857-+ val = readl(regs + SNF_MISC_CTL);
5858-+ val |= SW_RST;
5859-+ writel(val, regs + SNF_MISC_CTL);
5860-+
5861-+ ret = readx_poll_timeout_atomic(readw, regs + SNF_STA_CTL1, val,
5862-+ !(val & SPI_STATE), 50,
5863-+ NFI_TIMEOUT);
5864-+ if (ret) {
5865-+ pr_info("spi state active in reset [0x%x] = 0x%x\n",
5866-+ SNF_STA_CTL1, val);
5867-+ return ret;
5868-+ }
5869-+
5870-+ val = readl(regs + SNF_MISC_CTL);
5871-+ val &= ~SW_RST;
5872-+ writel(val, regs + SNF_MISC_CTL);
5873-+
5874-+ return 0;
5875-+}
5876-+
5877-+static int snfi_config_for_write(struct nfi_base *nb, int count)
5878-+{
5879-+ struct nfi_spi *nfi_spi = base_to_snfi(nb);
5880-+ void *regs = nb->res.nfi_regs;
5881-+ u32 val;
5882-+
5883-+ nb->set_op_mode(regs, CNFG_CUSTOM_MODE);
5884-+
5885-+ val = readl(regs + SNF_MISC_CTL);
5886-+
5887-+ if (nfi_spi->write_cache_mode == SNFI_TX_114)
5888-+ val |= PG_LOAD_X4_EN;
5889-+
5890-+ if (nfi_spi->snfi_mode == SNFI_CUSTOM_MODE)
5891-+ val |= PG_LOAD_CUSTOM_EN;
5892-+
5893-+ writel(val, regs + SNF_MISC_CTL);
5894-+
5895-+ val = count * (nb->nfi.sector_size + nb->nfi.sector_spare_size);
5896-+ writel(val << PG_LOAD_SHIFT, regs + SNF_MISC_CTL2);
5897-+
5898-+ val = readl(regs + SNF_PG_CTL1);
5899-+
5900-+ if (nfi_spi->snfi_mode == SNFI_CUSTOM_MODE)
5901-+ val |= nfi_spi->cmd[0] << PG_LOAD_CMD_SHIFT;
5902-+ else {
5903-+ val |= nfi_spi->cmd[0] | nfi_spi->cmd[1] << PG_LOAD_CMD_SHIFT |
5904-+ nfi_spi->cmd[2] << PG_EXE_CMD_SHIFT;
5905-+
5906-+ writel(nfi_spi->row_addr[1], regs + SNF_PG_CTL3);
5907-+ writel(nfi_spi->cmd[3] << GF_CMD_SHIFT | nfi_spi->col_addr[2] <<
5908-+ GF_ADDR_SHIFT, regs + SNF_GF_CTL1);
5909-+ }
5910-+
5911-+ writel(val, regs + SNF_PG_CTL1);
5912-+ writel(nfi_spi->col_addr[1], regs + SNF_PG_CTL2);
5913-+
5914-+ writel(NFI_CMD_DUMMY_WR, regs + NFI_CMD);
5915-+
5916-+ return 0;
5917-+}
5918-+
5919-+static int snfi_config_for_read(struct nfi_base *nb, int count)
5920-+{
5921-+ struct nfi_spi *nfi_spi = base_to_snfi(nb);
5922-+ void *regs = nb->res.nfi_regs;
5923-+ u32 val;
5924-+ int ret = 0;
5925-+
5926-+ nb->set_op_mode(regs, CNFG_CUSTOM_MODE);
5927-+
5928-+ val = readl(regs + SNF_MISC_CTL);
5929-+ val &= ~DARA_READ_MODE_MASK;
5930-+
5931-+ switch (nfi_spi->read_cache_mode) {
5932-+
5933-+ case SNFI_RX_111:
5934-+ break;
5935-+
5936-+ case SNFI_RX_112:
5937-+ val |= X2_DATA_MODE << READ_MODE_SHIFT;
5938-+ break;
5939-+
5940-+ case SNFI_RX_114:
5941-+ val |= X4_DATA_MODE << READ_MODE_SHIFT;
5942-+ break;
5943-+
5944-+ case SNFI_RX_122:
5945-+ val |= DUAL_IO_MODE << READ_MODE_SHIFT;
5946-+ break;
5947-+
5948-+ case SNFI_RX_144:
5949-+ val |= QUAD_IO_MODE << READ_MODE_SHIFT;
5950-+ break;
5951-+
5952-+ default:
5953-+ pr_info("Not support this read operarion: %d!\n",
5954-+ nfi_spi->read_cache_mode);
5955-+ ret = -EINVAL;
5956-+ break;
5957-+ }
5958-+
5959-+ if (nfi_spi->snfi_mode == SNFI_CUSTOM_MODE)
5960-+ val |= DATARD_CUSTOM_EN;
5961-+
5962-+ writel(val, regs + SNF_MISC_CTL);
5963-+
5964-+ val = count * (nb->nfi.sector_size + nb->nfi.sector_spare_size);
5965-+ writel(val, regs + SNF_MISC_CTL2);
5966-+
5967-+ val = readl(regs + SNF_RD_CTL2);
5968-+
5969-+ if (nfi_spi->snfi_mode == SNFI_CUSTOM_MODE) {
5970-+ val |= nfi_spi->cmd[0];
5971-+ writel(nfi_spi->col_addr[1], regs + SNF_RD_CTL3);
5972-+ } else {
5973-+ val |= nfi_spi->cmd[2];
5974-+ writel(nfi_spi->cmd[0] << PAGE_READ_CMD_SHIFT |
5975-+ nfi_spi->row_addr[0], regs + SNF_RD_CTL1);
5976-+ writel(nfi_spi->cmd[1] << GF_CMD_SHIFT |
5977-+ nfi_spi->col_addr[1] << GF_ADDR_SHIFT,
5978-+ regs + SNF_GF_CTL1);
5979-+ writel(nfi_spi->col_addr[2], regs + SNF_RD_CTL3);
5980-+ }
5981-+
5982-+ writel(val, regs + SNF_RD_CTL2);
5983-+
5984-+ writel(NFI_CMD_DUMMY_RD, regs + NFI_CMD);
5985-+
5986-+ return ret;
5987-+}
5988-+
5989-+static bool is_page_empty(struct nfi_base *nb, u8 *data, u8 *fdm,
5990-+ int sectors)
5991-+{
5992-+ u32 *data32 = (u32 *)data;
5993-+ u32 *fdm32 = (u32 *)fdm;
5994-+ u32 i, count = 0;
5995-+
5996-+ for (i = 0; i < nb->format.page_size >> 2; i++) {
5997-+ if (data32[i] != 0xffff) {
5998-+ count += zero_popcount(data32[i]);
5999-+ if (count > 10) {
6000-+ pr_info("%s %d %d count:%d\n",
6001-+ __func__, __LINE__, i, count);
6002-+ return false;
6003-+ }
6004-+ }
6005-+ }
6006-+
6007-+ if (fdm) {
6008-+ for (i = 0; i < (nb->nfi.fdm_size * sectors >> 2); i++)
6009-+ if (fdm32[i] != 0xffff) {
6010-+ count += zero_popcount(fdm32[i]);
6011-+ if (count > 10) {
6012-+ pr_info("%s %d %d count:%d\n",
6013-+ __func__, __LINE__, i, count);
6014-+ return false;
6015-+ }
6016-+ }
6017-+ }
6018-+
6019-+ return true;
6020-+}
6021-+
6022-+static int rw_prepare(struct nfi_base *nb, int sectors, u8 *data,
6023-+ u8 *fdm,
6024-+ bool read)
6025-+{
6026-+ struct nfi_spi *nfi_spi = base_to_snfi(nb);
6027-+ int ret;
6028-+
6029-+ ret = nfi_spi->parent->rw_prepare(nb, sectors, data, fdm, read);
6030-+ if (ret)
6031-+ return ret;
6032-+
6033-+ if (read)
6034-+ ret = snfi_config_for_read(nb, sectors);
6035-+ else
6036-+ ret = snfi_config_for_write(nb, sectors);
6037-+
6038-+ return ret;
6039-+}
6040-+
6041-+static void rw_complete(struct nfi_base *nb, u8 *data, u8 *fdm,
6042-+ bool read)
6043-+{
6044-+ struct nfi_spi *nfi_spi = base_to_snfi(nb);
6045-+ void *regs = nb->res.nfi_regs;
6046-+ u32 val;
6047-+
6048-+ nfi_spi->parent->rw_complete(nb, data, fdm, read);
6049-+
6050-+ val = readl(regs + SNF_MISC_CTL);
6051-+
6052-+ if (read)
6053-+ val &= ~DATARD_CUSTOM_EN;
6054-+ else
6055-+ val &= ~PG_LOAD_CUSTOM_EN;
6056-+
6057-+ writel(val, regs + SNF_MISC_CTL);
6058-+
6059-+ nfi_spi->tx_count = 0;
6060-+ nfi_spi->cur_cmd_idx = 0;
6061-+ nfi_spi->cur_addr_idx = 0;
6062-+}
6063-+
6064-+static void set_nfi_base_funcs(struct nfi_base *nb)
6065-+{
6066-+ nb->nfi.reset = snfi_reset;
6067-+ nb->nfi.set_timing = snfi_set_timing;
6068-+ nb->nfi.wait_ready = snfi_wait_ready;
6069-+
6070-+ nb->nfi.send_cmd = snfi_send_command;
6071-+ nb->nfi.send_addr = snfi_send_address;
6072-+ nb->nfi.trigger = snfi_trigger;
6073-+ nb->nfi.nfi_ctrl = snfi_ctrl;
6074-+ nb->nfi.select_chip = snfi_select_chip;
6075-+
6076-+ nb->nfi.read_bytes = snfi_read_bytes;
6077-+ nb->nfi.write_bytes = snfi_write_bytes;
6078-+
6079-+ nb->rw_prepare = rw_prepare;
6080-+ nb->rw_complete = rw_complete;
6081-+ nb->is_page_empty = is_page_empty;
6082-+
6083-+}
6084-+
6085-+struct nfi *nfi_extend_init(struct nfi_base *nb)
6086-+{
6087-+ struct nfi_spi *nfi_spi;
6088-+
6089-+ nfi_spi = mem_alloc(1, sizeof(struct nfi_spi));
6090-+ if (!nfi_spi) {
6091-+ pr_info("snfi alloc memory fail @%s.\n", __func__);
6092-+ return NULL;
6093-+ }
6094-+
6095-+ memcpy(&nfi_spi->base, nb, sizeof(struct nfi_base));
6096-+ nfi_spi->parent = nb;
6097-+
6098-+ nfi_spi->read_cache_mode = SNFI_RX_114;
6099-+ nfi_spi->write_cache_mode = SNFI_TX_114;
6100-+
6101-+ set_nfi_base_funcs(&nfi_spi->base);
6102-+
6103-+ /* Change nfi to spi mode */
6104-+ writel(SPI_MODE, nb->res.nfi_regs + SNF_SNF_CNFG);
6105-+
6106-+ return &(nfi_spi->base.nfi);
6107-+}
6108-+
6109-+void nfi_extend_exit(struct nfi_base *nb)
6110-+{
6111-+ struct nfi_spi *nfi_spi = base_to_snfi(nb);
6112-+
6113-+ mem_free(nfi_spi->parent);
6114-+ mem_free(nfi_spi);
6115-+}
6116-+
6117-diff --git a/drivers/mtd/nandx/core/nfi/nfi_spi.h b/drivers/mtd/nandx/core/nfi/nfi_spi.h
6118-new file mode 100644
6119-index 0000000000..a52255663a
6120---- /dev/null
6121-+++ b/drivers/mtd/nandx/core/nfi/nfi_spi.h
6122-@@ -0,0 +1,44 @@
6123-+/*
6124-+ * Copyright (C) 2017 MediaTek Inc.
6125-+ * Licensed under either
6126-+ * BSD Licence, (see NOTICE for more details)
6127-+ * GNU General Public License, version 2.0, (see NOTICE for more details)
6128-+ */
6129-+
6130-+#ifndef __NFI_SPI_H__
6131-+#define __NFI_SPI_H__
6132-+
6133-+#define SPI_NAND_MAX_DELAY 6
6134-+#define SPI_NAND_MAX_OP 4
6135-+
6136-+/*TODO - add comments */
6137-+struct nfi_spi_delay {
6138-+ u8 tCLK_SAM_DLY;
6139-+ u8 tCLK_OUT_DLY;
6140-+ u8 tCS_DLY;
6141-+ u8 tWR_EN_DLY;
6142-+ u8 tIO_IN_DLY[4];
6143-+ u8 tIO_OUT_DLY[4];
6144-+ u8 tREAD_LATCH_LATENCY;
6145-+};
6146-+
6147-+/* SPI Nand structure */
6148-+struct nfi_spi {
6149-+ struct nfi_base base;
6150-+ struct nfi_base *parent;
6151-+
6152-+ u8 snfi_mode;
6153-+ u8 tx_count;
6154-+
6155-+ u8 cmd[SPI_NAND_MAX_OP];
6156-+ u8 cur_cmd_idx;
6157-+
6158-+ u32 row_addr[SPI_NAND_MAX_OP];
6159-+ u32 col_addr[SPI_NAND_MAX_OP];
6160-+ u8 cur_addr_idx;
6161-+
6162-+ u8 read_cache_mode;
6163-+ u8 write_cache_mode;
6164-+};
6165-+
6166-+#endif /* __NFI_SPI_H__ */
6167-diff --git a/drivers/mtd/nandx/core/nfi/nfi_spi_regs.h b/drivers/mtd/nandx/core/nfi/nfi_spi_regs.h
6168-new file mode 100644
6169-index 0000000000..77adf46782
6170---- /dev/null
6171-+++ b/drivers/mtd/nandx/core/nfi/nfi_spi_regs.h
6172-@@ -0,0 +1,64 @@
6173-+/*
6174-+ * Copyright (C) 2017 MediaTek Inc.
6175-+ * Licensed under either
6176-+ * BSD Licence, (see NOTICE for more details)
6177-+ * GNU General Public License, version 2.0, (see NOTICE for more details)
6178-+ */
6179-+
6180-+#ifndef __NFI_SPI_REGS_H__
6181-+#define __NFI_SPI_REGS_H__
6182-+
6183-+#define SNF_MAC_CTL 0x500
6184-+#define WIP BIT(0)
6185-+#define WIP_READY BIT(1)
6186-+#define SF_TRIG BIT(2)
6187-+#define SF_MAC_EN BIT(3)
6188-+#define MAC_XIO_SEL BIT(4)
6189-+#define SNF_MAC_OUTL 0x504
6190-+#define SNF_MAC_INL 0x508
6191-+#define SNF_RD_CTL1 0x50c
6192-+#define PAGE_READ_CMD_SHIFT 24
6193-+#define SNF_RD_CTL2 0x510
6194-+#define SNF_RD_CTL3 0x514
6195-+#define SNF_GF_CTL1 0x518
6196-+#define GF_ADDR_SHIFT 16
6197-+#define GF_CMD_SHIFT 24
6198-+#define SNF_GF_CTL3 0x520
6199-+#define SNF_PG_CTL1 0x524
6200-+#define PG_EXE_CMD_SHIFT 16
6201-+#define PG_LOAD_CMD_SHIFT 8
6202-+#define SNF_PG_CTL2 0x528
6203-+#define SNF_PG_CTL3 0x52c
6204-+#define SNF_ER_CTL 0x530
6205-+#define SNF_ER_CTL2 0x534
6206-+#define SNF_MISC_CTL 0x538
6207-+#define SW_RST BIT(28)
6208-+#define PG_LOAD_X4_EN BIT(20)
6209-+#define X2_DATA_MODE 1
6210-+#define X4_DATA_MODE 2
6211-+#define DUAL_IO_MODE 5
6212-+#define QUAD_IO_MODE 6
6213-+#define READ_MODE_SHIFT 16
6214-+#define LATCH_LAT_SHIFT 8
6215-+#define LATCH_LAT_MASK GENMASK(9, 8)
6216-+#define DARA_READ_MODE_MASK GENMASK(18, 16)
6217-+#define SF2CS_SEL BIT(13)
6218-+#define SF2CS_EN BIT(12)
6219-+#define PG_LOAD_CUSTOM_EN BIT(7)
6220-+#define DATARD_CUSTOM_EN BIT(6)
6221-+#define SNF_MISC_CTL2 0x53c
6222-+#define PG_LOAD_SHIFT 16
6223-+#define SNF_DLY_CTL1 0x540
6224-+#define SNF_DLY_CTL2 0x544
6225-+#define SNF_DLY_CTL3 0x548
6226-+#define SNF_DLY_CTL4 0x54c
6227-+#define SNF_STA_CTL1 0x550
6228-+#define SPI_STATE GENMASK(3, 0)
6229-+#define SNF_STA_CTL2 0x554
6230-+#define SNF_STA_CTL3 0x558
6231-+#define SNF_SNF_CNFG 0x55c
6232-+#define SPI_MODE BIT(0)
6233-+#define SNF_DEBUG_SEL 0x560
6234-+#define SPI_GPRAM_ADDR 0x800
6235-+
6236-+#endif /* __NFI_SPI_REGS_H__ */
6237-diff --git a/drivers/mtd/nandx/core/nfi/nfiecc.c b/drivers/mtd/nandx/core/nfi/nfiecc.c
6238-new file mode 100644
6239-index 0000000000..14246fbc3e
6240---- /dev/null
6241-+++ b/drivers/mtd/nandx/core/nfi/nfiecc.c
6242-@@ -0,0 +1,510 @@
6243-+/*
6244-+ * Copyright (C) 2017 MediaTek Inc.
6245-+ * Licensed under either
6246-+ * BSD Licence, (see NOTICE for more details)
6247-+ * GNU General Public License, version 2.0, (see NOTICE for more details)
6248-+ */
6249-+
6250-+#include "nandx_util.h"
6251-+#include "nandx_core.h"
6252-+#include "nfiecc_regs.h"
6253-+#include "nfiecc.h"
6254-+
6255-+#define NFIECC_IDLE_REG(op) \
6256-+ ((op) == ECC_ENCODE ? NFIECC_ENCIDLE : NFIECC_DECIDLE)
6257-+#define IDLE_MASK 1
6258-+#define NFIECC_CTL_REG(op) \
6259-+ ((op) == ECC_ENCODE ? NFIECC_ENCCON : NFIECC_DECCON)
6260-+#define NFIECC_IRQ_REG(op) \
6261-+ ((op) == ECC_ENCODE ? NFIECC_ENCIRQEN : NFIECC_DECIRQEN)
6262-+#define NFIECC_ADDR(op) \
6263-+ ((op) == ECC_ENCODE ? NFIECC_ENCDIADDR : NFIECC_DECDIADDR)
6264-+
6265-+#define ECC_TIMEOUT 500000
6266-+
6267-+/* ecc strength that each IP supports */
6268-+static const int ecc_strength_mt7622[] = {
6269-+ 4, 6, 8, 10, 12, 14, 16
6270-+};
6271-+
6272-+static int nfiecc_irq_handler(void *data)
6273-+{
6274-+ struct nfiecc *ecc = data;
6275-+ void *regs = ecc->res.regs;
6276-+ u32 status;
6277-+
6278-+ status = readl(regs + NFIECC_DECIRQSTA) & DEC_IRQSTA_GEN;
6279-+ if (status) {
6280-+ status = readl(regs + NFIECC_DECDONE);
6281-+ if (!(status & ecc->config.sectors))
6282-+ return NAND_IRQ_NONE;
6283-+
6284-+ /*
6285-+ * Clear decode IRQ status once again to ensure that
6286-+ * there will be no extra IRQ.
6287-+ */
6288-+ readl(regs + NFIECC_DECIRQSTA);
6289-+ ecc->config.sectors = 0;
6290-+ nandx_event_complete(ecc->done);
6291-+ } else {
6292-+ status = readl(regs + NFIECC_ENCIRQSTA) & ENC_IRQSTA_GEN;
6293-+ if (!status)
6294-+ return NAND_IRQ_NONE;
6295-+
6296-+ nandx_event_complete(ecc->done);
6297-+ }
6298-+
6299-+ return NAND_IRQ_HANDLED;
6300-+}
6301-+
6302-+static inline int nfiecc_wait_idle(struct nfiecc *ecc)
6303-+{
6304-+ int op = ecc->config.op;
6305-+ int ret, val;
6306-+
6307-+ ret = readl_poll_timeout_atomic(ecc->res.regs + NFIECC_IDLE_REG(op),
6308-+ val, val & IDLE_MASK,
6309-+ 10, ECC_TIMEOUT);
6310-+ if (ret)
6311-+ pr_info("%s not idle\n",
6312-+ op == ECC_ENCODE ? "encoder" : "decoder");
6313-+
6314-+ return ret;
6315-+}
6316-+
6317-+static int nfiecc_wait_encode_done(struct nfiecc *ecc)
6318-+{
6319-+ int ret, val;
6320-+
6321-+ if (ecc->ecc_irq_en) {
6322-+ /* poll one time to avoid missing irq event */
6323-+ ret = readl_poll_timeout_atomic(ecc->res.regs + NFIECC_ENCSTA,
6324-+ val, val & ENC_FSM_IDLE, 1, 1);
6325-+ if (!ret)
6326-+ return 0;
6327-+
6328-+ /* irq done, if not, we can go on to poll status for a while */
6329-+ ret = nandx_event_wait_complete(ecc->done, ECC_TIMEOUT);
6330-+ if (ret)
6331-+ return 0;
6332-+ }
6333-+
6334-+ ret = readl_poll_timeout_atomic(ecc->res.regs + NFIECC_ENCSTA,
6335-+ val, val & ENC_FSM_IDLE,
6336-+ 10, ECC_TIMEOUT);
6337-+ if (ret)
6338-+ pr_info("encode timeout\n");
6339-+
6340-+ return ret;
6341-+
6342-+}
6343-+
6344-+static int nfiecc_wait_decode_done(struct nfiecc *ecc)
6345-+{
6346-+ u32 secbit = BIT(ecc->config.sectors - 1);
6347-+ void *regs = ecc->res.regs;
6348-+ int ret, val;
6349-+
6350-+ if (ecc->ecc_irq_en) {
6351-+ ret = readl_poll_timeout_atomic(regs + NFIECC_DECDONE,
6352-+ val, val & secbit, 1, 1);
6353-+ if (!ret)
6354-+ return 0;
6355-+
6356-+ ret = nandx_event_wait_complete(ecc->done, ECC_TIMEOUT);
6357-+ if (ret)
6358-+ return 0;
6359-+ }
6360-+
6361-+ ret = readl_poll_timeout_atomic(regs + NFIECC_DECDONE,
6362-+ val, val & secbit,
6363-+ 10, ECC_TIMEOUT);
6364-+ if (ret) {
6365-+ pr_info("decode timeout\n");
6366-+ return ret;
6367-+ }
6368-+
6369-+ /* decode done does not stands for ecc all work done.
6370-+ * we need check syn, bma, chien, autoc all idle.
6371-+ * just check it when ECC_DECCNFG[13:12] is 3,
6372-+ * which means auto correct.
6373-+ */
6374-+ ret = readl_poll_timeout_atomic(regs + NFIECC_DECFSM,
6375-+ val, (val & FSM_MASK) == FSM_IDLE,
6376-+ 10, ECC_TIMEOUT);
6377-+ if (ret)
6378-+ pr_info("decode fsm(0x%x) is not idle\n",
6379-+ readl(regs + NFIECC_DECFSM));
6380-+
6381-+ return ret;
6382-+}
6383-+
6384-+static int nfiecc_wait_done(struct nfiecc *ecc)
6385-+{
6386-+ if (ecc->config.op == ECC_ENCODE)
6387-+ return nfiecc_wait_encode_done(ecc);
6388-+
6389-+ return nfiecc_wait_decode_done(ecc);
6390-+}
6391-+
6392-+static void nfiecc_encode_config(struct nfiecc *ecc, u32 ecc_idx)
6393-+{
6394-+ struct nfiecc_config *config = &ecc->config;
6395-+ u32 val;
6396-+
6397-+ val = ecc_idx | (config->mode << ecc->caps->ecc_mode_shift);
6398-+
6399-+ if (config->mode == ECC_DMA_MODE)
6400-+ val |= ENC_BURST_EN;
6401-+
6402-+ val |= (config->len << 3) << ENCCNFG_MS_SHIFT;
6403-+ writel(val, ecc->res.regs + NFIECC_ENCCNFG);
6404-+}
6405-+
6406-+static void nfiecc_decode_config(struct nfiecc *ecc, u32 ecc_idx)
6407-+{
6408-+ struct nfiecc_config *config = &ecc->config;
6409-+ u32 dec_sz = (config->len << 3) +
6410-+ config->strength * ecc->caps->parity_bits;
6411-+ u32 val;
6412-+
6413-+ val = ecc_idx | (config->mode << ecc->caps->ecc_mode_shift);
6414-+
6415-+ if (config->mode == ECC_DMA_MODE)
6416-+ val |= DEC_BURST_EN;
6417-+
6418-+ val |= (dec_sz << DECCNFG_MS_SHIFT) |
6419-+ (config->deccon << DEC_CON_SHIFT);
6420-+ val |= DEC_EMPTY_EN;
6421-+ writel(val, ecc->res.regs + NFIECC_DECCNFG);
6422-+}
6423-+
6424-+static void nfiecc_config(struct nfiecc *ecc)
6425-+{
6426-+ u32 idx;
6427-+
6428-+ for (idx = 0; idx < ecc->caps->ecc_strength_num; idx++) {
6429-+ if (ecc->config.strength == ecc->caps->ecc_strength[idx])
6430-+ break;
6431-+ }
6432-+
6433-+ if (ecc->config.op == ECC_ENCODE)
6434-+ nfiecc_encode_config(ecc, idx);
6435-+ else
6436-+ nfiecc_decode_config(ecc, idx);
6437-+}
6438-+
6439-+static int nfiecc_enable(struct nfiecc *ecc)
6440-+{
6441-+ enum nfiecc_operation op = ecc->config.op;
6442-+ void *regs = ecc->res.regs;
6443-+
6444-+ nfiecc_config(ecc);
6445-+
6446-+ writel(ECC_OP_EN, regs + NFIECC_CTL_REG(op));
6447-+
6448-+ if (ecc->ecc_irq_en) {
6449-+ writel(ECC_IRQEN, regs + NFIECC_IRQ_REG(op));
6450-+
6451-+ if (ecc->page_irq_en)
6452-+ writel(ECC_IRQEN | ECC_PG_IRQ_SEL,
6453-+ regs + NFIECC_IRQ_REG(op));
6454-+
6455-+ nandx_event_init(ecc->done);
6456-+ }
6457-+
6458-+ return 0;
6459-+}
6460-+
6461-+static int nfiecc_disable(struct nfiecc *ecc)
6462-+{
6463-+ enum nfiecc_operation op = ecc->config.op;
6464-+ void *regs = ecc->res.regs;
6465-+
6466-+ nfiecc_wait_idle(ecc);
6467-+
6468-+ writel(0, regs + NFIECC_IRQ_REG(op));
6469-+ writel(~ECC_OP_EN, regs + NFIECC_CTL_REG(op));
6470-+
6471-+ return 0;
6472-+}
6473-+
6474-+static int nfiecc_correct_data(struct nfiecc *ecc,
6475-+ struct nfiecc_status *status,
6476-+ u8 *data, u32 sector)
6477-+{
6478-+ u32 err, offset, i;
6479-+ u32 loc, byteloc, bitloc;
6480-+
6481-+ status->corrected = 0;
6482-+ status->failed = 0;
6483-+
6484-+ offset = (sector >> 2);
6485-+ err = readl(ecc->res.regs + NFIECC_DECENUM(offset));
6486-+ err >>= (sector % 4) * 8;
6487-+ err &= ecc->caps->err_mask;
6488-+
6489-+ if (err == ecc->caps->err_mask) {
6490-+ status->failed++;
6491-+ return -ENANDREAD;
6492-+ }
6493-+
6494-+ status->corrected += err;
6495-+ status->bitflips = max_t(u32, status->bitflips, err);
6496-+
6497-+ for (i = 0; i < err; i++) {
6498-+ loc = readl(ecc->res.regs + NFIECC_DECEL(i >> 1));
6499-+ loc >>= ((i & 0x1) << 4);
6500-+ byteloc = loc >> 3;
6501-+ bitloc = loc & 0x7;
6502-+ data[byteloc] ^= (1 << bitloc);
6503-+ }
6504-+
6505-+ return 0;
6506-+}
6507-+
6508-+static int nfiecc_fill_data(struct nfiecc *ecc, u8 *data)
6509-+{
6510-+ struct nfiecc_config *config = &ecc->config;
6511-+ void *regs = ecc->res.regs;
6512-+ int size, ret, i;
6513-+ u32 val;
6514-+
6515-+ if (config->mode == ECC_DMA_MODE) {
6516-+ if ((unsigned long)config->dma_addr & 0x3)
6517-+ pr_info("encode address is not 4B aligned: 0x%x\n",
6518-+ (u32)(unsigned long)config->dma_addr);
6519-+
6520-+ writel((unsigned long)config->dma_addr,
6521-+ regs + NFIECC_ADDR(config->op));
6522-+ } else if (config->mode == ECC_PIO_MODE) {
6523-+ if (config->op == ECC_ENCODE) {
6524-+ size = (config->len + 3) >> 2;
6525-+ } else {
6526-+ size = config->strength * ecc->caps->parity_bits;
6527-+ size = (size + 7) >> 3;
6528-+ size += config->len;
6529-+ size >>= 2;
6530-+ }
6531-+
6532-+ for (i = 0; i < size; i++) {
6533-+ ret = readl_poll_timeout_atomic(regs + NFIECC_PIO_DIRDY,
6534-+ val, val & PIO_DI_RDY,
6535-+ 10, ECC_TIMEOUT);
6536-+ if (ret)
6537-+ return ret;
6538-+
6539-+ writel(*((u32 *)data + i), regs + NFIECC_PIO_DI);
6540-+ }
6541-+ }
6542-+
6543-+ return 0;
6544-+}
6545-+
6546-+static int nfiecc_encode(struct nfiecc *ecc, u8 *data)
6547-+{
6548-+ struct nfiecc_config *config = &ecc->config;
6549-+ u32 len, i, val = 0;
6550-+ u8 *p;
6551-+ int ret;
6552-+
6553-+ /* Under NFI mode, nothing need to do */
6554-+ if (config->mode == ECC_NFI_MODE)
6555-+ return 0;
6556-+
6557-+ ret = nfiecc_fill_data(ecc, data);
6558-+ if (ret)
6559-+ return ret;
6560-+
6561-+ ret = nfiecc_wait_encode_done(ecc);
6562-+ if (ret)
6563-+ return ret;
6564-+
6565-+ ret = nfiecc_wait_idle(ecc);
6566-+ if (ret)
6567-+ return ret;
6568-+
6569-+ /* Program ECC bytes to OOB: per sector oob = FDM + ECC + SPARE */
6570-+ len = (config->strength * ecc->caps->parity_bits + 7) >> 3;
6571-+ p = data + config->len;
6572-+
6573-+ /* Write the parity bytes generated by the ECC back to the OOB region */
6574-+ for (i = 0; i < len; i++) {
6575-+ if ((i % 4) == 0)
6576-+ val = readl(ecc->res.regs + NFIECC_ENCPAR(i / 4));
6577-+
6578-+ p[i] = (val >> ((i % 4) * 8)) & 0xff;
6579-+ }
6580-+
6581-+ return 0;
6582-+}
6583-+
6584-+static int nfiecc_decode(struct nfiecc *ecc, u8 *data)
6585-+{
6586-+ int ret;
6587-+
6588-+ /* Under NFI mode, nothing need to do */
6589-+ if (ecc->config.mode == ECC_NFI_MODE)
6590-+ return 0;
6591-+
6592-+ ret = nfiecc_fill_data(ecc, data);
6593-+ if (ret)
6594-+ return ret;
6595-+
6596-+ return nfiecc_wait_decode_done(ecc);
6597-+}
6598-+
6599-+static int nfiecc_decode_status(struct nfiecc *ecc, u32 start_sector,
6600-+ u32 sectors)
6601-+{
6602-+ void *regs = ecc->res.regs;
6603-+ u32 i, val = 0, err;
6604-+ u32 bitflips = 0;
6605-+
6606-+ for (i = start_sector; i < start_sector + sectors; i++) {
6607-+ if ((i % 4) == 0)
6608-+ val = readl(regs + NFIECC_DECENUM(i / 4));
6609-+
6610-+ err = val >> ((i % 4) * 5);
6611-+ err &= ecc->caps->err_mask;
6612-+
6613-+ if (err == ecc->caps->err_mask)
6614-+ pr_err("sector %d is uncorrect\n", i);
6615-+
6616-+ bitflips = max_t(u32, bitflips, err);
6617-+ }
6618-+
6619-+ if (bitflips == ecc->caps->err_mask)
6620-+ return -ENANDREAD;
6621-+
6622-+ if (bitflips)
6623-+ pr_info("bitflips %d is corrected\n", bitflips);
6624-+
6625-+ return bitflips;
6626-+}
6627-+
6628-+static int nfiecc_adjust_strength(struct nfiecc *ecc, int strength)
6629-+{
6630-+ struct nfiecc_caps *caps = ecc->caps;
6631-+ int i, count = caps->ecc_strength_num;
6632-+
6633-+ if (strength >= caps->ecc_strength[count - 1])
6634-+ return caps->ecc_strength[count - 1];
6635-+
6636-+ if (strength < caps->ecc_strength[0])
6637-+ return -EINVAL;
6638-+
6639-+ for (i = 1; i < count; i++) {
6640-+ if (strength < caps->ecc_strength[i])
6641-+ return caps->ecc_strength[i - 1];
6642-+ }
6643-+
6644-+ return -EINVAL;
6645-+}
6646-+
6647-+static int nfiecc_ctrl(struct nfiecc *ecc, int cmd, void *args)
6648-+{
6649-+ int ret = 0;
6650-+
6651-+ switch (cmd) {
6652-+ case NFI_CTRL_ECC_IRQ:
6653-+ ecc->ecc_irq_en = *(bool *)args;
6654-+ break;
6655-+
6656-+ case NFI_CTRL_ECC_PAGE_IRQ:
6657-+ ecc->page_irq_en = *(bool *)args;
6658-+ break;
6659-+
6660-+ default:
6661-+ pr_info("invalid arguments.\n");
6662-+ ret = -EINVAL;
6663-+ break;
6664-+ }
6665-+
6666-+ return ret;
6667-+}
6668-+
6669-+static int nfiecc_hw_init(struct nfiecc *ecc)
6670-+{
6671-+ int ret;
6672-+
6673-+ ret = nfiecc_wait_idle(ecc);
6674-+ if (ret)
6675-+ return ret;
6676-+
6677-+ writel(~ECC_OP_EN, ecc->res.regs + NFIECC_ENCCON);
6678-+
6679-+ ret = nfiecc_wait_idle(ecc);
6680-+ if (ret)
6681-+ return ret;
6682-+
6683-+ writel(~ECC_OP_EN, ecc->res.regs + NFIECC_DECCON);
6684-+
6685-+ return 0;
6686-+}
6687-+
6688-+static struct nfiecc_caps nfiecc_caps_mt7622 = {
6689-+ .err_mask = 0x1f,
6690-+ .ecc_mode_shift = 4,
6691-+ .parity_bits = 13,
6692-+ .ecc_strength = ecc_strength_mt7622,
6693-+ .ecc_strength_num = 7,
6694-+};
6695-+
6696-+static struct nfiecc_caps *nfiecc_get_match_data(enum mtk_ic_version ic)
6697-+{
6698-+ /* NOTE: add other IC's data */
6699-+ return &nfiecc_caps_mt7622;
6700-+}
6701-+
6702-+struct nfiecc *nfiecc_init(struct nfiecc_resource *res)
6703-+{
6704-+ struct nfiecc *ecc;
6705-+ int ret;
6706-+
6707-+ ecc = mem_alloc(1, sizeof(struct nfiecc));
6708-+ if (!ecc)
6709-+ return NULL;
6710-+
6711-+ ecc->res = *res;
6712-+
6713-+ ret = nandx_irq_register(res->dev, res->irq_id, nfiecc_irq_handler,
6714-+ "mtk-ecc", ecc);
6715-+ if (ret) {
6716-+ pr_info("ecc irq register failed!\n");
6717-+ goto error;
6718-+ }
6719-+
6720-+ ecc->ecc_irq_en = false;
6721-+ ecc->page_irq_en = false;
6722-+ ecc->done = nandx_event_create();
6723-+ ecc->caps = nfiecc_get_match_data(res->ic_ver);
6724-+
6725-+ ecc->adjust_strength = nfiecc_adjust_strength;
6726-+ ecc->enable = nfiecc_enable;
6727-+ ecc->disable = nfiecc_disable;
6728-+ ecc->decode = nfiecc_decode;
6729-+ ecc->encode = nfiecc_encode;
6730-+ ecc->wait_done = nfiecc_wait_done;
6731-+ ecc->decode_status = nfiecc_decode_status;
6732-+ ecc->correct_data = nfiecc_correct_data;
6733-+ ecc->nfiecc_ctrl = nfiecc_ctrl;
6734-+
6735-+ ret = nfiecc_hw_init(ecc);
6736-+ if (ret)
6737-+ return NULL;
6738-+
6739-+ return ecc;
6740-+
6741-+error:
6742-+ mem_free(ecc);
6743-+
6744-+ return NULL;
6745-+}
6746-+
6747-+void nfiecc_exit(struct nfiecc *ecc)
6748-+{
6749-+ nandx_event_destroy(ecc->done);
6750-+ mem_free(ecc);
6751-+}
6752-+
6753-diff --git a/drivers/mtd/nandx/core/nfi/nfiecc.h b/drivers/mtd/nandx/core/nfi/nfiecc.h
6754-new file mode 100644
6755-index 0000000000..b02a5c3534
6756---- /dev/null
6757-+++ b/drivers/mtd/nandx/core/nfi/nfiecc.h
6758-@@ -0,0 +1,90 @@
6759-+/*
6760-+ * Copyright (C) 2017 MediaTek Inc.
6761-+ * Licensed under either
6762-+ * BSD Licence, (see NOTICE for more details)
6763-+ * GNU General Public License, version 2.0, (see NOTICE for more details)
6764-+ */
6765-+
6766-+#ifndef __NFIECC_H__
6767-+#define __NFIECC_H__
6768-+
6769-+enum nfiecc_mode {
6770-+ ECC_DMA_MODE,
6771-+ ECC_NFI_MODE,
6772-+ ECC_PIO_MODE
6773-+};
6774-+
6775-+enum nfiecc_operation {
6776-+ ECC_ENCODE,
6777-+ ECC_DECODE
6778-+};
6779-+
6780-+enum nfiecc_deccon {
6781-+ ECC_DEC_FER = 1,
6782-+ ECC_DEC_LOCATE = 2,
6783-+ ECC_DEC_CORRECT = 3
6784-+};
6785-+
6786-+struct nfiecc_resource {
6787-+ int ic_ver;
6788-+ void *dev;
6789-+ void *regs;
6790-+ int irq_id;
6791-+
6792-+};
6793-+
6794-+struct nfiecc_status {
6795-+ u32 corrected;
6796-+ u32 failed;
6797-+ u32 bitflips;
6798-+};
6799-+
6800-+struct nfiecc_caps {
6801-+ u32 err_mask;
6802-+ u32 ecc_mode_shift;
6803-+ u32 parity_bits;
6804-+ const int *ecc_strength;
6805-+ u32 ecc_strength_num;
6806-+};
6807-+
6808-+struct nfiecc_config {
6809-+ enum nfiecc_operation op;
6810-+ enum nfiecc_mode mode;
6811-+ enum nfiecc_deccon deccon;
6812-+
6813-+ void *dma_addr; /* DMA use only */
6814-+ u32 strength;
6815-+ u32 sectors;
6816-+ u32 len;
6817-+};
6818-+
6819-+struct nfiecc {
6820-+ struct nfiecc_resource res;
6821-+ struct nfiecc_config config;
6822-+ struct nfiecc_caps *caps;
6823-+
6824-+ bool ecc_irq_en;
6825-+ bool page_irq_en;
6826-+
6827-+ void *done;
6828-+
6829-+ int (*adjust_strength)(struct nfiecc *ecc, int strength);
6830-+ int (*enable)(struct nfiecc *ecc);
6831-+ int (*disable)(struct nfiecc *ecc);
6832-+
6833-+ int (*decode)(struct nfiecc *ecc, u8 *data);
6834-+ int (*encode)(struct nfiecc *ecc, u8 *data);
6835-+
6836-+ int (*decode_status)(struct nfiecc *ecc, u32 start_sector, u32 sectors);
6837-+ int (*correct_data)(struct nfiecc *ecc,
6838-+ struct nfiecc_status *status,
6839-+ u8 *data, u32 sector);
6840-+ int (*wait_done)(struct nfiecc *ecc);
6841-+
6842-+ int (*nfiecc_ctrl)(struct nfiecc *ecc, int cmd, void *args);
6843-+};
6844-+
6845-+struct nfiecc *nfiecc_init(struct nfiecc_resource *res);
6846-+void nfiecc_exit(struct nfiecc *ecc);
6847-+
6848-+#endif /* __NFIECC_H__ */
6849-diff --git a/drivers/mtd/nandx/core/nfi/nfiecc_regs.h b/drivers/mtd/nandx/core/nfi/nfiecc_regs.h
6850-new file mode 100644
6851-index 0000000000..96564cf872
6852---- /dev/null
6853-+++ b/drivers/mtd/nandx/core/nfi/nfiecc_regs.h
6854-@@ -0,0 +1,51 @@
6855-+/*
6856-+ * Copyright (C) 2017 MediaTek Inc.
6857-+ * Licensed under either
6858-+ * BSD Licence, (see NOTICE for more details)
6859-+ * GNU General Public License, version 2.0, (see NOTICE for more details)
6860-+ */
6861-+
6862-+#ifndef __NFIECC_REGS_H__
6863-+#define __NFIECC_REGS_H__
6864-+
6865-+#define NFIECC_ENCCON 0x000
6866-+/* NFIECC_DECCON has same bit define */
6867-+#define ECC_OP_EN BIT(0)
6868-+#define NFIECC_ENCCNFG 0x004
6869-+#define ENCCNFG_MS_SHIFT 16
6870-+#define ENC_BURST_EN BIT(8)
6871-+#define NFIECC_ENCDIADDR 0x008
6872-+#define NFIECC_ENCIDLE 0x00c
6873-+#define NFIECC_ENCSTA 0x02c
6874-+#define ENC_FSM_IDLE 1
6875-+#define NFIECC_ENCIRQEN 0x030
6876-+/* NFIECC_DECIRQEN has same bit define */
6877-+#define ECC_IRQEN BIT(0)
6878-+#define ECC_PG_IRQ_SEL BIT(1)
6879-+#define NFIECC_ENCIRQSTA 0x034
6880-+#define ENC_IRQSTA_GEN BIT(0)
6881-+#define NFIECC_PIO_DIRDY 0x080
6882-+#define PIO_DI_RDY BIT(0)
6883-+#define NFIECC_PIO_DI 0x084
6884-+#define NFIECC_DECCON 0x100
6885-+#define NFIECC_DECCNFG 0x104
6886-+#define DEC_BURST_EN BIT(8)
6887-+#define DEC_EMPTY_EN BIT(31)
6888-+#define DEC_CON_SHIFT 12
6889-+#define DECCNFG_MS_SHIFT 16
6890-+#define NFIECC_DECDIADDR 0x108
6891-+#define NFIECC_DECIDLE 0x10c
6892-+#define NFIECC_DECENUM(x) (0x114 + (x) * 4)
6893-+#define NFIECC_DECDONE 0x11c
6894-+#define NFIECC_DECIRQEN 0x140
6895-+#define NFIECC_DECIRQSTA 0x144
6896-+#define DEC_IRQSTA_GEN BIT(0)
6897-+#define NFIECC_DECFSM 0x14c
6898-+#define FSM_MASK 0x7f0f0f0f
6899-+#define FSM_IDLE 0x01010101
6900-+#define NFIECC_BYPASS 0x20c
6901-+#define NFIECC_BYPASS_EN BIT(0)
6902-+#define NFIECC_ENCPAR(x) (0x010 + (x) * 4)
6903-+#define NFIECC_DECEL(x) (0x120 + (x) * 4)
6904-+
6905-+#endif /* __NFIECC_REGS_H__ */
6906-diff --git a/drivers/mtd/nandx/driver/Nandx.mk b/drivers/mtd/nandx/driver/Nandx.mk
6907-new file mode 100644
6908-index 0000000000..3fb93d37c5
6909---- /dev/null
6910-+++ b/drivers/mtd/nandx/driver/Nandx.mk
6911-@@ -0,0 +1,18 @@
6912-+#
6913-+# Copyright (C) 2017 MediaTek Inc.
6914-+# Licensed under either
6915-+# BSD Licence, (see NOTICE for more details)
6916-+# GNU General Public License, version 2.0, (see NOTICE for more details)
6917-+#
6918-+
6919-+nandx-$(NANDX_SIMULATOR_SUPPORT) += simulator/driver.c
6920-+
6921-+nandx-$(NANDX_CTP_SUPPORT) += ctp/ts_nand.c
6922-+nandx-$(NANDX_CTP_SUPPORT) += ctp/nand_test.c
6923-+nandx-header-$(NANDX_CTP_SUPPORT) += ctp/nand_test.h
6924-+
6925-+nandx-$(NANDX_BBT_SUPPORT) += bbt/bbt.c
6926-+nandx-$(NANDX_BROM_SUPPORT) += brom/driver.c
6927-+nandx-$(NANDX_KERNEL_SUPPORT) += kernel/driver.c
6928-+nandx-$(NANDX_LK_SUPPORT) += lk/driver.c
6929-+nandx-$(NANDX_UBOOT_SUPPORT) += uboot/driver.c
6930-diff --git a/drivers/mtd/nandx/driver/bbt/bbt.c b/drivers/mtd/nandx/driver/bbt/bbt.c
6931-new file mode 100644
6932-index 0000000000..c9d4823e09
6933---- /dev/null
6934-+++ b/drivers/mtd/nandx/driver/bbt/bbt.c
6935-@@ -0,0 +1,408 @@
6936-+/*
6937-+ * Copyright (C) 2017 MediaTek Inc.
6938-+ * Licensed under either
6939-+ * BSD Licence, (see NOTICE for more details)
6940-+ * GNU General Public License, version 2.0, (see NOTICE for more details)
6941-+ */
6942-+
6943-+#include "nandx_util.h"
6944-+#include "nandx_core.h"
6945-+#include "bbt.h"
6946-+
6947-+/* Not support: multi-chip */
6948-+static u8 main_bbt_pattern[] = {'B', 'b', 't', '0' };
6949-+static u8 mirror_bbt_pattern[] = {'1', 't', 'b', 'B' };
6950-+
6951-+static struct bbt_manager g_bbt_manager = {
6952-+ { {{main_bbt_pattern, 4}, 0, BBT_INVALID_ADDR},
6953-+ {{mirror_bbt_pattern, 4}, 0, BBT_INVALID_ADDR}
6954-+ },
6955-+ NAND_BBT_SCAN_MAXBLOCKS, NULL
6956-+};
6957-+
6958-+static inline void set_bbt_mark(u8 *bbt, int block, u8 mark)
6959-+{
6960-+ int index, offset;
6961-+
6962-+ index = GET_ENTRY(block);
6963-+ offset = GET_POSITION(block);
6964-+
6965-+ bbt[index] &= ~(BBT_ENTRY_MASK << offset);
6966-+ bbt[index] |= (mark & BBT_ENTRY_MASK) << offset;
6967-+ pr_info("%s %d block:%d, bbt[%d]:0x%x, offset:%d, mark:%d\n",
6968-+ __func__, __LINE__, block, index, bbt[index], offset, mark);
6969-+}
6970-+
6971-+static inline u8 get_bbt_mark(u8 *bbt, int block)
6972-+{
6973-+ int offset = GET_POSITION(block);
6974-+ int index = GET_ENTRY(block);
6975-+ u8 value = bbt[index];
6976-+
6977-+ return (value >> offset) & BBT_ENTRY_MASK;
6978-+}
6979-+
6980-+static void mark_nand_bad(struct nandx_info *nand, int block)
6981-+{
6982-+ u8 *buf;
6983-+
6984-+ buf = mem_alloc(1, nand->page_size + nand->oob_size);
6985-+ if (!buf) {
6986-+ pr_info("%s, %d, memory alloc fail, pagesize:%d, oobsize:%d\n",
6987-+ __func__, __LINE__, nand->page_size, nand->oob_size);
6988-+ return;
6989-+ }
6990-+ memset(buf, 0, nand->page_size + nand->oob_size);
6991-+ nandx_erase(block * nand->block_size, nand->block_size);
6992-+ nandx_write(buf, buf + nand->page_size, block * nand->block_size,
6993-+ nand->page_size);
6994-+ mem_free(buf);
6995-+}
6996-+
6997-+static inline bool is_bbt_data(u8 *buf, struct bbt_pattern *pattern)
6998-+{
6999-+ int i;
7000-+
7001-+ for (i = 0; i < pattern->len; i++) {
7002-+ if (buf[i] != pattern->data[i])
7003-+ return false;
7004-+ }
7005-+
7006-+ return true;
7007-+}
7008-+
7009-+static u64 get_bbt_address(struct nandx_info *nand, u8 *bbt,
7010-+ u64 mirror_addr,
7011-+ int max_blocks)
7012-+{
7013-+ u64 addr, end_addr;
7014-+ u8 mark;
7015-+
7016-+ addr = nand->total_size;
7017-+ end_addr = nand->total_size - nand->block_size * max_blocks;
7018-+
7019-+ while (addr > end_addr) {
7020-+ addr -= nand->block_size;
7021-+ mark = get_bbt_mark(bbt, div_down(addr, nand->block_size));
7022-+
7023-+ if (mark == BBT_BLOCK_WORN || mark == BBT_BLOCK_FACTORY_BAD)
7024-+ continue;
7025-+ if (addr != mirror_addr)
7026-+ return addr;
7027-+ }
7028-+
7029-+ return BBT_INVALID_ADDR;
7030-+}
7031-+
7032-+static int read_bbt(struct bbt_desc *desc, u8 *bbt, u32 len)
7033-+{
7034-+ int ret;
7035-+
7036-+ ret = nandx_read(bbt, NULL, desc->bbt_addr + desc->pattern.len + 1,
7037-+ len);
7038-+ if (ret < 0)
7039-+ pr_info("nand_bbt: error reading BBT page, ret:-%x\n", ret);
7040-+
7041-+ return ret;
7042-+}
7043-+
7044-+static void create_bbt(struct nandx_info *nand, u8 *bbt)
7045-+{
7046-+ u32 offset = 0, block = 0;
7047-+
7048-+ do {
7049-+ if (nandx_is_bad_block(offset)) {
7050-+ pr_info("Create bbt at bad block:%d\n", block);
7051-+ set_bbt_mark(bbt, block, BBT_BLOCK_FACTORY_BAD);
7052-+ }
7053-+ block++;
7054-+ offset += nand->block_size;
7055-+ } while (offset < nand->total_size);
7056-+}
7057-+
7058-+static int search_bbt(struct nandx_info *nand, struct bbt_desc *desc,
7059-+ int max_blocks)
7060-+{
7061-+ u64 addr, end_addr;
7062-+ u8 *buf;
7063-+ int ret;
7064-+
7065-+ buf = mem_alloc(1, nand->page_size);
7066-+ if (!buf) {
7067-+ pr_info("%s, %d, mem alloc fail!!! len:%d\n",
7068-+ __func__, __LINE__, nand->page_size);
7069-+ return -ENOMEM;
7070-+ }
7071-+
7072-+ addr = nand->total_size;
7073-+ end_addr = nand->total_size - max_blocks * nand->block_size;
7074-+ while (addr > end_addr) {
7075-+ addr -= nand->block_size;
7076-+
7077-+ nandx_read(buf, NULL, addr, nand->page_size);
7078-+
7079-+ if (is_bbt_data(buf, &desc->pattern)) {
7080-+ desc->bbt_addr = addr;
7081-+ desc->version = buf[desc->pattern.len];
7082-+ pr_info("BBT is found at addr 0x%llx, version %d\n",
7083-+ desc->bbt_addr, desc->version);
7084-+ ret = 0;
7085-+ break;
7086-+ }
7087-+ ret = -EFAULT;
7088-+ }
7089-+
7090-+ mem_free(buf);
7091-+ return ret;
7092-+}
7093-+
7094-+static int save_bbt(struct nandx_info *nand, struct bbt_desc *desc,
7095-+ u8 *bbt)
7096-+{
7097-+ u32 page_size_mask, total_block;
7098-+ int write_len;
7099-+ u8 *buf;
7100-+ int ret;
7101-+
7102-+ ret = nandx_erase(desc->bbt_addr, nand->block_size);
7103-+ if (ret) {
7104-+ pr_info("erase addr 0x%llx fail !!!, ret %d\n",
7105-+ desc->bbt_addr, ret);
7106-+ return ret;
7107-+ }
7108-+
7109-+ total_block = div_down(nand->total_size, nand->block_size);
7110-+ write_len = GET_BBT_LENGTH(total_block) + desc->pattern.len + 1;
7111-+ page_size_mask = nand->page_size - 1;
7112-+ write_len = (write_len + page_size_mask) & (~page_size_mask);
7113-+
7114-+ buf = (u8 *)mem_alloc(1, write_len);
7115-+ if (!buf) {
7116-+ pr_info("%s, %d, mem alloc fail!!! len:%d\n",
7117-+ __func__, __LINE__, write_len);
7118-+ return -ENOMEM;
7119-+ }
7120-+ memset(buf, 0xFF, write_len);
7121-+
7122-+ memcpy(buf, desc->pattern.data, desc->pattern.len);
7123-+ buf[desc->pattern.len] = desc->version;
7124-+
7125-+ memcpy(buf + desc->pattern.len + 1, bbt, GET_BBT_LENGTH(total_block));
7126-+
7127-+ ret = nandx_write(buf, NULL, desc->bbt_addr, write_len);
7128-+
7129-+ if (ret)
7130-+ pr_info("nandx_write fail(%d), offset:0x%llx, len(%d)\n",
7131-+ ret, desc->bbt_addr, write_len);
7132-+ mem_free(buf);
7133-+
7134-+ return ret;
7135-+}
7136-+
7137-+static int write_bbt(struct nandx_info *nand, struct bbt_desc *main,
7138-+ struct bbt_desc *mirror, u8 *bbt, int max_blocks)
7139-+{
7140-+ int block;
7141-+ int ret;
7142-+
7143-+ do {
7144-+ if (main->bbt_addr == BBT_INVALID_ADDR) {
7145-+ main->bbt_addr = get_bbt_address(nand, bbt,
7146-+ mirror->bbt_addr, max_blocks);
7147-+ if (main->bbt_addr == BBT_INVALID_ADDR)
7148-+ return -ENOSPC;
7149-+ }
7150-+
7151-+ ret = save_bbt(nand, main, bbt);
7152-+ if (!ret)
7153-+ break;
7154-+
7155-+ block = div_down(main->bbt_addr, nand->block_size);
7156-+ set_bbt_mark(bbt, block, BBT_BLOCK_WORN);
7157-+ main->version++;
7158-+ mark_nand_bad(nand, block);
7159-+ main->bbt_addr = BBT_INVALID_ADDR;
7160-+ } while (1);
7161-+
7162-+ return 0;
7163-+}
7164-+
7165-+static void mark_bbt_region(struct nandx_info *nand, u8 *bbt, int bbt_blocks)
7166-+{
7167-+ int total_block;
7168-+ int block;
7169-+ u8 mark;
7170-+
7171-+ total_block = div_down(nand->total_size, nand->block_size);
7172-+ block = total_block - bbt_blocks;
7173-+
7174-+ while (bbt_blocks) {
7175-+ mark = get_bbt_mark(bbt, block);
7176-+ if (mark == BBT_BLOCK_GOOD)
7177-+ set_bbt_mark(bbt, block, BBT_BLOCK_RESERVED);
7178-+ block++;
7179-+ bbt_blocks--;
7180-+ }
7181-+}
7182-+
7183-+static void unmark_bbt_region(struct nandx_info *nand, u8 *bbt, int bbt_blocks)
7184-+{
7185-+ int total_block;
7186-+ int block;
7187-+ u8 mark;
7188-+
7189-+ total_block = div_down(nand->total_size, nand->block_size);
7190-+ block = total_block - bbt_blocks;
7191-+
7192-+ while (bbt_blocks) {
7193-+ mark = get_bbt_mark(bbt, block);
7194-+ if (mark == BBT_BLOCK_RESERVED)
7195-+ set_bbt_mark(bbt, block, BBT_BLOCK_GOOD);
7196-+ block++;
7197-+ bbt_blocks--;
7198-+ }
7199-+}
7200-+
7201-+static int update_bbt(struct nandx_info *nand, struct bbt_desc *desc,
7202-+ u8 *bbt,
7203-+ int max_blocks)
7204-+{
7205-+ int ret = 0, i;
7206-+
7207-+ /* The reserved info is not stored in NAND*/
7208-+ unmark_bbt_region(nand, bbt, max_blocks);
7209-+
7210-+ desc[0].version++;
7211-+ for (i = 0; i < 2; i++) {
7212-+ if (i > 0)
7213-+ desc[i].version = desc[i - 1].version;
7214-+
7215-+ ret = write_bbt(nand, &desc[i], &desc[1 - i], bbt, max_blocks);
7216-+ if (ret)
7217-+ break;
7218-+ }
7219-+ mark_bbt_region(nand, bbt, max_blocks);
7220-+
7221-+ return ret;
7222-+}
7223-+
7224-+int scan_bbt(struct nandx_info *nand)
7225-+{
7226-+ struct bbt_manager *manager = &g_bbt_manager;
7227-+ struct bbt_desc *pdesc;
7228-+ int total_block, len, i;
7229-+ int valid_desc = 0;
7230-+ int ret = 0;
7231-+ u8 *bbt;
7232-+
7233-+ total_block = div_down(nand->total_size, nand->block_size);
7234-+ len = GET_BBT_LENGTH(total_block);
7235-+
7236-+ if (!manager->bbt) {
7237-+ manager->bbt = (u8 *)mem_alloc(1, len);
7238-+ if (!manager->bbt) {
7239-+ pr_info("%s, %d, mem alloc fail!!! len:%d\n",
7240-+ __func__, __LINE__, len);
7241-+ return -ENOMEM;
7242-+ }
7243-+ }
7244-+ bbt = manager->bbt;
7245-+ memset(bbt, 0xFF, len);
7246-+
7247-+ /* scan bbt */
7248-+ for (i = 0; i < 2; i++) {
7249-+ pdesc = &manager->desc[i];
7250-+ pdesc->bbt_addr = BBT_INVALID_ADDR;
7251-+ pdesc->version = 0;
7252-+ ret = search_bbt(nand, pdesc, manager->max_blocks);
7253-+ if (!ret && (pdesc->bbt_addr != BBT_INVALID_ADDR))
7254-+ valid_desc += 1 << i;
7255-+ }
7256-+
7257-+ pdesc = &manager->desc[0];
7258-+ if ((valid_desc == 0x3) && (pdesc[0].version != pdesc[1].version))
7259-+ valid_desc = (pdesc[0].version > pdesc[1].version) ? 1 : 2;
7260-+
7261-+ /* read bbt */
7262-+ for (i = 0; i < 2; i++) {
7263-+ if (!(valid_desc & (1 << i)))
7264-+ continue;
7265-+ ret = read_bbt(&pdesc[i], bbt, len);
7266-+ if (ret) {
7267-+ pdesc->bbt_addr = BBT_INVALID_ADDR;
7268-+ pdesc->version = 0;
7269-+ valid_desc &= ~(1 << i);
7270-+ }
7271-+ /* If two BBT version is same, only need to read the first bbt*/
7272-+ if ((valid_desc == 0x3) &&
7273-+ (pdesc[0].version == pdesc[1].version))
7274-+ break;
7275-+ }
7276-+
7277-+ if (!valid_desc) {
7278-+ create_bbt(nand, bbt);
7279-+ pdesc[0].version = 1;
7280-+ pdesc[1].version = 1;
7281-+ }
7282-+
7283-+ pdesc[0].version = max_t(u8, pdesc[0].version, pdesc[1].version);
7284-+ pdesc[1].version = pdesc[0].version;
7285-+
7286-+ for (i = 0; i < 2; i++) {
7287-+ if (valid_desc & (1 << i))
7288-+ continue;
7289-+
7290-+ ret = write_bbt(nand, &pdesc[i], &pdesc[1 - i], bbt,
7291-+ manager->max_blocks);
7292-+ if (ret) {
7293-+ pr_info("write bbt(%d) fail, ret:%d\n", i, ret);
7294-+ manager->bbt = NULL;
7295-+ return ret;
7296-+ }
7297-+ }
7298-+
7299-+ /* Prevent the bbt regions from erasing / writing */
7300-+ mark_bbt_region(nand, manager->bbt, manager->max_blocks);
7301-+
7302-+ for (i = 0; i < total_block; i++) {
7303-+ if (get_bbt_mark(manager->bbt, i) == BBT_BLOCK_WORN)
7304-+ pr_info("Checked WORN bad blk: %d\n", i);
7305-+ else if (get_bbt_mark(manager->bbt, i) == BBT_BLOCK_FACTORY_BAD)
7306-+ pr_info("Checked Factory bad blk: %d\n", i);
7307-+ else if (get_bbt_mark(manager->bbt, i) == BBT_BLOCK_RESERVED)
7308-+ pr_info("Checked Reserved blk: %d\n", i);
7309-+ else if (get_bbt_mark(manager->bbt, i) != BBT_BLOCK_GOOD)
7310-+ pr_info("Checked unknown blk: %d\n", i);
7311-+ }
7312-+
7313-+ return 0;
7314-+}
7315-+
7316-+int bbt_mark_bad(struct nandx_info *nand, off_t offset)
7317-+{
7318-+ struct bbt_manager *manager = &g_bbt_manager;
7319-+ int block = div_down(offset, nand->block_size);
7320-+ int ret = 0;
7321-+
7322-+ mark_nand_bad(nand, block);
7323-+
7324-+#if 0
7325-+ set_bbt_mark(manager->bbt, block, BBT_BLOCK_WORN);
7326-+
7327-+ /* Update flash-based bad block table */
7328-+ ret = update_bbt(nand, manager->desc, manager->bbt,
7329-+ manager->max_blocks);
7330-+#endif
7331-+ pr_info("block %d, update result %d.\n", block, ret);
7332-+
7333-+ return ret;
7334-+}
7335-+
7336-+int bbt_is_bad(struct nandx_info *nand, off_t offset)
7337-+{
7338-+ int block;
7339-+
7340-+ block = div_down(offset, nand->block_size);
7341-+
7342-+ return get_bbt_mark(g_bbt_manager.bbt, block) != BBT_BLOCK_GOOD;
7343-+}
7344-diff --git a/drivers/mtd/nandx/driver/uboot/driver.c b/drivers/mtd/nandx/driver/uboot/driver.c
7345-new file mode 100644
7346-index 0000000000..7bd3342452
7347---- /dev/null
7348-+++ b/drivers/mtd/nandx/driver/uboot/driver.c
7349-@@ -0,0 +1,574 @@
7350-+/*
7351-+ * Copyright (C) 2017 MediaTek Inc.
7352-+ * Licensed under either
7353-+ * BSD Licence, (see NOTICE for more details)
7354-+ * GNU General Public License, version 2.0, (see NOTICE for more details)
7355-+ */
7356-+
7357-+#include <common.h>
7358-+#include <linux/io.h>
7359-+#include <dm.h>
7360-+#include <clk.h>
7361-+#include <nand.h>
7362-+#include <linux/iopoll.h>
7363-+#include <linux/delay.h>
7364-+#include <linux/mtd/nand.h>
7365-+#include <linux/mtd/mtd.h>
7366-+#include <linux/mtd/partitions.h>
7367-+#include "nandx_core.h"
7368-+#include "nandx_util.h"
7369-+#include "bbt.h"
7370-+
7371-+typedef int (*func_nandx_operation)(u8 *, u8 *, u64, size_t);
7372-+
7373-+struct nandx_clk {
7374-+ struct clk *nfi_clk;
7375-+ struct clk *ecc_clk;
7376-+ struct clk *snfi_clk;
7377-+ struct clk *snfi_clk_sel;
7378-+ struct clk *snfi_parent_50m;
7379-+};
7380-+
7381-+struct nandx_nfc {
7382-+ struct nandx_info info;
7383-+ struct nandx_clk clk;
7384-+ struct nfi_resource *res;
7385-+
7386-+ struct nand_chip *nand;
7387-+ spinlock_t lock;
7388-+};
7389-+
7390-+/* Default flash layout for MTK nand controller
7391-+ * 64Bytes oob format.
7392-+ */
7393-+static struct nand_ecclayout eccoob = {
7394-+ .eccbytes = 42,
7395-+ .eccpos = {
7396-+ 17, 18, 19, 20, 21, 22, 23, 24, 25,
7397-+ 26, 27, 28, 29, 30, 31, 32, 33, 34,
7398-+ 35, 36, 37, 38, 39, 40, 41
7399-+ },
7400-+ .oobavail = 16,
7401-+ .oobfree = {
7402-+ {
7403-+ .offset = 0,
7404-+ .length = 16,
7405-+ },
7406-+ }
7407-+};
7408-+
7409-+static struct nandx_nfc *mtd_to_nfc(struct mtd_info *mtd)
7410-+{
7411-+ struct nand_chip *nand = mtd_to_nand(mtd);
7412-+
7413-+ return (struct nandx_nfc *)nand_get_controller_data(nand);
7414-+}
7415-+
7416-+static int nandx_enable_clk(struct nandx_clk *clk)
7417-+{
7418-+ int ret;
7419-+
7420-+ ret = clk_enable(clk->nfi_clk);
7421-+ if (ret) {
7422-+ pr_info("failed to enable nfi clk\n");
7423-+ return ret;
7424-+ }
7425-+
7426-+ ret = clk_enable(clk->ecc_clk);
7427-+ if (ret) {
7428-+ pr_info("failed to enable ecc clk\n");
7429-+ goto disable_nfi_clk;
7430-+ }
7431-+
7432-+ ret = clk_enable(clk->snfi_clk);
7433-+ if (ret) {
7434-+ pr_info("failed to enable snfi clk\n");
7435-+ goto disable_ecc_clk;
7436-+ }
7437-+
7438-+ ret = clk_enable(clk->snfi_clk_sel);
7439-+ if (ret) {
7440-+ pr_info("failed to enable snfi clk sel\n");
7441-+ goto disable_snfi_clk;
7442-+ }
7443-+
7444-+ ret = clk_set_parent(clk->snfi_clk_sel, clk->snfi_parent_50m);
7445-+ if (ret) {
7446-+ pr_info("failed to set snfi parent 50MHz\n");
7447-+ goto disable_snfi_clk;
7448-+ }
7449-+
7450-+ return 0;
7451-+
7452-+disable_snfi_clk:
7453-+ clk_disable(clk->snfi_clk);
7454-+disable_ecc_clk:
7455-+ clk_disable(clk->ecc_clk);
7456-+disable_nfi_clk:
7457-+ clk_disable(clk->nfi_clk);
7458-+
7459-+ return ret;
7460-+}
7461-+
7462-+static void nandx_disable_clk(struct nandx_clk *clk)
7463-+{
7464-+ clk_disable(clk->ecc_clk);
7465-+ clk_disable(clk->nfi_clk);
7466-+ clk_disable(clk->snfi_clk);
7467-+}
7468-+
7469-+static int mtk_nfc_ooblayout_free(struct mtd_info *mtd, int section,
7470-+ struct mtd_oob_region *oob_region)
7471-+{
7472-+ struct nandx_nfc *nfc = (struct nandx_nfc *)mtd_to_nfc(mtd);
7473-+ u32 eccsteps;
7474-+
7475-+ eccsteps = div_down(mtd->writesize, mtd->ecc_step_size);
7476-+
7477-+ if (section >= eccsteps)
7478-+ return -EINVAL;
7479-+
7480-+ oob_region->length = nfc->info.fdm_reg_size - nfc->info.fdm_ecc_size;
7481-+ oob_region->offset = section * nfc->info.fdm_reg_size
7482-+ + nfc->info.fdm_ecc_size;
7483-+
7484-+ return 0;
7485-+}
7486-+
7487-+static int mtk_nfc_ooblayout_ecc(struct mtd_info *mtd, int section,
7488-+ struct mtd_oob_region *oob_region)
7489-+{
7490-+ struct nandx_nfc *nfc = (struct nandx_nfc *)mtd_to_nfc(mtd);
7491-+ u32 eccsteps;
7492-+
7493-+ if (section)
7494-+ return -EINVAL;
7495-+
7496-+ eccsteps = div_down(mtd->writesize, mtd->ecc_step_size);
7497-+ oob_region->offset = nfc->info.fdm_reg_size * eccsteps;
7498-+ oob_region->length = mtd->oobsize - oob_region->offset;
7499-+
7500-+ return 0;
7501-+}
7502-+
7503-+static const struct mtd_ooblayout_ops mtk_nfc_ooblayout_ops = {
7504-+ .rfree = mtk_nfc_ooblayout_free,
7505-+ .ecc = mtk_nfc_ooblayout_ecc,
7506-+};
7507-+
7508-+struct nfc_compatible {
7509-+ enum mtk_ic_version ic_ver;
7510-+
7511-+ u32 clock_1x;
7512-+ u32 *clock_2x;
7513-+ int clock_2x_num;
7514-+
7515-+ int min_oob_req;
7516-+};
7517-+
7518-+static const struct nfc_compatible nfc_compats_mt7622 = {
7519-+ .ic_ver = NANDX_MT7622,
7520-+ .clock_1x = 26000000,
7521-+ .clock_2x = NULL,
7522-+ .clock_2x_num = 8,
7523-+ .min_oob_req = 1,
7524-+};
7525-+
7526-+static const struct udevice_id ic_of_match[] = {
7527-+ {.compatible = "mediatek,mt7622-nfc", .data = &nfc_compats_mt7622},
7528-+ {}
7529-+};
7530-+
7531-+static int nand_operation(struct mtd_info *mtd, loff_t addr, size_t len,
7532-+ size_t *retlen, uint8_t *data, uint8_t *oob, bool read)
7533-+{
7534-+ struct nandx_split64 split = {0};
7535-+ func_nandx_operation operation;
7536-+ u64 block_oobs, val, align;
7537-+ uint8_t *databuf, *oobbuf;
7538-+ struct nandx_nfc *nfc;
7539-+ bool readoob;
7540-+ int ret = 0;
7541-+
7542-+ nfc = (struct nandx_nfc *)nand_get_controller_data;
7543-+ spin_lock(&nfc->lock);
7544-+
7545-+ databuf = data;
7546-+ oobbuf = oob;
7547-+
7548-+ readoob = data ? false : true;
7549-+ block_oobs = div_up(mtd->erasesize, mtd->writesize) * mtd->oobavail;
7550-+ align = readoob ? block_oobs : mtd->erasesize;
7551-+
7552-+ operation = read ? nandx_read : nandx_write;
7553-+
7554-+ nandx_split(&split, addr, len, val, align);
7555-+
7556-+ if (split.head_len) {
7557-+ ret = operation((u8 *) databuf, oobbuf, addr, split.head_len);
7558-+
7559-+ if (databuf)
7560-+ databuf += split.head_len;
7561-+
7562-+ if (oobbuf)
7563-+ oobbuf += split.head_len;
7564-+
7565-+ addr += split.head_len;
7566-+ *retlen += split.head_len;
7567-+ }
7568-+
7569-+ if (split.body_len) {
7570-+ while (div_up(split.body_len, align)) {
7571-+ ret = operation((u8 *) databuf, oobbuf, addr, align);
7572-+
7573-+ if (databuf) {
7574-+ databuf += mtd->erasesize;
7575-+ split.body_len -= mtd->erasesize;
7576-+ *retlen += mtd->erasesize;
7577-+ }
7578-+
7579-+ if (oobbuf) {
7580-+ oobbuf += block_oobs;
7581-+ split.body_len -= block_oobs;
7582-+ *retlen += block_oobs;
7583-+ }
7584-+
7585-+ addr += mtd->erasesize;
7586-+ }
7587-+
7588-+ }
7589-+
7590-+ if (split.tail_len) {
7591-+ ret = operation((u8 *) databuf, oobbuf, addr, split.tail_len);
7592-+ *retlen += split.tail_len;
7593-+ }
7594-+
7595-+ spin_unlock(&nfc->lock);
7596-+
7597-+ return ret;
7598-+}
7599-+
7600-+static int mtk_nand_read(struct mtd_info *mtd, loff_t from, size_t len,
7601-+ size_t *retlen, u_char *buf)
7602-+{
7603-+ return nand_operation(mtd, from, len, retlen, buf, NULL, true);
7604-+}
7605-+
7606-+static int mtk_nand_write(struct mtd_info *mtd, loff_t to, size_t len,
7607-+ size_t *retlen, const u_char *buf)
7608-+{
7609-+ return nand_operation(mtd, to, len, retlen, (uint8_t *)buf,
7610-+ NULL, false);
7611-+}
7612-+
7613-+int mtk_nand_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
7614-+{
7615-+ size_t retlen;
7616-+
7617-+ return nand_operation(mtd, from, ops->ooblen, &retlen, NULL,
7618-+ ops->oobbuf, true);
7619-+}
7620-+
7621-+int mtk_nand_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops)
7622-+{
7623-+ size_t retlen;
7624-+
7625-+ return nand_operation(mtd, to, ops->ooblen, &retlen, NULL,
7626-+ ops->oobbuf, false);
7627-+}
7628-+
7629-+static int mtk_nand_erase(struct mtd_info *mtd, struct erase_info *instr)
7630-+{
7631-+ struct nandx_nfc *nfc;
7632-+ u64 erase_len, erase_addr;
7633-+ u32 block_size;
7634-+ int ret = 0;
7635-+
7636-+ nfc = (struct nandx_nfc *)mtd_to_nfc(mtd);
7637-+ block_size = nfc->info.block_size;
7638-+ erase_len = instr->len;
7639-+ erase_addr = instr->addr;
7640-+ spin_lock(&nfc->lock);
7641-+ instr->state = MTD_ERASING;
7642-+
7643-+ while (erase_len) {
7644-+ if (mtk_nand_is_bad(mtd, erase_addr)) {
7645-+ pr_info("block(0x%llx) is bad, not erase\n",
7646-+ erase_addr);
7647-+ instr->state = MTD_ERASE_FAILED;
7648-+ goto erase_exit;
7649-+ } else {
7650-+ ret = nandx_erase(erase_addr, block_size);
7651-+ if (ret < 0) {
7652-+ instr->state = MTD_ERASE_FAILED;
7653-+ goto erase_exit;
7654-+ pr_info("erase fail at blk %llu, ret:%d\n",
7655-+ erase_addr, ret);
7656-+ }
7657-+ }
7658-+ erase_addr += block_size;
7659-+ erase_len -= block_size;
7660-+ }
7661-+
7662-+ instr->state = MTD_ERASE_DONE;
7663-+
7664-+erase_exit:
7665-+ ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
7666-+
7667-+ spin_unlock(&nfc->lock);
7668-+ /* Do mtd call back function */
7669-+ if (!ret)
7670-+ mtd_erase_callback(instr);
7671-+
7672-+ return ret;
7673-+}
7674-+
7675-+int mtk_nand_is_bad(struct mtd_info *mtd, loff_t ofs)
7676-+{
7677-+ struct nandx_nfc *nfc;
7678-+ int ret;
7679-+
7680-+ nfc = (struct nandx_nfc *)mtd_to_nfc(mtd);
7681-+ spin_lock(&nfc->lock);
7682-+
7683-+ /*ret = bbt_is_bad(&nfc->info, ofs);*/
7684-+ ret = nandx_is_bad_block(ofs);
7685-+ spin_unlock(&nfc->lock);
7686-+
7687-+ if (ret) {
7688-+ pr_info("nand block 0x%x is bad, ret %d!\n", ofs, ret);
7689-+ return 1;
7690-+ } else {
7691-+ return 0;
7692-+ }
7693-+}
7694-+
7695-+int mtk_nand_mark_bad(struct mtd_info *mtd, loff_t ofs)
7696-+{
7697-+ struct nandx_nfc *nfc;
7698-+ int ret;
7699-+
7700-+ nfc = (struct nandx_nfc *)mtd_to_nfc(mtd);
7701-+ spin_lock(&nfc->lock);
7702-+ pr_info("%s, %d\n", __func__, __LINE__);
7703-+ ret = bbt_mark_bad(&nfc->info, ofs);
7704-+
7705-+ spin_unlock(&nfc->lock);
7706-+
7707-+ return ret;
7708-+}
7709-+
7710-+void mtk_nand_sync(struct mtd_info *mtd)
7711-+{
7712-+ nandx_sync();
7713-+}
7714-+
7715-+static struct mtd_info *mtd_info_create(struct udevice *pdev,
7716-+ struct nandx_nfc *nfc, struct nand_chip *nand)
7717-+{
7718-+ struct mtd_info *mtd = nand_to_mtd(nand);
7719-+ int ret;
7720-+
7721-+ nand_set_controller_data(nand, nfc);
7722-+
7723-+ nand->flash_node = dev_of_offset(pdev);
7724-+ nand->ecc.layout = &eccoob;
7725-+
7726-+ ret = nandx_ioctl(CORE_CTRL_NAND_INFO, &nfc->info);
7727-+ if (ret) {
7728-+ pr_info("fail to get nand info (%d)!\n", ret);
7729-+ mem_free(mtd);
7730-+ return NULL;
7731-+ }
7732-+
7733-+ mtd->owner = THIS_MODULE;
7734-+
7735-+ mtd->name = "MTK-SNand";
7736-+ mtd->writesize = nfc->info.page_size;
7737-+ mtd->erasesize = nfc->info.block_size;
7738-+ mtd->oobsize = nfc->info.oob_size;
7739-+ mtd->size = nfc->info.total_size;
7740-+ mtd->type = MTD_NANDFLASH;
7741-+ mtd->flags = MTD_CAP_NANDFLASH;
7742-+ mtd->_erase = mtk_nand_erase;
7743-+ mtd->_read = mtk_nand_read;
7744-+ mtd->_write = mtk_nand_write;
7745-+ mtd->_read_oob = mtk_nand_read_oob;
7746-+ mtd->_write_oob = mtk_nand_write_oob;
7747-+ mtd->_sync = mtk_nand_sync;
7748-+ mtd->_lock = NULL;
7749-+ mtd->_unlock = NULL;
7750-+ mtd->_block_isbad = mtk_nand_is_bad;
7751-+ mtd->_block_markbad = mtk_nand_mark_bad;
7752-+ mtd->writebufsize = mtd->writesize;
7753-+
7754-+ mtd_set_ooblayout(mtd, &mtk_nfc_ooblayout_ops);
7755-+
7756-+ mtd->ecc_strength = nfc->info.ecc_strength;
7757-+ mtd->ecc_step_size = nfc->info.sector_size;
7758-+
7759-+ if (!mtd->bitflip_threshold)
7760-+ mtd->bitflip_threshold = mtd->ecc_strength;
7761-+
7762-+ return mtd;
7763-+}
7764-+
7765-+int board_nand_init(struct nand_chip *nand)
7766-+{
7767-+ struct udevice *dev;
7768-+ struct mtd_info *mtd;
7769-+ struct nandx_nfc *nfc;
7770-+ int arg = 1;
7771-+ int ret;
7772-+
7773-+ ret = uclass_get_device_by_driver(UCLASS_MTD,
7774-+ DM_GET_DRIVER(mtk_snand_drv),
7775-+ &dev);
7776-+ if (ret) {
7777-+ pr_err("Failed to get mtk_nand_drv. (error %d)\n", ret);
7778-+ return ret;
7779-+ }
7780-+
7781-+ nfc = dev_get_priv(dev);
7782-+
7783-+ ret = nandx_enable_clk(&nfc->clk);
7784-+ if (ret) {
7785-+ pr_err("failed to enable nfi clk (error %d)\n", ret);
7786-+ return ret;
7787-+ }
7788-+
7789-+ ret = nandx_init(nfc->res);
7790-+ if (ret) {
7791-+ pr_err("nandx init error (%d)!\n", ret);
7792-+ goto disable_clk;
7793-+ }
7794-+
7795-+ arg = 1;
7796-+ nandx_ioctl(NFI_CTRL_DMA, &arg);
7797-+ nandx_ioctl(NFI_CTRL_ECC, &arg);
7798-+
7799-+#ifdef NANDX_UNIT_TEST
7800-+ nandx_unit_test(0x780000, 0x800);
7801-+#endif
7802-+
7803-+ mtd = mtd_info_create(dev, nfc, nand);
7804-+ if (!mtd) {
7805-+ ret = -ENOMEM;
7806-+ goto disable_clk;
7807-+ }
7808-+
7809-+ spin_lock_init(&nfc->lock);
7810-+#if 0
7811-+ ret = scan_bbt(&nfc->info);
7812-+ if (ret) {
7813-+ pr_info("bbt init error (%d)!\n", ret);
7814-+ goto disable_clk;
7815-+ }
7816-+#endif
7817-+ return ret;
7818-+
7819-+disable_clk:
7820-+ nandx_disable_clk(&nfc->clk);
7821-+
7822-+ return ret;
7823-+}
7824-+
7825-+static int mtk_snand_ofdata_to_platdata(struct udevice *dev)
7826-+{
7827-+ struct nandx_nfc *nfc = dev_get_priv(dev);
7828-+ struct nfc_compatible *compat;
7829-+ struct nfi_resource *res;
7830-+
7831-+ int ret = 0;
7832-+
7833-+ res = mem_alloc(1, sizeof(struct nfi_resource));
7834-+ if (!res)
7835-+ return -ENOMEM;
7836-+
7837-+ nfc->res = res;
7838-+
7839-+ res->nfi_regs = (void *)dev_read_addr_index(dev, 0);
7840-+ res->ecc_regs = (void *)dev_read_addr_index(dev, 1);
7841-+ pr_debug("mtk snand nfi_regs:0x%x ecc_regs:0x%x\n",
7842-+ res->nfi_regs, res->ecc_regs);
7843-+
7844-+ compat = (struct nfc_compatible *)dev_get_driver_data(dev);
7845-+
7846-+ res->ic_ver = (enum mtk_ic_version)(compat->ic_ver);
7847-+ res->clock_1x = compat->clock_1x;
7848-+ res->clock_2x = compat->clock_2x;
7849-+ res->clock_2x_num = compat->clock_2x_num;
7850-+
7851-+ memset(&nfc->clk, 0, sizeof(struct nandx_clk));
7852-+ nfc->clk.nfi_clk =
7853-+ kmalloc(sizeof(*nfc->clk.nfi_clk), GFP_KERNEL);
7854-+ nfc->clk.ecc_clk =
7855-+ kmalloc(sizeof(*nfc->clk.ecc_clk), GFP_KERNEL);
7856-+ nfc->clk.snfi_clk=
7857-+ kmalloc(sizeof(*nfc->clk.snfi_clk), GFP_KERNEL);
7858-+ nfc->clk.snfi_clk_sel =
7859-+ kmalloc(sizeof(*nfc->clk.snfi_clk_sel), GFP_KERNEL);
7860-+ nfc->clk.snfi_parent_50m =
7861-+ kmalloc(sizeof(*nfc->clk.snfi_parent_50m), GFP_KERNEL);
7862-+
7863-+ if (!nfc->clk.nfi_clk || !nfc->clk.ecc_clk || !nfc->clk.snfi_clk ||
7864-+ !nfc->clk.snfi_clk_sel || !nfc->clk.snfi_parent_50m) {
7865-+ ret = -ENOMEM;
7866-+ goto err;
7867-+ }
7868-+
7869-+ ret = clk_get_by_name(dev, "nfi_clk", nfc->clk.nfi_clk);
7870-+ if (IS_ERR(nfc->clk.nfi_clk)) {
7871-+ ret = PTR_ERR(nfc->clk.nfi_clk);
7872-+ goto err;
7873-+ }
7874-+
7875-+ ret = clk_get_by_name(dev, "ecc_clk", nfc->clk.ecc_clk);
7876-+ if (IS_ERR(nfc->clk.ecc_clk)) {
7877-+ ret = PTR_ERR(nfc->clk.ecc_clk);
7878-+ goto err;
7879-+ }
7880-+
7881-+ ret = clk_get_by_name(dev, "snfi_clk", nfc->clk.snfi_clk);
7882-+ if (IS_ERR(nfc->clk.snfi_clk)) {
7883-+ ret = PTR_ERR(nfc->clk.snfi_clk);
7884-+ goto err;
7885-+ }
7886-+
7887-+ ret = clk_get_by_name(dev, "spinfi_sel", nfc->clk.snfi_clk_sel);
7888-+ if (IS_ERR(nfc->clk.snfi_clk_sel)) {
7889-+ ret = PTR_ERR(nfc->clk.snfi_clk_sel);
7890-+ goto err;
7891-+ }
7892-+
7893-+ ret = clk_get_by_name(dev, "spinfi_parent_50m", nfc->clk.snfi_parent_50m);
7894-+ if (IS_ERR(nfc->clk.snfi_parent_50m))
7895-+ pr_info("spinfi parent 50MHz is not configed\n");
7896-+
7897-+ return 0;
7898-+err:
7899-+ if (nfc->clk.nfi_clk)
7900-+ kfree(nfc->clk.nfi_clk);
7901-+ if (nfc->clk.snfi_clk)
7902-+ kfree(nfc->clk.snfi_clk);
7903-+ if (nfc->clk.ecc_clk)
7904-+ kfree(nfc->clk.ecc_clk);
7905-+ if (nfc->clk.snfi_clk_sel)
7906-+ kfree(nfc->clk.snfi_clk_sel);
7907-+ if (nfc->clk.snfi_parent_50m)
7908-+ kfree(nfc->clk.snfi_parent_50m);
7909-+
7910-+ return ret;
7911-+}
7912-+
7913-+U_BOOT_DRIVER(mtk_snand_drv) = {
7914-+ .name = "mtk_snand",
7915-+ .id = UCLASS_MTD,
7916-+ .of_match = ic_of_match,
7917-+ .ofdata_to_platdata = mtk_snand_ofdata_to_platdata,
7918-+ .priv_auto_alloc_size = sizeof(struct nandx_nfc),
7919-+};
7920-+
7921-+MODULE_LICENSE("GPL v2");
7922-+MODULE_DESCRIPTION("MTK Nand Flash Controller Driver");
7923-+MODULE_AUTHOR("MediaTek");
7924-diff --git a/drivers/mtd/nandx/include/Nandx.mk b/drivers/mtd/nandx/include/Nandx.mk
7925-new file mode 100644
7926-index 0000000000..667402790e
7927---- /dev/null
7928-+++ b/drivers/mtd/nandx/include/Nandx.mk
7929-@@ -0,0 +1,16 @@
7930-+#
7931-+# Copyright (C) 2017 MediaTek Inc.
7932-+# Licensed under either
7933-+# BSD Licence, (see NOTICE for more details)
7934-+# GNU General Public License, version 2.0, (see NOTICE for more details)
7935-+#
7936-+
7937-+nandx-header-y += internal/nandx_core.h
7938-+nandx-header-y += internal/nandx_errno.h
7939-+nandx-header-y += internal/nandx_util.h
7940-+nandx-header-$(NANDX_BBT_SUPPORT) += internal/bbt.h
7941-+nandx-header-$(NANDX_SIMULATOR_SUPPORT) += simulator/nandx_os.h
7942-+nandx-header-$(NANDX_CTP_SUPPORT) += ctp/nandx_os.h
7943-+nandx-header-$(NANDX_LK_SUPPORT) += lk/nandx_os.h
7944-+nandx-header-$(NANDX_KERNEL_SUPPORT) += kernel/nandx_os.h
7945-+nandx-header-$(NANDX_UBOOT_SUPPORT) += uboot/nandx_os.h
7946-diff --git a/drivers/mtd/nandx/include/internal/bbt.h b/drivers/mtd/nandx/include/internal/bbt.h
7947-new file mode 100644
7948-index 0000000000..4676def1f5
7949---- /dev/null
7950-+++ b/drivers/mtd/nandx/include/internal/bbt.h
7951-@@ -0,0 +1,62 @@
7952-+/*
7953-+ * Copyright (C) 2017 MediaTek Inc.
7954-+ * Licensed under either
7955-+ * BSD Licence, (see NOTICE for more details)
7956-+ * GNU General Public License, version 2.0, (see NOTICE for more details)
7957-+ */
7958-+
7959-+#ifndef __BBT_H__
7960-+#define __BBT_H__
7961-+
7962-+#define BBT_BLOCK_GOOD 0x03
7963-+#define BBT_BLOCK_WORN 0x02
7964-+#define BBT_BLOCK_RESERVED 0x01
7965-+#define BBT_BLOCK_FACTORY_BAD 0x00
7966-+
7967-+#define BBT_INVALID_ADDR 0
7968-+/* The maximum number of blocks to scan for a bbt */
7969-+#define NAND_BBT_SCAN_MAXBLOCKS 4
7970-+#define NAND_BBT_USE_FLASH 0x00020000
7971-+#define NAND_BBT_NO_OOB 0x00040000
7972-+
7973-+/* Search good / bad pattern on the first and the second page */
7974-+#define NAND_BBT_SCAN2NDPAGE 0x00008000
7975-+/* Search good / bad pattern on the last page of the eraseblock */
7976-+#define NAND_BBT_SCANLASTPAGE 0x00010000
7977-+
7978-+#define NAND_DRAM_BUF_DATABUF_ADDR (NAND_BUF_ADDR)
7979-+
7980-+struct bbt_pattern {
7981-+ u8 *data;
7982-+ int len;
7983-+};
7984-+
7985-+struct bbt_desc {
7986-+ struct bbt_pattern pattern;
7987-+ u8 version;
7988-+ u64 bbt_addr;/*0: invalid value; otherwise, valid value*/
7989-+};
7990-+
7991-+struct bbt_manager {
7992-+ /* main bbt descriptor and mirror descriptor */
7993-+ struct bbt_desc desc[2];/* 0: main bbt; 1: mirror bbt */
7994-+ int max_blocks;
7995-+ u8 *bbt;
7996-+};
7997-+
7998-+#define BBT_ENTRY_MASK 0x03
7999-+#define BBT_ENTRY_SHIFT 2
8000-+
8001-+#define GET_BBT_LENGTH(blocks) (blocks >> 2)
8002-+#define GET_ENTRY(block) ((block) >> BBT_ENTRY_SHIFT)
8003-+#define GET_POSITION(block) (((block) & BBT_ENTRY_MASK) * 2)
8004-+#define GET_MARK_VALUE(block, mark) \
8005-+ (((mark) & BBT_ENTRY_MASK) << GET_POSITION(block))
8006-+
8007-+int scan_bbt(struct nandx_info *nand);
8008-+
8009-+int bbt_mark_bad(struct nandx_info *nand, off_t offset);
8010-+
8011-+int bbt_is_bad(struct nandx_info *nand, off_t offset);
8012-+
8013-+#endif /*__BBT_H__*/
8014-diff --git a/drivers/mtd/nandx/include/internal/nandx_core.h b/drivers/mtd/nandx/include/internal/nandx_core.h
8015-new file mode 100644
8016-index 0000000000..09aff72224
8017---- /dev/null
8018-+++ b/drivers/mtd/nandx/include/internal/nandx_core.h
8019-@@ -0,0 +1,250 @@
8020-+/*
8021-+ * Copyright (C) 2017 MediaTek Inc.
8022-+ * Licensed under either
8023-+ * BSD Licence, (see NOTICE for more details)
8024-+ * GNU General Public License, version 2.0, (see NOTICE for more details)
8025-+ */
8026-+
8027-+#ifndef __NANDX_CORE_H__
8028-+#define __NANDX_CORE_H__
8029-+
8030-+/**
8031-+ * mtk_ic_version - indicates specifical IC, IP need this to load some info
8032-+ */
8033-+enum mtk_ic_version {
8034-+ NANDX_MT7622,
8035-+};
8036-+
8037-+/**
8038-+ * nandx_ioctl_cmd - operations supported by nandx
8039-+ *
8040-+ * @NFI_CTRL_DMA dma enable or not
8041-+ * @NFI_CTRL_NFI_MODE customer/read/program/erase...
8042-+ * @NFI_CTRL_ECC ecc enable or not
8043-+ * @NFI_CTRL_ECC_MODE nfi/dma/pio
8044-+ * @CHIP_CTRL_DRIVE_STRENGTH enum chip_ctrl_drive_strength
8045-+ */
8046-+enum nandx_ctrl_cmd {
8047-+ CORE_CTRL_NAND_INFO,
8048-+
8049-+ NFI_CTRL_DMA,
8050-+ NFI_CTRL_NFI_MODE,
8051-+ NFI_CTRL_AUTOFORMAT,
8052-+ NFI_CTRL_NFI_IRQ,
8053-+ NFI_CTRL_PAGE_IRQ,
8054-+ NFI_CTRL_RANDOMIZE,
8055-+ NFI_CTRL_BAD_MARK_SWAP,
8056-+
8057-+ NFI_CTRL_ECC,
8058-+ NFI_CTRL_ECC_MODE,
8059-+ NFI_CTRL_ECC_CLOCK,
8060-+ NFI_CTRL_ECC_IRQ,
8061-+ NFI_CTRL_ECC_PAGE_IRQ,
8062-+ NFI_CTRL_ECC_DECODE_MODE,
8063-+
8064-+ SNFI_CTRL_OP_MODE,
8065-+ SNFI_CTRL_RX_MODE,
8066-+ SNFI_CTRL_TX_MODE,
8067-+ SNFI_CTRL_DELAY_MODE,
8068-+
8069-+ CHIP_CTRL_OPS_CACHE,
8070-+ CHIP_CTRL_OPS_MULTI,
8071-+ CHIP_CTRL_PSLC_MODE,
8072-+ CHIP_CTRL_DRIVE_STRENGTH,
8073-+ CHIP_CTRL_DDR_MODE,
8074-+ CHIP_CTRL_ONDIE_ECC,
8075-+ CHIP_CTRL_TIMING_MODE
8076-+};
8077-+
8078-+enum snfi_ctrl_op_mode {
8079-+ SNFI_CUSTOM_MODE,
8080-+ SNFI_AUTO_MODE,
8081-+ SNFI_MAC_MODE
8082-+};
8083-+
8084-+enum snfi_ctrl_rx_mode {
8085-+ SNFI_RX_111,
8086-+ SNFI_RX_112,
8087-+ SNFI_RX_114,
8088-+ SNFI_RX_122,
8089-+ SNFI_RX_144
8090-+};
8091-+
8092-+enum snfi_ctrl_tx_mode {
8093-+ SNFI_TX_111,
8094-+ SNFI_TX_114,
8095-+};
8096-+
8097-+enum chip_ctrl_drive_strength {
8098-+ CHIP_DRIVE_NORMAL,
8099-+ CHIP_DRIVE_HIGH,
8100-+ CHIP_DRIVE_MIDDLE,
8101-+ CHIP_DRIVE_LOW
8102-+};
8103-+
8104-+enum chip_ctrl_timing_mode {
8105-+ CHIP_TIMING_MODE0,
8106-+ CHIP_TIMING_MODE1,
8107-+ CHIP_TIMING_MODE2,
8108-+ CHIP_TIMING_MODE3,
8109-+ CHIP_TIMING_MODE4,
8110-+ CHIP_TIMING_MODE5,
8111-+};
8112-+
8113-+/**
8114-+ * nandx_info - basic information
8115-+ */
8116-+struct nandx_info {
8117-+ u32 max_io_count;
8118-+ u32 min_write_pages;
8119-+ u32 plane_num;
8120-+ u32 oob_size;
8121-+ u32 page_parity_size;
8122-+ u32 page_size;
8123-+ u32 block_size;
8124-+ u64 total_size;
8125-+ u32 fdm_reg_size;
8126-+ u32 fdm_ecc_size;
8127-+ u32 ecc_strength;
8128-+ u32 sector_size;
8129-+};
8130-+
8131-+/**
8132-+ * nfi_resource - the resource needed by nfi & ecc to do initialization
8133-+ */
8134-+struct nfi_resource {
8135-+ int ic_ver;
8136-+ void *dev;
8137-+
8138-+ void *ecc_regs;
8139-+ int ecc_irq_id;
8140-+
8141-+ void *nfi_regs;
8142-+ int nfi_irq_id;
8143-+
8144-+ u32 clock_1x;
8145-+ u32 *clock_2x;
8146-+ int clock_2x_num;
8147-+
8148-+ int min_oob_req;
8149-+};
8150-+
8151-+/**
8152-+ * nandx_init - init all related modules below
8153-+ *
8154-+ * @res: basic resource of the project
8155-+ *
8156-+ * return 0 if init success, otherwise return negative error code
8157-+ */
8158-+int nandx_init(struct nfi_resource *res);
8159-+
8160-+/**
8161-+ * nandx_exit - release resource those that obtained in init flow
8162-+ */
8163-+void nandx_exit(void);
8164-+
8165-+/**
8166-+ * nandx_read - read data from nand this function can read data and related
8167-+ * oob from specifical address
8168-+ * if do multi_ops, set one operation per time, and call nandx_sync at last
8169-+ * in multi mode, not support page partial read
8170-+ * oob not support partial read
8171-+ *
8172-+ * @data: buf to receive data from nand
8173-+ * @oob: buf to receive oob data from nand which related to data page
8174-+ * length of @oob should oob size aligned, oob not support partial read
8175-+ * @offset: offset address on the whole flash
8176-+ * @len: the length of @data that need to read
8177-+ *
8178-+ * if read success return 0, otherwise return negative error code
8179-+ */
8180-+int nandx_read(u8 *data, u8 *oob, u64 offset, size_t len);
8181-+
8182-+/**
8183-+ * nandx_write - write data to nand
8184-+ * this function can write data and related oob to specifical address
8185-+ * if do multi_ops, set one operation per time, and call nandx_sync at last
8186-+ *
8187-+ * @data: source data to be written to nand,
8188-+ * for multi operation, the length of @data should be page size aliged
8189-+ * @oob: source oob which related to data page to be written to nand,
8190-+ * length of @oob should oob size aligned
8191-+ * @offset: offset address on the whole flash, the value should be start address
8192-+ * of a page
8193-+ * @len: the length of @data that need to write,
8194-+ * for multi operation, the len should be page size aliged
8195-+ *
8196-+ * if write success return 0, otherwise return negative error code
8197-+ * if return value > 0, it indicates that how many pages still need to write,
8198-+ * and data has not been written to nand
8199-+ * please call nandx_sync after pages alligned $nandx_info.min_write_pages
8200-+ */
8201-+int nandx_write(u8 *data, u8 *oob, u64 offset, size_t len);
8202-+
8203-+/**
8204-+ * nandx_erase - erase an area of nand
8205-+ * if do multi_ops, set one operation per time, and call nandx_sync at last
8206-+ *
8207-+ * @offset: offset address on the flash
8208-+ * @len: erase length which should be block size aligned
8209-+ *
8210-+ * if erase success return 0, otherwise return negative error code
8211-+ */
8212-+int nandx_erase(u64 offset, size_t len);
8213-+
8214-+/**
8215-+ * nandx_sync - sync all operations to nand
8216-+ * when do multi_ops, this function will be called at last operation
8217-+ * when write data, if number of pages not alligned
8218-+ * by $nandx_info.min_write_pages, this interface could be called to do
8219-+ * force write, 0xff will be padded to blanked pages.
8220-+ */
8221-+int nandx_sync(void);
8222-+
8223-+/**
8224-+ * nandx_is_bad_block - check if the block is bad
8225-+ * only check the flag that marked by the flash vendor
8226-+ *
8227-+ * @offset: offset address on the whole flash
8228-+ *
8229-+ * return true if the block is bad, otherwise return false
8230-+ */
8231-+bool nandx_is_bad_block(u64 offset);
8232-+
8233-+/**
8234-+ * nandx_ioctl - set/get property of nand chip
8235-+ *
8236-+ * @cmd: parameter that defined in enum nandx_ioctl_cmd
8237-+ * @arg: operate parameter
8238-+ *
8239-+ * return 0 if operate success, otherwise return negative error code
8240-+ */
8241-+int nandx_ioctl(int cmd, void *arg);
8242-+
8243-+/**
8244-+ * nandx_suspend - suspend nand, and store some data
8245-+ *
8246-+ * return 0 if suspend success, otherwise return negative error code
8247-+ */
8248-+int nandx_suspend(void);
8249-+
8250-+/**
8251-+ * nandx_resume - resume nand, and replay some data
8252-+ *
8253-+ * return 0 if resume success, otherwise return negative error code
8254-+ */
8255-+int nandx_resume(void);
8256-+
8257-+#ifdef NANDX_UNIT_TEST
8258-+/**
8259-+ * nandx_unit_test - unit test
8260-+ *
8261-+ * @offset: offset address on the whole flash
8262-+ * @len: should be not larger than a block size, we only test a block per time
8263-+ *
8264-+ * return 0 if test success, otherwise return negative error code
8265-+ */
8266-+int nandx_unit_test(u64 offset, size_t len);
8267-+#endif
8268-+
8269-+#endif /* __NANDX_CORE_H__ */
8270-diff --git a/drivers/mtd/nandx/include/internal/nandx_errno.h b/drivers/mtd/nandx/include/internal/nandx_errno.h
8271-new file mode 100644
8272-index 0000000000..51fb299c03
8273---- /dev/null
8274-+++ b/drivers/mtd/nandx/include/internal/nandx_errno.h
8275-@@ -0,0 +1,40 @@
8276-+/*
8277-+ * Copyright (C) 2017 MediaTek Inc.
8278-+ * Licensed under either
8279-+ * BSD Licence, (see NOTICE for more details)
8280-+ * GNU General Public License, version 2.0, (see NOTICE for more details)
8281-+ */
8282-+
8283-+#ifndef __NANDX_ERRNO_H__
8284-+#define __NANDX_ERRNO_H__
8285-+
8286-+#ifndef EIO
8287-+#define EIO 5 /* I/O error */
8288-+#define ENOMEM 12 /* Out of memory */
8289-+#define EFAULT 14 /* Bad address */
8290-+#define EBUSY 16 /* Device or resource busy */
8291-+#define ENODEV 19 /* No such device */
8292-+#define EINVAL 22 /* Invalid argument */
8293-+#define ENOSPC 28 /* No space left on device */
8294-+/* Operation not supported on transport endpoint */
8295-+#define EOPNOTSUPP 95
8296-+#define ETIMEDOUT 110 /* Connection timed out */
8297-+#endif
8298-+
8299-+#define ENANDFLIPS 1024 /* Too many bitflips, uncorrected */
8300-+#define ENANDREAD 1025 /* Read fail, can't correct */
8301-+#define ENANDWRITE 1026 /* Write fail */
8302-+#define ENANDERASE 1027 /* Erase fail */
8303-+#define ENANDBAD 1028 /* Bad block */
8304-+#define ENANDWP 1029
8305-+
8306-+#define IS_NAND_ERR(err) ((err) >= -ENANDBAD && (err) <= -ENANDFLIPS)
8307-+
8308-+#ifndef MAX_ERRNO
8309-+#define MAX_ERRNO 4096
8310-+#define ERR_PTR(errno) ((void *)((long)errno))
8311-+#define PTR_ERR(ptr) ((long)(ptr))
8312-+#define IS_ERR(ptr) ((unsigned long)(ptr) > (unsigned long)-MAX_ERRNO)
8313-+#endif
8314-+
8315-+#endif /* __NANDX_ERRNO_H__ */
8316-diff --git a/drivers/mtd/nandx/include/internal/nandx_util.h b/drivers/mtd/nandx/include/internal/nandx_util.h
8317-new file mode 100644
8318-index 0000000000..1990b000ee
8319---- /dev/null
8320-+++ b/drivers/mtd/nandx/include/internal/nandx_util.h
8321-@@ -0,0 +1,221 @@
8322-+/*
8323-+ * Copyright (C) 2017 MediaTek Inc.
8324-+ * Licensed under either
8325-+ * BSD Licence, (see NOTICE for more details)
8326-+ * GNU General Public License, version 2.0, (see NOTICE for more details)
8327-+ */
8328-+
8329-+#ifndef __NANDX_UTIL_H__
8330-+#define __NANDX_UTIL_H__
8331-+
8332-+typedef unsigned char u8;
8333-+typedef unsigned short u16;
8334-+typedef unsigned int u32;
8335-+typedef unsigned long long u64;
8336-+
8337-+enum nand_irq_return {
8338-+ NAND_IRQ_NONE,
8339-+ NAND_IRQ_HANDLED,
8340-+};
8341-+
8342-+enum nand_dma_operation {
8343-+ NDMA_FROM_DEV,
8344-+ NDMA_TO_DEV,
8345-+};
8346-+
8347-+
8348-+/*
8349-+ * Compatible function
8350-+ * used for preloader/lk/kernel environment
8351-+ */
8352-+#include "nandx_os.h"
8353-+#include "nandx_errno.h"
8354-+
8355-+#ifndef BIT
8356-+#define BIT(a) (1 << (a))
8357-+#endif
8358-+
8359-+#ifndef min_t
8360-+#define min_t(type, x, y) ({ \
8361-+ type __min1 = (x); \
8362-+ type __min2 = (y); \
8363-+ __min1 < __min2 ? __min1 : __min2; })
8364-+
8365-+#define max_t(type, x, y) ({ \
8366-+ type __max1 = (x); \
8367-+ type __max2 = (y); \
8368-+ __max1 > __max2 ? __max1 : __max2; })
8369-+#endif
8370-+
8371-+#ifndef GENMASK
8372-+#define GENMASK(h, l) \
8373-+ (((~0UL) << (l)) & (~0UL >> ((sizeof(unsigned long) * 8) - 1 - (h))))
8374-+#endif
8375-+
8376-+#ifndef __weak
8377-+#define __weak __attribute__((__weak__))
8378-+#endif
8379-+
8380-+#ifndef __packed
8381-+#define __packed __attribute__((__packed__))
8382-+#endif
8383-+
8384-+#ifndef KB
8385-+#define KB(x) ((x) << 10)
8386-+#define MB(x) (KB(x) << 10)
8387-+#define GB(x) (MB(x) << 10)
8388-+#endif
8389-+
8390-+#ifndef offsetof
8391-+#define offsetof(type, member) ((size_t)&((type *)0)->member)
8392-+#endif
8393-+
8394-+#ifndef NULL
8395-+#define NULL (void *)0
8396-+#endif
8397-+static inline u32 nandx_popcount(u32 x)
8398-+{
8399-+ x = (x & 0x55555555) + ((x >> 1) & 0x55555555);
8400-+ x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
8401-+ x = (x & 0x0F0F0F0F) + ((x >> 4) & 0x0F0F0F0F);
8402-+ x = (x & 0x00FF00FF) + ((x >> 8) & 0x00FF00FF);
8403-+ x = (x & 0x0000FFFF) + ((x >> 16) & 0x0000FFFF);
8404-+
8405-+ return x;
8406-+}
8407-+
8408-+#ifndef zero_popcount
8409-+#define zero_popcount(x) (32 - nandx_popcount(x))
8410-+#endif
8411-+
8412-+#ifndef do_div
8413-+#define do_div(n, base) \
8414-+ ({ \
8415-+ u32 __base = (base); \
8416-+ u32 __rem; \
8417-+ __rem = ((u64)(n)) % __base; \
8418-+ (n) = ((u64)(n)) / __base; \
8419-+ __rem; \
8420-+ })
8421-+#endif
8422-+
8423-+#define div_up(x, y) \
8424-+ ({ \
8425-+ u64 __temp = ((x) + (y) - 1); \
8426-+ do_div(__temp, (y)); \
8427-+ __temp; \
8428-+ })
8429-+
8430-+#define div_down(x, y) \
8431-+ ({ \
8432-+ u64 __temp = (x); \
8433-+ do_div(__temp, (y)); \
8434-+ __temp; \
8435-+ })
8436-+
8437-+#define div_round_up(x, y) (div_up(x, y) * (y))
8438-+#define div_round_down(x, y) (div_down(x, y) * (y))
8439-+
8440-+#define reminder(x, y) \
8441-+ ({ \
8442-+ u64 __temp = (x); \
8443-+ do_div(__temp, (y)); \
8444-+ })
8445-+
8446-+#ifndef round_up
8447-+#define round_up(x, y) ((((x) - 1) | ((y) - 1)) + 1)
8448-+#define round_down(x, y) ((x) & ~((y) - 1))
8449-+#endif
8450-+
8451-+#ifndef readx_poll_timeout_atomic
8452-+#define readx_poll_timeout_atomic(op, addr, val, cond, delay_us, timeout_us) \
8453-+ ({ \
8454-+ u64 end = get_current_time_us() + timeout_us; \
8455-+ for (;;) { \
8456-+ u64 now = get_current_time_us(); \
8457-+ (val) = op(addr); \
8458-+ if (cond) \
8459-+ break; \
8460-+ if (now > end) { \
8461-+ (val) = op(addr); \
8462-+ break; \
8463-+ } \
8464-+ } \
8465-+ (cond) ? 0 : -ETIMEDOUT; \
8466-+ })
8467-+
8468-+#define readl_poll_timeout_atomic(addr, val, cond, delay_us, timeout_us) \
8469-+ readx_poll_timeout_atomic(readl, addr, val, cond, delay_us, timeout_us)
8470-+#define readw_poll_timeout_atomic(addr, val, cond, delay_us, timeout_us) \
8471-+ readx_poll_timeout_atomic(readw, addr, val, cond, delay_us, timeout_us)
8472-+#define readb_poll_timeout_atomic(addr, val, cond, delay_us, timeout_us) \
8473-+ readx_poll_timeout_atomic(readb, addr, val, cond, delay_us, timeout_us)
8474-+#endif
8475-+
8476-+struct nandx_split64 {
8477-+ u64 head;
8478-+ size_t head_len;
8479-+ u64 body;
8480-+ size_t body_len;
8481-+ u64 tail;
8482-+ size_t tail_len;
8483-+};
8484-+
8485-+struct nandx_split32 {
8486-+ u32 head;
8487-+ u32 head_len;
8488-+ u32 body;
8489-+ u32 body_len;
8490-+ u32 tail;
8491-+ u32 tail_len;
8492-+};
8493-+
8494-+#define nandx_split(split, offset, len, val, align) \
8495-+ do { \
8496-+ (split)->head = (offset); \
8497-+ (val) = div_round_down((offset), (align)); \
8498-+ (val) = (align) - ((offset) - (val)); \
8499-+ if ((val) == (align)) \
8500-+ (split)->head_len = 0; \
8501-+ else if ((val) > (len)) \
8502-+ (split)->head_len = len; \
8503-+ else \
8504-+ (split)->head_len = val; \
8505-+ (split)->body = (offset) + (split)->head_len; \
8506-+ (split)->body_len = div_round_down((len) - \
8507-+ (split)->head_len,\
8508-+ (align)); \
8509-+ (split)->tail = (split)->body + (split)->body_len; \
8510-+ (split)->tail_len = (len) - (split)->head_len - \
8511-+ (split)->body_len; \
8512-+ } while (0)
8513-+
8514-+#ifndef container_of
8515-+#define container_of(ptr, type, member) \
8516-+ ({const __typeof__(((type *)0)->member) * __mptr = (ptr); \
8517-+ (type *)((char *)__mptr - offsetof(type, member)); })
8518-+#endif
8519-+
8520-+static inline u32 nandx_cpu_to_be32(u32 val)
8521-+{
8522-+ u32 temp = 1;
8523-+ u8 *p_temp = (u8 *)&temp;
8524-+
8525-+ if (*p_temp)
8526-+ return ((val & 0xff) << 24) | ((val & 0xff00) << 8) |
8527-+ ((val >> 8) & 0xff00) | ((val >> 24) & 0xff);
8528-+
8529-+ return val;
8530-+}
8531-+
8532-+static inline void nandx_set_bits32(unsigned long addr, u32 mask,
8533-+ u32 val)
8534-+{
8535-+ u32 temp = readl((void *)addr);
8536-+
8537-+ temp &= ~(mask);
8538-+ temp |= val;
8539-+ writel(temp, (void *)addr);
8540-+}
8541-+
8542-+#endif /* __NANDX_UTIL_H__ */
8543-diff --git a/drivers/mtd/nandx/include/uboot/nandx_os.h b/drivers/mtd/nandx/include/uboot/nandx_os.h
8544-new file mode 100644
8545-index 0000000000..8ea53378bf
8546---- /dev/null
8547-+++ b/drivers/mtd/nandx/include/uboot/nandx_os.h
8548-@@ -0,0 +1,78 @@
8549-+/*
8550-+ * Copyright (C) 2017 MediaTek Inc.
8551-+ * Licensed under either
8552-+ * BSD Licence, (see NOTICE for more details)
8553-+ * GNU General Public License, version 2.0, (see NOTICE for more details)
8554-+ */
8555-+
8556-+#ifndef __NANDX_OS_H__
8557-+#define __NANDX_OS_H__
8558-+
8559-+#include <common.h>
8560-+#include <dm.h>
8561-+#include <clk.h>
8562-+#include <asm/dma-mapping.h>
8563-+#include <linux/io.h>
8564-+#include <linux/err.h>
8565-+#include <linux/errno.h>
8566-+#include <linux/bitops.h>
8567-+#include <linux/kernel.h>
8568-+#include <linux/compiler-gcc.h>
8569-+
8570-+#define NANDX_BULK_IO_USE_DRAM 0
8571-+
8572-+#define nandx_event_create() NULL
8573-+#define nandx_event_destroy(event)
8574-+#define nandx_event_complete(event)
8575-+#define nandx_event_init(event)
8576-+#define nandx_event_wait_complete(event, timeout) true
8577-+
8578-+#define nandx_irq_register(dev, irq, irq_handler, name, data) NULL
8579-+
8580-+static inline void *mem_alloc(u32 count, u32 size)
8581-+{
8582-+ return kmalloc(count * size, GFP_KERNEL | __GFP_ZERO);
8583-+}
8584-+
8585-+static inline void mem_free(void *mem)
8586-+{
8587-+ kfree(mem);
8588-+}
8589-+
8590-+static inline u64 get_current_time_us(void)
8591-+{
8592-+ return timer_get_us();
8593-+}
8594-+
8595-+static inline u32 nandx_dma_map(void *dev, void *buf, u64 len,
8596-+ enum nand_dma_operation op)
8597-+{
8598-+ unsigned long addr = (unsigned long)buf;
8599-+ u64 size;
8600-+
8601-+ size = ALIGN(len, ARCH_DMA_MINALIGN);
8602-+
8603-+ if (op == NDMA_FROM_DEV)
8604-+ invalidate_dcache_range(addr, addr + size);
8605-+ else
8606-+ flush_dcache_range(addr, addr + size);
8607-+
8608-+ return addr;
8609-+}
8610-+
8611-+static inline void nandx_dma_unmap(void *dev, void *buf, void *addr,
8612-+ u64 len, enum nand_dma_operation op)
8613-+{
8614-+ u64 size;
8615-+
8616-+ size = ALIGN(len, ARCH_DMA_MINALIGN);
8617-+
8618-+ if (op != NDMA_FROM_DEV)
8619-+ invalidate_dcache_range((unsigned long)addr, addr + size);
8620-+ else
8621-+ flush_dcache_range((unsigned long)addr, addr + size);
8622-+
8623-+ return addr;
8624-+}
8625-+
8626-+#endif /* __NANDX_OS_H__ */
8627-diff --git a/include/configs/mt7622.h b/include/configs/mt7622.h
8628-index dfd506ed24..6d0c956484 100644
8629---- a/include/configs/mt7622.h
8630-+++ b/include/configs/mt7622.h
8631-@@ -11,6 +11,31 @@
8632-
8633- #include <linux/sizes.h>
8634-
8635-+/* SPI Nand */
8636-+#if defined(CONFIG_MTD_RAW_NAND)
8637-+#define CONFIG_SYS_MAX_NAND_DEVICE 1
8638-+#define CONFIG_SYS_NAND_BASE 0x1100d000
8639-+
8640-+#define ENV_BOOT_READ_IMAGE \
8641-+ "boot_rd_img=" \
8642-+ "nand read 0x4007ff28 0x380000 0x1400000" \
8643-+ ";iminfo 0x4007ff28 \0"
8644-+
8645-+#define ENV_BOOT_WRITE_IMAGE \
8646-+ "boot_wr_img=" \
8647-+ "nand write 0x4007ff28 0x380000 0x1400000" \
8648-+ ";iminfo 0x4007ff28 \0"
8649-+
8650-+#define ENV_BOOT_CMD \
8651-+ "mtk_boot=run boot_rd_img;bootm;\0"
8652-+
8653-+#define CONFIG_EXTRA_ENV_SETTINGS \
8654-+ ENV_BOOT_READ_IMAGE \
8655-+ ENV_BOOT_CMD \
8656-+ "bootcmd=run mtk_boot;\0"
8657-+
8658-+#endif
8659-+
8660- #define CONFIG_SYS_MAXARGS 8
8661- #define CONFIG_SYS_BOOTM_LEN SZ_64M
8662- #define CONFIG_SYS_CBSIZE SZ_1K
8663---
8664-2.17.1
8665-
8666diff --git a/package/boot/uboot-mediatek/patches/003-mt7622-uboot-add-dts-and-config-for-spi-nand.patch b/package/boot/uboot-mediatek/patches/003-mt7622-uboot-add-dts-and-config-for-spi-nand.patch
8667deleted file mode 100644
8668index 2c021e1..0000000
8669--- a/package/boot/uboot-mediatek/patches/003-mt7622-uboot-add-dts-and-config-for-spi-nand.patch
8670+++ /dev/null
8671@@ -1,64 +0,0 @@
8672-From b1b3c3d2ce62872c8dec4a7d645af6b3c565e094 Mon Sep 17 00:00:00 2001
8673-From: Sam Shih <sam.shih@mediatek.com>
8674-Date: Mon, 20 Apr 2020 17:11:32 +0800
8675-Subject: [PATCH 2/3] mt7622 uboot: add dts and config for spi nand
8676-
8677-This patch add dts and config for mt7622 spi nand
8678-
8679-Signed-off-by: Xiangsheng Hou <xiangsheng.hou@mediatek.com>
8680----
8681- arch/arm/dts/mt7622-rfb.dts | 6 ++++++
8682- arch/arm/dts/mt7622.dtsi | 20 ++++++++++++++++++++
8683- 2 files changed, 26 insertions(+)
8684-
8685-diff --git a/arch/arm/dts/mt7622-rfb.dts b/arch/arm/dts/mt7622-rfb.dts
8686-index f05c3fe14d..05502bddec 100644
8687---- a/arch/arm/dts/mt7622-rfb.dts
8688-+++ b/arch/arm/dts/mt7622-rfb.dts
8689-@@ -143,6 +143,12 @@
8690- };
8691- };
8692-
8693-+&nandc {
8694-+ pinctrl-names = "default";
8695-+ pinctrl-0 = <&snfi_pins>;
8696-+ status = "okay";
8697-+};
8698-+
8699- &uart0 {
8700- pinctrl-names = "default";
8701- pinctrl-0 = <&uart0_pins>;
8702-diff --git a/arch/arm/dts/mt7622.dtsi b/arch/arm/dts/mt7622.dtsi
8703-index 1e8ec9b48b..63fdb63d4a 100644
8704---- a/arch/arm/dts/mt7622.dtsi
8705-+++ b/arch/arm/dts/mt7622.dtsi
8706-@@ -52,6 +52,26 @@
8707- #size-cells = <0>;
8708- };
8709-
8710-+ nandc: nfi@1100d000 {
8711-+ compatible = "mediatek,mt7622-nfc";
8712-+ reg = <0x1100d000 0x1000>,
8713-+ <0x1100e000 0x1000>;
8714-+ interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_LOW>,
8715-+ <GIC_SPI 95 IRQ_TYPE_LEVEL_LOW>;
8716-+ clocks = <&pericfg CLK_PERI_NFI_PD>,
8717-+ <&pericfg CLK_PERI_NFIECC_PD>,
8718-+ <&pericfg CLK_PERI_SNFI_PD>,
8719-+ <&topckgen CLK_TOP_NFI_INFRA_SEL>,
8720-+ <&topckgen CLK_TOP_UNIVPLL2_D8>;
8721-+ clock-names = "nfi_clk",
8722-+ "ecc_clk",
8723-+ "snfi_clk",
8724-+ "spinfi_sel",
8725-+ "spinfi_parent_50m";
8726-+ nand-ecc-mode = "hw";
8727-+ status = "disabled";
8728-+ };
8729-+
8730- timer {
8731- compatible = "arm,armv8-timer";
8732- interrupt-parent = <&gic>;
8733---
8734-2.17.1
8735-
8736diff --git a/package/boot/uboot-mediatek/patches/004-configs-enable-mtd-and-mtk_spi_nand-in-defconfig.patch b/package/boot/uboot-mediatek/patches/004-configs-enable-mtd-and-mtk_spi_nand-in-defconfig.patch
8737deleted file mode 100644
8738index cb56496..0000000
8739--- a/package/boot/uboot-mediatek/patches/004-configs-enable-mtd-and-mtk_spi_nand-in-defconfig.patch
8740+++ /dev/null
8741@@ -1,39 +0,0 @@
8742-From e5745143a2984cf44fbfc0b3aedb49e57873f109 Mon Sep 17 00:00:00 2001
8743-From: Sam Shih <sam.shih@mediatek.com>
8744-Date: Mon, 20 Apr 2020 17:17:04 +0800
8745-Subject: [PATCH 3/3] configs: enable mtd and mtk_spi_nand in defconfig
8746-
8747-This patch enable mtk and mtk_spi_nand in mt7622_rfb defconfig
8748-
8749-Signed-off-by: Sam Shih <sam.shih@mediatek.com>
8750----
8751- configs/mt7622_rfb_defconfig | 5 +++++
8752- 1 file changed, 5 insertions(+)
8753-
8754-diff --git a/configs/mt7622_rfb_defconfig b/configs/mt7622_rfb_defconfig
8755-index 1ce6ebdfeb..816126267b 100644
8756---- a/configs/mt7622_rfb_defconfig
8757-+++ b/configs/mt7622_rfb_defconfig
8758-@@ -13,6 +13,7 @@ CONFIG_DEFAULT_FDT_FILE="mt7622-rfb"
8759- CONFIG_SYS_PROMPT="MT7622> "
8760- CONFIG_CMD_BOOTMENU=y
8761- CONFIG_CMD_MMC=y
8762-+CONFIG_CMD_NAND=y
8763- CONFIG_CMD_PCI=y
8764- CONFIG_CMD_SF_TEST=y
8765- CONFIG_CMD_PING=y
8766- CONFIG_CMD_SMC=y
8767-@@ -25,6 +26,10 @@ CONFIG_CLK=y
8768- CONFIG_DM_MMC=y
8769- CONFIG_MMC_HS200_SUPPORT=y
8770- CONFIG_MMC_MTK=y
8771-+CONFIG_MTD=y
8772-+CONFIG_DM_MTD=y
8773-+CONFIG_MTK_SPI_NAND=y
8774-+CONFIG_MTD_RAW_NAND=y
8775- CONFIG_DM_SPI_FLASH=y
8776- CONFIG_SPI_FLASH_EON=y
8777- CONFIG_SPI_FLASH_GIGADEVICE=y
8778---
8779-2.17.1
8780-
8781diff --git a/package/boot/uboot-mediatek/patches/010-no-binman.patch b/package/boot/uboot-mediatek/patches/010-no-binman.patch
8782deleted file mode 100644
8783index a2680e5..0000000
8784--- a/package/boot/uboot-mediatek/patches/010-no-binman.patch
8785+++ /dev/null
8786@@ -1,23 +0,0 @@
8787---- a/Makefile 2020-10-13 13:39:06.471438591 +0800
8788-+++ b/Makefile 2020-10-13 13:39:39.190798462 +0800
8789-@@ -1725,6 +1725,10 @@
8790-
8791- ifeq ($(CONFIG_SPL),y)
8792- spl/u-boot-spl-mtk.bin: spl/u-boot-spl
8793-+OBJCOPYFLAGS_u-boot-mtk.bin = -I binary -O binary \
8794-+ --pad-to=$(CONFIG_SPL_PAD_TO) --gap-fill=0xff
8795-+u-boot-mtk.bin: u-boot.img spl/u-boot-spl-mtk.bin FORCE
8796-+ $(call if_changed,pad_cat)
8797- else
8798- MKIMAGEFLAGS_u-boot-mtk.bin = -T mtk_image \
8799- -a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_TEXT_BASE) \
8800---- a/arch/arm/mach-mediatek/Kconfig
8801-+++ b/arch/arm/mach-mediatek/Kconfig
8802-@@ -36,7 +36,6 @@ config TARGET_MT7629
8803- bool "MediaTek MT7629 SoC"
8804- select CPU_V7A
8805- select SPL
8806-- select BINMAN
8807- help
8808- The MediaTek MT7629 is a ARM-based SoC with a dual-core Cortex-A7
8809- including DDR3, crypto engine, 3x3 11n/ac Wi-Fi, Gigabit Ethernet,