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