]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - k3conf/k3conf.git/blob - mmio.c
148f01ea32a4d7022db606875d313c78837f0fc3
[k3conf/k3conf.git] / mmio.c
1 /*
2  * K3CONF mmio helpers
3  *
4  * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
5  *      Lokesh Vutla <lokeshvutla@ti.com>
6  *      Nishanth Menon <nm@ti.com>
7  *
8  *  Redistribution and use in source and binary forms, with or without
9  *  modification, are permitted provided that the following conditions
10  *  are met:
11  *
12  *    Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  *    Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the
18  *    distribution.
19  *
20  *    Neither the name of Texas Instruments Incorporated nor the names of
21  *    its contributors may be used to endorse or promote products derived
22  *    from this software without specific prior written permission.
23  *
24  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  */
37 #include <sys/mman.h>
38 #include <fcntl.h>
39 #include <stdio.h>
40 #include <stdint.h>
41 #include <unistd.h>
42 #include <mmio.h>
43 #include <error.h>
45 #define MEMORY "/dev/mem"
47 unsigned page_size, mapped_size, offset_in_page;
48 void *map_base, *virt_addr;
49 int fd;
51 static int map_address(off_t target)
52 {
53         unsigned int width = 8 * sizeof(uint64_t);
55         fd = open(MEMORY, (O_RDWR | O_SYNC));
56         if (fd < 0) {
57                 fprintf(stderr, "Could not open %s!\n", MEMORY);
58                 return -5;
59         }
61         mapped_size = page_size = getpagesize();
62         offset_in_page = (unsigned)target & (page_size - 1);
63         if (offset_in_page + width > page_size) {
64                 /*
65                  * This access spans pages.
66                  * Must map two pages to make it possible:
67                  */
68                 mapped_size *= 2;
69         }
70         map_base = mmap(NULL,
71                         mapped_size,
72                         (PROT_READ | PROT_WRITE),
73                         MAP_SHARED, fd, target & ~(off_t) (page_size - 1));
74         if (map_base == MAP_FAILED) {
75                 fprintf(stderr, "Map fail\n");
76                 return -1;
77         }
79         virt_addr = (char *)map_base + offset_in_page;
80         return 0;
81 }
83 static uint64_t read_reg(int width)
84 {
85         uint64_t read_result = 0x0;
87         switch (width) {
88         case 8:
89                 read_result = *(volatile uint8_t *)virt_addr;
90                 break;
91         case 16:
92                 read_result = *(volatile uint16_t *)virt_addr;
93                 break;
94         case 32:
95                 read_result = *(volatile uint32_t *)virt_addr;
96                 break;
97         case 64:
98                 read_result = *(volatile uint64_t *)virt_addr;
99                 break;
100         default:
101                 fprintf(stderr, "bad width");
102         }
104         return read_result;
107 static void write_reg(int width, uint64_t writeval)
109         switch (width) {
110         case 8:
111                 *(volatile uint8_t *)virt_addr = writeval;
112                 break;
113         case 16:
114                 *(volatile uint16_t *)virt_addr = writeval;
115                 break;
116         case 32:
117                 *(volatile uint32_t *)virt_addr = writeval;
118                 break;
119         case 64:
120                 *(volatile uint64_t *)virt_addr = writeval;
121                 break;
122         default:
123                 fprintf(stderr, "bad width");
124         }
128 static void unmap_address(void)
130         if (munmap(map_base, mapped_size) == -1)
131                 fprintf(stderr, "munmap");
132         close(fd);
136 void mmio_write_8(uintptr_t addr, uint8_t value)
138         int r;
140         r = map_address(addr);
141         if (r)
142                 return;
143         write_reg(8, value);
144         unmap_address();
147 uint8_t mmio_read_8(uintptr_t addr)
149         uint8_t v = 0;
150         int r;
152         r = map_address(addr);
153         if (r)
154                 return 0;
155         v = read_reg(8);
156         unmap_address();
157         return v;
160 void mmio_write_16(uintptr_t addr, uint16_t value)
162         int r;
164         r = map_address(addr);
165         if (r)
166                 return;
167         write_reg(16, value);
168         unmap_address();
171 uint16_t mmio_read_16(uintptr_t addr)
173         uint16_t v = 0;
174         int r;
176         r = map_address(addr);
177         if (r)
178                 return 0;
179         v = read_reg(16);
180         unmap_address();
181         return v;
184 void mmio_write_32(uintptr_t addr, uint32_t value)
186         int r;
188         r = map_address(addr);
189         if (r)
190                 return;
191         write_reg(32, value);
192         unmap_address();
195 uint32_t mmio_read_32(uintptr_t addr)
197         uint32_t v = 0;
198         int r;
200         r = map_address(addr);
201         if (r)
202                 return 0;
203         v = read_reg(32);
204         unmap_address();
205         return v;
208 void mmio_write_64(uintptr_t addr, uint64_t value)
210         int r;
212         r = map_address(addr);
213         if (r)
214                 return;
215         write_reg(64, value);
216         unmap_address();
219 uint64_t mmio_read_64(uintptr_t addr)
221         uint64_t v = 0;
222         int r;
224         r = map_address(addr);
225         if (r)
226                 return 0;
227         v = read_reg(64);
228         unmap_address();
229         return v;