xref: /openbsd/sys/dev/pci/drm/include/linux/iosys-map.h (revision be5961cd)
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