1 /* $NetBSD: elb.c,v 1.11 2021/08/07 16:18:52 thorpej Exp $ */
2
3 /*-
4 * Copyright (c) 2003 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Juergen Hannken-Illjes.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. 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 distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: elb.c,v 1.11 2021/08/07 16:18:52 thorpej Exp $");
34
35 #include <sys/param.h>
36 #include <sys/conf.h>
37 #include <sys/device.h>
38 #include <sys/systm.h>
39 #include <sys/extent.h>
40
41 #include <machine/explora.h>
42 #define _POWERPC_BUS_DMA_PRIVATE
43 #include <sys/bus.h>
44
45 #include <powerpc/ibm4xx/dcr403cgx.h>
46
47 #include <evbppc/explora/dev/elbvar.h>
48
49 struct elb_dev {
50 const char *elb_name;
51 int elb_addr;
52 int elb_addr2;
53 int elb_irq;
54 bus_space_tag_t elb_bt;
55 };
56
57 static int elb_match(device_t, cfdata_t, void *);
58 static void elb_attach(device_t, device_t, void *);
59 static int elb_print(void *, const char *);
60
61 static struct powerpc_bus_space elb_tag = {
62 _BUS_SPACE_LITTLE_ENDIAN | _BUS_SPACE_MEM_TYPE | 1, /* stride 1 */
63 0x00000000,
64 BASE_PCKBC,
65 BASE_PCKBC + 0x6ff
66 };
67 static struct powerpc_bus_space elb_fb_tag = {
68 _BUS_SPACE_LITTLE_ENDIAN | _BUS_SPACE_MEM_TYPE,
69 0x00000000,
70 BASE_FB,
71 BASE_FB2 + SIZE_FB - 1
72 };
73
74 static char elb_ex_storage[EXTENT_FIXED_STORAGE_SIZE(8)]
75 __attribute__((aligned(8)));
76 static char elbfb_ex_storage[EXTENT_FIXED_STORAGE_SIZE(8)]
77 __attribute__((aligned(8)));
78
79 static bool elb_tag_init_done;
80 static bool elbfb_tag_init_done;
81
82 /*
83 * DMA struct, nothing special.
84 */
85 static struct powerpc_bus_dma_tag elb_bus_dma_tag = {
86 0, /* _bounce_thresh */
87 _bus_dmamap_create,
88 _bus_dmamap_destroy,
89 _bus_dmamap_load,
90 _bus_dmamap_load_mbuf,
91 _bus_dmamap_load_uio,
92 _bus_dmamap_load_raw,
93 _bus_dmamap_unload,
94 _bus_dmamap_sync,
95 _bus_dmamem_alloc,
96 _bus_dmamem_free,
97 _bus_dmamem_map,
98 _bus_dmamem_unmap,
99 _bus_dmamem_mmap,
100 _bus_dma_phys_to_bus_mem_generic,
101 _bus_dma_bus_mem_to_phys_generic,
102 };
103
104 static const struct elb_dev elb_devs[] = {
105 { "cpu", 0, 0, -1, NULL },
106 { "pckbc", BASE_PCKBC, BASE_PCKBC2, 31, &elb_tag },
107 { "com", BASE_COM, 0, 30, &elb_tag },
108 { "lpt", BASE_LPT, 0, -1, &elb_tag },
109 { "fb", BASE_FB, BASE_FB2, -1, &elb_fb_tag },
110 { "le", BASE_LE, 0, 28, &elb_fb_tag },
111 };
112
113 CFATTACH_DECL_NEW(elb, 0,
114 elb_match, elb_attach, NULL, NULL);
115
116 /*
117 * Probe for the elb; always succeeds.
118 */
119 static int
elb_match(device_t parent,cfdata_t cf,void * aux)120 elb_match(device_t parent, cfdata_t cf, void *aux)
121 {
122 return (1);
123 }
124
125 /*
126 * Attach the Explora local bus.
127 */
128 static void
elb_attach(device_t parent,device_t self,void * aux)129 elb_attach(device_t parent, device_t self, void *aux)
130 {
131 struct elb_attach_args eaa;
132 const struct elb_dev *elb;
133 size_t i;
134
135 printf("\n");
136 for (i = 0, elb = elb_devs; i < __arraycount(elb_devs); i++, elb++) {
137 eaa.elb_name = elb->elb_name;
138 eaa.elb_bt = elb_get_bus_space_tag(elb->elb_addr);
139 eaa.elb_dmat = &elb_bus_dma_tag;
140 eaa.elb_base = elb->elb_addr;
141 eaa.elb_base2 = elb->elb_addr2;
142 eaa.elb_irq = elb->elb_irq;
143
144 (void) config_found(self, &eaa, elb_print, CFARGS_NONE);
145 }
146 }
147
148 static int
elb_print(void * aux,const char * pnp)149 elb_print(void *aux, const char *pnp)
150 {
151 struct elb_attach_args *eaa = aux;
152
153 if (pnp)
154 aprint_normal("%s at %s", eaa->elb_name, pnp);
155 if (eaa->elb_irq != -1)
156 aprint_normal(" irq %d", eaa->elb_irq);
157
158 return (UNCONF);
159 }
160
161 bus_space_tag_t
elb_get_bus_space_tag(bus_addr_t addr)162 elb_get_bus_space_tag(bus_addr_t addr)
163 {
164
165 if ((addr & 0xff000000) == 0x74000000) {
166 if (!elb_tag_init_done) {
167 if (bus_space_init(&elb_tag, "elbtag",
168 elb_ex_storage, sizeof(elb_ex_storage)))
169 panic("elb_get_bus_space_tag: elb_tag");
170
171 elb_tag_init_done = true;
172 }
173 return (&elb_tag);
174 } else {
175 if (!elbfb_tag_init_done) {
176 if (bus_space_init(&elb_fb_tag, "elbfbtag",
177 elbfb_ex_storage, sizeof(elbfb_ex_storage)))
178 panic("elb_get_bus_space_tag: elb_fb_tag");
179
180 elbfb_tag_init_done = true;
181 }
182 return (&elb_fb_tag);
183 }
184 }
185