1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
21da177e4SLinus Torvalds #ifndef _LINUX_NVRAM_H
31da177e4SLinus Torvalds #define _LINUX_NVRAM_H
41da177e4SLinus Torvalds
51278cf66SFinn Thain #include <linux/errno.h>
6607ca46eSDavid Howells #include <uapi/linux/nvram.h>
71da177e4SLinus Torvalds
8f9c3a570SFinn Thain #ifdef CONFIG_PPC
9f9c3a570SFinn Thain #include <asm/machdep.h>
10f9c3a570SFinn Thain #endif
11f9c3a570SFinn Thain
12d5bbb502SFinn Thain /**
13d5bbb502SFinn Thain * struct nvram_ops - NVRAM functionality made available to drivers
14d5bbb502SFinn Thain * @read: validate checksum (if any) then load a range of bytes from NVRAM
15d5bbb502SFinn Thain * @write: store a range of bytes to NVRAM then update checksum (if any)
16d5bbb502SFinn Thain * @read_byte: load a single byte from NVRAM
17d5bbb502SFinn Thain * @write_byte: store a single byte to NVRAM
18d5bbb502SFinn Thain * @get_size: return the fixed number of bytes in the NVRAM
19d5bbb502SFinn Thain *
20d5bbb502SFinn Thain * Architectures which provide an nvram ops struct need not implement all
21d5bbb502SFinn Thain * of these methods. If the NVRAM hardware can be accessed only one byte
22d5bbb502SFinn Thain * at a time then it may be sufficient to provide .read_byte and .write_byte.
23d5bbb502SFinn Thain * If the NVRAM has a checksum (and it is to be checked) the .read and
24d5bbb502SFinn Thain * .write methods can be used to implement that efficiently.
25d5bbb502SFinn Thain *
26d5bbb502SFinn Thain * Portable drivers may use the wrapper functions defined here.
27d5bbb502SFinn Thain * The nvram_read() and nvram_write() functions call the .read and .write
28d5bbb502SFinn Thain * methods when available and fall back on the .read_byte and .write_byte
29d5bbb502SFinn Thain * methods otherwise.
30d5bbb502SFinn Thain */
31d5bbb502SFinn Thain
32a084dbf6SFinn Thain struct nvram_ops {
33a084dbf6SFinn Thain ssize_t (*get_size)(void);
34d5bbb502SFinn Thain unsigned char (*read_byte)(int);
35d5bbb502SFinn Thain void (*write_byte)(unsigned char, int);
36a084dbf6SFinn Thain ssize_t (*read)(char *, size_t, loff_t *);
37a084dbf6SFinn Thain ssize_t (*write)(char *, size_t, loff_t *);
3895ac14b8SFinn Thain #if defined(CONFIG_X86) || defined(CONFIG_M68K)
392d58636eSFinn Thain long (*initialize)(void);
402d58636eSFinn Thain long (*set_checksum)(void);
4195ac14b8SFinn Thain #endif
42a084dbf6SFinn Thain };
43a084dbf6SFinn Thain
44a084dbf6SFinn Thain extern const struct nvram_ops arch_nvram_ops;
45a084dbf6SFinn Thain
nvram_get_size(void)461278cf66SFinn Thain static inline ssize_t nvram_get_size(void)
471278cf66SFinn Thain {
48a156c7baSFinn Thain #ifdef CONFIG_PPC
49f9c3a570SFinn Thain if (ppc_md.nvram_size)
50f9c3a570SFinn Thain return ppc_md.nvram_size();
51a156c7baSFinn Thain #else
52a084dbf6SFinn Thain if (arch_nvram_ops.get_size)
53a084dbf6SFinn Thain return arch_nvram_ops.get_size();
54a156c7baSFinn Thain #endif
551278cf66SFinn Thain return -ENODEV;
561278cf66SFinn Thain }
571278cf66SFinn Thain
nvram_read_byte(int addr)581278cf66SFinn Thain static inline unsigned char nvram_read_byte(int addr)
591278cf66SFinn Thain {
60d5bbb502SFinn Thain #ifdef CONFIG_PPC
61f9c3a570SFinn Thain if (ppc_md.nvram_read_val)
62f9c3a570SFinn Thain return ppc_md.nvram_read_val(addr);
63d5bbb502SFinn Thain #else
64d5bbb502SFinn Thain if (arch_nvram_ops.read_byte)
65d5bbb502SFinn Thain return arch_nvram_ops.read_byte(addr);
66d5bbb502SFinn Thain #endif
671278cf66SFinn Thain return 0xFF;
681278cf66SFinn Thain }
691278cf66SFinn Thain
nvram_write_byte(unsigned char val,int addr)701278cf66SFinn Thain static inline void nvram_write_byte(unsigned char val, int addr)
711278cf66SFinn Thain {
72d5bbb502SFinn Thain #ifdef CONFIG_PPC
73f9c3a570SFinn Thain if (ppc_md.nvram_write_val)
74f9c3a570SFinn Thain ppc_md.nvram_write_val(addr, val);
75d5bbb502SFinn Thain #else
76d5bbb502SFinn Thain if (arch_nvram_ops.write_byte)
77d5bbb502SFinn Thain arch_nvram_ops.write_byte(val, addr);
78d5bbb502SFinn Thain #endif
791278cf66SFinn Thain }
801278cf66SFinn Thain
nvram_read_bytes(char * buf,size_t count,loff_t * ppos)81109b3a89SFinn Thain static inline ssize_t nvram_read_bytes(char *buf, size_t count, loff_t *ppos)
82109b3a89SFinn Thain {
83109b3a89SFinn Thain ssize_t nvram_size = nvram_get_size();
84109b3a89SFinn Thain loff_t i;
85109b3a89SFinn Thain char *p = buf;
86109b3a89SFinn Thain
87109b3a89SFinn Thain if (nvram_size < 0)
88109b3a89SFinn Thain return nvram_size;
89109b3a89SFinn Thain for (i = *ppos; count > 0 && i < nvram_size; ++i, ++p, --count)
90109b3a89SFinn Thain *p = nvram_read_byte(i);
91109b3a89SFinn Thain *ppos = i;
92109b3a89SFinn Thain return p - buf;
93109b3a89SFinn Thain }
94109b3a89SFinn Thain
nvram_write_bytes(char * buf,size_t count,loff_t * ppos)95109b3a89SFinn Thain static inline ssize_t nvram_write_bytes(char *buf, size_t count, loff_t *ppos)
96109b3a89SFinn Thain {
97109b3a89SFinn Thain ssize_t nvram_size = nvram_get_size();
98109b3a89SFinn Thain loff_t i;
99109b3a89SFinn Thain char *p = buf;
100109b3a89SFinn Thain
101109b3a89SFinn Thain if (nvram_size < 0)
102109b3a89SFinn Thain return nvram_size;
103109b3a89SFinn Thain for (i = *ppos; count > 0 && i < nvram_size; ++i, ++p, --count)
104109b3a89SFinn Thain nvram_write_byte(*p, i);
105109b3a89SFinn Thain *ppos = i;
106109b3a89SFinn Thain return p - buf;
107109b3a89SFinn Thain }
108109b3a89SFinn Thain
nvram_read(char * buf,size_t count,loff_t * ppos)1091278cf66SFinn Thain static inline ssize_t nvram_read(char *buf, size_t count, loff_t *ppos)
1101278cf66SFinn Thain {
111f9c3a570SFinn Thain #ifdef CONFIG_PPC
112f9c3a570SFinn Thain if (ppc_md.nvram_read)
113f9c3a570SFinn Thain return ppc_md.nvram_read(buf, count, ppos);
114f9c3a570SFinn Thain #else
115a084dbf6SFinn Thain if (arch_nvram_ops.read)
116a084dbf6SFinn Thain return arch_nvram_ops.read(buf, count, ppos);
117f9c3a570SFinn Thain #endif
118109b3a89SFinn Thain return nvram_read_bytes(buf, count, ppos);
1191278cf66SFinn Thain }
1201278cf66SFinn Thain
nvram_write(char * buf,size_t count,loff_t * ppos)1211278cf66SFinn Thain static inline ssize_t nvram_write(char *buf, size_t count, loff_t *ppos)
1221278cf66SFinn Thain {
123f9c3a570SFinn Thain #ifdef CONFIG_PPC
124f9c3a570SFinn Thain if (ppc_md.nvram_write)
125f9c3a570SFinn Thain return ppc_md.nvram_write(buf, count, ppos);
126f9c3a570SFinn Thain #else
127a084dbf6SFinn Thain if (arch_nvram_ops.write)
128a084dbf6SFinn Thain return arch_nvram_ops.write(buf, count, ppos);
129f9c3a570SFinn Thain #endif
130109b3a89SFinn Thain return nvram_write_bytes(buf, count, ppos);
1311278cf66SFinn Thain }
1321278cf66SFinn Thain
1331da177e4SLinus Torvalds #endif /* _LINUX_NVRAM_H */
134