linux/drivers/mtd/nand/raw/atmel/pmecc.c

// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright 2017 ATMEL
 * Copyright 2017 Free Electrons
 *
 * Author: Boris Brezillon <[email protected]>
 *
 * Derived from the atmel_nand.c driver which contained the following
 * copyrights:
 *
 *   Copyright 2003 Rick Bronson
 *
 *   Derived from drivers/mtd/nand/autcpu12.c (removed in v3.8)
 *	Copyright 2001 Thomas Gleixner ([email protected])
 *
 *   Derived from drivers/mtd/spia.c (removed in v3.8)
 *	Copyright 2000 Steven J. Hill ([email protected])
 *
 *   Add Hardware ECC support for AT91SAM9260 / AT91SAM9263
 *	Richard Genoud ([email protected]), Adeneo Copyright 2007
 *
 *   Derived from Das U-Boot source code
 *	(u-boot-1.1.5/board/atmel/at91sam9263ek/nand.c)
 *      Copyright 2006 ATMEL Rousset, Lacressonniere Nicolas
 *
 *   Add Programmable Multibit ECC support for various AT91 SoC
 *	Copyright 2012 ATMEL, Hong Xu
 *
 *   Add Nand Flash Controller support for SAMA5 SoC
 *	Copyright 2013 ATMEL, Josh Wu ([email protected])
 *
 * The PMECC is an hardware assisted BCH engine, which means part of the
 * ECC algorithm is left to the software. The hardware/software repartition
 * is explained in the "PMECC Controller Functional Description" chapter in
 * Atmel datasheets, and some of the functions in this file are directly
 * implementing the algorithms described in the "Software Implementation"
 * sub-section.
 *
 * TODO: it seems that the software BCH implementation in lib/bch.c is already
 * providing some of the logic we are implementing here. It would be smart
 * to expose the needed lib/bch.c helpers/functions and re-use them here.
 */

#include <linux/genalloc.h>
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/mtd/rawnand.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/slab.h>

#include "pmecc.h"

/* Galois field dimension */
#define PMECC_GF_DIMENSION_13
#define PMECC_GF_DIMENSION_14

/* Primitive Polynomial used by PMECC */
#define PMECC_GF_13_PRIMITIVE_POLY
#define PMECC_GF_14_PRIMITIVE_POLY

#define PMECC_LOOKUP_TABLE_SIZE_512
#define PMECC_LOOKUP_TABLE_SIZE_1024

/* Time out value for reading PMECC status register */
#define PMECC_MAX_TIMEOUT_MS

/* PMECC Register Definitions */
#define ATMEL_PMECC_CFG
#define PMECC_CFG_BCH_STRENGTH(x)
#define PMECC_CFG_BCH_STRENGTH_MASK
#define PMECC_CFG_SECTOR512
#define PMECC_CFG_SECTOR1024
#define PMECC_CFG_NSECTORS(x)
#define PMECC_CFG_READ_OP
#define PMECC_CFG_WRITE_OP
#define PMECC_CFG_SPARE_ENABLE
#define PMECC_CFG_AUTO_ENABLE

#define ATMEL_PMECC_SAREA
#define ATMEL_PMECC_SADDR
#define ATMEL_PMECC_EADDR

#define ATMEL_PMECC_CLK
#define PMECC_CLK_133MHZ

#define ATMEL_PMECC_CTRL
#define PMECC_CTRL_RST
#define PMECC_CTRL_DATA
#define PMECC_CTRL_USER
#define PMECC_CTRL_ENABLE
#define PMECC_CTRL_DISABLE

#define ATMEL_PMECC_SR
#define PMECC_SR_BUSY
#define PMECC_SR_ENABLE

#define ATMEL_PMECC_IER
#define ATMEL_PMECC_IDR
#define ATMEL_PMECC_IMR
#define ATMEL_PMECC_ISR
#define PMECC_ERROR_INT

#define ATMEL_PMECC_ECC(sector, n)

#define ATMEL_PMECC_REM(sector, n)

/* PMERRLOC Register Definitions */
#define ATMEL_PMERRLOC_ELCFG
#define PMERRLOC_ELCFG_SECTOR_512
#define PMERRLOC_ELCFG_SECTOR_1024
#define PMERRLOC_ELCFG_NUM_ERRORS(n)

#define ATMEL_PMERRLOC_ELPRIM
#define ATMEL_PMERRLOC_ELEN
#define ATMEL_PMERRLOC_ELDIS
#define PMERRLOC_DISABLE

#define ATMEL_PMERRLOC_ELSR
#define PMERRLOC_ELSR_BUSY

#define ATMEL_PMERRLOC_ELIER
#define ATMEL_PMERRLOC_ELIDR
#define ATMEL_PMERRLOC_ELIMR
#define ATMEL_PMERRLOC_ELISR
#define PMERRLOC_ERR_NUM_MASK
#define PMERRLOC_CALC_DONE

#define ATMEL_PMERRLOC_SIGMA(x)

#define ATMEL_PMERRLOC_EL(offs, x)

struct atmel_pmecc_gf_tables {};

struct atmel_pmecc_caps {};

struct atmel_pmecc {};

struct atmel_pmecc_user_conf_cache {};

struct atmel_pmecc_user {};

static DEFINE_MUTEX(pmecc_gf_tables_lock);
static const struct atmel_pmecc_gf_tables *pmecc_gf_tables_512;
static const struct atmel_pmecc_gf_tables *pmecc_gf_tables_1024;

static inline int deg(unsigned int poly)
{}

static int atmel_pmecc_build_gf_tables(int mm, unsigned int poly,
				       struct atmel_pmecc_gf_tables *gf_tables)
{}

static const struct atmel_pmecc_gf_tables *
atmel_pmecc_create_gf_tables(const struct atmel_pmecc_user_req *req)
{}

static const struct atmel_pmecc_gf_tables *
atmel_pmecc_get_gf_tables(const struct atmel_pmecc_user_req *req)
{}

static int atmel_pmecc_prepare_user_req(struct atmel_pmecc *pmecc,
					struct atmel_pmecc_user_req *req)
{}

struct atmel_pmecc_user *
atmel_pmecc_create_user(struct atmel_pmecc *pmecc,
			struct atmel_pmecc_user_req *req)
{}
EXPORT_SYMBOL_GPL();

void atmel_pmecc_destroy_user(struct atmel_pmecc_user *user)
{}
EXPORT_SYMBOL_GPL();

static int get_strength(struct atmel_pmecc_user *user)
{}

static int get_sectorsize(struct atmel_pmecc_user *user)
{}

static void atmel_pmecc_gen_syndrome(struct atmel_pmecc_user *user, int sector)
{}

static void atmel_pmecc_substitute(struct atmel_pmecc_user *user)
{}

static void atmel_pmecc_get_sigma(struct atmel_pmecc_user *user)
{}

static int atmel_pmecc_err_location(struct atmel_pmecc_user *user)
{}

int atmel_pmecc_correct_sector(struct atmel_pmecc_user *user, int sector,
			       void *data, void *ecc)
{}
EXPORT_SYMBOL_GPL();

bool atmel_pmecc_correct_erased_chunks(struct atmel_pmecc_user *user)
{}
EXPORT_SYMBOL_GPL();

void atmel_pmecc_get_generated_eccbytes(struct atmel_pmecc_user *user,
					int sector, void *ecc)
{}
EXPORT_SYMBOL_GPL();

void atmel_pmecc_reset(struct atmel_pmecc *pmecc)
{}
EXPORT_SYMBOL_GPL();

int atmel_pmecc_enable(struct atmel_pmecc_user *user, int op)
{}
EXPORT_SYMBOL_GPL();

void atmel_pmecc_disable(struct atmel_pmecc_user *user)
{}
EXPORT_SYMBOL_GPL();

int atmel_pmecc_wait_rdy(struct atmel_pmecc_user *user)
{}
EXPORT_SYMBOL_GPL();

static struct atmel_pmecc *atmel_pmecc_create(struct platform_device *pdev,
					const struct atmel_pmecc_caps *caps,
					int pmecc_res_idx, int errloc_res_idx)
{}

static void devm_atmel_pmecc_put(struct device *dev, void *res)
{}

static struct atmel_pmecc *atmel_pmecc_get_by_node(struct device *userdev,
						   struct device_node *np)
{}

static const int atmel_pmecc_strengths[] =;

static struct atmel_pmecc_caps at91sam9g45_caps =;

static struct atmel_pmecc_caps sama5d4_caps =;

static struct atmel_pmecc_caps sama5d2_caps =;

static const struct of_device_id __maybe_unused atmel_pmecc_legacy_match[] =;

struct atmel_pmecc *devm_atmel_pmecc_get(struct device *userdev)
{}
EXPORT_SYMBOL();

static const struct of_device_id atmel_pmecc_match[] =;
MODULE_DEVICE_TABLE(of, atmel_pmecc_match);

static int atmel_pmecc_probe(struct platform_device *pdev)
{}

static struct platform_driver atmel_pmecc_driver =;
module_platform_driver();

MODULE_LICENSE();
MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_ALIAS();