162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *	Copyright (c) 2001, 2003  Maciej W. Rozycki
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci *	DEC MS02-NV (54-20948-01) battery backed-up NVRAM module for
662306a36Sopenharmony_ci *	DECstation/DECsystem 5000/2x0 and DECsystem 5900 and 5900/260
762306a36Sopenharmony_ci *	systems.
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/ioport.h>
1162306a36Sopenharmony_ci#include <linux/mtd/mtd.h>
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci/*
1462306a36Sopenharmony_ci * Addresses are decoded as follows:
1562306a36Sopenharmony_ci *
1662306a36Sopenharmony_ci * 0x000000 - 0x3fffff	SRAM
1762306a36Sopenharmony_ci * 0x400000 - 0x7fffff	CSR
1862306a36Sopenharmony_ci *
1962306a36Sopenharmony_ci * Within the SRAM area the following ranges are forced by the system
2062306a36Sopenharmony_ci * firmware:
2162306a36Sopenharmony_ci *
2262306a36Sopenharmony_ci * 0x000000 - 0x0003ff	diagnostic area, destroyed upon a reboot
2362306a36Sopenharmony_ci * 0x000400 - ENDofRAM	storage area, available to operating systems
2462306a36Sopenharmony_ci *
2562306a36Sopenharmony_ci * but we can't really use the available area right from 0x000400 as
2662306a36Sopenharmony_ci * the first word is used by the firmware as a status flag passed
2762306a36Sopenharmony_ci * from an operating system.  If anything but the valid data magic
2862306a36Sopenharmony_ci * ID value is found, the firmware considers the SRAM clean, i.e.
2962306a36Sopenharmony_ci * containing no valid data, and disables the battery resulting in
3062306a36Sopenharmony_ci * data being erased as soon as power is switched off.  So the choice
3162306a36Sopenharmony_ci * for the start address of the user-available is 0x001000 which is
3262306a36Sopenharmony_ci * nicely page aligned.  The area between 0x000404 and 0x000fff may
3362306a36Sopenharmony_ci * be used by the driver for own needs.
3462306a36Sopenharmony_ci *
3562306a36Sopenharmony_ci * The diagnostic area defines two status words to be read by an
3662306a36Sopenharmony_ci * operating system, a magic ID to distinguish a MS02-NV board from
3762306a36Sopenharmony_ci * anything else and a status information providing results of tests
3862306a36Sopenharmony_ci * as well as the size of SRAM available, which can be 1MiB or 2MiB
3962306a36Sopenharmony_ci * (that's what the firmware handles; no idea if 2MiB modules ever
4062306a36Sopenharmony_ci * existed).
4162306a36Sopenharmony_ci *
4262306a36Sopenharmony_ci * The firmware only handles the MS02-NV board if installed in the
4362306a36Sopenharmony_ci * last (15th) slot, so for any other location the status information
4462306a36Sopenharmony_ci * stored in the SRAM cannot be relied upon.  But from the hardware
4562306a36Sopenharmony_ci * point of view there is no problem using up to 14 such boards in a
4662306a36Sopenharmony_ci * system -- only the 1st slot needs to be filled with a DRAM module.
4762306a36Sopenharmony_ci * The MS02-NV board is ECC-protected, like other MS02 memory boards.
4862306a36Sopenharmony_ci *
4962306a36Sopenharmony_ci * The state of the battery as provided by the CSR is reflected on
5062306a36Sopenharmony_ci * the two onboard LEDs.  When facing the battery side of the board,
5162306a36Sopenharmony_ci * with the LEDs at the top left and the battery at the bottom right
5262306a36Sopenharmony_ci * (i.e. looking from the back side of the system box), their meaning
5362306a36Sopenharmony_ci * is as follows (the system has to be powered on):
5462306a36Sopenharmony_ci *
5562306a36Sopenharmony_ci * left LED		battery disable status: lit = enabled
5662306a36Sopenharmony_ci * right LED		battery condition status: lit = OK
5762306a36Sopenharmony_ci */
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci/* MS02-NV iomem register offsets. */
6062306a36Sopenharmony_ci#define MS02NV_CSR		0x400000	/* control & status register */
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci/* MS02-NV CSR status bits. */
6362306a36Sopenharmony_ci#define MS02NV_CSR_BATT_OK	0x01		/* battery OK */
6462306a36Sopenharmony_ci#define MS02NV_CSR_BATT_OFF	0x02		/* battery disabled */
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci/* MS02-NV memory offsets. */
6862306a36Sopenharmony_ci#define MS02NV_DIAG		0x0003f8	/* diagnostic status */
6962306a36Sopenharmony_ci#define MS02NV_MAGIC		0x0003fc	/* MS02-NV magic ID */
7062306a36Sopenharmony_ci#define MS02NV_VALID		0x000400	/* valid data magic ID */
7162306a36Sopenharmony_ci#define MS02NV_RAM		0x001000	/* user-exposed RAM start */
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci/* MS02-NV diagnostic status bits. */
7462306a36Sopenharmony_ci#define MS02NV_DIAG_TEST	0x01		/* SRAM test done (?) */
7562306a36Sopenharmony_ci#define MS02NV_DIAG_RO		0x02		/* SRAM r/o test done */
7662306a36Sopenharmony_ci#define MS02NV_DIAG_RW		0x04		/* SRAM r/w test done */
7762306a36Sopenharmony_ci#define MS02NV_DIAG_FAIL	0x08		/* SRAM test failed */
7862306a36Sopenharmony_ci#define MS02NV_DIAG_SIZE_MASK	0xf0		/* SRAM size mask */
7962306a36Sopenharmony_ci#define MS02NV_DIAG_SIZE_SHIFT	0x10		/* SRAM size shift (left) */
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci/* MS02-NV general constants. */
8262306a36Sopenharmony_ci#define MS02NV_ID		0x03021966	/* MS02-NV magic ID value */
8362306a36Sopenharmony_ci#define MS02NV_VALID_ID		0xbd100248	/* valid data magic ID value */
8462306a36Sopenharmony_ci#define MS02NV_SLOT_SIZE	0x800000	/* size of the address space
8562306a36Sopenharmony_ci						   decoded by the module */
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_citypedef volatile u32 ms02nv_uint;
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_cistruct ms02nv_private {
9162306a36Sopenharmony_ci	struct mtd_info *next;
9262306a36Sopenharmony_ci	struct {
9362306a36Sopenharmony_ci		struct resource *module;
9462306a36Sopenharmony_ci		struct resource *diag_ram;
9562306a36Sopenharmony_ci		struct resource *user_ram;
9662306a36Sopenharmony_ci		struct resource *csr;
9762306a36Sopenharmony_ci	} resource;
9862306a36Sopenharmony_ci	u_char *addr;
9962306a36Sopenharmony_ci	size_t size;
10062306a36Sopenharmony_ci	u_char *uaddr;
10162306a36Sopenharmony_ci};
102