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 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 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 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 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 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 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 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 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 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