1/*-
2 * Copyright (c) 2013 Hans Petter Selasky. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26#include "implementation/freebsd_sys.h"
27
28struct burst {
29	uint32_t dw0;
30	uint32_t dw1;
31	uint32_t dw2;
32	uint32_t dw3;
33	uint32_t dw4;
34	uint32_t dw5;
35	uint32_t dw6;
36	uint32_t dw7;
37};
38
39void	bus_space_write_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, uint8_t data);
40void	bus_space_write_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, uint16_t data);
41void	bus_space_write_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, uint32_t data);
42
43uint8_t	bus_space_read_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset);
44uint16_t	bus_space_read_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset);
45uint32_t	bus_space_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset);
46
47void	bus_space_read_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset,
48							    uint8_t *datap, bus_size_t count);
49void	bus_space_read_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset,
50							    uint16_t *datap, bus_size_t count);
51void	bus_space_read_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset,
52							    uint32_t *datap, bus_size_t count);
53
54void	bus_space_write_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset,
55							    uint8_t *datap, bus_size_t count);
56void	bus_space_write_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset,
57							    uint16_t *datap, bus_size_t count);
58void	bus_space_write_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset,
59							    uint32_t *datap, bus_size_t count);
60
61void	bus_space_read_region_1(bus_space_tag_t space, bus_space_handle_t handle, bus_size_t offset,
62							    uint8_t *datap, bus_size_t count);
63void	bus_space_write_region_1(bus_space_tag_t space, bus_space_handle_t handle, bus_size_t offset,
64							    uint8_t *datap, bus_size_t count);
65void	bus_space_read_region_4(bus_space_tag_t space, bus_space_handle_t handle, bus_size_t offset,
66							    uint32_t *datap, bus_size_t count);
67void	bus_space_write_region_4(bus_space_tag_t space, bus_space_handle_t handle, bus_size_t offset,
68							    uint32_t *datap, bus_size_t count);
69
70void
71bus_space_read_multi_1(bus_space_tag_t t, bus_space_handle_t h,
72    bus_size_t offset, uint8_t *datap, bus_size_t count)
73{
74	while (count--) {
75		*datap++ = bus_space_read_1(t, h, offset);
76	}
77}
78
79void
80bus_space_read_multi_2(bus_space_tag_t t, bus_space_handle_t h,
81    bus_size_t offset, uint16_t *datap, bus_size_t count)
82{
83	while (count--) {
84		*datap++ = bus_space_read_2(t, h, offset);
85	}
86}
87
88void
89bus_space_read_multi_4(bus_space_tag_t t, bus_space_handle_t h,
90    bus_size_t offset, uint32_t *datap, bus_size_t count)
91{
92	h += offset;
93
94	while (count--) {
95		*datap++ = *((volatile uint32_t *)h);
96	}
97}
98
99void
100bus_space_write_multi_1(bus_space_tag_t t, bus_space_handle_t h,
101    bus_size_t offset, uint8_t *datap, bus_size_t count)
102{
103	while (count--) {
104		uint8_t temp = *datap++;
105
106		bus_space_write_1(t, h, offset, temp);
107	}
108}
109
110void
111bus_space_write_multi_2(bus_space_tag_t t, bus_space_handle_t h,
112    bus_size_t offset, uint16_t *datap, bus_size_t count)
113{
114	while (count--) {
115		uint16_t temp = *datap++;
116
117		bus_space_write_2(t, h, offset, temp);
118	}
119}
120
121void
122bus_space_write_multi_4(bus_space_tag_t t, bus_space_handle_t h,
123    bus_size_t offset, uint32_t *datap, bus_size_t count)
124{
125	h += offset;
126
127	while (count--) {
128		*((volatile uint32_t *)h) = *datap++;
129	}
130}
131
132void
133bus_space_write_1(bus_space_tag_t t, bus_space_handle_t h,
134    bus_size_t offset, uint8_t data)
135{
136	*((volatile uint8_t *)(h + offset)) = data;
137}
138
139void
140bus_space_write_2(bus_space_tag_t t, bus_space_handle_t h,
141    bus_size_t offset, uint16_t data)
142{
143	*((volatile uint16_t *)(h + offset)) = data;
144}
145
146void
147bus_space_write_4(bus_space_tag_t t, bus_space_handle_t h,
148    bus_size_t offset, uint32_t data)
149{
150	*((volatile uint32_t *)(h + offset)) = data;
151}
152
153uint8_t
154bus_space_read_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset)
155{
156	return (*((volatile uint8_t *)(h + offset)));
157}
158
159uint16_t
160bus_space_read_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset)
161{
162	return (*((volatile uint16_t *)(h + offset)));
163}
164
165uint32_t
166bus_space_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset)
167{
168	return (*((volatile uint32_t *)(h + offset)));
169}
170
171void
172bus_space_read_region_1(bus_space_tag_t t, bus_space_handle_t h,
173    bus_size_t offset, uint8_t *datap, bus_size_t count)
174{
175	h += offset;
176
177	while (count--) {
178		*datap++ = *((volatile uint8_t *)h);
179		h += 1;
180	}
181}
182
183void
184bus_space_write_region_1(bus_space_tag_t t, bus_space_handle_t h,
185    bus_size_t offset, uint8_t *datap, bus_size_t count)
186{
187	h += offset;
188
189	while (count--) {
190		*((volatile uint8_t *)h) = *datap++;
191		h += 1;
192	}
193}
194
195void
196bus_space_read_region_4(bus_space_tag_t t, bus_space_handle_t h,
197    bus_size_t offset, uint32_t *datap, bus_size_t count)
198{
199	enum { BURST = sizeof(struct burst) / 4 };
200
201	h += offset;
202
203	while (count >= BURST) {
204		*(struct burst *)datap = *((/* volatile */ struct burst *)h);
205
206		h += BURST * 4;
207		datap += BURST;
208		count -= BURST;
209	}
210
211	while (count--) {
212		*datap++ = *((volatile uint32_t *)h);
213		h += 4;
214	}
215}
216
217void
218bus_space_write_region_4(bus_space_tag_t t, bus_space_handle_t h,
219    bus_size_t offset, uint32_t *datap, bus_size_t count)
220{
221	enum { BURST = sizeof(struct burst) / 4 };
222
223	h += offset;
224
225	while (count >= BURST) {
226		*((/* volatile */ struct burst *)h) = *(struct burst *)datap;
227
228		h += BURST * 4;
229		datap += BURST;
230		count -= BURST;
231	}
232
233	while (count--) {
234		*((volatile uint32_t *)h) = *datap++;
235		h += 4;
236	}
237}
238