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