1 /* Public domain. */
2
3 #ifndef _LINUX_IOSYS_MAP_H
4 #define _LINUX_IOSYS_MAP_H
5
6 #include <linux/io.h>
7 #include <linux/string.h>
8
9 struct iosys_map {
10 union {
11 void *vaddr_iomem;
12 void *vaddr;
13 };
14 bool is_iomem;
15 bus_space_handle_t bsh;
16 bus_size_t size;
17 };
18
19 static inline void
iosys_map_incr(struct iosys_map * ism,size_t n)20 iosys_map_incr(struct iosys_map *ism, size_t n)
21 {
22 if (ism->is_iomem)
23 ism->vaddr_iomem += n;
24 else
25 ism->vaddr += n;
26 }
27
28 static inline void
iosys_map_memcpy_to(struct iosys_map * ism,size_t off,const void * src,size_t len)29 iosys_map_memcpy_to(struct iosys_map *ism, size_t off, const void *src,
30 size_t len)
31 {
32 if (ism->is_iomem)
33 memcpy_toio(ism->vaddr_iomem + off, src, len);
34 else
35 memcpy(ism->vaddr + off, src, len);
36 }
37
38 static inline void
iosys_map_memset(struct iosys_map * ism,size_t off,int c,size_t len)39 iosys_map_memset(struct iosys_map *ism, size_t off, int c, size_t len)
40 {
41 if (ism->is_iomem)
42 memset_io(ism->vaddr_iomem + off, c, len);
43 else
44 memset(ism->vaddr + off, c, len);
45 }
46
47 static inline bool
iosys_map_is_null(const struct iosys_map * ism)48 iosys_map_is_null(const struct iosys_map *ism)
49 {
50 if (ism->is_iomem)
51 return (ism->vaddr_iomem == NULL);
52 else
53 return (ism->vaddr == NULL);
54 }
55
56 static inline bool
iosys_map_is_set(const struct iosys_map * ism)57 iosys_map_is_set(const struct iosys_map *ism)
58 {
59 if (ism->is_iomem)
60 return (ism->vaddr_iomem != NULL);
61 else
62 return (ism->vaddr != NULL);
63 }
64
65 static inline void
iosys_map_clear(struct iosys_map * ism)66 iosys_map_clear(struct iosys_map *ism)
67 {
68 if (ism->is_iomem) {
69 ism->vaddr_iomem = NULL;
70 ism->is_iomem = false;
71 } else {
72 ism->vaddr = NULL;
73 }
74 }
75
76 static inline void
iosys_map_set_vaddr_iomem(struct iosys_map * ism,void * addr)77 iosys_map_set_vaddr_iomem(struct iosys_map *ism, void *addr)
78 {
79 ism->vaddr_iomem = addr;
80 ism->is_iomem = true;
81 }
82
83 static inline void
iosys_map_set_vaddr(struct iosys_map * ism,void * addr)84 iosys_map_set_vaddr(struct iosys_map *ism, void *addr)
85 {
86 ism->vaddr = addr;
87 ism->is_iomem = false;
88 }
89
90 static inline struct iosys_map
IOSYS_MAP_INIT_OFFSET(struct iosys_map * ism,size_t off)91 IOSYS_MAP_INIT_OFFSET(struct iosys_map *ism, size_t off)
92 {
93 struct iosys_map nism = *ism;
94 iosys_map_incr(&nism, off);
95 return nism;
96 }
97
98 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112
99
100 #define iosys_map_rd(_ism, _o, _t) ({ \
101 _t v; \
102 if ((_ism)->is_iomem) { \
103 void *addr = (_ism)->vaddr_iomem + (_o); \
104 v = _Generic(v, \
105 uint8_t : ioread8(addr), \
106 uint16_t: ioread16(addr), \
107 uint32_t: ioread32(addr), \
108 uint64_t: ioread64(addr)); \
109 } else \
110 v = READ_ONCE(*(_t *)((_ism)->vaddr + (_o))); \
111 v; \
112 })
113
114 #define iosys_map_wr(_ism, _o, _t, _v) ({ \
115 _t v = (_v); \
116 if ((_ism)->is_iomem) { \
117 void *addr = (_ism)->vaddr_iomem + (_o); \
118 _Generic(v, \
119 uint8_t : iowrite8(v, addr), \
120 uint16_t: iowrite16(v, addr), \
121 uint32_t: iowrite32(v, addr), \
122 uint64_t: iowrite64(v, addr)); \
123 } else \
124 WRITE_ONCE(*(_t *)((_ism)->vaddr + (_o)), v); \
125 })
126
127 #define iosys_map_rd_field(_ism, _o, _t, _f) ({ \
128 _t *t; \
129 iosys_map_rd(_ism, _o + offsetof(_t, _f), __typeof(t->_f)); \
130 })
131
132 #define iosys_map_wr_field(_ism, _o, _t, _f, _v) ({ \
133 _t *t; \
134 iosys_map_wr(_ism, _o + offsetof(_t, _f), __typeof(t->_f), _v); \
135 })
136
137 #endif /* C11 */
138
139 #endif
140