xref: /openbmc/linux/include/linux/nvram.h (revision f9c3a570)
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