+#ifdef CONFIG_SYS_NAND_ONFI_DETECTION
+/*
+ * sanitize ONFI strings so we can safely print them
+ */
+static void sanitize_string(char *s, size_t len)
+{
+ ssize_t i;
+
+ /* null terminate */
+ s[len - 1] = 0;
+
+ /* remove non printable chars */
+ for (i = 0; i < len - 1; i++) {
+ if (s[i] < ' ' || s[i] > 127)
+ s[i] = '?';
+ }
+
+ /* remove trailing spaces */
+ strim(s);
+}
+
+static u16 onfi_crc16(u16 crc, u8 const *p, size_t len)
+{
+ int i;
+ while (len--) {
+ crc ^= *p++ << 8;
+ for (i = 0; i < 8; i++)
+ crc = (crc << 1) ^ ((crc & 0x8000) ? 0x8005 : 0);
+ }
+
+ return crc;
+}
+
+/*
+ * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise
+ */
+static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
+ int *busw)
+{
+ struct nand_onfi_params *p = &chip->onfi_params;
+ int i;
+ int val;
+
+ /* try ONFI for unknow chip or LP */
+ chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1);
+ if (chip->read_byte(mtd) != 'O' || chip->read_byte(mtd) != 'N' ||
+ chip->read_byte(mtd) != 'F' || chip->read_byte(mtd) != 'I')
+ return 0;
+
+ MTDDEBUG(MTD_DEBUG_LEVEL0, "ONFI flash detected\n");
+ chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1);
+ for (i = 0; i < 3; i++) {
+ chip->read_buf(mtd, (uint8_t *)p, sizeof(*p));
+ if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) ==
+ le16_to_cpu(p->crc)) {
+ MTDDEBUG(MTD_DEBUG_LEVEL0,
+ "ONFI param page %d valid\n", i);
+ break;
+ }
+ }
+
+ if (i == 3)
+ return 0;
+
+ /* check version */
+ val = le16_to_cpu(p->revision);
+ if (val & (1 << 5))
+ chip->onfi_version = 23;
+ else if (val & (1 << 4))
+ chip->onfi_version = 22;
+ else if (val & (1 << 3))
+ chip->onfi_version = 21;
+ else if (val & (1 << 2))
+ chip->onfi_version = 20;
+ else if (val & (1 << 1))
+ chip->onfi_version = 10;
+ else
+ chip->onfi_version = 0;
+
+ if (!chip->onfi_version) {
+ printk(KERN_INFO "%s: unsupported ONFI version: %d\n",
+ __func__, val);
+ return 0;