1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2016 Landon Fuller <landonf@FreeBSD.org>
5 * Copyright (c) 2017 The FreeBSD Foundation
6 * All rights reserved.
7 *
8 * Portions of this software were developed by Landon Fuller
9 * under sponsorship from the FreeBSD Foundation.
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 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
19 * redistribution must be conditioned upon including a substantially
20 * similar Disclaimer requirement for further binary redistribution.
21 *
22 * NO WARRANTY
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
26 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
27 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
28 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
31 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
33 * THE POSSIBILITY OF SUCH DAMAGES.
34 */
35
36 #include <sys/param.h>
37 #include <sys/bus.h>
38 #include <sys/kobj.h>
39
40 #include <machine/bus.h>
41 #include <sys/rman.h>
42 #include <machine/resource.h>
43
44 #include <dev/bhnd/bhndreg.h>
45 #include <dev/bhnd/bhndvar.h>
46
47 #include <dev/bhnd/bhnd_erom.h>
48 #include <dev/bhnd/bhnd_eromvar.h>
49
50 #include <dev/bhnd/cores/chipc/chipcreg.h>
51
52 static int bhnd_erom_iores_map(struct bhnd_erom_io *eio, bhnd_addr_t addr,
53 bhnd_size_t size);
54 static int bhnd_erom_iores_tell(struct bhnd_erom_io *eio,
55 bhnd_addr_t *addr, bhnd_size_t *size);
56 static uint32_t bhnd_erom_iores_read(struct bhnd_erom_io *eio,
57 bhnd_size_t offset, u_int width);
58 static void bhnd_erom_iores_fini(struct bhnd_erom_io *eio);
59
60 static int bhnd_erom_iobus_map(struct bhnd_erom_io *eio, bhnd_addr_t addr,
61 bhnd_size_t size);
62 static int bhnd_erom_iobus_tell(struct bhnd_erom_io *eio,
63 bhnd_addr_t *addr, bhnd_size_t *size);
64 static uint32_t bhnd_erom_iobus_read(struct bhnd_erom_io *eio,
65 bhnd_size_t offset, u_int width);
66
67 /**
68 * An implementation of bhnd_erom_io that manages mappings via
69 * bhnd_alloc_resource() and bhnd_release_resource().
70 */
71 struct bhnd_erom_iores {
72 struct bhnd_erom_io eio;
73 device_t owner; /**< device from which we'll allocate resources */
74 int owner_rid; /**< rid to use when allocating new mappings */
75 struct bhnd_resource *mapped; /**< current mapping, or NULL */
76 };
77
78 /**
79 * Fetch the device enumeration parser class from all bhnd(4)-compatible drivers
80 * registered for @p bus_devclass, probe @p eio for supporting parser classes,
81 * and return the best available supporting enumeration parser class.
82 *
83 * @param bus_devclass The bus device class to be queried for
84 * bhnd(4)-compatible drivers.
85 * @param eio An erom bus I/O instance, configured with a
86 * mapping of the first bus core.
87 * @param hint Identification hint used to identify the device.
88 * If the chipset supports standard chip
89 * identification registers within the first core,
90 * this parameter should be NULL.
91 * @param[out] cid On success, the probed chip identifier.
92 *
93 * @retval non-NULL on success, the best available EROM class.
94 * @retval NULL if no erom class returned a successful probe result for
95 * @p eio.
96 */
97 bhnd_erom_class_t *
bhnd_erom_probe_driver_classes(devclass_t bus_devclass,struct bhnd_erom_io * eio,const struct bhnd_chipid * hint,struct bhnd_chipid * cid)98 bhnd_erom_probe_driver_classes(devclass_t bus_devclass,
99 struct bhnd_erom_io *eio, const struct bhnd_chipid *hint,
100 struct bhnd_chipid *cid)
101 {
102 driver_t **drivers;
103 int drv_count;
104 bhnd_erom_class_t *erom_cls;
105 int error, prio, result;
106
107 erom_cls = NULL;
108 prio = 0;
109
110 /* Fetch all available drivers */
111 error = devclass_get_drivers(bus_devclass, &drivers, &drv_count);
112 if (error) {
113 printf("error fetching bhnd(4) drivers for %s: %d\n",
114 devclass_get_name(bus_devclass), error);
115 return (NULL);
116 }
117
118 /* Enumerate the drivers looking for the best available EROM class */
119 for (int i = 0; i < drv_count; i++) {
120 struct bhnd_chipid pcid;
121 bhnd_erom_class_t *cls;
122
123 /* The default implementation of BHND_BUS_GET_EROM_CLASS()
124 * returns NULL if unimplemented; this should always be safe
125 * to call on arbitrary drivers */
126 cls = bhnd_driver_get_erom_class(drivers[i]);
127 if (cls == NULL)
128 continue;
129
130 kobj_class_compile(cls);
131
132 /* Probe the bus */
133 result = bhnd_erom_probe(cls, eio, hint, &pcid);
134
135 /* The parser did not match if an error was returned */
136 if (result > 0)
137 continue;
138
139 /* Check for a new highest priority match */
140 if (erom_cls == NULL || result > prio) {
141 prio = result;
142
143 *cid = pcid;
144 erom_cls = cls;
145 }
146
147 /* Terminate immediately on BUS_PROBE_SPECIFIC */
148 if (result == BUS_PROBE_SPECIFIC)
149 break;
150 }
151
152 free(drivers, M_TEMP);
153 return (erom_cls);
154 }
155
156 /**
157 * Allocate and return a new device enumeration table parser.
158 *
159 * @param cls The parser class for which an instance will be
160 * allocated.
161 * @param eio The bus I/O callbacks to use when reading the device
162 * enumeration table.
163 * @param cid The device's chip identifier.
164 *
165 * @retval non-NULL success
166 * @retval NULL if an error occurred allocating or initializing the
167 * EROM parser.
168 */
169 bhnd_erom_t *
bhnd_erom_alloc(bhnd_erom_class_t * cls,const struct bhnd_chipid * cid,struct bhnd_erom_io * eio)170 bhnd_erom_alloc(bhnd_erom_class_t *cls, const struct bhnd_chipid *cid,
171 struct bhnd_erom_io *eio)
172 {
173 bhnd_erom_t *erom;
174 int error;
175
176 erom = (bhnd_erom_t *)kobj_create((kobj_class_t)cls, M_BHND,
177 M_WAITOK|M_ZERO);
178
179 if ((error = BHND_EROM_INIT(erom, cid, eio))) {
180 printf("error initializing %s parser at %#jx: %d\n", cls->name,
181 (uintmax_t)cid->enum_addr, error);
182
183 kobj_delete((kobj_t)erom, M_BHND);
184 return (NULL);
185 }
186
187 return (erom);
188 }
189
190 /**
191 * Perform static initialization of a device enumeration table parser.
192 *
193 * This may be used to initialize a caller-allocated erom instance state
194 * during early boot, prior to malloc availability.
195 *
196 * @param cls The parser class for which an instance will be
197 * allocated.
198 * @param erom The erom parser instance to initialize.
199 * @param esize The total available number of bytes allocated for
200 * @p erom. If this is less than is required by @p cls,
201 * ENOMEM will be returned.
202 * @param cid The device's chip identifier.
203 * @param eio The bus I/O callbacks to use when reading the device
204 * enumeration table.
205 *
206 * @retval 0 success
207 * @retval ENOMEM if @p esize is smaller than required by @p cls.
208 * @retval non-zero if an error occurs initializing the EROM parser,
209 * a regular unix error code will be returned.
210 */
211 int
bhnd_erom_init_static(bhnd_erom_class_t * cls,bhnd_erom_t * erom,size_t esize,const struct bhnd_chipid * cid,struct bhnd_erom_io * eio)212 bhnd_erom_init_static(bhnd_erom_class_t *cls, bhnd_erom_t *erom, size_t esize,
213 const struct bhnd_chipid *cid, struct bhnd_erom_io *eio)
214 {
215 kobj_class_t kcls;
216
217 kcls = (kobj_class_t)cls;
218
219 /* Verify allocation size */
220 if (kcls->size > esize)
221 return (ENOMEM);
222
223 /* Perform instance initialization */
224 kobj_init_static((kobj_t)erom, kcls);
225 return (BHND_EROM_INIT(erom, cid, eio));
226 }
227
228 /**
229 * Release any resources held by a @p erom parser previously
230 * initialized via bhnd_erom_init_static().
231 *
232 * @param erom An erom parser instance previously initialized via
233 * bhnd_erom_init_static().
234 */
235 void
bhnd_erom_fini_static(bhnd_erom_t * erom)236 bhnd_erom_fini_static(bhnd_erom_t *erom)
237 {
238 return (BHND_EROM_FINI(erom));
239 }
240
241 /**
242 * Release all resources held by a @p erom parser previously
243 * allocated via bhnd_erom_alloc().
244 *
245 * @param erom An erom parser instance previously allocated via
246 * bhnd_erom_alloc().
247 */
248 void
bhnd_erom_free(bhnd_erom_t * erom)249 bhnd_erom_free(bhnd_erom_t *erom)
250 {
251 BHND_EROM_FINI(erom);
252 kobj_delete((kobj_t)erom, M_BHND);
253 }
254
255 /**
256 * Read the chip identification registers mapped by @p eio, popuating @p cid
257 * with the parsed result
258 *
259 * @param eio A bus I/O instance, configured with a mapping
260 * of the ChipCommon core.
261 * @param[out] cid On success, the parsed chip identification.
262 *
263 * @warning
264 * On early siba(4) devices, the ChipCommon core does not provide
265 * a valid CHIPC_ID_NUMCORE field. On these ChipCommon revisions
266 * (see CHIPC_NCORES_MIN_HWREV()), this function will parse and return
267 * an invalid `ncores` value.
268 */
269 int
bhnd_erom_read_chipid(struct bhnd_erom_io * eio,struct bhnd_chipid * cid)270 bhnd_erom_read_chipid(struct bhnd_erom_io *eio, struct bhnd_chipid *cid)
271 {
272 bhnd_addr_t cc_addr;
273 bhnd_size_t cc_size;
274 uint32_t idreg, cc_caps;
275 int error;
276
277 /* Fetch ChipCommon address */
278 if ((error = bhnd_erom_io_tell(eio, &cc_addr, &cc_size)))
279 return (error);
280
281 /* Read chip identifier */
282 idreg = bhnd_erom_io_read(eio, CHIPC_ID, 4);
283
284 /* Extract the basic chip info */
285 cid->chip_id = CHIPC_GET_BITS(idreg, CHIPC_ID_CHIP);
286 cid->chip_pkg = CHIPC_GET_BITS(idreg, CHIPC_ID_PKG);
287 cid->chip_rev = CHIPC_GET_BITS(idreg, CHIPC_ID_REV);
288 cid->chip_type = CHIPC_GET_BITS(idreg, CHIPC_ID_BUS);
289 cid->ncores = CHIPC_GET_BITS(idreg, CHIPC_ID_NUMCORE);
290
291 /* Populate EROM address */
292 if (BHND_CHIPTYPE_HAS_EROM(cid->chip_type)) {
293 cid->enum_addr = bhnd_erom_io_read(eio, CHIPC_EROMPTR, 4);
294 } else {
295 cid->enum_addr = cc_addr;
296 }
297
298 /* Populate capability flags */
299 cc_caps = bhnd_erom_io_read(eio, CHIPC_CAPABILITIES, 4);
300 cid->chip_caps = 0x0;
301
302 if (cc_caps & CHIPC_CAP_BKPLN64)
303 cid->chip_caps |= BHND_CAP_BP64;
304
305 if (cc_caps & CHIPC_CAP_PMU)
306 cid->chip_caps |= BHND_CAP_PMU;
307
308 return (0);
309 }
310
311 /**
312 * Attempt to map @p size bytes at @p addr, replacing any existing
313 * @p eio mapping.
314 *
315 * @param eio I/O instance state.
316 * @param addr The address to be mapped.
317 * @param size The number of bytes to be mapped at @p addr.
318 *
319 * @retval 0 success
320 * @retval non-zero if mapping @p addr otherwise fails, a regular
321 * unix error code should be returned.
322 */
323 int
bhnd_erom_io_map(struct bhnd_erom_io * eio,bhnd_addr_t addr,bhnd_size_t size)324 bhnd_erom_io_map(struct bhnd_erom_io *eio, bhnd_addr_t addr, bhnd_size_t size)
325 {
326 return (eio->map(eio, addr, size));
327 }
328
329 /**
330 * Return the address range mapped by @p eio, if any.
331 *
332 * @param eio I/O instance state.
333 * @param[out] addr The address mapped by @p eio.
334 * @param[out] size The number of bytes mapped at @p addr.
335 *
336 * @retval 0 success
337 * @retval ENXIO if @p eio has no mapping.
338 */
339 int
bhnd_erom_io_tell(struct bhnd_erom_io * eio,bhnd_addr_t * addr,bhnd_size_t * size)340 bhnd_erom_io_tell(struct bhnd_erom_io *eio, bhnd_addr_t *addr,
341 bhnd_size_t *size)
342 {
343 return (eio->tell(eio, addr, size));
344 }
345
346 /**
347 * Read a 1, 2, or 4 byte data item from @p eio, at the given @p offset
348 * relative to @p eio's current mapping.
349 *
350 * @param eio erom I/O callbacks
351 * @param offset read offset.
352 * @param width item width (1, 2, or 4 bytes).
353 */
354 uint32_t
bhnd_erom_io_read(struct bhnd_erom_io * eio,bhnd_size_t offset,u_int width)355 bhnd_erom_io_read(struct bhnd_erom_io *eio, bhnd_size_t offset, u_int width)
356 {
357 return (eio->read(eio, offset, width));
358 }
359
360 /**
361 * Free all resources held by @p eio.
362 */
363 void
bhnd_erom_io_fini(struct bhnd_erom_io * eio)364 bhnd_erom_io_fini(struct bhnd_erom_io *eio)
365 {
366 if (eio->fini != NULL)
367 return (eio->fini(eio));
368 }
369
370 /**
371 * Allocate, initialize, and return a new I/O instance that will perform
372 * mapping by allocating SYS_RES_MEMORY resources from @p dev using @p rid.
373 *
374 * @param dev The device to pass to bhnd_alloc_resource() and
375 * bhnd_release_resource() functions.
376 * @param rid The resource ID to be used when allocating memory resources.
377 */
378 struct bhnd_erom_io *
bhnd_erom_iores_new(device_t dev,int rid)379 bhnd_erom_iores_new(device_t dev, int rid)
380 {
381 struct bhnd_erom_iores *iores;
382
383 iores = malloc(sizeof(*iores), M_BHND, M_WAITOK | M_ZERO);
384 iores->eio.map = bhnd_erom_iores_map;
385 iores->eio.tell = bhnd_erom_iores_tell;
386 iores->eio.read = bhnd_erom_iores_read;
387 iores->eio.fini = bhnd_erom_iores_fini;
388
389 iores->owner = dev;
390 iores->owner_rid = rid;
391 iores->mapped = NULL;
392
393 return (&iores->eio);
394 }
395
396 static int
bhnd_erom_iores_map(struct bhnd_erom_io * eio,bhnd_addr_t addr,bhnd_size_t size)397 bhnd_erom_iores_map(struct bhnd_erom_io *eio, bhnd_addr_t addr,
398 bhnd_size_t size)
399 {
400 struct bhnd_erom_iores *iores;
401
402 iores = (struct bhnd_erom_iores *)eio;
403
404 /* Sanity check the addr/size */
405 if (size == 0)
406 return (EINVAL);
407
408 if (BHND_ADDR_MAX - size < addr)
409 return (EINVAL); /* would overflow */
410
411 /* Check for an existing mapping */
412 if (iores->mapped) {
413 /* If already mapped, nothing else to do */
414 if (rman_get_start(iores->mapped->res) == addr &&
415 rman_get_size(iores->mapped->res) == size)
416 {
417 return (0);
418 }
419
420 /* Otherwise, we need to drop the existing mapping */
421 bhnd_release_resource(iores->owner, iores->mapped);
422 iores->mapped = NULL;
423 }
424
425 /* Try to allocate the new mapping */
426 iores->mapped = bhnd_alloc_resource(iores->owner, SYS_RES_MEMORY,
427 iores->owner_rid, addr, addr+size-1, size,
428 RF_ACTIVE|RF_SHAREABLE);
429 if (iores->mapped == NULL) {
430 return (ENXIO);
431 }
432
433 return (0);
434 }
435
436 static int
bhnd_erom_iores_tell(struct bhnd_erom_io * eio,bhnd_addr_t * addr,bhnd_size_t * size)437 bhnd_erom_iores_tell(struct bhnd_erom_io *eio, bhnd_addr_t *addr,
438 bhnd_size_t *size)
439 {
440 struct bhnd_erom_iores *iores = (struct bhnd_erom_iores *)eio;
441
442 if (iores->mapped == NULL)
443 return (ENXIO);
444
445 *addr = rman_get_start(iores->mapped->res);
446 *size = rman_get_size(iores->mapped->res);
447
448 return (0);
449 }
450
451 static uint32_t
bhnd_erom_iores_read(struct bhnd_erom_io * eio,bhnd_size_t offset,u_int width)452 bhnd_erom_iores_read(struct bhnd_erom_io *eio, bhnd_size_t offset, u_int width)
453 {
454 struct bhnd_erom_iores *iores = (struct bhnd_erom_iores *)eio;
455
456 if (iores->mapped == NULL)
457 panic("read with invalid mapping");
458
459 switch (width) {
460 case 1:
461 return (bhnd_bus_read_1(iores->mapped, offset));
462 case 2:
463 return (bhnd_bus_read_2(iores->mapped, offset));
464 case 4:
465 return (bhnd_bus_read_4(iores->mapped, offset));
466 default:
467 panic("invalid width %u", width);
468 }
469 }
470
471 static void
bhnd_erom_iores_fini(struct bhnd_erom_io * eio)472 bhnd_erom_iores_fini(struct bhnd_erom_io *eio)
473 {
474 struct bhnd_erom_iores *iores = (struct bhnd_erom_iores *)eio;
475
476 /* Release any mapping */
477 if (iores->mapped) {
478 bhnd_release_resource(iores->owner, iores->mapped);
479 iores->mapped = NULL;
480 }
481
482 free(eio, M_BHND);
483 }
484
485 /**
486 * Initialize an I/O instance that will perform mapping directly from the
487 * given bus space tag and handle.
488 *
489 * @param iobus The I/O instance to be initialized.
490 * @param addr The base address mapped by @p bsh.
491 * @param size The total size mapped by @p bsh.
492 * @param bst Bus space tag for @p bsh.
493 * @param bsh Bus space handle mapping the full bus enumeration space.
494 *
495 * @retval 0 success
496 * @retval non-zero if initializing @p iobus otherwise fails, a regular
497 * unix error code will be returned.
498 */
499 int
bhnd_erom_iobus_init(struct bhnd_erom_iobus * iobus,bhnd_addr_t addr,bhnd_size_t size,bus_space_tag_t bst,bus_space_handle_t bsh)500 bhnd_erom_iobus_init(struct bhnd_erom_iobus *iobus, bhnd_addr_t addr,
501 bhnd_size_t size, bus_space_tag_t bst, bus_space_handle_t bsh)
502 {
503 iobus->eio.map = bhnd_erom_iobus_map;
504 iobus->eio.tell = bhnd_erom_iobus_tell;
505 iobus->eio.read = bhnd_erom_iobus_read;
506 iobus->eio.fini = NULL;
507
508 iobus->addr = addr;
509 iobus->size = size;
510 iobus->bst = bst;
511 iobus->bsh = bsh;
512 iobus->mapped = false;
513
514 return (0);
515 }
516
517 static int
bhnd_erom_iobus_map(struct bhnd_erom_io * eio,bhnd_addr_t addr,bhnd_size_t size)518 bhnd_erom_iobus_map(struct bhnd_erom_io *eio, bhnd_addr_t addr,
519 bhnd_size_t size)
520 {
521 struct bhnd_erom_iobus *iobus = (struct bhnd_erom_iobus *)eio;
522
523 /* Sanity check the addr/size */
524 if (size == 0)
525 return (EINVAL);
526
527 /* addr+size must not overflow */
528 if (BHND_ADDR_MAX - size < addr)
529 return (EINVAL);
530
531 /* addr/size must fit within our bus tag's mapping */
532 if (addr < iobus->addr || size > iobus->size)
533 return (ENXIO);
534
535 if (iobus->size - (addr - iobus->addr) < size)
536 return (ENXIO);
537
538 /* The new addr offset and size must be representible as a bus_size_t */
539 if ((addr - iobus->addr) > BUS_SPACE_MAXSIZE)
540 return (ENXIO);
541
542 if (size > BUS_SPACE_MAXSIZE)
543 return (ENXIO);
544
545 iobus->offset = addr - iobus->addr;
546 iobus->limit = size;
547 iobus->mapped = true;
548
549 return (0);
550 }
551
552 static int
bhnd_erom_iobus_tell(struct bhnd_erom_io * eio,bhnd_addr_t * addr,bhnd_size_t * size)553 bhnd_erom_iobus_tell(struct bhnd_erom_io *eio, bhnd_addr_t *addr,
554 bhnd_size_t *size)
555 {
556 struct bhnd_erom_iobus *iobus = (struct bhnd_erom_iobus *)eio;
557
558 if (!iobus->mapped)
559 return (ENXIO);
560
561 *addr = iobus->addr + iobus->offset;
562 *size = iobus->limit;
563
564 return (0);
565 }
566
567 static uint32_t
bhnd_erom_iobus_read(struct bhnd_erom_io * eio,bhnd_size_t offset,u_int width)568 bhnd_erom_iobus_read(struct bhnd_erom_io *eio, bhnd_size_t offset, u_int width)
569 {
570 struct bhnd_erom_iobus *iobus = (struct bhnd_erom_iobus *)eio;
571
572 if (!iobus->mapped)
573 panic("no active mapping");
574
575 if (iobus->limit < width || iobus->limit - width < offset)
576 panic("invalid offset %#jx", offset);
577
578 switch (width) {
579 case 1:
580 return (bus_space_read_1(iobus->bst, iobus->bsh,
581 iobus->offset + offset));
582 case 2:
583 return (bus_space_read_2(iobus->bst, iobus->bsh,
584 iobus->offset + offset));
585 case 4:
586 return (bus_space_read_4(iobus->bst, iobus->bsh,
587 iobus->offset + offset));
588 default:
589 panic("invalid width %u", width);
590 }
591 }
592