
Refactor the RTC "CMOS" NVRAM functions so that they can be used as arch_nvram_ops methods. Checksumming logic is moved from the misc device operations to the nvram read/write operations. This makes the misc device implementation more generic. This preserves the locking mechanism such that "read if checksum valid" and "write and update checksum" remain atomic operations. Some platforms implement byte-range read/write methods which are similar to file_operations struct methods. Other platforms provide only byte-at-a-time methods. The former are more efficient but may be unavailable so fall back on the latter methods when necessary. Tested-by: Stan Johnson <userm57@yahoo.com> Signed-off-by: Finn Thain <fthain@telegraphics.com.au> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
112 lines
3.0 KiB
C
112 lines
3.0 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef _LINUX_NVRAM_H
|
|
#define _LINUX_NVRAM_H
|
|
|
|
#include <linux/errno.h>
|
|
#include <uapi/linux/nvram.h>
|
|
|
|
/**
|
|
* struct nvram_ops - NVRAM functionality made available to drivers
|
|
* @read: validate checksum (if any) then load a range of bytes from NVRAM
|
|
* @write: store a range of bytes to NVRAM then update checksum (if any)
|
|
* @read_byte: load a single byte from NVRAM
|
|
* @write_byte: store a single byte to NVRAM
|
|
* @get_size: return the fixed number of bytes in the NVRAM
|
|
*
|
|
* Architectures which provide an nvram ops struct need not implement all
|
|
* of these methods. If the NVRAM hardware can be accessed only one byte
|
|
* at a time then it may be sufficient to provide .read_byte and .write_byte.
|
|
* If the NVRAM has a checksum (and it is to be checked) the .read and
|
|
* .write methods can be used to implement that efficiently.
|
|
*
|
|
* Portable drivers may use the wrapper functions defined here.
|
|
* The nvram_read() and nvram_write() functions call the .read and .write
|
|
* methods when available and fall back on the .read_byte and .write_byte
|
|
* methods otherwise.
|
|
*/
|
|
|
|
struct nvram_ops {
|
|
ssize_t (*get_size)(void);
|
|
unsigned char (*read_byte)(int);
|
|
void (*write_byte)(unsigned char, int);
|
|
ssize_t (*read)(char *, size_t, loff_t *);
|
|
ssize_t (*write)(char *, size_t, loff_t *);
|
|
long (*initialize)(void);
|
|
long (*set_checksum)(void);
|
|
};
|
|
|
|
extern const struct nvram_ops arch_nvram_ops;
|
|
|
|
static inline ssize_t nvram_get_size(void)
|
|
{
|
|
#ifdef CONFIG_PPC
|
|
#else
|
|
if (arch_nvram_ops.get_size)
|
|
return arch_nvram_ops.get_size();
|
|
#endif
|
|
return -ENODEV;
|
|
}
|
|
|
|
static inline unsigned char nvram_read_byte(int addr)
|
|
{
|
|
#ifdef CONFIG_PPC
|
|
#else
|
|
if (arch_nvram_ops.read_byte)
|
|
return arch_nvram_ops.read_byte(addr);
|
|
#endif
|
|
return 0xFF;
|
|
}
|
|
|
|
static inline void nvram_write_byte(unsigned char val, int addr)
|
|
{
|
|
#ifdef CONFIG_PPC
|
|
#else
|
|
if (arch_nvram_ops.write_byte)
|
|
arch_nvram_ops.write_byte(val, addr);
|
|
#endif
|
|
}
|
|
|
|
static inline ssize_t nvram_read_bytes(char *buf, size_t count, loff_t *ppos)
|
|
{
|
|
ssize_t nvram_size = nvram_get_size();
|
|
loff_t i;
|
|
char *p = buf;
|
|
|
|
if (nvram_size < 0)
|
|
return nvram_size;
|
|
for (i = *ppos; count > 0 && i < nvram_size; ++i, ++p, --count)
|
|
*p = nvram_read_byte(i);
|
|
*ppos = i;
|
|
return p - buf;
|
|
}
|
|
|
|
static inline ssize_t nvram_write_bytes(char *buf, size_t count, loff_t *ppos)
|
|
{
|
|
ssize_t nvram_size = nvram_get_size();
|
|
loff_t i;
|
|
char *p = buf;
|
|
|
|
if (nvram_size < 0)
|
|
return nvram_size;
|
|
for (i = *ppos; count > 0 && i < nvram_size; ++i, ++p, --count)
|
|
nvram_write_byte(*p, i);
|
|
*ppos = i;
|
|
return p - buf;
|
|
}
|
|
|
|
static inline ssize_t nvram_read(char *buf, size_t count, loff_t *ppos)
|
|
{
|
|
if (arch_nvram_ops.read)
|
|
return arch_nvram_ops.read(buf, count, ppos);
|
|
return nvram_read_bytes(buf, count, ppos);
|
|
}
|
|
|
|
static inline ssize_t nvram_write(char *buf, size_t count, loff_t *ppos)
|
|
{
|
|
if (arch_nvram_ops.write)
|
|
return arch_nvram_ops.write(buf, count, ppos);
|
|
return nvram_write_bytes(buf, count, ppos);
|
|
}
|
|
|
|
#endif /* _LINUX_NVRAM_H */
|