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