| /* SPDX-License-Identifier: GPL-2.0 */ | |
| #ifndef _LINUX_NVRAM_H | |
| #define _LINUX_NVRAM_H | |
| #include <linux/errno.h> | |
| #include <uapi/linux/nvram.h> | |
| #ifdef CONFIG_PPC | |
| #include <asm/machdep.h> | |
| #endif | |
| /** | |
| * 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 *); | |
| #if defined(CONFIG_X86) || defined(CONFIG_M68K) | |
| long (*initialize)(void); | |
| long (*set_checksum)(void); | |
| #endif | |
| }; | |
| extern const struct nvram_ops arch_nvram_ops; | |
| static inline ssize_t nvram_get_size(void) | |
| { | |
| #ifdef CONFIG_PPC | |
| if (ppc_md.nvram_size) | |
| return ppc_md.nvram_size(); | |
| #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 | |
| if (ppc_md.nvram_read_val) | |
| return ppc_md.nvram_read_val(addr); | |
| #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 | |
| if (ppc_md.nvram_write_val) | |
| ppc_md.nvram_write_val(addr, val); | |
| #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) | |
| { | |
| #ifdef CONFIG_PPC | |
| if (ppc_md.nvram_read) | |
| return ppc_md.nvram_read(buf, count, ppos); | |
| #else | |
| if (arch_nvram_ops.read) | |
| return arch_nvram_ops.read(buf, count, ppos); | |
| #endif | |
| return nvram_read_bytes(buf, count, ppos); | |
| } | |
| static inline ssize_t nvram_write(char *buf, size_t count, loff_t *ppos) | |
| { | |
| #ifdef CONFIG_PPC | |
| if (ppc_md.nvram_write) | |
| return ppc_md.nvram_write(buf, count, ppos); | |
| #else | |
| if (arch_nvram_ops.write) | |
| return arch_nvram_ops.write(buf, count, ppos); | |
| #endif | |
| return nvram_write_bytes(buf, count, ppos); | |
| } | |
| #endif /* _LINUX_NVRAM_H */ |