xref: /freebsd/sys/dev/bhnd/bcma/bcma_subr.c (revision cdf63a700c77204252e3c2e38d7106965559f3c6)
1 /*-
2  * Copyright (c) 2015 Landon Fuller <landon@landonf.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer,
10  *    without modification.
11  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13  *    redistribution must be conditioned upon including a substantially
14  *    similar Disclaimer requirement for further binary redistribution.
15  *
16  * NO WARRANTY
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27  * THE POSSIBILITY OF SUCH DAMAGES.
28  */
29 
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32 
33 #include <sys/param.h>
34 #include <sys/bus.h>
35 #include <sys/kernel.h>
36 #include <sys/limits.h>
37 #include <sys/systm.h>
38 
39 #include <machine/bus.h>
40 #include <machine/resource.h>
41 
42 #include <dev/bhnd/bhndvar.h>
43 
44 #include "bcmavar.h"
45 
46  /**
47  * Allocate and initialize new core config structure.
48  *
49  * @param core_index Core index on the bus.
50  * @param core_unit Core unit number.
51  * @param vendor Core designer.
52  * @param device Core identifier (e.g. part number).
53  * @param hwrev Core revision.
54  */
55 struct bcma_corecfg *
56 bcma_alloc_corecfg(u_int core_index, int core_unit, uint16_t vendor,
57     uint16_t device, uint8_t hwrev)
58 {
59 	struct bcma_corecfg *cfg;
60 
61 	cfg = malloc(sizeof(*cfg), M_BHND, M_NOWAIT);
62 	if (cfg == NULL)
63 		return NULL;
64 
65 	cfg->core_info = (struct bhnd_core_info) {
66 		.vendor = vendor,
67 		.device = device,
68 		.hwrev = hwrev,
69 		.core_idx = core_index,
70 		.unit = core_unit
71 	};
72 
73 	STAILQ_INIT(&cfg->master_ports);
74 	cfg->num_master_ports = 0;
75 
76 	STAILQ_INIT(&cfg->dev_ports);
77 	cfg->num_dev_ports = 0;
78 
79 	STAILQ_INIT(&cfg->bridge_ports);
80 	cfg->num_bridge_ports = 0;
81 
82 	STAILQ_INIT(&cfg->wrapper_ports);
83 	cfg->num_wrapper_ports = 0;
84 
85 	return (cfg);
86 }
87 
88 /**
89  * Deallocate the given core config and any associated resources.
90  *
91  * @param corecfg Core info to be deallocated.
92  */
93 void
94 bcma_free_corecfg(struct bcma_corecfg *corecfg)
95 {
96 	struct bcma_mport *mport, *mnext;
97 	struct bcma_sport *sport, *snext;
98 
99 	STAILQ_FOREACH_SAFE(mport, &corecfg->master_ports, mp_link, mnext) {
100 		free(mport, M_BHND);
101 	}
102 
103 	STAILQ_FOREACH_SAFE(sport, &corecfg->dev_ports, sp_link, snext) {
104 		bcma_free_sport(sport);
105 	}
106 
107 	STAILQ_FOREACH_SAFE(sport, &corecfg->bridge_ports, sp_link, snext) {
108 		bcma_free_sport(sport);
109 	}
110 
111 	STAILQ_FOREACH_SAFE(sport, &corecfg->wrapper_ports, sp_link, snext) {
112 		bcma_free_sport(sport);
113 	}
114 
115 	free(corecfg, M_BHND);
116 }
117 
118 /**
119  * Return the @p cfg port list for @p type.
120  *
121  * @param cfg The core configuration.
122  * @param type The requested port type.
123  */
124 struct bcma_sport_list *
125 bcma_corecfg_get_port_list(struct bcma_corecfg *cfg, bhnd_port_type type)
126 {
127 	switch (type) {
128 	case BHND_PORT_DEVICE:
129 		return (&cfg->dev_ports);
130 		break;
131 	case BHND_PORT_BRIDGE:
132 		return (&cfg->bridge_ports);
133 		break;
134 	case BHND_PORT_AGENT:
135 		return (&cfg->wrapper_ports);
136 		break;
137 	default:
138 		return (NULL);
139 	}
140 }
141 
142 /**
143  * Populate the resource list and bcma_map RIDs using the maps defined on
144  * @p ports.
145  *
146  * @param bus The requesting bus device.
147  * @param dinfo The device info instance to be initialized.
148  * @param ports The set of ports to be enumerated
149  */
150 static void
151 bcma_dinfo_init_resource_info(device_t bus, struct bcma_devinfo *dinfo,
152     struct bcma_sport_list *ports)
153 {
154 	struct bcma_map		*map;
155 	struct bcma_sport	*port;
156 	bhnd_addr_t		 end;
157 
158 	STAILQ_FOREACH(port, ports, sp_link) {
159 		STAILQ_FOREACH(map, &port->sp_maps, m_link) {
160 			/*
161 			 * Create the corresponding device resource list entry.
162 			 *
163 			 * We necessarily skip registration if the region's
164 			 * device memory range is not representable via
165 			 * rman_res_t.
166 			 *
167 			 * When rman_res_t is migrated to uintmax_t, any
168 			 * range should be representable.
169 			 */
170 			end = map->m_base + map->m_size;
171 			if (map->m_base <= RM_MAX_END && end <= RM_MAX_END) {
172 				map->m_rid = resource_list_add_next(
173 				    &dinfo->resources, SYS_RES_MEMORY,
174 				    map->m_base, end, map->m_size);
175 			} else if (bootverbose) {
176 				device_printf(bus,
177 				    "core%u %s%u.%u: region %llx-%llx extends "
178 				        "beyond supported addressable range\n",
179 				    dinfo->corecfg->core_info.core_idx,
180 				    bhnd_port_type_name(port->sp_type),
181 				    port->sp_num, map->m_region_num,
182 				    (unsigned long long) map->m_base,
183 				    (unsigned long long) end);
184 			}
185 		}
186 	}
187 }
188 
189 /**
190  * Allocate and initialize new device info structure, assuming ownership
191  * of the provided core configuration.
192  *
193  * @param bus The requesting bus device.
194  * @param corecfg Device core configuration.
195  */
196 struct bcma_devinfo *
197 bcma_alloc_dinfo(device_t bus, struct bcma_corecfg *corecfg)
198 {
199 	struct bcma_devinfo *dinfo;
200 
201 	dinfo = malloc(sizeof(struct bcma_devinfo), M_BHND, M_NOWAIT);
202 	if (dinfo == NULL)
203 		return NULL;
204 
205 	dinfo->corecfg = corecfg;
206 	dinfo->res_agent = NULL;
207 	dinfo->rid_agent = -1;
208 
209 	resource_list_init(&dinfo->resources);
210 
211 	/* The device ports must always be initialized first to ensure that
212 	 * rid 0 maps to the first device port */
213 	bcma_dinfo_init_resource_info(bus, dinfo, &corecfg->dev_ports);
214 
215 	bcma_dinfo_init_resource_info(bus, dinfo, &corecfg->bridge_ports);
216 	bcma_dinfo_init_resource_info(bus, dinfo, &corecfg->wrapper_ports);
217 
218 	return dinfo;
219 }
220 
221 /**
222  * Deallocate the given device info structure and any associated resources.
223  *
224  * @param bus The requesting bus device.
225  * @param dinfo Device info to be deallocated.
226  */
227 void
228 bcma_free_dinfo(device_t bus, struct bcma_devinfo *dinfo)
229 {
230 	bcma_free_corecfg(dinfo->corecfg);
231 	resource_list_free(&dinfo->resources);
232 
233 	/* Release agent resource, if any */
234 	if (dinfo->res_agent != NULL) {
235 		bhnd_release_resource(bus, SYS_RES_MEMORY, dinfo->rid_agent,
236 		    dinfo->res_agent);
237 	}
238 
239 	free(dinfo, M_BHND);
240 }
241 
242 
243 /**
244  * Allocate and initialize new slave port descriptor.
245  *
246  * @param port_num Per-core port number.
247  * @param port_type Port type.
248  */
249 struct bcma_sport *
250 bcma_alloc_sport(bcma_pid_t port_num, bhnd_port_type port_type)
251 {
252 	struct bcma_sport *sport;
253 
254 	sport = malloc(sizeof(struct bcma_sport), M_BHND, M_NOWAIT);
255 	if (sport == NULL)
256 		return NULL;
257 
258 	sport->sp_num = port_num;
259 	sport->sp_type = port_type;
260 	sport->sp_num_maps = 0;
261 	STAILQ_INIT(&sport->sp_maps);
262 
263 	return sport;
264 }
265 
266 /**
267  * Deallocate all resources associated with the given port descriptor.
268  *
269  * @param sport Port descriptor to be deallocated.
270  */
271 void
272 bcma_free_sport(struct bcma_sport *sport) {
273 	struct bcma_map *map, *mapnext;
274 
275 	STAILQ_FOREACH_SAFE(map, &sport->sp_maps, m_link, mapnext) {
276 		free(map, M_BHND);
277 	}
278 
279 	free(sport, M_BHND);
280 }
281 
282