linux/drivers/mtd/chips/cfi_cmdset_0002.c

// SPDX-License-Identifier: GPL-2.0
/*
 * Common Flash Interface support:
 *   AMD & Fujitsu Standard Vendor Command Set (ID 0x0002)
 *
 * Copyright (C) 2000 Crossnet Co. <[email protected]>
 * Copyright (C) 2004 Arcom Control Systems Ltd <[email protected]>
 * Copyright (C) 2005 MontaVista Software Inc. <[email protected]>
 *
 * 2_by_8 routines added by Simon Munton
 *
 * 4_by_16 work by Carolyn J. Smith
 *
 * XIP support hooks by Vitaly Wool (based on code for Intel flash
 * by Nicolas Pitre)
 *
 * 25/09/2008 Christopher Moore: TopBottom fixup for many Macronix with CFI V1.0
 *
 * Occasionally maintained by Thayne Harbaugh tharbaugh at lnxi dot com
 */

#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <asm/io.h>
#include <asm/byteorder.h>

#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/reboot.h>
#include <linux/of.h>
#include <linux/mtd/map.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/cfi.h>
#include <linux/mtd/xip.h>

#define AMD_BOOTLOC_BUG
#define FORCE_WORD_WRITE

#define MAX_RETRIES

#define SST49LF004B
#define SST49LF040B
#define SST49LF008A
#define AT49BV6416
#define S29GL064N_MN12

/*
 * Status Register bit description. Used by flash devices that don't
 * support DQ polling (e.g. HyperFlash)
 */
#define CFI_SR_DRB
#define CFI_SR_ESB
#define CFI_SR_PSB
#define CFI_SR_WBASB
#define CFI_SR_SLSB

enum cfi_quirks {};

static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
#if !FORCE_WORD_WRITE
static int cfi_amdstd_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
#endif
static int cfi_amdstd_erase_chip(struct mtd_info *, struct erase_info *);
static int cfi_amdstd_erase_varsize(struct mtd_info *, struct erase_info *);
static void cfi_amdstd_sync (struct mtd_info *);
static int cfi_amdstd_suspend (struct mtd_info *);
static void cfi_amdstd_resume (struct mtd_info *);
static int cfi_amdstd_reboot(struct notifier_block *, unsigned long, void *);
static int cfi_amdstd_get_fact_prot_info(struct mtd_info *, size_t,
					 size_t *, struct otp_info *);
static int cfi_amdstd_get_user_prot_info(struct mtd_info *, size_t,
					 size_t *, struct otp_info *);
static int cfi_amdstd_secsi_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
static int cfi_amdstd_read_fact_prot_reg(struct mtd_info *, loff_t, size_t,
					 size_t *, u_char *);
static int cfi_amdstd_read_user_prot_reg(struct mtd_info *, loff_t, size_t,
					 size_t *, u_char *);
static int cfi_amdstd_write_user_prot_reg(struct mtd_info *, loff_t, size_t,
					  size_t *, const u_char *);
static int cfi_amdstd_lock_user_prot_reg(struct mtd_info *, loff_t, size_t);

static int cfi_amdstd_panic_write(struct mtd_info *mtd, loff_t to, size_t len,
				  size_t *retlen, const u_char *buf);

static void cfi_amdstd_destroy(struct mtd_info *);

struct mtd_info *cfi_cmdset_0002(struct map_info *, int);
static struct mtd_info *cfi_amdstd_setup (struct mtd_info *);

static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode);
static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr);
#include "fwh_lock.h"

static int cfi_atmel_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
static int cfi_atmel_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);

static int cfi_ppb_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
static int cfi_ppb_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
static int cfi_ppb_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len);

static struct mtd_chip_driver cfi_amdstd_chipdrv =;

/*
 * Use status register to poll for Erase/write completion when DQ is not
 * supported. This is indicated by Bit[1:0] of SoftwareFeatures field in
 * CFI Primary Vendor-Specific Extended Query table 1.5
 */
static int cfi_use_status_reg(struct cfi_private *cfi)
{}

static int cfi_check_err_status(struct map_info *map, struct flchip *chip,
				unsigned long adr)
{}

/* #define DEBUG_CFI_FEATURES */


#ifdef DEBUG_CFI_FEATURES
static void cfi_tell_features(struct cfi_pri_amdstd *extp)
{
	const char* erase_suspend[3] = {
		"Not supported", "Read only", "Read/write"
	};
	const char* top_bottom[6] = {
		"No WP", "8x8KiB sectors at top & bottom, no WP",
		"Bottom boot", "Top boot",
		"Uniform, Bottom WP", "Uniform, Top WP"
	};

	printk("  Silicon revision: %d\n", extp->SiliconRevision >> 1);
	printk("  Address sensitive unlock: %s\n",
	       (extp->SiliconRevision & 1) ? "Not required" : "Required");

	if (extp->EraseSuspend < ARRAY_SIZE(erase_suspend))
		printk("  Erase Suspend: %s\n", erase_suspend[extp->EraseSuspend]);
	else
		printk("  Erase Suspend: Unknown value %d\n", extp->EraseSuspend);

	if (extp->BlkProt == 0)
		printk("  Block protection: Not supported\n");
	else
		printk("  Block protection: %d sectors per group\n", extp->BlkProt);


	printk("  Temporary block unprotect: %s\n",
	       extp->TmpBlkUnprotect ? "Supported" : "Not supported");
	printk("  Block protect/unprotect scheme: %d\n", extp->BlkProtUnprot);
	printk("  Number of simultaneous operations: %d\n", extp->SimultaneousOps);
	printk("  Burst mode: %s\n",
	       extp->BurstMode ? "Supported" : "Not supported");
	if (extp->PageMode == 0)
		printk("  Page mode: Not supported\n");
	else
		printk("  Page mode: %d word page\n", extp->PageMode << 2);

	printk("  Vpp Supply Minimum Program/Erase Voltage: %d.%d V\n",
	       extp->VppMin >> 4, extp->VppMin & 0xf);
	printk("  Vpp Supply Maximum Program/Erase Voltage: %d.%d V\n",
	       extp->VppMax >> 4, extp->VppMax & 0xf);

	if (extp->TopBottom < ARRAY_SIZE(top_bottom))
		printk("  Top/Bottom Boot Block: %s\n", top_bottom[extp->TopBottom]);
	else
		printk("  Top/Bottom Boot Block: Unknown value %d\n", extp->TopBottom);
}
#endif

#ifdef AMD_BOOTLOC_BUG
/* Wheee. Bring me the head of someone at AMD. */
static void fixup_amd_bootblock(struct mtd_info *mtd)
{}
#endif

#if !FORCE_WORD_WRITE
static void fixup_use_write_buffers(struct mtd_info *mtd)
{}
#endif /* !FORCE_WORD_WRITE */

/* Atmel chips don't use the same PRI format as AMD chips */
static void fixup_convert_atmel_pri(struct mtd_info *mtd)
{}

static void fixup_use_secsi(struct mtd_info *mtd)
{}

static void fixup_use_erase_chip(struct mtd_info *mtd)
{}

/*
 * Some Atmel chips (e.g. the AT49BV6416) power-up with all sectors
 * locked by default.
 */
static void fixup_use_atmel_lock(struct mtd_info *mtd)
{}

static void fixup_old_sst_eraseregion(struct mtd_info *mtd)
{}

static void fixup_sst39vf(struct mtd_info *mtd)
{}

static void fixup_sst39vf_rev_b(struct mtd_info *mtd)
{}

static void fixup_sst38vf640x_sectorsize(struct mtd_info *mtd)
{}

static void fixup_s29gl064n_sectors(struct mtd_info *mtd)
{}

static void fixup_s29gl032n_sectors(struct mtd_info *mtd)
{}

static void fixup_s29ns512p_sectors(struct mtd_info *mtd)
{}

static void fixup_quirks(struct mtd_info *mtd)
{}

/* Used to fix CFI-Tables of chips without Extended Query Tables */
static struct cfi_fixup cfi_nopri_fixup_table[] =;

static struct cfi_fixup cfi_fixup_table[] =;
static struct cfi_fixup jedec_fixup_table[] =;

static struct cfi_fixup fixup_table[] =;


static void cfi_fixup_major_minor(struct cfi_private *cfi,
				  struct cfi_pri_amdstd *extp)
{}

static int is_m29ew(struct cfi_private *cfi)
{}

/*
 * From TN-13-07: Patching the Linux Kernel and U-Boot for M29 Flash, page 20:
 * Some revisions of the M29EW suffer from erase suspend hang ups. In
 * particular, it can occur when the sequence
 * Erase Confirm -> Suspend -> Program -> Resume
 * causes a lockup due to internal timing issues. The consequence is that the
 * erase cannot be resumed without inserting a dummy command after programming
 * and prior to resuming. [...] The work-around is to issue a dummy write cycle
 * that writes an F0 command code before the RESUME command.
 */
static void cfi_fixup_m29ew_erase_suspend(struct map_info *map,
					  unsigned long adr)
{}

/*
 * From TN-13-07: Patching the Linux Kernel and U-Boot for M29 Flash, page 22:
 *
 * Some revisions of the M29EW (for example, A1 and A2 step revisions)
 * are affected by a problem that could cause a hang up when an ERASE SUSPEND
 * command is issued after an ERASE RESUME operation without waiting for a
 * minimum delay.  The result is that once the ERASE seems to be completed
 * (no bits are toggling), the contents of the Flash memory block on which
 * the erase was ongoing could be inconsistent with the expected values
 * (typically, the array value is stuck to the 0xC0, 0xC4, 0x80, or 0x84
 * values), causing a consequent failure of the ERASE operation.
 * The occurrence of this issue could be high, especially when file system
 * operations on the Flash are intensive.  As a result, it is recommended
 * that a patch be applied.  Intensive file system operations can cause many
 * calls to the garbage routine to free Flash space (also by erasing physical
 * Flash blocks) and as a result, many consecutive SUSPEND and RESUME
 * commands can occur.  The problem disappears when a delay is inserted after
 * the RESUME command by using the udelay() function available in Linux.
 * The DELAY value must be tuned based on the customer's platform.
 * The maximum value that fixes the problem in all cases is 500us.
 * But, in our experience, a delay of 30 µs to 50 µs is sufficient
 * in most cases.
 * We have chosen 500µs because this latency is acceptable.
 */
static void cfi_fixup_m29ew_delay_after_resume(struct cfi_private *cfi)
{}

struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
{}
struct mtd_info *cfi_cmdset_0006(struct map_info *map, int primary) __attribute__((alias("cfi_cmdset_0002")));
struct mtd_info *cfi_cmdset_0701(struct map_info *map, int primary) __attribute__((alias("cfi_cmdset_0002")));
EXPORT_SYMBOL_GPL();
EXPORT_SYMBOL_GPL();
EXPORT_SYMBOL_GPL();

static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd)
{}

/*
 * Return true if the chip is ready and has the correct value.
 *
 * Ready is one of: read mode, query mode, erase-suspend-read mode (in any
 * non-suspended sector) and is indicated by no toggle bits toggling.
 *
 * Error are indicated by toggling bits or bits held with the wrong value,
 * or with bits toggling.
 *
 * Note that anything more complicated than checking if no bits are toggling
 * (including checking DQ5 for an error status) is tricky to get working
 * correctly and is therefore not done	(particularly with interleaved chips
 * as each chip must be checked independently of the others).
 */
static int __xipram chip_ready(struct map_info *map, struct flchip *chip,
			       unsigned long addr, map_word *expected)
{}

static int __xipram chip_good(struct map_info *map, struct flchip *chip,
			      unsigned long addr, map_word *expected)
{}

static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode)
{}


static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr)
{}

#ifdef CONFIG_MTD_XIP

/*
 * No interrupt what so ever can be serviced while the flash isn't in array
 * mode.  This is ensured by the xip_disable() and xip_enable() functions
 * enclosing any code path where the flash is known not to be in array mode.
 * And within a XIP disabled code path, only functions marked with __xipram
 * may be called and nothing else (it's a good thing to inspect generated
 * assembly to make sure inline functions were actually inlined and that gcc
 * didn't emit calls to its own support functions). Also configuring MTD CFI
 * support to a single buswidth and a single interleave is also recommended.
 */

static void xip_disable(struct map_info *map, struct flchip *chip,
			unsigned long adr)
{
	/* TODO: chips with no XIP use should ignore and return */
	(void) map_read(map, adr); /* ensure mmu mapping is up to date */
	local_irq_disable();
}

static void __xipram xip_enable(struct map_info *map, struct flchip *chip,
				unsigned long adr)
{
	struct cfi_private *cfi = map->fldrv_priv;

	if (chip->state != FL_POINT && chip->state != FL_READY) {
		map_write(map, CMD(0xf0), adr);
		chip->state = FL_READY;
	}
	(void) map_read(map, adr);
	xip_iprefetch();
	local_irq_enable();
}

/*
 * When a delay is required for the flash operation to complete, the
 * xip_udelay() function is polling for both the given timeout and pending
 * (but still masked) hardware interrupts.  Whenever there is an interrupt
 * pending then the flash erase operation is suspended, array mode restored
 * and interrupts unmasked.  Task scheduling might also happen at that
 * point.  The CPU eventually returns from the interrupt or the call to
 * schedule() and the suspended flash operation is resumed for the remaining
 * of the delay period.
 *
 * Warning: this function _will_ fool interrupt latency tracing tools.
 */

static void __xipram xip_udelay(struct map_info *map, struct flchip *chip,
				unsigned long adr, int usec)
{
	struct cfi_private *cfi = map->fldrv_priv;
	struct cfi_pri_amdstd *extp = cfi->cmdset_priv;
	map_word status, OK = CMD(0x80);
	unsigned long suspended, start = xip_currtime();
	flstate_t oldstate;

	do {
		cpu_relax();
		if (xip_irqpending() && extp &&
		    ((chip->state == FL_ERASING && (extp->EraseSuspend & 2))) &&
		    (cfi_interleave_is_1(cfi) || chip->oldstate == FL_READY)) {
			/*
			 * Let's suspend the erase operation when supported.
			 * Note that we currently don't try to suspend
			 * interleaved chips if there is already another
			 * operation suspended (imagine what happens
			 * when one chip was already done with the current
			 * operation while another chip suspended it, then
			 * we resume the whole thing at once).  Yes, it
			 * can happen!
			 */
			map_write(map, CMD(0xb0), adr);
			usec -= xip_elapsed_since(start);
			suspended = xip_currtime();
			do {
				if (xip_elapsed_since(suspended) > 100000) {
					/*
					 * The chip doesn't want to suspend
					 * after waiting for 100 msecs.
					 * This is a critical error but there
					 * is not much we can do here.
					 */
					return;
				}
				status = map_read(map, adr);
			} while (!map_word_andequal(map, status, OK, OK));

			/* Suspend succeeded */
			oldstate = chip->state;
			if (!map_word_bitsset(map, status, CMD(0x40)))
				break;
			chip->state = FL_XIP_WHILE_ERASING;
			chip->erase_suspended = 1;
			map_write(map, CMD(0xf0), adr);
			(void) map_read(map, adr);
			xip_iprefetch();
			local_irq_enable();
			mutex_unlock(&chip->mutex);
			xip_iprefetch();
			cond_resched();

			/*
			 * We're back.  However someone else might have
			 * decided to go write to the chip if we are in
			 * a suspended erase state.  If so let's wait
			 * until it's done.
			 */
			mutex_lock(&chip->mutex);
			while (chip->state != FL_XIP_WHILE_ERASING) {
				DECLARE_WAITQUEUE(wait, current);
				set_current_state(TASK_UNINTERRUPTIBLE);
				add_wait_queue(&chip->wq, &wait);
				mutex_unlock(&chip->mutex);
				schedule();
				remove_wait_queue(&chip->wq, &wait);
				mutex_lock(&chip->mutex);
			}
			/* Disallow XIP again */
			local_irq_disable();

			/* Correct Erase Suspend Hangups for M29EW */
			cfi_fixup_m29ew_erase_suspend(map, adr);
			/* Resume the write or erase operation */
			map_write(map, cfi->sector_erase_cmd, adr);
			chip->state = oldstate;
			start = xip_currtime();
		} else if (usec >= 1000000/HZ) {
			/*
			 * Try to save on CPU power when waiting delay
			 * is at least a system timer tick period.
			 * No need to be extremely accurate here.
			 */
			xip_cpu_idle();
		}
		status = map_read(map, adr);
	} while (!map_word_andequal(map, status, OK, OK)
		 && xip_elapsed_since(start) < usec);
}

#define UDELAY

/*
 * The INVALIDATE_CACHED_RANGE() macro is normally used in parallel while
 * the flash is actively programming or erasing since we have to poll for
 * the operation to complete anyway.  We can't do that in a generic way with
 * a XIP setup so do it before the actual flash operation in this case
 * and stub it out from INVALIDATE_CACHE_UDELAY.
 */
#define XIP_INVAL_CACHED_RANGE

#define INVALIDATE_CACHE_UDELAY

/*
 * Extra notes:
 *
 * Activating this XIP support changes the way the code works a bit.  For
 * example the code to suspend the current process when concurrent access
 * happens is never executed because xip_udelay() will always return with the
 * same chip state as it was entered with.  This is why there is no care for
 * the presence of add_wait_queue() or schedule() calls from within a couple
 * xip_disable()'d  areas of code, like in do_erase_oneblock for example.
 * The queueing and scheduling are always happening within xip_udelay().
 *
 * Similarly, get_chip() and put_chip() just happen to always be executed
 * with chip->state set to FL_READY (or FL_XIP_WHILE_*) where flash state
 * is in array mode, therefore never executing many cases therein and not
 * causing any problem with XIP.
 */

#else

#define xip_disable(map, chip, adr)
#define xip_enable(map, chip, adr)
#define XIP_INVAL_CACHED_RANGE(x...)

#define UDELAY(map, chip, adr, usec)

#define INVALIDATE_CACHE_UDELAY(map, chip, adr, len, usec)

#endif

static inline int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf)
{}


static int cfi_amdstd_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
{}

otp_op_t;

static inline void otp_enter(struct map_info *map, struct flchip *chip,
			     loff_t adr, size_t len)
{}

static inline void otp_exit(struct map_info *map, struct flchip *chip,
			    loff_t adr, size_t len)
{}

static inline int do_read_secsi_onechip(struct map_info *map,
					struct flchip *chip, loff_t adr,
					size_t len, u_char *buf,
					size_t grouplen)
{}

static int cfi_amdstd_secsi_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
{}

static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
				     unsigned long adr, map_word datum,
				     int mode);

static int do_otp_write(struct map_info *map, struct flchip *chip, loff_t adr,
			size_t len, u_char *buf, size_t grouplen)
{}

static int do_otp_lock(struct map_info *map, struct flchip *chip, loff_t adr,
		       size_t len, u_char *buf, size_t grouplen)
{}

static int cfi_amdstd_otp_walk(struct mtd_info *mtd, loff_t from, size_t len,
			       size_t *retlen, u_char *buf,
			       otp_op_t action, int user_regs)
{}

static int cfi_amdstd_get_fact_prot_info(struct mtd_info *mtd, size_t len,
					 size_t *retlen, struct otp_info *buf)
{}

static int cfi_amdstd_get_user_prot_info(struct mtd_info *mtd, size_t len,
					 size_t *retlen, struct otp_info *buf)
{}

static int cfi_amdstd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from,
					 size_t len, size_t *retlen,
					 u_char *buf)
{}

static int cfi_amdstd_read_user_prot_reg(struct mtd_info *mtd, loff_t from,
					 size_t len, size_t *retlen,
					 u_char *buf)
{}

static int cfi_amdstd_write_user_prot_reg(struct mtd_info *mtd, loff_t from,
					  size_t len, size_t *retlen,
					  const u_char *buf)
{}

static int cfi_amdstd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from,
					 size_t len)
{}

static int __xipram do_write_oneword_once(struct map_info *map,
					  struct flchip *chip,
					  unsigned long adr, map_word datum,
					  int mode, struct cfi_private *cfi)
{}

static int __xipram do_write_oneword_start(struct map_info *map,
					   struct flchip *chip,
					   unsigned long adr, int mode)
{}

static void __xipram do_write_oneword_done(struct map_info *map,
					   struct flchip *chip,
					   unsigned long adr, int mode)
{}

static int __xipram do_write_oneword_retry(struct map_info *map,
					   struct flchip *chip,
					   unsigned long adr, map_word datum,
					   int mode)
{}

static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
				     unsigned long adr, map_word datum,
				     int mode)
{}


static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len,
				  size_t *retlen, const u_char *buf)
{}

#if !FORCE_WORD_WRITE
static int __xipram do_write_buffer_wait(struct map_info *map,
					 struct flchip *chip, unsigned long adr,
					 map_word datum)
{}

static void __xipram do_write_buffer_reset(struct map_info *map,
					   struct flchip *chip,
					   struct cfi_private *cfi)
{}

/*
 * FIXME: interleaved mode not tested, and probably not supported!
 */
static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
				    unsigned long adr, const u_char *buf,
				    int len)
{}


static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len,
				    size_t *retlen, const u_char *buf)
{}
#endif /* !FORCE_WORD_WRITE */

/*
 * Wait for the flash chip to become ready to write data
 *
 * This is only called during the panic_write() path. When panic_write()
 * is called, the kernel is in the process of a panic, and will soon be
 * dead. Therefore we don't take any locks, and attempt to get access
 * to the chip as soon as possible.
 */
static int cfi_amdstd_panic_wait(struct map_info *map, struct flchip *chip,
				 unsigned long adr)
{}

/*
 * Write out one word of data to a single flash chip during a kernel panic
 *
 * This is only called during the panic_write() path. When panic_write()
 * is called, the kernel is in the process of a panic, and will soon be
 * dead. Therefore we don't take any locks, and attempt to get access
 * to the chip as soon as possible.
 *
 * The implementation of this routine is intentionally similar to
 * do_write_oneword(), in order to ease code maintenance.
 */
static int do_panic_write_oneword(struct map_info *map, struct flchip *chip,
				  unsigned long adr, map_word datum)
{}

/*
 * Write out some data during a kernel panic
 *
 * This is used by the mtdoops driver to save the dying messages from a
 * kernel which has panic'd.
 *
 * This routine ignores all of the locking used throughout the rest of the
 * driver, in order to ensure that the data gets written out no matter what
 * state this driver (and the flash chip itself) was in when the kernel crashed.
 *
 * The implementation of this routine is intentionally similar to
 * cfi_amdstd_write_words(), in order to ease code maintenance.
 */
static int cfi_amdstd_panic_write(struct mtd_info *mtd, loff_t to, size_t len,
				  size_t *retlen, const u_char *buf)
{}


/*
 * Handle devices with one erase region, that only implement
 * the chip erase command.
 */
static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip)
{}


static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr, int len, void *thunk)
{}


static int cfi_amdstd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
{}


static int cfi_amdstd_erase_chip(struct mtd_info *mtd, struct erase_info *instr)
{}

static int do_atmel_lock(struct map_info *map, struct flchip *chip,
			 unsigned long adr, int len, void *thunk)
{}

static int do_atmel_unlock(struct map_info *map, struct flchip *chip,
			   unsigned long adr, int len, void *thunk)
{}

static int cfi_atmel_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
{}

static int cfi_atmel_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
{}

/*
 * Advanced Sector Protection - PPB (Persistent Protection Bit) locking
 */

struct ppb_lock {};

#define DO_XXLOCK_ONEBLOCK_LOCK
#define DO_XXLOCK_ONEBLOCK_UNLOCK
#define DO_XXLOCK_ONEBLOCK_GETLOCK

static int __maybe_unused do_ppb_xxlock(struct map_info *map,
					struct flchip *chip,
					unsigned long adr, int len, void *thunk)
{}

static int __maybe_unused cfi_ppb_lock(struct mtd_info *mtd, loff_t ofs,
				       uint64_t len)
{}

static int __maybe_unused cfi_ppb_unlock(struct mtd_info *mtd, loff_t ofs,
					 uint64_t len)
{}

static int __maybe_unused cfi_ppb_is_locked(struct mtd_info *mtd, loff_t ofs,
					    uint64_t len)
{}

static void cfi_amdstd_sync (struct mtd_info *mtd)
{}


static int cfi_amdstd_suspend(struct mtd_info *mtd)
{}


static void cfi_amdstd_resume(struct mtd_info *mtd)
{}


/*
 * Ensure that the flash device is put back into read array mode before
 * unloading the driver or rebooting.  On some systems, rebooting while
 * the flash is in query/program/erase mode will prevent the CPU from
 * fetching the bootloader code, requiring a hard reset or power cycle.
 */
static int cfi_amdstd_reset(struct mtd_info *mtd)
{}


static int cfi_amdstd_reboot(struct notifier_block *nb, unsigned long val,
			       void *v)
{}


static void cfi_amdstd_destroy(struct mtd_info *mtd)
{}

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