Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)  * (C) 2003 Red Hat, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  * (C) 2004 Dan Brown <dan_brown@ieee.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5)  * (C) 2004 Kalev Lember <kalev@smartlink.ee>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7)  * Author: David Woodhouse <dwmw2@infradead.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8)  * Additional Diskonchip 2000 and Millennium support by Dan Brown <dan_brown@ieee.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9)  * Diskonchip Millennium Plus support by Kalev Lember <kalev@smartlink.ee>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11)  * Error correction code lifted from the old docecc code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12)  * Author: Fabrice Bellard (fabrice.bellard@netgem.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13)  * Copyright (C) 2000 Netgem S.A.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14)  * converted to the generic Reed-Solomon library by Thomas Gleixner <tglx@linutronix.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16)  * Interface to generic NAND code for M-Systems DiskOnChip devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23) #include <linux/rslib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24) #include <linux/moduleparam.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28) #include <linux/mtd/mtd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29) #include <linux/mtd/rawnand.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30) #include <linux/mtd/doc2000.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31) #include <linux/mtd/partitions.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32) #include <linux/mtd/inftl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) /* Where to look for the devices? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) #ifndef CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) #define CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) static unsigned long doc_locations[] __initdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) #if defined (__alpha__) || defined(__i386__) || defined(__x86_64__)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) #ifdef CONFIG_MTD_NAND_DISKONCHIP_PROBE_HIGH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) 	0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) 	0xfffd0000, 0xfffd2000, 0xfffd4000, 0xfffd6000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) 	0xfffd8000, 0xfffda000, 0xfffdc000, 0xfffde000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) 	0xfffe0000, 0xfffe2000, 0xfffe4000, 0xfffe6000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) 	0xfffe8000, 0xfffea000, 0xfffec000, 0xfffee000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) 	0xc8000, 0xca000, 0xcc000, 0xce000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) 	0xd0000, 0xd2000, 0xd4000, 0xd6000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51) 	0xd8000, 0xda000, 0xdc000, 0xde000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52) 	0xe0000, 0xe2000, 0xe4000, 0xe6000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) 	0xe8000, 0xea000, 0xec000, 0xee000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) 	0xffffffff };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) static struct mtd_info *doclist = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) struct doc_priv {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) 	struct nand_controller base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62) 	void __iomem *virtadr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) 	unsigned long physadr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) 	u_char ChipID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) 	u_char CDSNControl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) 	int chips_per_floor;	/* The number of chips detected on each floor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) 	int curfloor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) 	int curchip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) 	int mh0_page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) 	int mh1_page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) 	struct rs_control *rs_decoder;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) 	struct mtd_info *nextdoc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) 	bool supports_32b_reads;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) 	/* Handle the last stage of initialization (BBT scan, partitioning) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) 	int (*late_init)(struct mtd_info *mtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) /* This is the ecc value computed by the HW ecc generator upon writing an empty
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80)    page, one with all 0xff for data. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) static u_char empty_write_ecc[6] = { 0x4b, 0x00, 0xe2, 0x0e, 0x93, 0xf7 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) #define INFTL_BBT_RESERVED_BLOCKS 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) #define DoC_is_MillenniumPlus(doc) ((doc)->ChipID == DOC_ChipID_DocMilPlus16 || (doc)->ChipID == DOC_ChipID_DocMilPlus32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) #define DoC_is_Millennium(doc) ((doc)->ChipID == DOC_ChipID_DocMil)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) #define DoC_is_2000(doc) ((doc)->ChipID == DOC_ChipID_Doc2k)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) static int debug = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) module_param(debug, int, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) static int try_dword = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) module_param(try_dword, int, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) static int no_ecc_failures = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) module_param(no_ecc_failures, int, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) static int no_autopart = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99) module_param(no_autopart, int, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101) static int show_firmware_partition = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) module_param(show_firmware_partition, int, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104) #ifdef CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105) static int inftl_bbt_write = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) static int inftl_bbt_write = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) module_param(inftl_bbt_write, int, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) static unsigned long doc_config_location = CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) module_param(doc_config_location, ulong, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) MODULE_PARM_DESC(doc_config_location, "Physical memory address at which to probe for DiskOnChip");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) /* Sector size for HW ECC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) #define SECTOR_SIZE 512
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117) /* The sector bytes are packed into NB_DATA 10 bit words */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) #define NB_DATA (((SECTOR_SIZE + 1) * 8 + 6) / 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) /* Number of roots */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) #define NROOTS 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) /* First consective root */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) #define FCR 510
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) /* Number of symbols */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) #define NN 1023
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127)  * The HW decoder in the DoC ASIC's provides us a error syndrome,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128)  * which we must convert to a standard syndrome usable by the generic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129)  * Reed-Solomon library code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131)  * Fabrice Bellard figured this out in the old docecc code. I added
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132)  * some comments, improved a minor bit and converted it to make use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133)  * of the generic Reed-Solomon library. tglx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) 	int i, j, nerr, errpos[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) 	uint8_t parity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) 	uint16_t ds[4], s[5], tmp, errval[8], syn[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) 	struct rs_codec *cd = rs->codec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) 	memset(syn, 0, sizeof(syn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) 	/* Convert the ecc bytes into words */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) 	ds[0] = ((ecc[4] & 0xff) >> 0) | ((ecc[5] & 0x03) << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) 	ds[1] = ((ecc[5] & 0xfc) >> 2) | ((ecc[2] & 0x0f) << 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) 	ds[2] = ((ecc[2] & 0xf0) >> 4) | ((ecc[3] & 0x3f) << 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) 	ds[3] = ((ecc[3] & 0xc0) >> 6) | ((ecc[0] & 0xff) << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) 	parity = ecc[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) 	/* Initialize the syndrome buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) 	for (i = 0; i < NROOTS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) 		s[i] = ds[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) 	 *  Evaluate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) 	 *  s[i] = ds[3]x^3 + ds[2]x^2 + ds[1]x^1 + ds[0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) 	 *  where x = alpha^(FCR + i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) 	for (j = 1; j < NROOTS; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) 		if (ds[j] == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) 		tmp = cd->index_of[ds[j]];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) 		for (i = 0; i < NROOTS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) 			s[i] ^= cd->alpha_to[rs_modnn(cd, tmp + (FCR + i) * j)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166) 	/* Calc syn[i] = s[i] / alpha^(v + i) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) 	for (i = 0; i < NROOTS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) 		if (s[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) 			syn[i] = rs_modnn(cd, cd->index_of[s[i]] + (NN - FCR - i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) 	/* Call the decoder library */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) 	nerr = decode_rs16(rs, NULL, NULL, 1019, syn, 0, errpos, 0, errval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) 	/* Incorrectable errors ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) 	if (nerr < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) 		return nerr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) 	 * Correct the errors. The bitpositions are a bit of magic,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) 	 * but they are given by the design of the de/encoder circuit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) 	 * in the DoC ASIC's.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) 	for (i = 0; i < nerr; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) 		int index, bitpos, pos = 1015 - errpos[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) 		uint8_t val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) 		if (pos >= NB_DATA && pos < 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) 		if (pos < NB_DATA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) 			/* extract bit position (MSB first) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) 			pos = 10 * (NB_DATA - 1 - pos) - 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) 			/* now correct the following 10 bits. At most two bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) 			   can be modified since pos is even */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) 			index = (pos >> 3) ^ 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) 			bitpos = pos & 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) 			if ((index >= 0 && index < SECTOR_SIZE) || index == (SECTOR_SIZE + 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) 				val = (uint8_t) (errval[i] >> (2 + bitpos));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) 				parity ^= val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) 				if (index < SECTOR_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) 					data[index] ^= val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) 			index = ((pos >> 3) + 1) ^ 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) 			bitpos = (bitpos + 10) & 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) 			if (bitpos == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 				bitpos = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) 			if ((index >= 0 && index < SECTOR_SIZE) || index == (SECTOR_SIZE + 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) 				val = (uint8_t) (errval[i] << (8 - bitpos));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) 				parity ^= val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) 				if (index < SECTOR_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 					data[index] ^= val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) 	/* If the parity is wrong, no rescue possible */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) 	return parity ? -EBADMSG : nerr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) static void DoC_Delay(struct doc_priv *doc, unsigned short cycles)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) 	volatile char dummy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) 	for (i = 0; i < cycles; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) 		if (DoC_is_Millennium(doc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) 			dummy = ReadDOC(doc->virtadr, NOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) 		else if (DoC_is_MillenniumPlus(doc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) 			dummy = ReadDOC(doc->virtadr, Mplus_NOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) 			dummy = ReadDOC(doc->virtadr, DOCStatus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) #define CDSN_CTRL_FR_B_MASK	(CDSN_CTRL_FR_B0 | CDSN_CTRL_FR_B1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) /* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) static int _DoC_WaitReady(struct doc_priv *doc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) 	void __iomem *docptr = doc->virtadr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) 	unsigned long timeo = jiffies + (HZ * 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) 	if (debug)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) 		printk("_DoC_WaitReady...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) 	/* Out-of-line routine to wait for chip response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) 	if (DoC_is_MillenniumPlus(doc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) 		while ((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) 			if (time_after(jiffies, timeo)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) 				printk("_DoC_WaitReady timed out.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) 				return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) 			udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) 			cond_resched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) 		while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) 			if (time_after(jiffies, timeo)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) 				printk("_DoC_WaitReady timed out.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) 				return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) 			udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) 			cond_resched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) static inline int DoC_WaitReady(struct doc_priv *doc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) 	void __iomem *docptr = doc->virtadr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) 	if (DoC_is_MillenniumPlus(doc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) 		DoC_Delay(doc, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) 		if ((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) 			/* Call the out-of-line routine to wait */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) 			ret = _DoC_WaitReady(doc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) 		DoC_Delay(doc, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) 		if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) 			/* Call the out-of-line routine to wait */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) 			ret = _DoC_WaitReady(doc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) 		DoC_Delay(doc, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) 	if (debug)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) 		printk("DoC_WaitReady OK\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) static void doc2000_write_byte(struct nand_chip *this, u_char datum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) 	struct doc_priv *doc = nand_get_controller_data(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) 	void __iomem *docptr = doc->virtadr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) 	if (debug)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) 		printk("write_byte %02x\n", datum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) 	WriteDOC(datum, docptr, CDSNSlowIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) 	WriteDOC(datum, docptr, 2k_CDSN_IO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) static void doc2000_writebuf(struct nand_chip *this, const u_char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) 			     int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) 	struct doc_priv *doc = nand_get_controller_data(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) 	void __iomem *docptr = doc->virtadr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) 	if (debug)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) 		printk("writebuf of %d bytes: ", len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) 	for (i = 0; i < len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) 		WriteDOC_(buf[i], docptr, DoC_2k_CDSN_IO + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) 		if (debug && i < 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) 			printk("%02x ", buf[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) 	if (debug)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) 		printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) static void doc2000_readbuf(struct nand_chip *this, u_char *buf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) 	struct doc_priv *doc = nand_get_controller_data(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) 	void __iomem *docptr = doc->virtadr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) 	u32 *buf32 = (u32 *)buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) 	if (debug)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 		printk("readbuf of %d bytes: ", len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) 	if (!doc->supports_32b_reads ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) 	    ((((unsigned long)buf) | len) & 3)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) 		for (i = 0; i < len; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) 			buf[i] = ReadDOC(docptr, 2k_CDSN_IO + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) 		for (i = 0; i < len / 4; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) 			buf32[i] = readl(docptr + DoC_2k_CDSN_IO + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341)  * We need our own readid() here because it's called before the NAND chip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342)  * has been initialized, and calling nand_op_readid() would lead to a NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343)  * pointer exception when dereferencing the NAND timings.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) static void doc200x_readid(struct nand_chip *this, unsigned int cs, u8 *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) 	u8 addr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) 	struct nand_op_instr instrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) 		NAND_OP_CMD(NAND_CMD_READID, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) 		NAND_OP_ADDR(1, &addr, 50),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) 		NAND_OP_8BIT_DATA_IN(2, id, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) 	struct nand_operation op = NAND_OPERATION(cs, instrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) 	if (!id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) 		op.ninstrs--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) 	this->controller->ops->exec_op(this, &op, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) 	struct nand_chip *this = mtd_to_nand(mtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) 	struct doc_priv *doc = nand_get_controller_data(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) 	uint16_t ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) 	u8 id[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) 	doc200x_readid(this, nr, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) 	ret = ((u16)id[0] << 8) | id[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) 	if (doc->ChipID == DOC_ChipID_Doc2k && try_dword && !nr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) 		/* First chip probe. See if we get same results by 32-bit access */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) 		union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) 			uint32_t dword;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) 			uint8_t byte[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) 		} ident;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) 		void __iomem *docptr = doc->virtadr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 		doc200x_readid(this, nr, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) 		ident.dword = readl(docptr + DoC_2k_CDSN_IO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) 		if (((ident.byte[0] << 8) | ident.byte[1]) == ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) 			pr_info("DiskOnChip 2000 responds to DWORD access\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) 			doc->supports_32b_reads = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) static void __init doc2000_count_chips(struct mtd_info *mtd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) 	struct nand_chip *this = mtd_to_nand(mtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) 	struct doc_priv *doc = nand_get_controller_data(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) 	uint16_t mfrid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) 	/* Max 4 chips per floor on DiskOnChip 2000 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401) 	doc->chips_per_floor = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) 	/* Find out what the first chip is */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) 	mfrid = doc200x_ident_chip(mtd, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) 	/* Find how many chips in each floor. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 	for (i = 1; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) 		if (doc200x_ident_chip(mtd, i) != mfrid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 	doc->chips_per_floor = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) 	pr_debug("Detected %d chips per floor.\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) static void doc2001_write_byte(struct nand_chip *this, u_char datum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) 	struct doc_priv *doc = nand_get_controller_data(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) 	void __iomem *docptr = doc->virtadr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) 	WriteDOC(datum, docptr, CDSNSlowIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) 	WriteDOC(datum, docptr, Mil_CDSN_IO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) 	WriteDOC(datum, docptr, WritePipeTerm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) static void doc2001_writebuf(struct nand_chip *this, const u_char *buf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) 	struct doc_priv *doc = nand_get_controller_data(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) 	void __iomem *docptr = doc->virtadr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) 	for (i = 0; i < len; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) 		WriteDOC_(buf[i], docptr, DoC_Mil_CDSN_IO + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) 	/* Terminate write pipeline */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) 	WriteDOC(0x00, docptr, WritePipeTerm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) static void doc2001_readbuf(struct nand_chip *this, u_char *buf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 	struct doc_priv *doc = nand_get_controller_data(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) 	void __iomem *docptr = doc->virtadr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) 	/* Start read pipeline */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) 	ReadDOC(docptr, ReadPipeInit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) 	for (i = 0; i < len - 1; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 		buf[i] = ReadDOC(docptr, Mil_CDSN_IO + (i & 0xff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) 	/* Terminate read pipeline */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) 	buf[i] = ReadDOC(docptr, LastDataRead);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) static void doc2001plus_writebuf(struct nand_chip *this, const u_char *buf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) 	struct doc_priv *doc = nand_get_controller_data(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) 	void __iomem *docptr = doc->virtadr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) 	if (debug)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) 		printk("writebuf of %d bytes: ", len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) 	for (i = 0; i < len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 		WriteDOC_(buf[i], docptr, DoC_Mil_CDSN_IO + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) 		if (debug && i < 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 			printk("%02x ", buf[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 	if (debug)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 		printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) static void doc2001plus_readbuf(struct nand_chip *this, u_char *buf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) 	struct doc_priv *doc = nand_get_controller_data(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 	void __iomem *docptr = doc->virtadr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 	if (debug)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 		printk("readbuf of %d bytes: ", len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) 	/* Start read pipeline */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 	ReadDOC(docptr, Mplus_ReadPipeInit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) 	ReadDOC(docptr, Mplus_ReadPipeInit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) 	for (i = 0; i < len - 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) 		buf[i] = ReadDOC(docptr, Mil_CDSN_IO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) 		if (debug && i < 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) 			printk("%02x ", buf[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) 	/* Terminate read pipeline */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) 	if (len >= 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) 		buf[len - 2] = ReadDOC(docptr, Mplus_LastDataRead);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) 		if (debug && i < 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) 			printk("%02x ", buf[len - 2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) 	buf[len - 1] = ReadDOC(docptr, Mplus_LastDataRead);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) 	if (debug && i < 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498) 		printk("%02x ", buf[len - 1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) 	if (debug)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) 		printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) static void doc200x_write_control(struct doc_priv *doc, u8 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) 	WriteDOC(value, doc->virtadr, CDSNControl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) 	/* 11.4.3 -- 4 NOPs after CSDNControl write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) 	DoC_Delay(doc, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) static void doc200x_exec_instr(struct nand_chip *this,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) 			       const struct nand_op_instr *instr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 	struct doc_priv *doc = nand_get_controller_data(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) 	unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 	switch (instr->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) 	case NAND_OP_CMD_INSTR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) 		doc200x_write_control(doc, CDSN_CTRL_CE | CDSN_CTRL_CLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) 		doc2000_write_byte(this, instr->ctx.cmd.opcode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) 	case NAND_OP_ADDR_INSTR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 		doc200x_write_control(doc, CDSN_CTRL_CE | CDSN_CTRL_ALE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 		for (i = 0; i < instr->ctx.addr.naddrs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) 			u8 addr = instr->ctx.addr.addrs[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) 			if (DoC_is_2000(doc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 				doc2000_write_byte(this, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 				doc2001_write_byte(this, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) 	case NAND_OP_DATA_IN_INSTR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 		doc200x_write_control(doc, CDSN_CTRL_CE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) 		if (DoC_is_2000(doc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 			doc2000_readbuf(this, instr->ctx.data.buf.in,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 					instr->ctx.data.len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 			doc2001_readbuf(this, instr->ctx.data.buf.in,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 					instr->ctx.data.len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) 	case NAND_OP_DATA_OUT_INSTR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) 		doc200x_write_control(doc, CDSN_CTRL_CE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) 		if (DoC_is_2000(doc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) 			doc2000_writebuf(this, instr->ctx.data.buf.out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) 					 instr->ctx.data.len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) 			doc2001_writebuf(this, instr->ctx.data.buf.out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) 					 instr->ctx.data.len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) 	case NAND_OP_WAITRDY_INSTR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) 		DoC_WaitReady(doc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) 	if (instr->delay_ns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) 		ndelay(instr->delay_ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) static int doc200x_exec_op(struct nand_chip *this,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) 			   const struct nand_operation *op,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) 			   bool check_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 	struct doc_priv *doc = nand_get_controller_data(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 	unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 	if (check_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) 		return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) 	doc->curchip = op->cs % doc->chips_per_floor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) 	doc->curfloor = op->cs / doc->chips_per_floor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 	WriteDOC(doc->curfloor, doc->virtadr, FloorSelect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 	WriteDOC(doc->curchip, doc->virtadr, CDSNDeviceSelect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 	/* Assert CE pin */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 	doc200x_write_control(doc, CDSN_CTRL_CE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 	for (i = 0; i < op->ninstrs; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 		doc200x_exec_instr(this, &op->instrs[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 	/* De-assert CE pin */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 	doc200x_write_control(doc, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) static void doc2001plus_write_pipe_term(struct doc_priv *doc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) 	WriteDOC(0x00, doc->virtadr, Mplus_WritePipeTerm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) 	WriteDOC(0x00, doc->virtadr, Mplus_WritePipeTerm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) static void doc2001plus_exec_instr(struct nand_chip *this,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) 				   const struct nand_op_instr *instr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) 	struct doc_priv *doc = nand_get_controller_data(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) 	unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) 	switch (instr->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) 	case NAND_OP_CMD_INSTR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) 		WriteDOC(instr->ctx.cmd.opcode, doc->virtadr, Mplus_FlashCmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) 		doc2001plus_write_pipe_term(doc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) 	case NAND_OP_ADDR_INSTR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) 		for (i = 0; i < instr->ctx.addr.naddrs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) 			u8 addr = instr->ctx.addr.addrs[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) 			WriteDOC(addr, doc->virtadr, Mplus_FlashAddress);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) 		doc2001plus_write_pipe_term(doc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) 		/* deassert ALE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 		WriteDOC(0, doc->virtadr, Mplus_FlashControl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) 	case NAND_OP_DATA_IN_INSTR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) 		doc2001plus_readbuf(this, instr->ctx.data.buf.in,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) 				    instr->ctx.data.len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) 	case NAND_OP_DATA_OUT_INSTR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) 		doc2001plus_writebuf(this, instr->ctx.data.buf.out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) 				     instr->ctx.data.len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) 		doc2001plus_write_pipe_term(doc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) 	case NAND_OP_WAITRDY_INSTR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) 		DoC_WaitReady(doc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 	if (instr->delay_ns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) 		ndelay(instr->delay_ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) static int doc2001plus_exec_op(struct nand_chip *this,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) 			       const struct nand_operation *op,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) 			       bool check_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) 	struct doc_priv *doc = nand_get_controller_data(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) 	unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) 	if (check_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) 		return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) 	doc->curchip = op->cs % doc->chips_per_floor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 	doc->curfloor = op->cs / doc->chips_per_floor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 	/* Assert ChipEnable and deassert WriteProtect */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 	WriteDOC(DOC_FLASH_CE, doc->virtadr, Mplus_FlashSelect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) 	for (i = 0; i < op->ninstrs; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) 		doc2001plus_exec_instr(this, &op->instrs[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 	/* De-assert ChipEnable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 	WriteDOC(0, doc->virtadr, Mplus_FlashSelect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) static void doc200x_enable_hwecc(struct nand_chip *this, int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 	struct doc_priv *doc = nand_get_controller_data(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 	void __iomem *docptr = doc->virtadr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 	/* Prime the ECC engine */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) 	switch (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 	case NAND_ECC_READ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 		WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) 		WriteDOC(DOC_ECC_EN, docptr, ECCConf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) 	case NAND_ECC_WRITE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) 		WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) 		WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) static void doc2001plus_enable_hwecc(struct nand_chip *this, int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) 	struct doc_priv *doc = nand_get_controller_data(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) 	void __iomem *docptr = doc->virtadr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) 	/* Prime the ECC engine */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) 	switch (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 	case NAND_ECC_READ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) 		WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) 		WriteDOC(DOC_ECC_EN, docptr, Mplus_ECCConf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) 	case NAND_ECC_WRITE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 		WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 		WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, Mplus_ECCConf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) /* This code is only called on write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) static int doc200x_calculate_ecc(struct nand_chip *this, const u_char *dat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 				 unsigned char *ecc_code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 	struct doc_priv *doc = nand_get_controller_data(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 	void __iomem *docptr = doc->virtadr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 	int emptymatch = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 	/* flush the pipeline */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) 	if (DoC_is_2000(doc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) 		WriteDOC(doc->CDSNControl & ~CDSN_CTRL_FLASH_IO, docptr, CDSNControl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 		WriteDOC(0, docptr, 2k_CDSN_IO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 		WriteDOC(0, docptr, 2k_CDSN_IO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 		WriteDOC(0, docptr, 2k_CDSN_IO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 		WriteDOC(doc->CDSNControl, docptr, CDSNControl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 	} else if (DoC_is_MillenniumPlus(doc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) 		WriteDOC(0, docptr, Mplus_NOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) 		WriteDOC(0, docptr, Mplus_NOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) 		WriteDOC(0, docptr, Mplus_NOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 		WriteDOC(0, docptr, NOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 		WriteDOC(0, docptr, NOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) 		WriteDOC(0, docptr, NOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 	for (i = 0; i < 6; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 		if (DoC_is_MillenniumPlus(doc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 			ecc_code[i] = ReadDOC_(docptr, DoC_Mplus_ECCSyndrome0 + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 			ecc_code[i] = ReadDOC_(docptr, DoC_ECCSyndrome0 + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 		if (ecc_code[i] != empty_write_ecc[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 			emptymatch = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 	if (DoC_is_MillenniumPlus(doc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) 		WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 		WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) 	/* If emptymatch=1, we might have an all-0xff data buffer.  Check. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) 	if (emptymatch) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) 		/* Note: this somewhat expensive test should not be triggered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) 		   often.  It could be optimized away by examining the data in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 		   the writebuf routine, and remembering the result. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) 		for (i = 0; i < 512; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) 			if (dat[i] == 0xff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) 			emptymatch = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) 	/* If emptymatch still =1, we do have an all-0xff data buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 	   Return all-0xff ecc value instead of the computed one, so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) 	   it'll look just like a freshly-erased page. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) 	if (emptymatch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) 		memset(ecc_code, 0xff, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) static int doc200x_correct_data(struct nand_chip *this, u_char *dat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 				u_char *read_ecc, u_char *isnull)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 	int i, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 	struct doc_priv *doc = nand_get_controller_data(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 	void __iomem *docptr = doc->virtadr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 	uint8_t calc_ecc[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 	volatile u_char dummy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) 	/* flush the pipeline */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 	if (DoC_is_2000(doc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) 		dummy = ReadDOC(docptr, 2k_ECCStatus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) 		dummy = ReadDOC(docptr, 2k_ECCStatus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) 		dummy = ReadDOC(docptr, 2k_ECCStatus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) 	} else if (DoC_is_MillenniumPlus(doc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) 		dummy = ReadDOC(docptr, Mplus_ECCConf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) 		dummy = ReadDOC(docptr, Mplus_ECCConf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) 		dummy = ReadDOC(docptr, Mplus_ECCConf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) 		dummy = ReadDOC(docptr, ECCConf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) 		dummy = ReadDOC(docptr, ECCConf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 		dummy = ReadDOC(docptr, ECCConf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 	/* Error occurred ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 	if (dummy & 0x80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) 		for (i = 0; i < 6; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 			if (DoC_is_MillenniumPlus(doc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 				calc_ecc[i] = ReadDOC_(docptr, DoC_Mplus_ECCSyndrome0 + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 				calc_ecc[i] = ReadDOC_(docptr, DoC_ECCSyndrome0 + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 		ret = doc_ecc_decode(doc->rs_decoder, dat, calc_ecc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 		if (ret > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 			pr_err("doc200x_correct_data corrected %d errors\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 			       ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) 	if (DoC_is_MillenniumPlus(doc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 		WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) 		WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) 	if (no_ecc_failures && mtd_is_eccerr(ret)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) 		pr_err("suppressing ECC failure\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 		ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) //u_char mydatabuf[528];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) static int doc200x_ooblayout_ecc(struct mtd_info *mtd, int section,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) 				 struct mtd_oob_region *oobregion)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) 	if (section)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) 		return -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 	oobregion->offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 	oobregion->length = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) static int doc200x_ooblayout_free(struct mtd_info *mtd, int section,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) 				  struct mtd_oob_region *oobregion)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 	if (section > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) 		return -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) 	 * The strange out-of-order free bytes definition is a (possibly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) 	 * unneeded) attempt to retain compatibility.  It used to read:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) 	 *	.oobfree = { {8, 8} }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) 	 * Since that leaves two bytes unusable, it was changed.  But the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) 	 * following scheme might affect existing jffs2 installs by moving the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) 	 * cleanmarker:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 	 *	.oobfree = { {6, 10} }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 	 * jffs2 seems to handle the above gracefully, but the current scheme
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 	 * seems safer. The only problem with it is that any code retrieving
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 	 * free bytes position must be able to handle out-of-order segments.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 	if (!section) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) 		oobregion->offset = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) 		oobregion->length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 		oobregion->offset = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) 		oobregion->length = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) static const struct mtd_ooblayout_ops doc200x_ooblayout_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) 	.ecc = doc200x_ooblayout_ecc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 	.free = doc200x_ooblayout_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) /* Find the (I)NFTL Media Header, and optionally also the mirror media header.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857)    On successful return, buf will contain a copy of the media header for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858)    further processing.  id is the string to scan for, and will presumably be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859)    either "ANAND" or "BNAND".  If findmirror=1, also look for the mirror media
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860)    header.  The page #s of the found media headers are placed in mh0_page and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861)    mh1_page in the DOC private structure. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, const char *id, int findmirror)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) 	struct nand_chip *this = mtd_to_nand(mtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 	struct doc_priv *doc = nand_get_controller_data(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 	unsigned offs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 	size_t retlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 	for (offs = 0; offs < mtd->size; offs += mtd->erasesize) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) 		ret = mtd_read(mtd, offs, mtd->writesize, &retlen, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 		if (retlen != mtd->writesize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 		if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 			pr_warn("ECC error scanning DOC at 0x%x\n", offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 		if (memcmp(buf, id, 6))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 		pr_info("Found DiskOnChip %s Media Header at 0x%x\n", id, offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 		if (doc->mh0_page == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 			doc->mh0_page = offs >> this->page_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 			if (!findmirror)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 				return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 		doc->mh1_page = offs >> this->page_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) 		return 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) 	if (doc->mh0_page == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) 		pr_warn("DiskOnChip %s Media Header not found.\n", id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) 	/* Only one mediaheader was found.  We want buf to contain a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) 	   mediaheader on return, so we'll have to re-read the one we found. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) 	offs = doc->mh0_page << this->page_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) 	ret = mtd_read(mtd, offs, mtd->writesize, &retlen, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) 	if (retlen != mtd->writesize) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) 		/* Insanity.  Give up. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) 		pr_err("Read DiskOnChip Media Header once, but can't reread it???\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) static inline int __init nftl_partscan(struct mtd_info *mtd, struct mtd_partition *parts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 	struct nand_chip *this = mtd_to_nand(mtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 	struct doc_priv *doc = nand_get_controller_data(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 	struct nand_memory_organization *memorg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 	u_char *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 	struct NFTLMediaHeader *mh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 	const unsigned psize = 1 << this->page_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 	int numparts = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 	unsigned blocks, maxblocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 	int offs, numheaders;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 	memorg = nanddev_get_memorg(&this->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) 	buf = kmalloc(mtd->writesize, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 	if (!buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) 	if (!(numheaders = find_media_headers(mtd, buf, "ANAND", 1)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) 	mh = (struct NFTLMediaHeader *)buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) 	le16_to_cpus(&mh->NumEraseUnits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 	le16_to_cpus(&mh->FirstPhysicalEUN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 	le32_to_cpus(&mh->FormattedSize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 	pr_info("    DataOrgID        = %s\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 		"    NumEraseUnits    = %d\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 		"    FirstPhysicalEUN = %d\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 		"    FormattedSize    = %d\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 		"    UnitSizeFactor   = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 		mh->DataOrgID, mh->NumEraseUnits,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) 		mh->FirstPhysicalEUN, mh->FormattedSize,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 		mh->UnitSizeFactor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) 	blocks = mtd->size >> this->phys_erase_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) 	maxblocks = min(32768U, mtd->erasesize - psize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) 	if (mh->UnitSizeFactor == 0x00) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) 		/* Auto-determine UnitSizeFactor.  The constraints are:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 		   - There can be at most 32768 virtual blocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) 		   - There can be at most (virtual block size - page size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) 		   virtual blocks (because MediaHeader+BBT must fit in 1).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 		mh->UnitSizeFactor = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 		while (blocks > maxblocks) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 			blocks >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 			maxblocks = min(32768U, (maxblocks << 1) + psize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 			mh->UnitSizeFactor--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 		pr_warn("UnitSizeFactor=0x00 detected.  Correct value is assumed to be 0x%02x.\n", mh->UnitSizeFactor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 	/* NOTE: The lines below modify internal variables of the NAND and MTD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 	   layers; variables with have already been configured by nand_scan.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) 	   Unfortunately, we didn't know before this point what these values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 	   should be.  Thus, this code is somewhat dependent on the exact
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) 	   implementation of the NAND layer.  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) 	if (mh->UnitSizeFactor != 0xff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 		this->bbt_erase_shift += (0xff - mh->UnitSizeFactor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) 		memorg->pages_per_eraseblock <<= (0xff - mh->UnitSizeFactor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 		mtd->erasesize <<= (0xff - mh->UnitSizeFactor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 		pr_info("Setting virtual erase size to %d\n", mtd->erasesize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 		blocks = mtd->size >> this->bbt_erase_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 		maxblocks = min(32768U, mtd->erasesize - psize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 	if (blocks > maxblocks) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 		pr_err("UnitSizeFactor of 0x%02x is inconsistent with device size.  Aborting.\n", mh->UnitSizeFactor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) 	/* Skip past the media headers. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 	offs = max(doc->mh0_page, doc->mh1_page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) 	offs <<= this->page_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) 	offs += mtd->erasesize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) 	if (show_firmware_partition == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) 		parts[0].name = " DiskOnChip Firmware / Media Header partition";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) 		parts[0].offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 		parts[0].size = offs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 		numparts = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 	parts[numparts].name = " DiskOnChip BDTL partition";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 	parts[numparts].offset = offs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 	parts[numparts].size = (mh->NumEraseUnits - numheaders) << this->bbt_erase_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 	offs += parts[numparts].size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 	numparts++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 	if (offs < mtd->size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 		parts[numparts].name = " DiskOnChip Remainder partition";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 		parts[numparts].offset = offs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 		parts[numparts].size = mtd->size - offs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 		numparts++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) 	ret = numparts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)  out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 	kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) /* This is a stripped-down copy of the code in inftlmount.c */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) static inline int __init inftl_partscan(struct mtd_info *mtd, struct mtd_partition *parts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) 	struct nand_chip *this = mtd_to_nand(mtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) 	struct doc_priv *doc = nand_get_controller_data(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 	u_char *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) 	struct INFTLMediaHeader *mh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) 	struct INFTLPartition *ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) 	int numparts = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) 	int blocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 	int vshift, lastvunit = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) 	int end = mtd->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) 	if (inftl_bbt_write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 		end -= (INFTL_BBT_RESERVED_BLOCKS << this->phys_erase_shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 	buf = kmalloc(mtd->writesize, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) 	if (!buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) 	if (!find_media_headers(mtd, buf, "BNAND", 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) 	doc->mh1_page = doc->mh0_page + (4096 >> this->page_shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) 	mh = (struct INFTLMediaHeader *)buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) 	le32_to_cpus(&mh->NoOfBootImageBlocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) 	le32_to_cpus(&mh->NoOfBinaryPartitions);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) 	le32_to_cpus(&mh->NoOfBDTLPartitions);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) 	le32_to_cpus(&mh->BlockMultiplierBits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) 	le32_to_cpus(&mh->FormatFlags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) 	le32_to_cpus(&mh->PercentUsed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) 	pr_info("    bootRecordID          = %s\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) 		"    NoOfBootImageBlocks   = %d\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) 		"    NoOfBinaryPartitions  = %d\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) 		"    NoOfBDTLPartitions    = %d\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) 		"    BlockMultiplierBits   = %d\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) 		"    FormatFlgs            = %d\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) 		"    OsakVersion           = %d.%d.%d.%d\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) 		"    PercentUsed           = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) 		mh->bootRecordID, mh->NoOfBootImageBlocks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) 		mh->NoOfBinaryPartitions,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) 		mh->NoOfBDTLPartitions,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) 		mh->BlockMultiplierBits, mh->FormatFlags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) 		((unsigned char *) &mh->OsakVersion)[0] & 0xf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) 		((unsigned char *) &mh->OsakVersion)[1] & 0xf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) 		((unsigned char *) &mh->OsakVersion)[2] & 0xf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) 		((unsigned char *) &mh->OsakVersion)[3] & 0xf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) 		mh->PercentUsed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) 	vshift = this->phys_erase_shift + mh->BlockMultiplierBits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) 	blocks = mtd->size >> vshift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) 	if (blocks > 32768) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) 		pr_err("BlockMultiplierBits=%d is inconsistent with device size.  Aborting.\n", mh->BlockMultiplierBits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) 	blocks = doc->chips_per_floor << (this->chip_shift - this->phys_erase_shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) 	if (inftl_bbt_write && (blocks > mtd->erasesize)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) 		pr_err("Writeable BBTs spanning more than one erase block are not yet supported.  FIX ME!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) 	/* Scan the partitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) 	for (i = 0; (i < 4); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) 		ip = &(mh->Partitions[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) 		le32_to_cpus(&ip->virtualUnits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) 		le32_to_cpus(&ip->firstUnit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) 		le32_to_cpus(&ip->lastUnit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) 		le32_to_cpus(&ip->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) 		le32_to_cpus(&ip->spareUnits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) 		le32_to_cpus(&ip->Reserved0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) 		pr_info("    PARTITION[%d] ->\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) 			"        virtualUnits    = %d\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) 			"        firstUnit       = %d\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) 			"        lastUnit        = %d\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) 			"        flags           = 0x%x\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) 			"        spareUnits      = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) 			i, ip->virtualUnits, ip->firstUnit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) 			ip->lastUnit, ip->flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) 			ip->spareUnits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) 		if ((show_firmware_partition == 1) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) 		    (i == 0) && (ip->firstUnit > 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) 			parts[0].name = " DiskOnChip IPL / Media Header partition";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) 			parts[0].offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) 			parts[0].size = mtd->erasesize * ip->firstUnit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) 			numparts = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) 		if (ip->flags & INFTL_BINARY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) 			parts[numparts].name = " DiskOnChip BDK partition";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) 			parts[numparts].name = " DiskOnChip BDTL partition";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) 		parts[numparts].offset = ip->firstUnit << vshift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) 		parts[numparts].size = (1 + ip->lastUnit - ip->firstUnit) << vshift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) 		numparts++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) 		if (ip->lastUnit > lastvunit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) 			lastvunit = ip->lastUnit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) 		if (ip->flags & INFTL_LAST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) 	lastvunit++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) 	if ((lastvunit << vshift) < end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) 		parts[numparts].name = " DiskOnChip Remainder partition";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) 		parts[numparts].offset = lastvunit << vshift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) 		parts[numparts].size = end - parts[numparts].offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) 		numparts++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) 	ret = numparts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125)  out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) 	kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) static int __init nftl_scan_bbt(struct mtd_info *mtd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) 	int ret, numparts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) 	struct nand_chip *this = mtd_to_nand(mtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) 	struct doc_priv *doc = nand_get_controller_data(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) 	struct mtd_partition parts[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) 	memset((char *)parts, 0, sizeof(parts));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) 	/* On NFTL, we have to find the media headers before we can read the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) 	   BBTs, since they're stored in the media header eraseblocks. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) 	numparts = nftl_partscan(mtd, parts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) 	if (!numparts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) 	this->bbt_td->options = NAND_BBT_ABSPAGE | NAND_BBT_8BIT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) 				NAND_BBT_SAVECONTENT | NAND_BBT_WRITE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) 				NAND_BBT_VERSION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) 	this->bbt_td->veroffs = 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) 	this->bbt_td->pages[0] = doc->mh0_page + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) 	if (doc->mh1_page != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) 		this->bbt_md->options = NAND_BBT_ABSPAGE | NAND_BBT_8BIT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) 					NAND_BBT_SAVECONTENT | NAND_BBT_WRITE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) 					NAND_BBT_VERSION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) 		this->bbt_md->veroffs = 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) 		this->bbt_md->pages[0] = doc->mh1_page + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) 		this->bbt_md = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) 	ret = nand_create_bbt(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) 	return mtd_device_register(mtd, parts, no_autopart ? 0 : numparts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) static int __init inftl_scan_bbt(struct mtd_info *mtd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) 	int ret, numparts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) 	struct nand_chip *this = mtd_to_nand(mtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) 	struct doc_priv *doc = nand_get_controller_data(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) 	struct mtd_partition parts[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) 	if (nanddev_ntargets(&this->base) > doc->chips_per_floor) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) 		pr_err("Multi-floor INFTL devices not yet supported.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) 	if (DoC_is_MillenniumPlus(doc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) 		this->bbt_td->options = NAND_BBT_2BIT | NAND_BBT_ABSPAGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) 		if (inftl_bbt_write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) 			this->bbt_td->options |= NAND_BBT_WRITE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) 		this->bbt_td->pages[0] = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) 		this->bbt_md = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) 		this->bbt_td->options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT | NAND_BBT_VERSION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) 		if (inftl_bbt_write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) 			this->bbt_td->options |= NAND_BBT_WRITE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) 		this->bbt_td->offs = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) 		this->bbt_td->len = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) 		this->bbt_td->veroffs = 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) 		this->bbt_td->maxblocks = INFTL_BBT_RESERVED_BLOCKS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) 		this->bbt_td->reserved_block_code = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) 		this->bbt_td->pattern = "MSYS_BBT";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) 		this->bbt_md->options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT | NAND_BBT_VERSION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) 		if (inftl_bbt_write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) 			this->bbt_md->options |= NAND_BBT_WRITE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) 		this->bbt_md->offs = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) 		this->bbt_md->len = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) 		this->bbt_md->veroffs = 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) 		this->bbt_md->maxblocks = INFTL_BBT_RESERVED_BLOCKS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) 		this->bbt_md->reserved_block_code = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) 		this->bbt_md->pattern = "TBB_SYSM";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) 	ret = nand_create_bbt(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) 	memset((char *)parts, 0, sizeof(parts));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) 	numparts = inftl_partscan(mtd, parts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) 	/* At least for now, require the INFTL Media Header.  We could probably
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) 	   do without it for non-INFTL use, since all it gives us is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) 	   autopartitioning, but I want to give it more thought. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) 	if (!numparts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) 	return mtd_device_register(mtd, parts, no_autopart ? 0 : numparts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) static inline int __init doc2000_init(struct mtd_info *mtd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) 	struct nand_chip *this = mtd_to_nand(mtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) 	struct doc_priv *doc = nand_get_controller_data(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) 	doc->late_init = nftl_scan_bbt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) 	doc->CDSNControl = CDSN_CTRL_FLASH_IO | CDSN_CTRL_ECC_IO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) 	doc2000_count_chips(mtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) 	mtd->name = "DiskOnChip 2000 (NFTL Model)";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) 	return (4 * doc->chips_per_floor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) static inline int __init doc2001_init(struct mtd_info *mtd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) 	struct nand_chip *this = mtd_to_nand(mtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) 	struct doc_priv *doc = nand_get_controller_data(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) 	ReadDOC(doc->virtadr, ChipID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) 	ReadDOC(doc->virtadr, ChipID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) 	ReadDOC(doc->virtadr, ChipID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) 	if (ReadDOC(doc->virtadr, ChipID) != DOC_ChipID_DocMil) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) 		/* It's not a Millennium; it's one of the newer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) 		   DiskOnChip 2000 units with a similar ASIC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) 		   Treat it like a Millennium, except that it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) 		   can have multiple chips. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) 		doc2000_count_chips(mtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) 		mtd->name = "DiskOnChip 2000 (INFTL Model)";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) 		doc->late_init = inftl_scan_bbt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) 		return (4 * doc->chips_per_floor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) 		/* Bog-standard Millennium */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) 		doc->chips_per_floor = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) 		mtd->name = "DiskOnChip Millennium";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) 		doc->late_init = nftl_scan_bbt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) static inline int __init doc2001plus_init(struct mtd_info *mtd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) 	struct nand_chip *this = mtd_to_nand(mtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) 	struct doc_priv *doc = nand_get_controller_data(this);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) 	doc->late_init = inftl_scan_bbt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) 	this->ecc.hwctl = doc2001plus_enable_hwecc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) 	doc->chips_per_floor = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) 	mtd->name = "DiskOnChip Millennium Plus";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) static int doc200x_attach_chip(struct nand_chip *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) 	if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) 	chip->ecc.placement = NAND_ECC_PLACEMENT_INTERLEAVED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) 	chip->ecc.size = 512;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) 	chip->ecc.bytes = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) 	chip->ecc.strength = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) 	chip->ecc.options = NAND_ECC_GENERIC_ERASED_CHECK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) 	chip->ecc.hwctl = doc200x_enable_hwecc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) 	chip->ecc.calculate = doc200x_calculate_ecc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) 	chip->ecc.correct = doc200x_correct_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) static const struct nand_controller_ops doc200x_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) 	.exec_op = doc200x_exec_op,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) 	.attach_chip = doc200x_attach_chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) static const struct nand_controller_ops doc2001plus_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) 	.exec_op = doc2001plus_exec_op,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) 	.attach_chip = doc200x_attach_chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) static int __init doc_probe(unsigned long physadr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) 	struct nand_chip *nand = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) 	struct doc_priv *doc = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) 	unsigned char ChipID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) 	struct mtd_info *mtd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) 	void __iomem *virtadr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) 	unsigned char save_control;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) 	unsigned char tmp, tmpb, tmpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) 	int reg, len, numchips;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) 	if (!request_mem_region(physadr, DOC_IOREMAP_LEN, "DiskOnChip"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) 		return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) 	virtadr = ioremap(physadr, DOC_IOREMAP_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) 	if (!virtadr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) 		pr_err("Diskonchip ioremap failed: 0x%x bytes at 0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) 		       DOC_IOREMAP_LEN, physadr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) 		ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) 		goto error_ioremap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) 	/* It's not possible to cleanly detect the DiskOnChip - the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) 	 * bootup procedure will put the device into reset mode, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) 	 * it's not possible to talk to it without actually writing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) 	 * to the DOCControl register. So we store the current contents
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) 	 * of the DOCControl register's location, in case we later decide
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) 	 * that it's not a DiskOnChip, and want to put it back how we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) 	 * found it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) 	save_control = ReadDOC(virtadr, DOCControl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) 	/* Reset the DiskOnChip ASIC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) 	WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, virtadr, DOCControl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) 	WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, virtadr, DOCControl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) 	/* Enable the DiskOnChip ASIC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) 	WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, virtadr, DOCControl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) 	WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, virtadr, DOCControl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) 	ChipID = ReadDOC(virtadr, ChipID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) 	switch (ChipID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) 	case DOC_ChipID_Doc2k:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) 		reg = DoC_2k_ECCStatus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) 	case DOC_ChipID_DocMil:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) 		reg = DoC_ECCConf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) 	case DOC_ChipID_DocMilPlus16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) 	case DOC_ChipID_DocMilPlus32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) 	case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) 		/* Possible Millennium Plus, need to do more checks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) 		/* Possibly release from power down mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) 		for (tmp = 0; (tmp < 4); tmp++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) 			ReadDOC(virtadr, Mplus_Power);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) 		/* Reset the Millennium Plus ASIC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) 		tmp = DOC_MODE_RESET | DOC_MODE_MDWREN | DOC_MODE_RST_LAT | DOC_MODE_BDECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) 		WriteDOC(tmp, virtadr, Mplus_DOCControl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) 		WriteDOC(~tmp, virtadr, Mplus_CtrlConfirm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) 		usleep_range(1000, 2000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) 		/* Enable the Millennium Plus ASIC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) 		tmp = DOC_MODE_NORMAL | DOC_MODE_MDWREN | DOC_MODE_RST_LAT | DOC_MODE_BDECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) 		WriteDOC(tmp, virtadr, Mplus_DOCControl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) 		WriteDOC(~tmp, virtadr, Mplus_CtrlConfirm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) 		usleep_range(1000, 2000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) 		ChipID = ReadDOC(virtadr, ChipID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) 		switch (ChipID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) 		case DOC_ChipID_DocMilPlus16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) 			reg = DoC_Mplus_Toggle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) 		case DOC_ChipID_DocMilPlus32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) 			pr_err("DiskOnChip Millennium Plus 32MB is not supported, ignoring.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) 			fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) 			ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) 			goto notfound;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) 		ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) 		goto notfound;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) 	/* Check the TOGGLE bit in the ECC register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) 	tmp = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) 	tmpb = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) 	tmpc = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) 	if ((tmp == tmpb) || (tmp != tmpc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) 		pr_warn("Possible DiskOnChip at 0x%lx failed TOGGLE test, dropping.\n", physadr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) 		ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) 		goto notfound;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) 	for (mtd = doclist; mtd; mtd = doc->nextdoc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) 		unsigned char oldval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) 		unsigned char newval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) 		nand = mtd_to_nand(mtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) 		doc = nand_get_controller_data(nand);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) 		/* Use the alias resolution register to determine if this is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) 		   in fact the same DOC aliased to a new address.  If writes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) 		   to one chip's alias resolution register change the value on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) 		   the other chip, they're the same chip. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) 		if (ChipID == DOC_ChipID_DocMilPlus16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) 			oldval = ReadDOC(doc->virtadr, Mplus_AliasResolution);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) 			newval = ReadDOC(virtadr, Mplus_AliasResolution);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) 			oldval = ReadDOC(doc->virtadr, AliasResolution);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) 			newval = ReadDOC(virtadr, AliasResolution);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) 		if (oldval != newval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) 		if (ChipID == DOC_ChipID_DocMilPlus16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) 			WriteDOC(~newval, virtadr, Mplus_AliasResolution);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) 			oldval = ReadDOC(doc->virtadr, Mplus_AliasResolution);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) 			WriteDOC(newval, virtadr, Mplus_AliasResolution);	// restore it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) 			WriteDOC(~newval, virtadr, AliasResolution);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) 			oldval = ReadDOC(doc->virtadr, AliasResolution);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) 			WriteDOC(newval, virtadr, AliasResolution);	// restore it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) 		newval = ~newval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) 		if (oldval == newval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) 			pr_debug("Found alias of DOC at 0x%lx to 0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) 				 doc->physadr, physadr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) 			goto notfound;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) 	pr_notice("DiskOnChip found at 0x%lx\n", physadr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) 	len = sizeof(struct nand_chip) + sizeof(struct doc_priv) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) 	      (2 * sizeof(struct nand_bbt_descr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) 	nand = kzalloc(len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) 	if (!nand) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) 		ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) 		goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) 	 * Allocate a RS codec instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) 	 * Symbolsize is 10 (bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) 	 * Primitve polynomial is x^10+x^3+1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) 	 * First consecutive root is 510
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) 	 * Primitve element to generate roots = 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) 	 * Generator polinomial degree = 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) 	doc = (struct doc_priv *) (nand + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) 	doc->rs_decoder = init_rs(10, 0x409, FCR, 1, NROOTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) 	if (!doc->rs_decoder) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) 		pr_err("DiskOnChip: Could not create a RS codec\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) 		ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) 		goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) 	nand_controller_init(&doc->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) 	if (ChipID == DOC_ChipID_DocMilPlus16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) 		doc->base.ops = &doc2001plus_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) 		doc->base.ops = &doc200x_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) 	mtd			= nand_to_mtd(nand);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) 	nand->bbt_td		= (struct nand_bbt_descr *) (doc + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) 	nand->bbt_md		= nand->bbt_td + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) 	mtd->owner		= THIS_MODULE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) 	mtd_set_ooblayout(mtd, &doc200x_ooblayout_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) 	nand->controller	= &doc->base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) 	nand_set_controller_data(nand, doc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) 	nand->bbt_options	= NAND_BBT_USE_FLASH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) 	/* Skip the automatic BBT scan so we can run it manually */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) 	nand->options		|= NAND_SKIP_BBTSCAN | NAND_NO_BBM_QUIRK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) 	doc->physadr		= physadr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) 	doc->virtadr		= virtadr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) 	doc->ChipID		= ChipID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) 	doc->curfloor		= -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) 	doc->curchip		= -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) 	doc->mh0_page		= -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) 	doc->mh1_page		= -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) 	doc->nextdoc		= doclist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) 	if (ChipID == DOC_ChipID_Doc2k)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) 		numchips = doc2000_init(mtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) 	else if (ChipID == DOC_ChipID_DocMilPlus16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) 		numchips = doc2001plus_init(mtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) 		numchips = doc2001_init(mtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) 	if ((ret = nand_scan(nand, numchips)) || (ret = doc->late_init(mtd))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) 		/* DBB note: i believe nand_cleanup is necessary here, as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) 		   buffers may have been allocated in nand_base.  Check with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) 		   Thomas. FIX ME! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) 		nand_cleanup(nand);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) 		goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) 	/* Success! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) 	doclist = mtd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506)  notfound:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) 	/* Put back the contents of the DOCControl register, in case it's not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) 	   actually a DiskOnChip.  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) 	WriteDOC(save_control, virtadr, DOCControl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510)  fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) 	if (doc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) 		free_rs(doc->rs_decoder);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) 	kfree(nand);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) 	iounmap(virtadr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) error_ioremap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) 	release_mem_region(physadr, DOC_IOREMAP_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) static void release_nanddoc(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) 	struct mtd_info *mtd, *nextmtd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) 	struct nand_chip *nand;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) 	struct doc_priv *doc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) 	for (mtd = doclist; mtd; mtd = nextmtd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) 		nand = mtd_to_nand(mtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) 		doc = nand_get_controller_data(nand);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) 		nextmtd = doc->nextdoc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) 		ret = mtd_device_unregister(mtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) 		WARN_ON(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) 		nand_cleanup(nand);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) 		iounmap(doc->virtadr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) 		release_mem_region(doc->physadr, DOC_IOREMAP_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) 		free_rs(doc->rs_decoder);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) 		kfree(nand);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) static int __init init_nanddoc(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) 	int i, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) 	if (doc_config_location) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) 		pr_info("Using configured DiskOnChip probe address 0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) 			doc_config_location);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) 		ret = doc_probe(doc_config_location);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) 		for (i = 0; (doc_locations[i] != 0xffffffff); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) 			doc_probe(doc_locations[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) 	/* No banner message any more. Print a message if no DiskOnChip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) 	   found, so the user knows we at least tried. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) 	if (!doclist) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) 		pr_info("No valid DiskOnChip devices found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) 		ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) static void __exit cleanup_nanddoc(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) 	/* Cleanup the nand/DoC resources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) 	release_nanddoc();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) module_init(init_nanddoc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) module_exit(cleanup_nanddoc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) MODULE_DESCRIPTION("M-Systems DiskOnChip 2000, Millennium and Millennium Plus device driver");