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