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 } 138 } 139 140 /** 141 * Populate the resource list and bcma_map RIDs using the maps defined on 142 * @p ports. 143 * 144 * @param bus The requesting bus device. 145 * @param dinfo The device info instance to be initialized. 146 * @param ports The set of ports to be enumerated 147 */ 148 static void 149 bcma_dinfo_init_resource_info(device_t bus, struct bcma_devinfo *dinfo, 150 struct bcma_sport_list *ports) 151 { 152 struct bcma_map *map; 153 struct bcma_sport *port; 154 bhnd_addr_t end; 155 156 STAILQ_FOREACH(port, ports, sp_link) { 157 STAILQ_FOREACH(map, &port->sp_maps, m_link) { 158 /* 159 * Create the corresponding device resource list entry. 160 * 161 * We necessarily skip registration if the region's 162 * device memory range is not representable via 163 * rman_res_t. 164 * 165 * When rman_res_t is migrated to uintmax_t, any 166 * range should be representable. 167 */ 168 end = map->m_base + map->m_size; 169 if (map->m_base <= RM_MAX_END && end <= RM_MAX_END) { 170 map->m_rid = resource_list_add_next( 171 &dinfo->resources, SYS_RES_MEMORY, 172 map->m_base, end, map->m_size); 173 } else if (bootverbose) { 174 device_printf(bus, 175 "core%u %s%u.%u: region %llx-%llx extends " 176 "beyond supported addressable range\n", 177 dinfo->corecfg->core_info.core_idx, 178 bhnd_port_type_name(port->sp_type), 179 port->sp_num, map->m_region_num, 180 (unsigned long long) map->m_base, 181 (unsigned long long) end); 182 } 183 } 184 } 185 } 186 187 /** 188 * Allocate and initialize new device info structure, assuming ownership 189 * of the provided core configuration. 190 * 191 * @param bus The requesting bus device. 192 * @param corecfg Device core configuration. 193 */ 194 struct bcma_devinfo * 195 bcma_alloc_dinfo(device_t bus, struct bcma_corecfg *corecfg) 196 { 197 struct bcma_devinfo *dinfo; 198 199 dinfo = malloc(sizeof(struct bcma_devinfo), M_BHND, M_NOWAIT); 200 if (dinfo == NULL) 201 return NULL; 202 203 dinfo->corecfg = corecfg; 204 dinfo->res_agent = NULL; 205 dinfo->rid_agent = -1; 206 207 resource_list_init(&dinfo->resources); 208 209 /* The device ports must always be initialized first to ensure that 210 * rid 0 maps to the first device port */ 211 bcma_dinfo_init_resource_info(bus, dinfo, &corecfg->dev_ports); 212 213 bcma_dinfo_init_resource_info(bus, dinfo, &corecfg->bridge_ports); 214 bcma_dinfo_init_resource_info(bus, dinfo, &corecfg->wrapper_ports); 215 216 return dinfo; 217 } 218 219 /** 220 * Deallocate the given device info structure and any associated resources. 221 * 222 * @param bus The requesting bus device. 223 * @param dinfo Device info to be deallocated. 224 */ 225 void 226 bcma_free_dinfo(device_t bus, struct bcma_devinfo *dinfo) 227 { 228 bcma_free_corecfg(dinfo->corecfg); 229 resource_list_free(&dinfo->resources); 230 231 /* Release agent resource, if any */ 232 if (dinfo->res_agent != NULL) { 233 bhnd_release_resource(bus, SYS_RES_MEMORY, dinfo->rid_agent, 234 dinfo->res_agent); 235 } 236 237 free(dinfo, M_BHND); 238 } 239 240 241 /** 242 * Allocate and initialize new slave port descriptor. 243 * 244 * @param port_num Per-core port number. 245 * @param port_type Port type. 246 */ 247 struct bcma_sport * 248 bcma_alloc_sport(bcma_pid_t port_num, bhnd_port_type port_type) 249 { 250 struct bcma_sport *sport; 251 252 sport = malloc(sizeof(struct bcma_sport), M_BHND, M_NOWAIT); 253 if (sport == NULL) 254 return NULL; 255 256 sport->sp_num = port_num; 257 sport->sp_type = port_type; 258 sport->sp_num_maps = 0; 259 STAILQ_INIT(&sport->sp_maps); 260 261 return sport; 262 } 263 264 /** 265 * Deallocate all resources associated with the given port descriptor. 266 * 267 * @param sport Port descriptor to be deallocated. 268 */ 269 void 270 bcma_free_sport(struct bcma_sport *sport) { 271 struct bcma_map *map, *mapnext; 272 273 STAILQ_FOREACH_SAFE(map, &sport->sp_maps, m_link, mapnext) { 274 free(map, M_BHND); 275 } 276 277 free(sport, M_BHND); 278 } 279 280