1 /*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 2006-2008, Juniper Networks, Inc.
5 * Copyright (c) 2008 Semihalf, Rafal Czubak
6 * Copyright (c) 2009 The FreeBSD Foundation
7 * All rights reserved.
8 *
9 * Portions of this software were developed by Semihalf
10 * under sponsorship from the FreeBSD Foundation.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36 #include "opt_platform.h"
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/ktr.h>
41 #include <sys/kernel.h>
42 #include <sys/malloc.h>
43 #include <sys/module.h>
44 #include <sys/bus.h>
45 #include <sys/rman.h>
46 #include <machine/bus.h>
47
48 #include <vm/vm.h>
49 #include <vm/pmap.h>
50
51 #include <dev/fdt/fdt_common.h>
52 #include <dev/ofw/ofw_bus.h>
53 #include <dev/ofw/ofw_bus_subr.h>
54
55 #include <powerpc/mpc85xx/mpc85xx.h>
56
57 #include "ofw_bus_if.h"
58 #include "lbc.h"
59
60 #ifdef DEBUG
61 #define debugf(fmt, args...) do { printf("%s(): ", __func__); \
62 printf(fmt,##args); } while (0)
63 #else
64 #define debugf(fmt, args...)
65 #endif
66
67 static MALLOC_DEFINE(M_LBC, "localbus", "localbus devices information");
68
69 static int lbc_probe(device_t);
70 static int lbc_attach(device_t);
71 static int lbc_shutdown(device_t);
72 static int lbc_map_resource(device_t, device_t, struct resource *,
73 struct resource_map_request *, struct resource_map *);
74 static int lbc_unmap_resource(device_t, device_t, struct resource *,
75 struct resource_map *map);
76 static int lbc_activate_resource(device_t bus, device_t child,
77 struct resource *r);
78 static int lbc_deactivate_resource(device_t bus, device_t child,
79 struct resource *r);
80 static struct rman *lbc_get_rman(device_t, int, u_int);
81 static struct resource *lbc_alloc_resource(device_t, device_t, int, int *,
82 rman_res_t, rman_res_t, rman_res_t, u_int);
83 static int lbc_adjust_resource(device_t, device_t, struct resource *,
84 rman_res_t, rman_res_t);
85 static int lbc_print_child(device_t, device_t);
86 static int lbc_release_resource(device_t, device_t, struct resource *);
87 static const struct ofw_bus_devinfo *lbc_get_devinfo(device_t, device_t);
88
89 /*
90 * Bus interface definition
91 */
92 static device_method_t lbc_methods[] = {
93 /* Device interface */
94 DEVMETHOD(device_probe, lbc_probe),
95 DEVMETHOD(device_attach, lbc_attach),
96 DEVMETHOD(device_shutdown, lbc_shutdown),
97
98 /* Bus interface */
99 DEVMETHOD(bus_print_child, lbc_print_child),
100 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
101 DEVMETHOD(bus_teardown_intr, NULL),
102
103 DEVMETHOD(bus_get_rman, lbc_get_rman),
104 DEVMETHOD(bus_alloc_resource, lbc_alloc_resource),
105 DEVMETHOD(bus_adjust_resource, lbc_adjust_resource),
106 DEVMETHOD(bus_release_resource, lbc_release_resource),
107 DEVMETHOD(bus_activate_resource, lbc_activate_resource),
108 DEVMETHOD(bus_deactivate_resource, lbc_deactivate_resource),
109 DEVMETHOD(bus_map_resource, lbc_map_resource),
110 DEVMETHOD(bus_unmap_resource, lbc_unmap_resource),
111
112 /* OFW bus interface */
113 DEVMETHOD(ofw_bus_get_devinfo, lbc_get_devinfo),
114 DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat),
115 DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model),
116 DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name),
117 DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
118 DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
119 { 0, 0 }
120 };
121
122 static driver_t lbc_driver = {
123 "lbc",
124 lbc_methods,
125 sizeof(struct lbc_softc)
126 };
127
128 EARLY_DRIVER_MODULE(lbc, ofwbus, lbc_driver, 0, 0, BUS_PASS_BUS);
129
130 /*
131 * Calculate address mask used by OR(n) registers. Use memory region size to
132 * determine mask value. The size must be a power of two and within the range
133 * of 32KB - 4GB. Otherwise error code is returned. Value representing
134 * 4GB size can be passed as 0xffffffff.
135 */
136 static uint32_t
lbc_address_mask(uint32_t size)137 lbc_address_mask(uint32_t size)
138 {
139 int n = 15;
140
141 if (size == ~0)
142 return (0);
143
144 while (n < 32) {
145 if (size == (1U << n))
146 break;
147 n++;
148 }
149
150 if (n == 32)
151 return (EINVAL);
152
153 return (0xffff8000 << (n - 15));
154 }
155
156 static void
lbc_banks_unmap(struct lbc_softc * sc)157 lbc_banks_unmap(struct lbc_softc *sc)
158 {
159 int r;
160
161 r = 0;
162 while (r < LBC_DEV_MAX) {
163 if (sc->sc_range[r].size == 0)
164 return;
165
166 pmap_unmapdev((void *)sc->sc_range[r].kva,
167 sc->sc_range[r].size);
168 law_disable(OCP85XX_TGTIF_LBC, sc->sc_range[r].addr,
169 sc->sc_range[r].size);
170 r++;
171 }
172 }
173
174 static int
lbc_banks_map(struct lbc_softc * sc)175 lbc_banks_map(struct lbc_softc *sc)
176 {
177 vm_paddr_t end, start;
178 vm_size_t size;
179 u_int i, r, ranges, s;
180 int error;
181
182 bzero(sc->sc_range, sizeof(sc->sc_range));
183
184 /*
185 * Determine number of discontiguous address ranges to program.
186 */
187 ranges = 0;
188 for (i = 0; i < LBC_DEV_MAX; i++) {
189 size = sc->sc_banks[i].size;
190 if (size == 0)
191 continue;
192
193 start = sc->sc_banks[i].addr;
194 for (r = 0; r < ranges; r++) {
195 /* Avoid wrap-around bugs. */
196 end = sc->sc_range[r].addr - 1 + sc->sc_range[r].size;
197 if (start > 0 && end == start - 1) {
198 sc->sc_range[r].size += size;
199 break;
200 }
201 /* Avoid wrap-around bugs. */
202 end = start - 1 + size;
203 if (sc->sc_range[r].addr > 0 &&
204 end == sc->sc_range[r].addr - 1) {
205 sc->sc_range[r].addr = start;
206 sc->sc_range[r].size += size;
207 break;
208 }
209 }
210 if (r == ranges) {
211 /* New range; add using insertion sort */
212 r = 0;
213 while (r < ranges && sc->sc_range[r].addr < start)
214 r++;
215 for (s = ranges; s > r; s--)
216 sc->sc_range[s] = sc->sc_range[s-1];
217 sc->sc_range[r].addr = start;
218 sc->sc_range[r].size = size;
219 ranges++;
220 }
221 }
222
223 /*
224 * Ranges are sorted so quickly go over the list to merge ranges
225 * that grew toward each other while building the ranges.
226 */
227 r = 0;
228 while (r < ranges - 1) {
229 end = sc->sc_range[r].addr + sc->sc_range[r].size;
230 if (end != sc->sc_range[r+1].addr) {
231 r++;
232 continue;
233 }
234 sc->sc_range[r].size += sc->sc_range[r+1].size;
235 for (s = r + 1; s < ranges - 1; s++)
236 sc->sc_range[s] = sc->sc_range[s+1];
237 bzero(&sc->sc_range[s], sizeof(sc->sc_range[s]));
238 ranges--;
239 }
240
241 /*
242 * Configure LAW for the LBC ranges and map the physical memory
243 * range into KVA.
244 */
245 for (r = 0; r < ranges; r++) {
246 start = sc->sc_range[r].addr;
247 size = sc->sc_range[r].size;
248 error = law_enable(OCP85XX_TGTIF_LBC, start, size);
249 if (error)
250 return (error);
251 sc->sc_range[r].kva = (vm_offset_t)pmap_mapdev(start, size);
252 }
253
254 /* XXX: need something better here? */
255 if (ranges == 0)
256 return (EINVAL);
257
258 /* Assign KVA to banks based on the enclosing range. */
259 for (i = 0; i < LBC_DEV_MAX; i++) {
260 size = sc->sc_banks[i].size;
261 if (size == 0)
262 continue;
263
264 start = sc->sc_banks[i].addr;
265 for (r = 0; r < ranges; r++) {
266 end = sc->sc_range[r].addr - 1 + sc->sc_range[r].size;
267 if (start >= sc->sc_range[r].addr &&
268 start - 1 + size <= end)
269 break;
270 }
271 if (r < ranges) {
272 sc->sc_banks[i].kva = sc->sc_range[r].kva +
273 (start - sc->sc_range[r].addr);
274 }
275 }
276
277 return (0);
278 }
279
280 static int
lbc_banks_enable(struct lbc_softc * sc)281 lbc_banks_enable(struct lbc_softc *sc)
282 {
283 uint32_t size;
284 uint32_t regval;
285 int error, i;
286
287 for (i = 0; i < LBC_DEV_MAX; i++) {
288 size = sc->sc_banks[i].size;
289 if (size == 0)
290 continue;
291
292 /*
293 * Compute and program BR value.
294 */
295 regval = sc->sc_banks[i].addr;
296 switch (sc->sc_banks[i].width) {
297 case 8:
298 regval |= (1 << 11);
299 break;
300 case 16:
301 regval |= (2 << 11);
302 break;
303 case 32:
304 regval |= (3 << 11);
305 break;
306 default:
307 error = EINVAL;
308 goto fail;
309 }
310 regval |= (sc->sc_banks[i].decc << 9);
311 regval |= (sc->sc_banks[i].wp << 8);
312 regval |= (sc->sc_banks[i].msel << 5);
313 regval |= (sc->sc_banks[i].atom << 2);
314 regval |= 1;
315 bus_space_write_4(sc->sc_bst, sc->sc_bsh,
316 LBC85XX_BR(i), regval);
317
318 /*
319 * Compute and program OR value.
320 */
321 regval = lbc_address_mask(size);
322 switch (sc->sc_banks[i].msel) {
323 case LBCRES_MSEL_GPCM:
324 /* TODO Add flag support for option registers */
325 regval |= 0x0ff7;
326 break;
327 case LBCRES_MSEL_FCM:
328 /* TODO Add flag support for options register */
329 regval |= 0x0796;
330 break;
331 case LBCRES_MSEL_UPMA:
332 case LBCRES_MSEL_UPMB:
333 case LBCRES_MSEL_UPMC:
334 printf("UPM mode not supported yet!");
335 error = ENOSYS;
336 goto fail;
337 }
338 bus_space_write_4(sc->sc_bst, sc->sc_bsh,
339 LBC85XX_OR(i), regval);
340 }
341
342 return (0);
343
344 fail:
345 lbc_banks_unmap(sc);
346 return (error);
347 }
348
349 static void
fdt_lbc_fixup(phandle_t node,struct lbc_softc * sc,struct lbc_devinfo * di)350 fdt_lbc_fixup(phandle_t node, struct lbc_softc *sc, struct lbc_devinfo *di)
351 {
352 pcell_t width;
353 int bank;
354
355 if (OF_getprop(node, "bank-width", (void *)&width, sizeof(width)) <= 0)
356 return;
357
358 bank = di->di_bank;
359 if (sc->sc_banks[bank].size == 0)
360 return;
361
362 /* Express width in bits. */
363 sc->sc_banks[bank].width = width * 8;
364 }
365
366 static int
fdt_lbc_reg_decode(phandle_t node,struct lbc_softc * sc,struct lbc_devinfo * di)367 fdt_lbc_reg_decode(phandle_t node, struct lbc_softc *sc,
368 struct lbc_devinfo *di)
369 {
370 rman_res_t start, end, count;
371 pcell_t *reg, *regptr;
372 pcell_t addr_cells, size_cells;
373 int tuple_size, tuples;
374 int i, j, rv, bank;
375
376 if (fdt_addrsize_cells(OF_parent(node), &addr_cells, &size_cells) != 0)
377 return (ENXIO);
378
379 tuple_size = sizeof(pcell_t) * (addr_cells + size_cells);
380 tuples = OF_getencprop_alloc_multi(node, "reg", tuple_size,
381 (void **)®);
382 debugf("addr_cells = %d, size_cells = %d\n", addr_cells, size_cells);
383 debugf("tuples = %d, tuple size = %d\n", tuples, tuple_size);
384 if (tuples <= 0)
385 /* No 'reg' property in this node. */
386 return (0);
387
388 regptr = reg;
389 for (i = 0; i < tuples; i++) {
390 bank = fdt_data_get((void *)reg, 1);
391 di->di_bank = bank;
392 reg += 1;
393
394 /* Get address/size. */
395 start = count = 0;
396 for (j = 0; j < addr_cells - 1; j++) {
397 start <<= 32;
398 start |= reg[j];
399 }
400 for (j = 0; j < size_cells; j++) {
401 count <<= 32;
402 count |= reg[addr_cells + j - 1];
403 }
404 reg += addr_cells - 1 + size_cells;
405
406 /* Calculate address range relative to VA base. */
407 start = sc->sc_banks[bank].kva + start;
408 end = start + count - 1;
409
410 debugf("reg addr bank = %d, start = %jx, end = %jx, "
411 "count = %jx\n", bank, start, end, count);
412
413 /* Use bank (CS) cell as rid. */
414 resource_list_add(&di->di_res, SYS_RES_MEMORY, bank, start,
415 end, count);
416 }
417 rv = 0;
418 OF_prop_free(regptr);
419 return (rv);
420 }
421
422 static void
lbc_intr(void * arg)423 lbc_intr(void *arg)
424 {
425 struct lbc_softc *sc = arg;
426 uint32_t ltesr;
427
428 ltesr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTESR);
429 sc->sc_ltesr = ltesr;
430 bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTESR, ltesr);
431 wakeup(sc->sc_dev);
432 }
433
434 static int
lbc_probe(device_t dev)435 lbc_probe(device_t dev)
436 {
437
438 if (!(ofw_bus_is_compatible(dev, "fsl,lbc") ||
439 ofw_bus_is_compatible(dev, "fsl,elbc")))
440 return (ENXIO);
441
442 device_set_desc(dev, "Freescale Local Bus Controller");
443 return (BUS_PROBE_DEFAULT);
444 }
445
446 static int
lbc_attach(device_t dev)447 lbc_attach(device_t dev)
448 {
449 struct lbc_softc *sc;
450 struct lbc_devinfo *di;
451 struct rman *rm;
452 uintmax_t offset, size;
453 vm_paddr_t start;
454 device_t cdev;
455 phandle_t node, child;
456 pcell_t *ranges, *rangesptr;
457 int tuple_size, tuples;
458 int par_addr_cells;
459 int bank, error, i, j;
460
461 sc = device_get_softc(dev);
462 sc->sc_dev = dev;
463
464 sc->sc_mrid = 0;
465 sc->sc_mres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_mrid,
466 RF_ACTIVE);
467 if (sc->sc_mres == NULL)
468 return (ENXIO);
469
470 sc->sc_bst = rman_get_bustag(sc->sc_mres);
471 sc->sc_bsh = rman_get_bushandle(sc->sc_mres);
472
473 for (bank = 0; bank < LBC_DEV_MAX; bank++) {
474 bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_BR(bank), 0);
475 bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_OR(bank), 0);
476 }
477
478 /*
479 * Initialize configuration register:
480 * - enable Local Bus
481 * - set data buffer control signal function
482 * - disable parity byte select
483 * - set ECC parity type
484 * - set bus monitor timing and timer prescale
485 */
486 bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LBCR, 0);
487
488 /*
489 * Initialize clock ratio register:
490 * - disable PLL bypass mode
491 * - configure LCLK delay cycles for the assertion of LALE
492 * - set system clock divider
493 */
494 bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LCRR, 0x00030008);
495
496 bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTEDR, 0);
497 bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTESR, ~0);
498 bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTEIR, 0x64080001);
499
500 sc->sc_irid = 0;
501 sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irid,
502 RF_ACTIVE | RF_SHAREABLE);
503 if (sc->sc_ires != NULL) {
504 error = bus_setup_intr(dev, sc->sc_ires,
505 INTR_TYPE_MISC | INTR_MPSAFE, NULL, lbc_intr, sc,
506 &sc->sc_icookie);
507 if (error) {
508 device_printf(dev, "could not activate interrupt\n");
509 bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid,
510 sc->sc_ires);
511 sc->sc_ires = NULL;
512 }
513 }
514
515 sc->sc_ltesr = ~0;
516
517 rangesptr = NULL;
518
519 rm = &sc->sc_rman;
520 rm->rm_type = RMAN_ARRAY;
521 rm->rm_descr = "Local Bus Space";
522 error = rman_init(rm);
523 if (error)
524 goto fail;
525
526 error = rman_manage_region(rm, rm->rm_start, rm->rm_end);
527 if (error) {
528 rman_fini(rm);
529 goto fail;
530 }
531
532 /*
533 * Process 'ranges' property.
534 */
535 node = ofw_bus_get_node(dev);
536 if ((fdt_addrsize_cells(node, &sc->sc_addr_cells,
537 &sc->sc_size_cells)) != 0) {
538 error = ENXIO;
539 goto fail;
540 }
541
542 par_addr_cells = fdt_parent_addr_cells(node);
543 if (par_addr_cells > 2) {
544 device_printf(dev, "unsupported parent #addr-cells\n");
545 error = ERANGE;
546 goto fail;
547 }
548 tuple_size = sizeof(pcell_t) * (sc->sc_addr_cells + par_addr_cells +
549 sc->sc_size_cells);
550
551 tuples = OF_getencprop_alloc_multi(node, "ranges", tuple_size,
552 (void **)&ranges);
553 if (tuples < 0) {
554 device_printf(dev, "could not retrieve 'ranges' property\n");
555 error = ENXIO;
556 goto fail;
557 }
558 rangesptr = ranges;
559
560 debugf("par addr_cells = %d, addr_cells = %d, size_cells = %d, "
561 "tuple_size = %d, tuples = %d\n", par_addr_cells,
562 sc->sc_addr_cells, sc->sc_size_cells, tuple_size, tuples);
563
564 start = 0;
565 size = 0;
566 for (i = 0; i < tuples; i++) {
567 /* The first cell is the bank (chip select) number. */
568 bank = fdt_data_get(ranges, 1);
569 if (bank < 0 || bank > LBC_DEV_MAX) {
570 device_printf(dev, "bank out of range: %d\n", bank);
571 error = ERANGE;
572 goto fail;
573 }
574 ranges += 1;
575
576 /*
577 * Remaining cells of the child address define offset into
578 * this CS.
579 */
580 offset = 0;
581 for (j = 0; j < sc->sc_addr_cells - 1; j++) {
582 offset <<= sizeof(pcell_t) * 8;
583 offset |= *ranges;
584 ranges++;
585 }
586
587 /* Parent bus start address of this bank. */
588 start = 0;
589 for (j = 0; j < par_addr_cells; j++) {
590 start <<= sizeof(pcell_t) * 8;
591 start |= *ranges;
592 ranges++;
593 }
594
595 size = fdt_data_get((void *)ranges, sc->sc_size_cells);
596 ranges += sc->sc_size_cells;
597 debugf("bank = %d, start = %jx, size = %jx\n", bank,
598 (uintmax_t)start, size);
599
600 sc->sc_banks[bank].addr = start + offset;
601 sc->sc_banks[bank].size = size;
602
603 /*
604 * Attributes for the bank.
605 *
606 * XXX Note there are no DT bindings defined for them at the
607 * moment, so we need to provide some defaults.
608 */
609 sc->sc_banks[bank].width = 16;
610 sc->sc_banks[bank].msel = LBCRES_MSEL_GPCM;
611 sc->sc_banks[bank].decc = LBCRES_DECC_DISABLED;
612 sc->sc_banks[bank].atom = LBCRES_ATOM_DISABLED;
613 sc->sc_banks[bank].wp = 0;
614 }
615
616 /*
617 * Initialize mem-mappings for the LBC banks (i.e. chip selects).
618 */
619 error = lbc_banks_map(sc);
620 if (error)
621 goto fail;
622
623 /*
624 * Walk the localbus and add direct subordinates as our children.
625 */
626 for (child = OF_child(node); child != 0; child = OF_peer(child)) {
627 di = malloc(sizeof(*di), M_LBC, M_WAITOK | M_ZERO);
628
629 if (ofw_bus_gen_setup_devinfo(&di->di_ofw, child) != 0) {
630 free(di, M_LBC);
631 device_printf(dev, "could not set up devinfo\n");
632 continue;
633 }
634
635 resource_list_init(&di->di_res);
636
637 if (fdt_lbc_reg_decode(child, sc, di)) {
638 device_printf(dev, "could not process 'reg' "
639 "property\n");
640 ofw_bus_gen_destroy_devinfo(&di->di_ofw);
641 free(di, M_LBC);
642 continue;
643 }
644
645 fdt_lbc_fixup(child, sc, di);
646
647 /* Add newbus device for this FDT node */
648 cdev = device_add_child(dev, NULL, DEVICE_UNIT_ANY);
649 if (cdev == NULL) {
650 device_printf(dev, "could not add child: %s\n",
651 di->di_ofw.obd_name);
652 resource_list_free(&di->di_res);
653 ofw_bus_gen_destroy_devinfo(&di->di_ofw);
654 free(di, M_LBC);
655 continue;
656 }
657 debugf("added child name='%s', node=%x\n", di->di_ofw.obd_name,
658 child);
659 device_set_ivars(cdev, di);
660 }
661
662 /*
663 * Enable the LBC.
664 */
665 lbc_banks_enable(sc);
666
667 OF_prop_free(rangesptr);
668 bus_attach_children(dev);
669 return (0);
670
671 fail:
672 OF_prop_free(rangesptr);
673 bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_mrid, sc->sc_mres);
674 return (error);
675 }
676
677 static int
lbc_shutdown(device_t dev)678 lbc_shutdown(device_t dev)
679 {
680
681 /* TODO */
682 return(0);
683 }
684
685 static struct rman *
lbc_get_rman(device_t bus,int type,u_int flags)686 lbc_get_rman(device_t bus, int type, u_int flags)
687 {
688 struct lbc_softc *sc;
689
690 sc = device_get_softc(bus);
691 switch (type) {
692 case SYS_RES_MEMORY:
693 return (&sc->sc_rman);
694 default:
695 return (NULL);
696 }
697 }
698
699 static struct resource *
lbc_alloc_resource(device_t bus,device_t child,int type,int * rid,rman_res_t start,rman_res_t end,rman_res_t count,u_int flags)700 lbc_alloc_resource(device_t bus, device_t child, int type, int *rid,
701 rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
702 {
703 struct lbc_devinfo *di;
704 struct resource_list_entry *rle;
705
706 /* We only support default allocations. */
707 if (!RMAN_IS_DEFAULT_RANGE(start, end))
708 return (NULL);
709
710 if (type == SYS_RES_IRQ)
711 return (bus_alloc_resource(bus, type, rid, start, end, count,
712 flags));
713
714 /*
715 * Request for the default allocation with a given rid: use resource
716 * list stored in the local device info.
717 */
718 if ((di = device_get_ivars(child)) == NULL)
719 return (NULL);
720
721 if (type == SYS_RES_IOPORT)
722 type = SYS_RES_MEMORY;
723
724 /*
725 * XXX: We are supposed to return a value to the user, so this
726 * doesn't seem right.
727 */
728 rid = &di->di_bank;
729
730 rle = resource_list_find(&di->di_res, type, *rid);
731 if (rle == NULL) {
732 device_printf(bus, "no default resources for "
733 "rid = %d, type = %d\n", *rid, type);
734 return (NULL);
735 }
736 start = rle->start;
737 count = rle->count;
738 end = start + count - 1;
739
740 return (bus_generic_rman_alloc_resource(bus, child, type, rid, start,
741 end, count, flags));
742 }
743
744 static int
lbc_print_child(device_t dev,device_t child)745 lbc_print_child(device_t dev, device_t child)
746 {
747 struct lbc_devinfo *di;
748 struct resource_list *rl;
749 int rv;
750
751 di = device_get_ivars(child);
752 rl = &di->di_res;
753
754 rv = 0;
755 rv += bus_print_child_header(dev, child);
756 rv += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx");
757 rv += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd");
758 rv += bus_print_child_footer(dev, child);
759
760 return (rv);
761 }
762
763 static int
lbc_adjust_resource(device_t dev,device_t child,struct resource * r,rman_res_t start,rman_res_t end)764 lbc_adjust_resource(device_t dev, device_t child, struct resource *r,
765 rman_res_t start, rman_res_t end)
766 {
767 switch (rman_get_type(r)) {
768 case SYS_RES_MEMORY:
769 return (bus_generic_rman_adjust_resource(dev, child, r, start,
770 end));
771 case SYS_RES_IRQ:
772 return (bus_generic_adjust_resource(dev, child, r, start, end));
773 default:
774 return (EINVAL);
775 }
776 }
777
778 static int
lbc_release_resource(device_t dev,device_t child,struct resource * res)779 lbc_release_resource(device_t dev, device_t child, struct resource *res)
780 {
781 switch (rman_get_type(res)) {
782 case SYS_RES_MEMORY:
783 return (bus_generic_rman_release_resource(dev, child, res));
784 case SYS_RES_IRQ:
785 return (bus_generic_release_resource(dev, child, res));
786 default:
787 return (EINVAL);
788 }
789 }
790
791 static int
lbc_activate_resource(device_t bus,device_t child,struct resource * r)792 lbc_activate_resource(device_t bus, device_t child, struct resource *r)
793 {
794 switch (rman_get_type(r)) {
795 case SYS_RES_MEMORY:
796 return (bus_generic_rman_activate_resource(bus, child, r));
797 case SYS_RES_IRQ:
798 return (bus_generic_activate_resource(bus, child, r));
799 default:
800 return (EINVAL);
801 }
802 }
803
804 static int
lbc_deactivate_resource(device_t bus,device_t child,struct resource * r)805 lbc_deactivate_resource(device_t bus, device_t child, struct resource *r)
806 {
807 switch (rman_get_type(r)) {
808 case SYS_RES_MEMORY:
809 return (bus_generic_rman_deactivate_resource(bus, child, r));
810 case SYS_RES_IRQ:
811 return (bus_generic_deactivate_resource(bus, child, r));
812 default:
813 return (EINVAL);
814 }
815 }
816
817 static int
lbc_map_resource(device_t bus,device_t child,struct resource * r,struct resource_map_request * argsp,struct resource_map * map)818 lbc_map_resource(device_t bus, device_t child, struct resource *r,
819 struct resource_map_request *argsp, struct resource_map *map)
820 {
821 struct resource_map_request args;
822 rman_res_t length, start;
823 int error;
824
825 /* Resources must be active to be mapped. */
826 if (!(rman_get_flags(r) & RF_ACTIVE))
827 return (ENXIO);
828
829 /* Mappings are only supported on I/O and memory resources. */
830 switch (rman_get_type(r)) {
831 case SYS_RES_IOPORT:
832 case SYS_RES_MEMORY:
833 break;
834 default:
835 return (EINVAL);
836 }
837
838 resource_init_map_request(&args);
839 error = resource_validate_map_request(r, argsp, &args, &start, &length);
840 if (error)
841 return (error);
842
843 map->r_bustag = &bs_be_tag;
844 map->r_bushandle = start;
845 map->r_size = length;
846 map->r_vaddr = NULL;
847 return (0);
848 }
849
850 static int
lbc_unmap_resource(device_t bus,device_t child,struct resource * r,struct resource_map * map)851 lbc_unmap_resource(device_t bus, device_t child, struct resource *r,
852 struct resource_map *map)
853 {
854
855 /* Mappings are only supported on I/O and memory resources. */
856 switch (rman_get_type(r)) {
857 case SYS_RES_IOPORT:
858 case SYS_RES_MEMORY:
859 break;
860 default:
861 return (EINVAL);
862 }
863 return (0);
864 }
865
866 static const struct ofw_bus_devinfo *
lbc_get_devinfo(device_t bus,device_t child)867 lbc_get_devinfo(device_t bus, device_t child)
868 {
869 struct lbc_devinfo *di;
870
871 di = device_get_ivars(child);
872 return (&di->di_ofw);
873 }
874
875 void
lbc_write_reg(device_t child,u_int off,uint32_t val)876 lbc_write_reg(device_t child, u_int off, uint32_t val)
877 {
878 device_t dev;
879 struct lbc_softc *sc;
880
881 dev = device_get_parent(child);
882
883 if (off >= 0x1000) {
884 device_printf(dev, "%s(%s): invalid offset %#x\n",
885 __func__, device_get_nameunit(child), off);
886 return;
887 }
888
889 sc = device_get_softc(dev);
890
891 if (off == LBC85XX_LTESR && sc->sc_ltesr != ~0u) {
892 sc->sc_ltesr ^= (val & sc->sc_ltesr);
893 return;
894 }
895
896 if (off == LBC85XX_LTEATR && (val & 1) == 0)
897 sc->sc_ltesr = ~0u;
898 bus_space_write_4(sc->sc_bst, sc->sc_bsh, off, val);
899 }
900
901 uint32_t
lbc_read_reg(device_t child,u_int off)902 lbc_read_reg(device_t child, u_int off)
903 {
904 device_t dev;
905 struct lbc_softc *sc;
906 uint32_t val;
907
908 dev = device_get_parent(child);
909
910 if (off >= 0x1000) {
911 device_printf(dev, "%s(%s): invalid offset %#x\n",
912 __func__, device_get_nameunit(child), off);
913 return (~0U);
914 }
915
916 sc = device_get_softc(dev);
917
918 if (off == LBC85XX_LTESR && sc->sc_ltesr != ~0U)
919 val = sc->sc_ltesr;
920 else
921 val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, off);
922 return (val);
923 }
924