/**
 * \brief Writes the data and/or spare area of a NANDFLASH page, after calculating an
 * ECC for the data area and storing it in the spare. If no data buffer is
 * provided, the ECC is read from the existing page spare. If no spare buffer
 * is provided, the spare area is still written with the ECC information
 * calculated on the data buffer.
 * \param nand Pointer to an EccNandFlash instance.
 * \param block  Number of the block to write in.
 * \param page  Number of the page to write inside the given block.
 * \param data  Data area buffer, can be 0.
 * \param spare  Spare area buffer, can be 0.
 * \return 0 if successful; otherwise returns an error code.
 */
static uint8_t ecc_write_page_with_swecc(const struct _nand_flash *nand,
		uint16_t block, uint16_t page, void *data, void *spare)
{
	uint8_t error;
	uint8_t hamming[NAND_MAX_SPARE_ECC_BYTES];
	uint16_t page_data_size = nand_model_get_page_data_size(&nand->model);
	uint16_t page_spare_size = nand_model_get_page_spare_size(&nand->model);

	/* Compute ECC on the new data, if provided */
	/* If not provided, hamming code set to 0xFFFF.. to keep existing bytes */
	memset(hamming, 0xFF, NAND_MAX_SPARE_ECC_BYTES);
	if (data) {
		/* Compute hamming code on data */
		hamming_compute_256x(data, page_data_size, hamming);
	}

	/* Store code in spare buffer (if no buffer provided, use a temp. one) */
	if (!spare) {
		spare = spare_buf;
		memset(spare, 0xFF, page_spare_size);
	}
	nand_spare_scheme_write_ecc(nand_model_get_scheme(&nand->model),
			spare, hamming);

	/* Perform write operation */
	error = nand_raw_write_page(nand, block, page, data, spare);
	if (error) {
		trace_error("nand_ecc_write_page: Failed to write page\r\n");
		return error;
	}

	return 0;
}
/**
 * \brief  Write the data and/or spare area of a NAND Flash page, after
 * calculating an ECC for the data area and storing it in the spare. If no
 * data buffer is provided, the ECC is read from the existing page spare. If
 * no spare buffer is provided, the spare area is still written with the ECC
 * information calculated on the data buffer.
 *
 * \param ecc  Pointer to an nand_flash_ecc instance.
 * \param block  Number of block to read from.
 * \param page  Number of page to read inside given block.
 * \param data  Data area buffer.
 * \param spare  Spare area buffer.
 *
 * \return 0 if successful; otherwise return the error code.
 */
uint32_t nand_flash_ecc_write_page(const struct nand_flash_ecc *ecc,
		uint16_t block, uint16_t page, uint8_t *data, uint8_t *spare)
{
	uint32_t error;

	uint16_t page_data_size
		= nand_flash_model_get_page_data_size(MODEL(ecc));

	uint8_t hamming_code[NAND_COMMON_MAX_SPARE_ECC_BYTES];
	uint8_t spare_buffer[NAND_COMMON_MAX_PAGE_SPARE_SIZE];

	/**
	 * Compute ECC on the new data, if provided. If not provided, hamming
	 * code set to 0xFFFF.. to keep existing bytes.
	 */
	memset(hamming_code, 0xFF, NAND_COMMON_MAX_SPARE_ECC_BYTES);
	if (data) {
		/* Compute hamming code on data */
		hamming_compute_256x(data, page_data_size, hamming_code);
	}

	/* if no buffer provided, use a temp one */
	if (!spare) {
		spare = spare_buffer;
	}

	memset(spare, 0xFF, NAND_COMMON_MAX_PAGE_SPARE_SIZE);

	nand_flash_spare_scheme_write_ecc(nand_flash_model_get_scheme(MODEL(ecc)),
			spare, hamming_code);

	/* Perform write operation */
	error = nand_flash_raw_write_page(RAW(ecc), block, page, data, spare);
	if (error) {
		return error;
	}

	return 0;
}