1212793Sdim/*	$NetBSD: drm_iomap_netbsd.h,v 1.1 2018/08/27 05:34:49 riastradh Exp $	*/
2212793Sdim
3212793Sdim/*-
4212793Sdim * Copyright (c) 2013 The NetBSD Foundation, Inc.
5212793Sdim * All rights reserved.
6212793Sdim *
7212793Sdim * This code is derived from software contributed to The NetBSD Foundation
8212793Sdim * by Taylor R. Campbell.
9212793Sdim *
10212793Sdim * Redistribution and use in source and binary forms, with or without
11212793Sdim * modification, are permitted provided that the following conditions
12212793Sdim * are met:
13212793Sdim * 1. Redistributions of source code must retain the above copyright
14212793Sdim *    notice, this list of conditions and the following disclaimer.
15212793Sdim * 2. Redistributions in binary form must reproduce the above copyright
16212793Sdim *    notice, this list of conditions and the following disclaimer in the
17212793Sdim *    documentation and/or other materials provided with the distribution.
18212793Sdim *
19212793Sdim * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20212793Sdim * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21249423Sdim * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22249423Sdim * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23249423Sdim * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24249423Sdim * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25249423Sdim * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26212793Sdim * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27212793Sdim * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28212793Sdim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29212793Sdim * POSSIBILITY OF SUCH DAMAGE.
30212793Sdim */
31212793Sdim
32212793Sdim#ifndef	_DRM_DRM_IOMAP_NETBSD_H_
33212793Sdim#define	_DRM_DRM_IOMAP_NETBSD_H_
34212793Sdim
35212793Sdim#include <sys/bus.h>
36212793Sdim#include <sys/endian.h>
37212793Sdim
38212793Sdim#include <drm/drm_legacy.h>
39212793Sdim
40212793Sdimstatic inline bool
41212793SdimDRM_IS_BUS_SPACE(struct drm_local_map *map)
42212793Sdim{
43212793Sdim	switch (map->type) {
44212793Sdim	case _DRM_FRAME_BUFFER:
45212793Sdim		panic("I don't know how to access drm frame buffer memory!");
46212793Sdim
47212793Sdim	case _DRM_REGISTERS:
48212793Sdim		return true;
49212793Sdim
50212793Sdim	case _DRM_SHM:
51212793Sdim		panic("I don't know how to access drm shared memory!");
52212793Sdim
53212793Sdim	case _DRM_AGP:
54212793Sdim		panic("I don't know how to access drm agp memory!");
55212793Sdim
56212793Sdim	case _DRM_SCATTER_GATHER:
57212793Sdim		panic("I don't know how to access drm scatter-gather memory!");
58212793Sdim
59212793Sdim	case _DRM_CONSISTENT:
60212793Sdim		/*
61212793Sdim		 * XXX Old drm uses bus space access for this, but
62212793Sdim		 * consistent maps don't have bus space handles!  They
63212793Sdim		 * do, however, have kernel virtual addresses in the
64212793Sdim		 * map->handle, so maybe that's right.
65212793Sdim		 */
66212793Sdim#if 0
67212793Sdim		return false;
68212793Sdim#endif
69212793Sdim		panic("I don't know how to access drm consistent memory!");
70212793Sdim
71212793Sdim	default:
72212793Sdim		panic("I don't know what kind of memory you mean!");
73212793Sdim	}
74212793Sdim}
75212793Sdim
76212793Sdimstatic inline uint8_t
77212793SdimDRM_READ8(struct drm_local_map *map, bus_size_t offset)
78212793Sdim{
79212793Sdim	if (DRM_IS_BUS_SPACE(map))
80212793Sdim		return bus_space_read_1(map->lm_data.bus_space.bst,
81212793Sdim		    map->lm_data.bus_space.bsh, offset);
82212793Sdim	else
83212793Sdim		return *(volatile uint8_t *)((vaddr_t)map->handle + offset);
84212793Sdim}
85212793Sdim
86212793Sdimstatic inline uint16_t
87212793SdimDRM_READ16(struct drm_local_map *map, bus_size_t offset)
88212793Sdim{
89212793Sdim	if (DRM_IS_BUS_SPACE(map))
90212793Sdim		return bus_space_read_2(map->lm_data.bus_space.bst,
91212793Sdim		    map->lm_data.bus_space.bsh, offset);
92212793Sdim	else
93212793Sdim		return *(volatile uint16_t *)((vaddr_t)map->handle + offset);
94212793Sdim}
95212793Sdim
96212793Sdimstatic inline uint32_t
97212793SdimDRM_READ32(struct drm_local_map *map, bus_size_t offset)
98212793Sdim{
99212793Sdim	if (DRM_IS_BUS_SPACE(map))
100212793Sdim		return bus_space_read_4(map->lm_data.bus_space.bst,
101212793Sdim		    map->lm_data.bus_space.bsh, offset);
102212793Sdim	else
103212793Sdim		return *(volatile uint32_t *)((vaddr_t)map->handle + offset);
104212793Sdim}
105212793Sdim
106212793Sdimstatic inline uint64_t
107212793SdimDRM_READ64(struct drm_local_map *map, bus_size_t offset)
108212793Sdim{
109212793Sdim	if (DRM_IS_BUS_SPACE(map)) {
110212793Sdim#if _LP64			/* XXX How to detect bus_space_read_8?  */
111212793Sdim		return bus_space_read_8(map->lm_data.bus_space.bst,
112212793Sdim		    map->lm_data.bus_space.bsh, offset);
113212793Sdim#elif _BYTE_ORDER == _LITTLE_ENDIAN
114212793Sdim		/* XXX Yes, this is sketchy.  */
115212793Sdim		return bus_space_read_4(map->lm_data.bus_space.bst,
116212793Sdim		    map->lm_data.bus_space.bsh, offset) |
117212793Sdim		    ((uint64_t)bus_space_read_4(map->lm_data.bus_space.bst,
118212793Sdim			map->lm_data.bus_space.bsh, (offset + 4)) << 32);
119212793Sdim#else
120212793Sdim		/* XXX Yes, this is sketchy.  */
121212793Sdim		return bus_space_read_4(map->lm_data.bus_space.bst,
122212793Sdim		    map->lm_data.bus_space.bsh, (offset + 4)) |
123212793Sdim		    ((uint64_t)bus_space_read_4(map->lm_data.bus_space.bst,
124212793Sdim			map->lm_data.bus_space.bsh, offset) << 32);
125212793Sdim#endif
126212793Sdim	} else {
127212793Sdim		return *(volatile uint64_t *)((vaddr_t)map->handle + offset);
128212793Sdim	}
129212793Sdim}
130212793Sdim
131212793Sdimstatic inline void
132212793SdimDRM_WRITE8(struct drm_local_map *map, bus_size_t offset, uint8_t value)
133212793Sdim{
134212793Sdim	if (DRM_IS_BUS_SPACE(map))
135212793Sdim		bus_space_write_1(map->lm_data.bus_space.bst,
136212793Sdim		    map->lm_data.bus_space.bsh, offset, value);
137212793Sdim	else
138212793Sdim		*(volatile uint8_t *)((vaddr_t)map->handle + offset) = value;
139212793Sdim}
140212793Sdim
141212793Sdimstatic inline void
142212793SdimDRM_WRITE16(struct drm_local_map *map, bus_size_t offset, uint16_t value)
143212793Sdim{
144212793Sdim	if (DRM_IS_BUS_SPACE(map))
145212793Sdim		bus_space_write_2(map->lm_data.bus_space.bst,
146212793Sdim		    map->lm_data.bus_space.bsh, offset, value);
147212793Sdim	else
148212793Sdim		*(volatile uint16_t *)((vaddr_t)map->handle + offset) = value;
149212793Sdim}
150212793Sdim
151212793Sdimstatic inline void
152212793SdimDRM_WRITE32(struct drm_local_map *map, bus_size_t offset, uint32_t value)
153212793Sdim{
154212793Sdim	if (DRM_IS_BUS_SPACE(map))
155212793Sdim		bus_space_write_4(map->lm_data.bus_space.bst,
156212793Sdim		    map->lm_data.bus_space.bsh, offset, value);
157212793Sdim	else
158212793Sdim		*(volatile uint32_t *)((vaddr_t)map->handle + offset) = value;
159212793Sdim}
160212793Sdim
161212793Sdimstatic inline void
162212793SdimDRM_WRITE64(struct drm_local_map *map, bus_size_t offset, uint64_t value)
163212793Sdim{
164212793Sdim	if (DRM_IS_BUS_SPACE(map)) {
165212793Sdim#if _LP64			/* XXX How to detect bus_space_write_8?  */
166212793Sdim		bus_space_write_8(map->lm_data.bus_space.bst,
167212793Sdim		    map->lm_data.bus_space.bsh, offset, value);
168212793Sdim#elif _BYTE_ORDER == _LITTLE_ENDIAN
169212793Sdim		bus_space_write_4(map->lm_data.bus_space.bst,
170212793Sdim		    map->lm_data.bus_space.bsh, offset, (value & 0xffffffffU));
171212793Sdim		bus_space_write_4(map->lm_data.bus_space.bst,
172212793Sdim		    map->lm_data.bus_space.bsh, (offset + 4), (value >> 32));
173212793Sdim#else
174212793Sdim		bus_space_write_4(map->lm_data.bus_space.bst,
175212793Sdim		    map->lm_data.bus_space.bsh, offset, (value >> 32));
176212793Sdim		bus_space_write_4(map->lm_data.bus_space.bst,
177212793Sdim		    map->lm_data.bus_space.bsh, (offset + 4),
178212793Sdim		    (value & 0xffffffffU));
179212793Sdim#endif
180212793Sdim	} else {
181212793Sdim		*(volatile uint64_t *)((vaddr_t)map->handle + offset) = value;
182212793Sdim	}
183212793Sdim}
184212793Sdim
185212793Sdim#endif	/* _DRM_DRM_IOMAP_NETBSD_H_ */
186212793Sdim