Add raw NAND framework

The raw NAND framework supports SLC NAND devices.

It introduces a new high level interface (io_mtd) that
defines operations a driver can register to the NAND framework.
This interface will fill in the io_mtd device specification:
	- device_size
        - erase_size
that could be used by the io_storage interface.

NAND core source file integrates the standard read loop that
performs NAND device read operations using a skip bad block strategy.
A platform buffer must be defined in case of unaligned
data. This buffer must fit to the maximum device page size
defined by PLATFORM_MTD_MAX_PAGE_SIZE.

The raw_nand.c source file embeds the specific NAND operations
to read data.
The read command is a raw page read without any ECC correction.
This can be overridden by a low level driver.
No generic support for write or erase command or software
ECC correction.

NAND ONFI detection is available and can be enabled using
NAND_ONFI_DETECT=1.
For non-ONFI NAND management, platform can define required
information.

Change-Id: Id80e9864456cf47f02b74938cf25d99261da8e82
Signed-off-by: Lionel Debieve <lionel.debieve@st.com>
Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
diff --git a/include/drivers/io/io_mtd.h b/include/drivers/io/io_mtd.h
new file mode 100644
index 0000000..1395ff6
--- /dev/null
+++ b/include/drivers/io/io_mtd.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IO_MTD_H
+#define IO_MTD_H
+
+#include <stdint.h>
+#include <stdio.h>
+
+#include <drivers/io/io_storage.h>
+
+/* MTD devices ops */
+typedef struct io_mtd_ops {
+	/*
+	 * Initialize MTD framework and retrieve device information.
+	 *
+	 * @size:  [out] MTD device size in bytes.
+	 * @erase_size: [out] MTD erase size in bytes.
+	 * Return 0 on success, a negative error code otherwise.
+	 */
+	int (*init)(unsigned long long *size, unsigned int *erase_size);
+
+	/*
+	 * Execute a read memory operation.
+	 *
+	 * @offset: Offset in bytes to start read operation.
+	 * @buffer: [out] Buffer to store read data.
+	 * @length: Required length to be read in bytes.
+	 * @out_length: [out] Length read in bytes.
+	 * Return 0 on success, a negative error code otherwise.
+	 */
+	int (*read)(unsigned int offset, uintptr_t buffer, size_t length,
+		    size_t *out_length);
+
+	/*
+	 * Execute a write memory operation.
+	 *
+	 * @offset: Offset in bytes to start write operation.
+	 * @buffer: Buffer to be written in device.
+	 * @length: Required length to be written in bytes.
+	 * Return 0 on success, a negative error code otherwise.
+	 */
+	int (*write)(unsigned int offset, uintptr_t buffer, size_t length);
+} io_mtd_ops_t;
+
+typedef struct io_mtd_dev_spec {
+	unsigned long long device_size;
+	unsigned int erase_size;
+	io_mtd_ops_t ops;
+} io_mtd_dev_spec_t;
+
+struct io_dev_connector;
+
+int register_io_dev_mtd(const struct io_dev_connector **dev_con);
+
+#endif /* IO_MTD_H */