148f01ea32a4d7022db606875d313c78837f0fc3
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;
105 }
107 static void write_reg(int width, uint64_t writeval)
108 {
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 }
126 }
128 static void unmap_address(void)
129 {
130 if (munmap(map_base, mapped_size) == -1)
131 fprintf(stderr, "munmap");
132 close(fd);
134 }
136 void mmio_write_8(uintptr_t addr, uint8_t value)
137 {
138 int r;
140 r = map_address(addr);
141 if (r)
142 return;
143 write_reg(8, value);
144 unmap_address();
145 }
147 uint8_t mmio_read_8(uintptr_t addr)
148 {
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;
158 }
160 void mmio_write_16(uintptr_t addr, uint16_t value)
161 {
162 int r;
164 r = map_address(addr);
165 if (r)
166 return;
167 write_reg(16, value);
168 unmap_address();
169 }
171 uint16_t mmio_read_16(uintptr_t addr)
172 {
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;
182 }
184 void mmio_write_32(uintptr_t addr, uint32_t value)
185 {
186 int r;
188 r = map_address(addr);
189 if (r)
190 return;
191 write_reg(32, value);
192 unmap_address();
193 }
195 uint32_t mmio_read_32(uintptr_t addr)
196 {
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;
206 }
208 void mmio_write_64(uintptr_t addr, uint64_t value)
209 {
210 int r;
212 r = map_address(addr);
213 if (r)
214 return;
215 write_reg(64, value);
216 unmap_address();
217 }
219 uint64_t mmio_read_64(uintptr_t addr)
220 {
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;
230 }