1f8ab2f5bSVladimir Kondratyev /* Public domain. */
2f8ab2f5bSVladimir Kondratyev 
3f8ab2f5bSVladimir Kondratyev #ifndef _LINUXKPI_LINUX_IOSYS_MAP_H
4f8ab2f5bSVladimir Kondratyev #define _LINUXKPI_LINUX_IOSYS_MAP_H
5f8ab2f5bSVladimir Kondratyev 
6f8ab2f5bSVladimir Kondratyev #include <linux/io.h>
7f8ab2f5bSVladimir Kondratyev #include <linux/string.h>
8f8ab2f5bSVladimir Kondratyev 
9f8ab2f5bSVladimir Kondratyev struct iosys_map {
10f8ab2f5bSVladimir Kondratyev 	union {
11f8ab2f5bSVladimir Kondratyev 		void *vaddr_iomem;
12f8ab2f5bSVladimir Kondratyev 		void *vaddr;
13f8ab2f5bSVladimir Kondratyev 	};
14f8ab2f5bSVladimir Kondratyev 	bool is_iomem;
15f8ab2f5bSVladimir Kondratyev #ifdef __OpenBSD__
16f8ab2f5bSVladimir Kondratyev 	bus_space_handle_t bsh;
17f8ab2f5bSVladimir Kondratyev 	bus_size_t size;
18f8ab2f5bSVladimir Kondratyev #endif
19f8ab2f5bSVladimir Kondratyev };
20f8ab2f5bSVladimir Kondratyev 
21f8ab2f5bSVladimir Kondratyev #define IOSYS_MAP_INIT_OFFSET(_ism_src_p, _off) ({			\
22f8ab2f5bSVladimir Kondratyev 	struct iosys_map ism_dst = *(_ism_src_p);			\
23f8ab2f5bSVladimir Kondratyev 	iosys_map_incr(&ism_dst, _off);					\
24f8ab2f5bSVladimir Kondratyev 	ism_dst;							\
25f8ab2f5bSVladimir Kondratyev })
26f8ab2f5bSVladimir Kondratyev 
27f8ab2f5bSVladimir Kondratyev static inline void
iosys_map_incr(struct iosys_map * ism,size_t n)28f8ab2f5bSVladimir Kondratyev iosys_map_incr(struct iosys_map *ism, size_t n)
29f8ab2f5bSVladimir Kondratyev {
30f8ab2f5bSVladimir Kondratyev 	if (ism->is_iomem)
31f8ab2f5bSVladimir Kondratyev 		ism->vaddr_iomem += n;
32f8ab2f5bSVladimir Kondratyev 	else
33f8ab2f5bSVladimir Kondratyev 		ism->vaddr += n;
34f8ab2f5bSVladimir Kondratyev }
35f8ab2f5bSVladimir Kondratyev 
36f8ab2f5bSVladimir Kondratyev static inline void
iosys_map_memcpy_to(struct iosys_map * ism,size_t off,const void * src,size_t len)37f8ab2f5bSVladimir Kondratyev iosys_map_memcpy_to(struct iosys_map *ism, size_t off, const void *src,
38f8ab2f5bSVladimir Kondratyev     size_t len)
39f8ab2f5bSVladimir Kondratyev {
40f8ab2f5bSVladimir Kondratyev 	if (ism->is_iomem)
41f8ab2f5bSVladimir Kondratyev 		memcpy_toio(ism->vaddr_iomem + off, src, len);
42f8ab2f5bSVladimir Kondratyev 	else
43f8ab2f5bSVladimir Kondratyev 		memcpy(ism->vaddr + off, src, len);
44f8ab2f5bSVladimir Kondratyev }
45f8ab2f5bSVladimir Kondratyev 
46f8ab2f5bSVladimir Kondratyev static inline bool
iosys_map_is_null(const struct iosys_map * ism)47f8ab2f5bSVladimir Kondratyev iosys_map_is_null(const struct iosys_map *ism)
48f8ab2f5bSVladimir Kondratyev {
49f8ab2f5bSVladimir Kondratyev 	if (ism->is_iomem)
50f8ab2f5bSVladimir Kondratyev 		return (ism->vaddr_iomem == NULL);
51f8ab2f5bSVladimir Kondratyev 	else
52f8ab2f5bSVladimir Kondratyev 		return (ism->vaddr == NULL);
53f8ab2f5bSVladimir Kondratyev }
54f8ab2f5bSVladimir Kondratyev 
55f8ab2f5bSVladimir Kondratyev static inline bool
iosys_map_is_set(const struct iosys_map * ism)56f8ab2f5bSVladimir Kondratyev iosys_map_is_set(const struct iosys_map *ism)
57f8ab2f5bSVladimir Kondratyev {
58f8ab2f5bSVladimir Kondratyev 	if (ism->is_iomem)
59f8ab2f5bSVladimir Kondratyev 		return (ism->vaddr_iomem != NULL);
60f8ab2f5bSVladimir Kondratyev 	else
61f8ab2f5bSVladimir Kondratyev 		return (ism->vaddr != NULL);
62f8ab2f5bSVladimir Kondratyev }
63f8ab2f5bSVladimir Kondratyev 
64f8ab2f5bSVladimir Kondratyev static inline bool
iosys_map_is_equal(const struct iosys_map * ism_a,const struct iosys_map * ism_b)65f8ab2f5bSVladimir Kondratyev iosys_map_is_equal(const struct iosys_map *ism_a,
66f8ab2f5bSVladimir Kondratyev     const struct iosys_map *ism_b)
67f8ab2f5bSVladimir Kondratyev {
68f8ab2f5bSVladimir Kondratyev 	if (ism_a->is_iomem != ism_b->is_iomem)
69f8ab2f5bSVladimir Kondratyev 		return (false);
70f8ab2f5bSVladimir Kondratyev 
71f8ab2f5bSVladimir Kondratyev 	if (ism_a->is_iomem)
72f8ab2f5bSVladimir Kondratyev 		return (ism_a->vaddr_iomem == ism_b->vaddr_iomem);
73f8ab2f5bSVladimir Kondratyev 	else
74f8ab2f5bSVladimir Kondratyev 		return (ism_a->vaddr == ism_b->vaddr);
75f8ab2f5bSVladimir Kondratyev }
76f8ab2f5bSVladimir Kondratyev 
77f8ab2f5bSVladimir Kondratyev static inline void
iosys_map_clear(struct iosys_map * ism)78f8ab2f5bSVladimir Kondratyev iosys_map_clear(struct iosys_map *ism)
79f8ab2f5bSVladimir Kondratyev {
80f8ab2f5bSVladimir Kondratyev 	if (ism->is_iomem) {
81f8ab2f5bSVladimir Kondratyev 		ism->vaddr_iomem = NULL;
82f8ab2f5bSVladimir Kondratyev 		ism->is_iomem = false;
83f8ab2f5bSVladimir Kondratyev 	} else {
84f8ab2f5bSVladimir Kondratyev 		ism->vaddr = NULL;
85f8ab2f5bSVladimir Kondratyev 	}
86f8ab2f5bSVladimir Kondratyev }
87f8ab2f5bSVladimir Kondratyev 
88f8ab2f5bSVladimir Kondratyev static inline void
iosys_map_set_vaddr_iomem(struct iosys_map * ism,void * addr)89f8ab2f5bSVladimir Kondratyev iosys_map_set_vaddr_iomem(struct iosys_map *ism, void *addr)
90f8ab2f5bSVladimir Kondratyev {
91f8ab2f5bSVladimir Kondratyev 	ism->vaddr_iomem = addr;
92f8ab2f5bSVladimir Kondratyev 	ism->is_iomem = true;
93f8ab2f5bSVladimir Kondratyev }
94f8ab2f5bSVladimir Kondratyev 
95f8ab2f5bSVladimir Kondratyev static inline void
iosys_map_set_vaddr(struct iosys_map * ism,void * addr)96f8ab2f5bSVladimir Kondratyev iosys_map_set_vaddr(struct iosys_map *ism, void *addr)
97f8ab2f5bSVladimir Kondratyev {
98f8ab2f5bSVladimir Kondratyev 	ism->vaddr = addr;
99f8ab2f5bSVladimir Kondratyev 	ism->is_iomem = false;
100f8ab2f5bSVladimir Kondratyev }
101f8ab2f5bSVladimir Kondratyev 
102f8ab2f5bSVladimir Kondratyev static inline void
iosys_map_memset(struct iosys_map * ism,size_t off,int value,size_t len)103f8ab2f5bSVladimir Kondratyev iosys_map_memset(struct iosys_map *ism, size_t off, int value, size_t len)
104f8ab2f5bSVladimir Kondratyev {
105f8ab2f5bSVladimir Kondratyev 	if (ism->is_iomem)
106f8ab2f5bSVladimir Kondratyev 		memset_io(ism->vaddr_iomem + off, value, len);
107f8ab2f5bSVladimir Kondratyev 	else
108f8ab2f5bSVladimir Kondratyev 		memset(ism->vaddr + off, value, len);
109f8ab2f5bSVladimir Kondratyev }
110f8ab2f5bSVladimir Kondratyev 
111f8ab2f5bSVladimir Kondratyev #ifdef __LP64__
112f8ab2f5bSVladimir Kondratyev #define	_iosys_map_readq(_addr)			readq(_addr)
113f8ab2f5bSVladimir Kondratyev #define	_iosys_map_writeq(_val, _addr)		writeq(_val, _addr)
114f8ab2f5bSVladimir Kondratyev #else
115f8ab2f5bSVladimir Kondratyev #define	_iosys_map_readq(_addr) ({					\
116f8ab2f5bSVladimir Kondratyev 	uint64_t val;							\
117f8ab2f5bSVladimir Kondratyev 	memcpy_fromio(&val, _addr, sizeof(uint64_t));			\
118f8ab2f5bSVladimir Kondratyev 	val;								\
119f8ab2f5bSVladimir Kondratyev })
120f8ab2f5bSVladimir Kondratyev #define	_iosys_map_writeq(_val, _addr)					\
121f8ab2f5bSVladimir Kondratyev 	memcpy_toio(_addr, &(_val), sizeof(uint64_t))
122f8ab2f5bSVladimir Kondratyev #endif
123f8ab2f5bSVladimir Kondratyev 
124f8ab2f5bSVladimir Kondratyev #define	iosys_map_rd(_ism, _off, _type) ({				\
125f8ab2f5bSVladimir Kondratyev 	_type val;							\
126f8ab2f5bSVladimir Kondratyev 	if ((_ism)->is_iomem) {						\
127f8ab2f5bSVladimir Kondratyev 		void *addr = (_ism)->vaddr_iomem + (_off);		\
128f8ab2f5bSVladimir Kondratyev 		val = _Generic(val,					\
129f8ab2f5bSVladimir Kondratyev 		    uint8_t : readb(addr),				\
130f8ab2f5bSVladimir Kondratyev 		    uint16_t: readw(addr),				\
131f8ab2f5bSVladimir Kondratyev 		    uint32_t: readl(addr),				\
132f8ab2f5bSVladimir Kondratyev 		    uint64_t: _iosys_map_readq(addr));			\
133f8ab2f5bSVladimir Kondratyev 	} else								\
134f8ab2f5bSVladimir Kondratyev 		val = READ_ONCE(*(_type *)((_ism)->vaddr + (_off)));	\
135f8ab2f5bSVladimir Kondratyev 	val;								\
136f8ab2f5bSVladimir Kondratyev })
137f8ab2f5bSVladimir Kondratyev #define	iosys_map_wr(_ism, _off, _type, _val) ({			\
138f8ab2f5bSVladimir Kondratyev 	_type val = (_val);						\
139f8ab2f5bSVladimir Kondratyev 	if ((_ism)->is_iomem) {						\
140f8ab2f5bSVladimir Kondratyev 		void *addr = (_ism)->vaddr_iomem + (_off);		\
141f8ab2f5bSVladimir Kondratyev 		_Generic(val,						\
142f8ab2f5bSVladimir Kondratyev 		    uint8_t : writeb(val, addr),			\
143f8ab2f5bSVladimir Kondratyev 		    uint16_t: writew(val, addr),			\
144f8ab2f5bSVladimir Kondratyev 		    uint32_t: writel(val, addr),			\
145f8ab2f5bSVladimir Kondratyev 		    uint64_t: _iosys_map_writeq(val, addr));		\
146f8ab2f5bSVladimir Kondratyev 	} else								\
147f8ab2f5bSVladimir Kondratyev 		WRITE_ONCE(*(_type *)((_ism)->vaddr + (_off)), val);	\
148f8ab2f5bSVladimir Kondratyev })
149f8ab2f5bSVladimir Kondratyev 
150f8ab2f5bSVladimir Kondratyev #define	iosys_map_rd_field(_ism, _off, _type, _field) ({		\
151f8ab2f5bSVladimir Kondratyev 	_type *s;							\
152f8ab2f5bSVladimir Kondratyev 	iosys_map_rd(_ism, (_off) + offsetof(_type, _field),		\
153f8ab2f5bSVladimir Kondratyev 	    __typeof(s->_field));					\
154f8ab2f5bSVladimir Kondratyev })
155f8ab2f5bSVladimir Kondratyev #define	iosys_map_wr_field(_ism, _off, _type, _field, _val) ({		\
156f8ab2f5bSVladimir Kondratyev 	_type *s;							\
157f8ab2f5bSVladimir Kondratyev 	iosys_map_wr(_ism, (_off) + offsetof(_type, _field),		\
158f8ab2f5bSVladimir Kondratyev 	    __typeof(s->_field), _val);					\
159f8ab2f5bSVladimir Kondratyev })
160f8ab2f5bSVladimir Kondratyev 
161f8ab2f5bSVladimir Kondratyev #endif
162