11bb76ff1Sjsg /* Public domain. */
21bb76ff1Sjsg
31bb76ff1Sjsg #ifndef _LINUX_IOSYS_MAP_H
41bb76ff1Sjsg #define _LINUX_IOSYS_MAP_H
51bb76ff1Sjsg
61bb76ff1Sjsg #include <linux/io.h>
71bb76ff1Sjsg #include <linux/string.h>
81bb76ff1Sjsg
91bb76ff1Sjsg struct iosys_map {
101bb76ff1Sjsg union {
111bb76ff1Sjsg void *vaddr_iomem;
121bb76ff1Sjsg void *vaddr;
131bb76ff1Sjsg };
141bb76ff1Sjsg bool is_iomem;
151bb76ff1Sjsg bus_space_handle_t bsh;
161bb76ff1Sjsg bus_size_t size;
171bb76ff1Sjsg };
181bb76ff1Sjsg
191bb76ff1Sjsg static inline void
iosys_map_incr(struct iosys_map * ism,size_t n)201bb76ff1Sjsg iosys_map_incr(struct iosys_map *ism, size_t n)
211bb76ff1Sjsg {
221bb76ff1Sjsg if (ism->is_iomem)
231bb76ff1Sjsg ism->vaddr_iomem += n;
241bb76ff1Sjsg else
251bb76ff1Sjsg ism->vaddr += n;
261bb76ff1Sjsg }
271bb76ff1Sjsg
281bb76ff1Sjsg static inline void
iosys_map_memcpy_to(struct iosys_map * ism,size_t off,const void * src,size_t len)291bb76ff1Sjsg iosys_map_memcpy_to(struct iosys_map *ism, size_t off, const void *src,
301bb76ff1Sjsg size_t len)
311bb76ff1Sjsg {
321bb76ff1Sjsg if (ism->is_iomem)
331bb76ff1Sjsg memcpy_toio(ism->vaddr_iomem + off, src, len);
341bb76ff1Sjsg else
351bb76ff1Sjsg memcpy(ism->vaddr + off, src, len);
361bb76ff1Sjsg }
371bb76ff1Sjsg
38*be5961cdSjsg static inline void
iosys_map_memset(struct iosys_map * ism,size_t off,int c,size_t len)39*be5961cdSjsg iosys_map_memset(struct iosys_map *ism, size_t off, int c, size_t len)
40*be5961cdSjsg {
41*be5961cdSjsg if (ism->is_iomem)
42*be5961cdSjsg memset_io(ism->vaddr_iomem + off, c, len);
43*be5961cdSjsg else
44*be5961cdSjsg memset(ism->vaddr + off, c, len);
45*be5961cdSjsg }
46*be5961cdSjsg
471bb76ff1Sjsg static inline bool
iosys_map_is_null(const struct iosys_map * ism)481bb76ff1Sjsg iosys_map_is_null(const struct iosys_map *ism)
491bb76ff1Sjsg {
501bb76ff1Sjsg if (ism->is_iomem)
511bb76ff1Sjsg return (ism->vaddr_iomem == NULL);
521bb76ff1Sjsg else
531bb76ff1Sjsg return (ism->vaddr == NULL);
541bb76ff1Sjsg }
551bb76ff1Sjsg
561bb76ff1Sjsg static inline bool
iosys_map_is_set(const struct iosys_map * ism)571bb76ff1Sjsg iosys_map_is_set(const struct iosys_map *ism)
581bb76ff1Sjsg {
591bb76ff1Sjsg if (ism->is_iomem)
601bb76ff1Sjsg return (ism->vaddr_iomem != NULL);
611bb76ff1Sjsg else
621bb76ff1Sjsg return (ism->vaddr != NULL);
631bb76ff1Sjsg }
641bb76ff1Sjsg
651bb76ff1Sjsg static inline void
iosys_map_clear(struct iosys_map * ism)661bb76ff1Sjsg iosys_map_clear(struct iosys_map *ism)
671bb76ff1Sjsg {
681bb76ff1Sjsg if (ism->is_iomem) {
691bb76ff1Sjsg ism->vaddr_iomem = NULL;
701bb76ff1Sjsg ism->is_iomem = false;
711bb76ff1Sjsg } else {
721bb76ff1Sjsg ism->vaddr = NULL;
731bb76ff1Sjsg }
741bb76ff1Sjsg }
751bb76ff1Sjsg
761bb76ff1Sjsg static inline void
iosys_map_set_vaddr_iomem(struct iosys_map * ism,void * addr)771bb76ff1Sjsg iosys_map_set_vaddr_iomem(struct iosys_map *ism, void *addr)
781bb76ff1Sjsg {
791bb76ff1Sjsg ism->vaddr_iomem = addr;
801bb76ff1Sjsg ism->is_iomem = true;
811bb76ff1Sjsg }
821bb76ff1Sjsg
831bb76ff1Sjsg static inline void
iosys_map_set_vaddr(struct iosys_map * ism,void * addr)841bb76ff1Sjsg iosys_map_set_vaddr(struct iosys_map *ism, void *addr)
851bb76ff1Sjsg {
861bb76ff1Sjsg ism->vaddr = addr;
871bb76ff1Sjsg ism->is_iomem = false;
881bb76ff1Sjsg }
891bb76ff1Sjsg
90*be5961cdSjsg static inline struct iosys_map
IOSYS_MAP_INIT_OFFSET(struct iosys_map * ism,size_t off)91*be5961cdSjsg IOSYS_MAP_INIT_OFFSET(struct iosys_map *ism, size_t off)
92*be5961cdSjsg {
93*be5961cdSjsg struct iosys_map nism = *ism;
94*be5961cdSjsg iosys_map_incr(&nism, off);
95*be5961cdSjsg return nism;
96*be5961cdSjsg }
97*be5961cdSjsg
98*be5961cdSjsg #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112
99*be5961cdSjsg
100*be5961cdSjsg #define iosys_map_rd(_ism, _o, _t) ({ \
101*be5961cdSjsg _t v; \
102*be5961cdSjsg if ((_ism)->is_iomem) { \
103*be5961cdSjsg void *addr = (_ism)->vaddr_iomem + (_o); \
104*be5961cdSjsg v = _Generic(v, \
105*be5961cdSjsg uint8_t : ioread8(addr), \
106*be5961cdSjsg uint16_t: ioread16(addr), \
107*be5961cdSjsg uint32_t: ioread32(addr), \
108*be5961cdSjsg uint64_t: ioread64(addr)); \
109*be5961cdSjsg } else \
110*be5961cdSjsg v = READ_ONCE(*(_t *)((_ism)->vaddr + (_o))); \
111*be5961cdSjsg v; \
112*be5961cdSjsg })
113*be5961cdSjsg
114*be5961cdSjsg #define iosys_map_wr(_ism, _o, _t, _v) ({ \
115*be5961cdSjsg _t v = (_v); \
116*be5961cdSjsg if ((_ism)->is_iomem) { \
117*be5961cdSjsg void *addr = (_ism)->vaddr_iomem + (_o); \
118*be5961cdSjsg _Generic(v, \
119*be5961cdSjsg uint8_t : iowrite8(v, addr), \
120*be5961cdSjsg uint16_t: iowrite16(v, addr), \
121*be5961cdSjsg uint32_t: iowrite32(v, addr), \
122*be5961cdSjsg uint64_t: iowrite64(v, addr)); \
123*be5961cdSjsg } else \
124*be5961cdSjsg WRITE_ONCE(*(_t *)((_ism)->vaddr + (_o)), v); \
125*be5961cdSjsg })
126*be5961cdSjsg
127*be5961cdSjsg #define iosys_map_rd_field(_ism, _o, _t, _f) ({ \
128*be5961cdSjsg _t *t; \
129*be5961cdSjsg iosys_map_rd(_ism, _o + offsetof(_t, _f), __typeof(t->_f)); \
130*be5961cdSjsg })
131*be5961cdSjsg
132*be5961cdSjsg #define iosys_map_wr_field(_ism, _o, _t, _f, _v) ({ \
133*be5961cdSjsg _t *t; \
134*be5961cdSjsg iosys_map_wr(_ism, _o + offsetof(_t, _f), __typeof(t->_f), _v); \
135*be5961cdSjsg })
136*be5961cdSjsg
137*be5961cdSjsg #endif /* C11 */
138*be5961cdSjsg
1391bb76ff1Sjsg #endif
140