134 lines · c
1/* SPDX-License-Identifier: GPL-2.0 */2#ifndef _LINUX_NVRAM_H3#define _LINUX_NVRAM_H4 5#include <linux/errno.h>6#include <uapi/linux/nvram.h>7 8#ifdef CONFIG_PPC9#include <asm/machdep.h>10#endif11 12/**13 * struct nvram_ops - NVRAM functionality made available to drivers14 * @read: validate checksum (if any) then load a range of bytes from NVRAM15 * @write: store a range of bytes to NVRAM then update checksum (if any)16 * @read_byte: load a single byte from NVRAM17 * @write_byte: store a single byte to NVRAM18 * @get_size: return the fixed number of bytes in the NVRAM19 *20 * Architectures which provide an nvram ops struct need not implement all21 * of these methods. If the NVRAM hardware can be accessed only one byte22 * at a time then it may be sufficient to provide .read_byte and .write_byte.23 * If the NVRAM has a checksum (and it is to be checked) the .read and24 * .write methods can be used to implement that efficiently.25 *26 * Portable drivers may use the wrapper functions defined here.27 * The nvram_read() and nvram_write() functions call the .read and .write28 * methods when available and fall back on the .read_byte and .write_byte29 * methods otherwise.30 */31 32struct nvram_ops {33 ssize_t (*get_size)(void);34 unsigned char (*read_byte)(int);35 void (*write_byte)(unsigned char, int);36 ssize_t (*read)(char *, size_t, loff_t *);37 ssize_t (*write)(char *, size_t, loff_t *);38#if defined(CONFIG_X86) || defined(CONFIG_M68K)39 long (*initialize)(void);40 long (*set_checksum)(void);41#endif42};43 44extern const struct nvram_ops arch_nvram_ops;45 46static inline ssize_t nvram_get_size(void)47{48#ifdef CONFIG_PPC49 if (ppc_md.nvram_size)50 return ppc_md.nvram_size();51#else52 if (arch_nvram_ops.get_size)53 return arch_nvram_ops.get_size();54#endif55 return -ENODEV;56}57 58static inline unsigned char nvram_read_byte(int addr)59{60#ifdef CONFIG_PPC61 if (ppc_md.nvram_read_val)62 return ppc_md.nvram_read_val(addr);63#else64 if (arch_nvram_ops.read_byte)65 return arch_nvram_ops.read_byte(addr);66#endif67 return 0xFF;68}69 70static inline void nvram_write_byte(unsigned char val, int addr)71{72#ifdef CONFIG_PPC73 if (ppc_md.nvram_write_val)74 ppc_md.nvram_write_val(addr, val);75#else76 if (arch_nvram_ops.write_byte)77 arch_nvram_ops.write_byte(val, addr);78#endif79}80 81static inline ssize_t nvram_read_bytes(char *buf, size_t count, loff_t *ppos)82{83 ssize_t nvram_size = nvram_get_size();84 loff_t i;85 char *p = buf;86 87 if (nvram_size < 0)88 return nvram_size;89 for (i = *ppos; count > 0 && i < nvram_size; ++i, ++p, --count)90 *p = nvram_read_byte(i);91 *ppos = i;92 return p - buf;93}94 95static inline ssize_t nvram_write_bytes(char *buf, size_t count, loff_t *ppos)96{97 ssize_t nvram_size = nvram_get_size();98 loff_t i;99 char *p = buf;100 101 if (nvram_size < 0)102 return nvram_size;103 for (i = *ppos; count > 0 && i < nvram_size; ++i, ++p, --count)104 nvram_write_byte(*p, i);105 *ppos = i;106 return p - buf;107}108 109static inline ssize_t nvram_read(char *buf, size_t count, loff_t *ppos)110{111#ifdef CONFIG_PPC112 if (ppc_md.nvram_read)113 return ppc_md.nvram_read(buf, count, ppos);114#else115 if (arch_nvram_ops.read)116 return arch_nvram_ops.read(buf, count, ppos);117#endif118 return nvram_read_bytes(buf, count, ppos);119}120 121static inline ssize_t nvram_write(char *buf, size_t count, loff_t *ppos)122{123#ifdef CONFIG_PPC124 if (ppc_md.nvram_write)125 return ppc_md.nvram_write(buf, count, ppos);126#else127 if (arch_nvram_ops.write)128 return arch_nvram_ops.write(buf, count, ppos);129#endif130 return nvram_write_bytes(buf, count, ppos);131}132 133#endif /* _LINUX_NVRAM_H */134