1 /* $NetBSD: bus_space.c,v 1.14 2023/12/20 15:29:05 thorpej Exp $ */
2
3 /*
4 * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
9 * Simulation Facility, NASA Ames Research Center.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: bus_space.c,v 1.14 2023/12/20 15:29:05 thorpej Exp $");
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38
39 #include <uvm/uvm_extern.h>
40
41 #include <machine/bus.h>
42
43 void
mipsco_bus_space_init(bus_space_tag_t bst,const char * name,paddr_t paddr,vaddr_t vaddr,bus_addr_t start,bus_size_t size)44 mipsco_bus_space_init(bus_space_tag_t bst, const char *name, paddr_t paddr, vaddr_t vaddr, bus_addr_t start, bus_size_t size)
45 {
46 bst->bs_name = name;
47 bst->bs_spare = NULL;
48 bst->bs_start = start;
49 bst->bs_size = size;
50 bst->bs_pbase = paddr;
51 bst->bs_vbase = vaddr;
52 bst->bs_compose_handle = mipsco_bus_space_compose_handle;
53 bst->bs_dispose_handle = mipsco_bus_space_dispose_handle;
54 bst->bs_paddr = mipsco_bus_space_paddr;
55 bst->bs_map = mipsco_bus_space_map;
56 bst->bs_unmap = mipsco_bus_space_unmap;
57 bst->bs_subregion = mipsco_bus_space_subregion;
58 bst->bs_mmap = mipsco_bus_space_mmap;
59 bst->bs_alloc = mipsco_bus_space_alloc;
60 bst->bs_free = mipsco_bus_space_free;
61 bst->bs_aux = NULL;
62 bst->bs_bswap = 0; /* No byte swap for stream methods */
63 mipsco_bus_space_set_aligned_stride(bst, 0);
64 }
65
66 void
mipsco_bus_space_set_aligned_stride(bus_space_tag_t bst,unsigned int shift)67 mipsco_bus_space_set_aligned_stride(bus_space_tag_t bst, unsigned int shift)
68 /* shift: log2(alignment) */
69 {
70 bst->bs_stride = shift;
71
72 if (shift == 2) { /* XXX Assumes Big Endian & 4B */
73 bst->bs_offset_1 = 3;
74 bst->bs_offset_2 = 2;
75 } else {
76 bst->bs_offset_1 = 0;
77 bst->bs_offset_2 = 0;
78 }
79 bst->bs_offset_4 = 0;
80 bst->bs_offset_8 = 0;
81 }
82
83 int
mipsco_bus_space_compose_handle(bus_space_tag_t bst,bus_addr_t addr,bus_size_t size,int flags,bus_space_handle_t * bshp)84 mipsco_bus_space_compose_handle(bus_space_tag_t bst, bus_addr_t addr, bus_size_t size, int flags, bus_space_handle_t *bshp)
85 {
86 bus_space_handle_t bsh = bst->bs_vbase +
87 ((addr - bst->bs_start) << bst->bs_stride);
88
89 /*
90 * Since all buses can be linearly mappable, we don't have to check
91 * BUS_SPACE_MAP_LINEAR and BUS_SPACE_MAP_PREFETCHABLE.
92 */
93 if ((flags & BUS_SPACE_MAP_CACHEABLE) == 0) {
94 *bshp = bsh;
95 return (0);
96 }
97 if (bsh < MIPS_KSEG1_START) /* KUSEG or KSEG0 */
98 panic("mipsco_bus_space_compose_handle: bad address 0x%x", bsh);
99 if (bsh < MIPS_KSEG2_START) { /* KSEG1 */
100 *bshp = MIPS_PHYS_TO_KSEG0(MIPS_KSEG1_TO_PHYS(bsh));
101 return (0);
102 }
103 /*
104 * KSEG2:
105 * Do not make the page cacheable in this case, since:
106 * - the page which this bus_space belongs might include
107 * other bus_spaces.
108 * or
109 * - this bus might be mapped by wired TLB, in that case,
110 * we cannot manupulate cacheable attribute with page granularity.
111 */
112 #ifdef DIAGNOSTIC
113 printf("mipsco_bus_space_compose_handle: ignore cacheable 0x%x\n", bsh);
114 #endif
115 *bshp = bsh;
116 return (0);
117 }
118
119 int
mipsco_bus_space_dispose_handle(bus_space_tag_t bst,bus_space_handle_t bsh,bus_size_t size)120 mipsco_bus_space_dispose_handle(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t size)
121 {
122 return (0);
123 }
124
125 int
mipsco_bus_space_paddr(bus_space_tag_t bst,bus_space_handle_t bsh,paddr_t * pap)126 mipsco_bus_space_paddr(bus_space_tag_t bst, bus_space_handle_t bsh, paddr_t *pap)
127 {
128 if (bsh < MIPS_KSEG0_START) /* KUSEG */
129 panic("mipsco_bus_space_paddr(%p): bad address", (void *)bsh);
130 else if (bsh < MIPS_KSEG1_START) /* KSEG0 */
131 *pap = MIPS_KSEG0_TO_PHYS(bsh);
132 else if (bsh < MIPS_KSEG2_START) /* KSEG1 */
133 *pap = MIPS_KSEG1_TO_PHYS(bsh);
134 else { /* KSEG2 */
135 /*
136 * Since this region may be mapped by wired TLB,
137 * kvtophys() is not always available.
138 */
139 *pap = bst->bs_pbase + (bsh - bst->bs_vbase);
140 }
141 return (0);
142 }
143
144 int
mipsco_bus_space_map(bus_space_tag_t bst,bus_addr_t addr,bus_size_t size,int flags,bus_space_handle_t * bshp)145 mipsco_bus_space_map(bus_space_tag_t bst, bus_addr_t addr, bus_size_t size, int flags, bus_space_handle_t *bshp)
146 {
147
148 if (addr < bst->bs_start || addr + size > bst->bs_start + bst->bs_size)
149 return (EINVAL);
150
151 return (bus_space_compose_handle(bst, addr, size, flags, bshp));
152 }
153
154 void
mipsco_bus_space_unmap(bus_space_tag_t bst,bus_space_handle_t bsh,bus_size_t size)155 mipsco_bus_space_unmap(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t size)
156 {
157 bus_space_dispose_handle(bst, bsh, size);
158 }
159
160 int
mipsco_bus_space_subregion(bus_space_tag_t bst,bus_space_handle_t bsh,bus_size_t offset,bus_size_t size,bus_space_handle_t * nbshp)161 mipsco_bus_space_subregion(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp)
162 {
163 *nbshp = bsh + (offset << bst->bs_stride);
164 return (0);
165 }
166
167 paddr_t
mipsco_bus_space_mmap(bus_space_tag_t bst,bus_addr_t addr,off_t off,int prot,int flags)168 mipsco_bus_space_mmap(bus_space_tag_t bst, bus_addr_t addr, off_t off, int prot, int flags)
169 {
170
171 /*
172 * XXX We do not disallow mmap'ing of I/O space here,
173 * XXX which we should be doing.
174 */
175
176 if (addr < bst->bs_start ||
177 (addr + off) >= (bst->bs_start + bst->bs_size))
178 return (-1);
179
180 return (mips_btop(bst->bs_pbase + (addr - bst->bs_start) + off));
181 }
182
183 int
mipsco_bus_space_alloc(bus_space_tag_t bst,bus_addr_t start,bus_addr_t end,bus_size_t size,bus_size_t align,bus_size_t boundary,int flags,bus_addr_t * addrp,bus_space_handle_t * bshp)184 mipsco_bus_space_alloc(bus_space_tag_t bst, bus_addr_t start, bus_addr_t end, bus_size_t size, bus_size_t align, bus_size_t boundary, int flags, bus_addr_t *addrp, bus_space_handle_t *bshp)
185 {
186
187 panic("bus_space_alloc() not implemented");
188 }
189