Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/powerpc/powermac/uninorth.c
39536 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (C) 2002 Benno Rice.
5
* All rights reserved.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
* 2. Redistributions in binary form must reproduce the above copyright
13
* notice, this list of conditions and the following disclaimer in the
14
* documentation and/or other materials provided with the distribution.
15
*
16
* THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
17
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19
* IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
*/
27
28
#include <sys/param.h>
29
#include <sys/systm.h>
30
#include <sys/module.h>
31
#include <sys/bus.h>
32
#include <sys/conf.h>
33
#include <sys/kernel.h>
34
35
#include <dev/ofw/openfirm.h>
36
#include <dev/ofw/ofw_pci.h>
37
#include <dev/ofw/ofw_bus.h>
38
#include <dev/ofw/ofw_bus_subr.h>
39
40
#include <dev/pci/pcivar.h>
41
#include <dev/pci/pcireg.h>
42
43
#include <machine/bus.h>
44
#include <machine/intr_machdep.h>
45
#include <machine/md_var.h>
46
#include <machine/pio.h>
47
#include <machine/resource.h>
48
49
#include <sys/rman.h>
50
51
#include <powerpc/powermac/uninorthvar.h>
52
53
#include <vm/vm.h>
54
#include <vm/pmap.h>
55
56
/*
57
* Driver for the Uninorth chip itself.
58
*/
59
60
static MALLOC_DEFINE(M_UNIN, "unin", "unin device information");
61
62
/*
63
* Device interface.
64
*/
65
66
static int unin_chip_probe(device_t);
67
static int unin_chip_attach(device_t);
68
69
/*
70
* Bus interface.
71
*/
72
static int unin_chip_print_child(device_t dev, device_t child);
73
static void unin_chip_probe_nomatch(device_t, device_t);
74
static struct rman *unin_chip_get_rman(device_t, int, u_int);
75
static struct resource *unin_chip_alloc_resource(device_t, device_t, int, int *,
76
rman_res_t, rman_res_t,
77
rman_res_t, u_int);
78
static int unin_chip_adjust_resource(device_t, device_t,
79
struct resource *, rman_res_t,
80
rman_res_t);
81
static int unin_chip_activate_resource(device_t, device_t,
82
struct resource *);
83
static int unin_chip_deactivate_resource(device_t, device_t,
84
struct resource *);
85
static int unin_chip_map_resource(device_t, device_t, struct resource *,
86
struct resource_map_request *,
87
struct resource_map *);
88
static int unin_chip_unmap_resource(device_t, device_t, struct resource *,
89
struct resource_map *);
90
static int unin_chip_release_resource(device_t, device_t, struct resource *);
91
static struct resource_list *unin_chip_get_resource_list (device_t, device_t);
92
93
/*
94
* OFW Bus interface
95
*/
96
97
static ofw_bus_get_devinfo_t unin_chip_get_devinfo;
98
99
/*
100
* Local routines
101
*/
102
103
static void unin_enable_gmac(device_t dev);
104
static void unin_enable_mpic(device_t dev);
105
106
/*
107
* Driver methods.
108
*/
109
static device_method_t unin_chip_methods[] = {
110
/* Device interface */
111
DEVMETHOD(device_probe, unin_chip_probe),
112
DEVMETHOD(device_attach, unin_chip_attach),
113
114
/* Bus interface */
115
DEVMETHOD(bus_print_child, unin_chip_print_child),
116
DEVMETHOD(bus_probe_nomatch, unin_chip_probe_nomatch),
117
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
118
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
119
120
DEVMETHOD(bus_get_rman, unin_chip_get_rman),
121
DEVMETHOD(bus_alloc_resource, unin_chip_alloc_resource),
122
DEVMETHOD(bus_adjust_resource, unin_chip_adjust_resource),
123
DEVMETHOD(bus_release_resource, unin_chip_release_resource),
124
DEVMETHOD(bus_activate_resource, unin_chip_activate_resource),
125
DEVMETHOD(bus_deactivate_resource, unin_chip_deactivate_resource),
126
DEVMETHOD(bus_map_resource, unin_chip_map_resource),
127
DEVMETHOD(bus_unmap_resource, unin_chip_unmap_resource),
128
DEVMETHOD(bus_get_resource_list, unin_chip_get_resource_list),
129
130
DEVMETHOD(bus_child_pnpinfo, ofw_bus_gen_child_pnpinfo),
131
132
/* ofw_bus interface */
133
DEVMETHOD(ofw_bus_get_devinfo, unin_chip_get_devinfo),
134
DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat),
135
DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model),
136
DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name),
137
DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
138
DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
139
{ 0, 0 }
140
};
141
142
static driver_t unin_chip_driver = {
143
"unin",
144
unin_chip_methods,
145
sizeof(struct unin_chip_softc)
146
};
147
148
/*
149
* Assume there is only one unin chip in a PowerMac, so that pmu.c functions can
150
* suspend the chip after the whole rest of the device tree is suspended, not
151
* earlier.
152
*/
153
static device_t unin_chip;
154
155
EARLY_DRIVER_MODULE(unin, ofwbus, unin_chip_driver, 0, 0, BUS_PASS_BUS);
156
157
/*
158
* Add an interrupt to the dev's resource list if present
159
*/
160
static void
161
unin_chip_add_intr(phandle_t devnode, struct unin_chip_devinfo *dinfo)
162
{
163
phandle_t iparent;
164
int *intr;
165
int i, nintr;
166
int icells;
167
168
if (dinfo->udi_ninterrupts >= 6) {
169
printf("unin: device has more than 6 interrupts\n");
170
return;
171
}
172
173
nintr = OF_getprop_alloc_multi(devnode, "interrupts", sizeof(*intr),
174
(void **)&intr);
175
if (nintr == -1) {
176
nintr = OF_getprop_alloc_multi(devnode, "AAPL,interrupts",
177
sizeof(*intr), (void **)&intr);
178
if (nintr == -1)
179
return;
180
}
181
182
if (intr[0] == -1)
183
return;
184
185
if (OF_getprop(devnode, "interrupt-parent", &iparent, sizeof(iparent))
186
<= 0)
187
panic("Interrupt but no interrupt parent!\n");
188
189
if (OF_searchprop(iparent, "#interrupt-cells", &icells, sizeof(icells))
190
<= 0)
191
icells = 1;
192
193
for (i = 0; i < nintr; i+=icells) {
194
u_int irq = MAP_IRQ(iparent, intr[i]);
195
196
resource_list_add(&dinfo->udi_resources, SYS_RES_IRQ,
197
dinfo->udi_ninterrupts, irq, irq, 1);
198
199
if (icells > 1) {
200
powerpc_config_intr(irq,
201
(intr[i+1] & 1) ? INTR_TRIGGER_LEVEL :
202
INTR_TRIGGER_EDGE, INTR_POLARITY_LOW);
203
}
204
205
dinfo->udi_interrupts[dinfo->udi_ninterrupts] = irq;
206
dinfo->udi_ninterrupts++;
207
}
208
}
209
210
static void
211
unin_chip_add_reg(phandle_t devnode, struct unin_chip_devinfo *dinfo)
212
{
213
struct unin_chip_reg *reg;
214
int i, nreg;
215
216
nreg = OF_getprop_alloc_multi(devnode, "reg", sizeof(*reg), (void **)&reg);
217
if (nreg == -1)
218
return;
219
220
for (i = 0; i < nreg; i++) {
221
resource_list_add(&dinfo->udi_resources, SYS_RES_MEMORY, i,
222
reg[i].mr_base,
223
reg[i].mr_base + reg[i].mr_size,
224
reg[i].mr_size);
225
}
226
}
227
228
static void
229
unin_update_reg(device_t dev, uint32_t regoff, uint32_t set, uint32_t clr)
230
{
231
volatile u_int *reg;
232
struct unin_chip_softc *sc;
233
u_int32_t tmpl;
234
235
sc = device_get_softc(dev);
236
reg = (void *)(sc->sc_addr + regoff);
237
tmpl = inl(reg);
238
tmpl &= ~clr;
239
tmpl |= set;
240
outl(reg, tmpl);
241
}
242
243
static void
244
unin_enable_gmac(device_t dev)
245
{
246
unin_update_reg(dev, UNIN_CLOCKCNTL, UNIN_CLOCKCNTL_GMAC, 0);
247
}
248
249
static void
250
unin_enable_mpic(device_t dev)
251
{
252
unin_update_reg(dev, UNIN_TOGGLE_REG, UNIN_MPIC_RESET | UNIN_MPIC_OUTPUT_ENABLE, 0);
253
}
254
255
static int
256
unin_chip_probe(device_t dev)
257
{
258
const char *name;
259
260
name = ofw_bus_get_name(dev);
261
262
if (name == NULL)
263
return (ENXIO);
264
265
if (strcmp(name, "uni-n") != 0 && strcmp(name, "u3") != 0
266
&& strcmp(name, "u4") != 0)
267
return (ENXIO);
268
269
device_set_desc(dev, "Apple UniNorth System Controller");
270
return (0);
271
}
272
273
static int
274
unin_chip_attach(device_t dev)
275
{
276
struct unin_chip_softc *sc;
277
struct unin_chip_devinfo *dinfo;
278
phandle_t root;
279
phandle_t child;
280
phandle_t iparent;
281
device_t cdev;
282
cell_t acells, scells;
283
char compat[32];
284
char name[32];
285
u_int irq, reg[3];
286
int error, i = 0;
287
288
sc = device_get_softc(dev);
289
root = ofw_bus_get_node(dev);
290
291
if (OF_getprop(root, "reg", reg, sizeof(reg)) < 8)
292
return (ENXIO);
293
294
acells = scells = 1;
295
OF_getprop(OF_parent(root), "#address-cells", &acells, sizeof(acells));
296
OF_getprop(OF_parent(root), "#size-cells", &scells, sizeof(scells));
297
298
i = 0;
299
sc->sc_physaddr = reg[i++];
300
if (acells == 2) {
301
sc->sc_physaddr <<= 32;
302
sc->sc_physaddr |= reg[i++];
303
}
304
sc->sc_size = reg[i++];
305
if (scells == 2) {
306
sc->sc_size <<= 32;
307
sc->sc_size |= reg[i++];
308
}
309
310
sc->sc_mem_rman.rm_type = RMAN_ARRAY;
311
sc->sc_mem_rman.rm_descr = "UniNorth Device Memory";
312
313
error = rman_init(&sc->sc_mem_rman);
314
315
if (error) {
316
device_printf(dev, "rman_init() failed. error = %d\n", error);
317
return (error);
318
}
319
320
error = rman_manage_region(&sc->sc_mem_rman, sc->sc_physaddr,
321
sc->sc_physaddr + sc->sc_size - 1);
322
if (error) {
323
device_printf(dev,
324
"rman_manage_region() failed. error = %d\n",
325
error);
326
return (error);
327
}
328
329
if (unin_chip == NULL)
330
unin_chip = dev;
331
332
/*
333
* Iterate through the sub-devices
334
*/
335
for (child = OF_child(root); child != 0; child = OF_peer(child)) {
336
dinfo = malloc(sizeof(*dinfo), M_UNIN, M_WAITOK | M_ZERO);
337
if (ofw_bus_gen_setup_devinfo(&dinfo->udi_obdinfo, child)
338
!= 0)
339
{
340
free(dinfo, M_UNIN);
341
continue;
342
}
343
344
resource_list_init(&dinfo->udi_resources);
345
dinfo->udi_ninterrupts = 0;
346
unin_chip_add_intr(child, dinfo);
347
348
/*
349
* Some Apple machines do have a bug in OF, they miss
350
* the interrupt entries on the U3 I2C node. That means they
351
* do not have an entry with number of interrupts nor the
352
* entry of the interrupt parent handle.
353
* We define an interrupt and hardwire it to the /u3/mpic
354
* handle.
355
*/
356
357
if (OF_getprop(child, "name", name, sizeof(name)) <= 0)
358
device_printf(dev, "device has no name!\n");
359
if (dinfo->udi_ninterrupts == 0 &&
360
(strcmp(name, "i2c-bus") == 0 ||
361
strcmp(name, "i2c") == 0)) {
362
if (OF_getprop(child, "interrupt-parent", &iparent,
363
sizeof(iparent)) <= 0) {
364
iparent = OF_finddevice("/u3/mpic");
365
device_printf(dev, "Set /u3/mpic as iparent!\n");
366
}
367
/* Add an interrupt number 0 to the parent. */
368
irq = MAP_IRQ(iparent, 0);
369
resource_list_add(&dinfo->udi_resources, SYS_RES_IRQ,
370
dinfo->udi_ninterrupts, irq, irq, 1);
371
dinfo->udi_interrupts[dinfo->udi_ninterrupts] = irq;
372
dinfo->udi_ninterrupts++;
373
}
374
375
unin_chip_add_reg(child, dinfo);
376
377
cdev = device_add_child(dev, NULL, DEVICE_UNIT_ANY);
378
if (cdev == NULL) {
379
device_printf(dev, "<%s>: device_add_child failed\n",
380
dinfo->udi_obdinfo.obd_name);
381
resource_list_free(&dinfo->udi_resources);
382
ofw_bus_gen_destroy_devinfo(&dinfo->udi_obdinfo);
383
free(dinfo, M_UNIN);
384
continue;
385
}
386
387
device_set_ivars(cdev, dinfo);
388
}
389
390
/*
391
* Only map the first page, since that is where the registers
392
* of interest lie.
393
*/
394
sc->sc_addr = (vm_offset_t)pmap_mapdev(sc->sc_physaddr, PAGE_SIZE);
395
396
sc->sc_version = *(u_int *)sc->sc_addr;
397
device_printf(dev, "Version %d\n", sc->sc_version);
398
399
/*
400
* Enable the GMAC Ethernet cell and the integrated OpenPIC
401
* if Open Firmware says they are used.
402
*/
403
for (child = OF_child(root); child; child = OF_peer(child)) {
404
memset(compat, 0, sizeof(compat));
405
OF_getprop(child, "compatible", compat, sizeof(compat));
406
if (strcmp(compat, "gmac") == 0)
407
unin_enable_gmac(dev);
408
if (strcmp(compat, "chrp,open-pic") == 0)
409
unin_enable_mpic(dev);
410
}
411
412
/*
413
* GMAC lives under the PCI bus, so just check if enet is gmac.
414
*/
415
child = OF_finddevice("enet");
416
memset(compat, 0, sizeof(compat));
417
OF_getprop(child, "compatible", compat, sizeof(compat));
418
if (strcmp(compat, "gmac") == 0)
419
unin_enable_gmac(dev);
420
421
bus_attach_children(dev);
422
return (0);
423
}
424
425
static int
426
unin_chip_print_child(device_t dev, device_t child)
427
{
428
struct unin_chip_devinfo *dinfo;
429
struct resource_list *rl;
430
int retval = 0;
431
432
dinfo = device_get_ivars(child);
433
rl = &dinfo->udi_resources;
434
435
retval += bus_print_child_header(dev, child);
436
437
retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx");
438
retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd");
439
440
retval += bus_print_child_footer(dev, child);
441
442
return (retval);
443
}
444
445
static void
446
unin_chip_probe_nomatch(device_t dev, device_t child)
447
{
448
struct unin_chip_devinfo *dinfo;
449
struct resource_list *rl;
450
const char *type;
451
452
if (bootverbose) {
453
dinfo = device_get_ivars(child);
454
rl = &dinfo->udi_resources;
455
456
if ((type = ofw_bus_get_type(child)) == NULL)
457
type = "(unknown)";
458
device_printf(dev, "<%s, %s>", type, ofw_bus_get_name(child));
459
resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx");
460
resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd");
461
printf(" (no driver attached)\n");
462
}
463
}
464
465
static struct rman *
466
unin_chip_get_rman(device_t bus, int type, u_int flags)
467
{
468
struct unin_chip_softc *sc;
469
470
sc = device_get_softc(bus);
471
switch (type) {
472
case SYS_RES_MEMORY:
473
case SYS_RES_IOPORT:
474
return (&sc->sc_mem_rman);
475
default:
476
return (NULL);
477
}
478
}
479
480
static struct resource *
481
unin_chip_alloc_resource(device_t bus, device_t child, int type, int *rid,
482
rman_res_t start, rman_res_t end, rman_res_t count,
483
u_int flags)
484
{
485
rman_res_t adjstart, adjend, adjcount;
486
struct unin_chip_devinfo *dinfo;
487
struct resource_list_entry *rle;
488
489
dinfo = device_get_ivars(child);
490
491
switch (type) {
492
case SYS_RES_MEMORY:
493
case SYS_RES_IOPORT:
494
rle = resource_list_find(&dinfo->udi_resources, SYS_RES_MEMORY,
495
*rid);
496
if (rle == NULL) {
497
device_printf(bus, "no rle for %s memory %d\n",
498
device_get_nameunit(child), *rid);
499
return (NULL);
500
}
501
502
rle->end = rle->end - 1; /* Hack? */
503
504
if (start < rle->start)
505
adjstart = rle->start;
506
else if (start > rle->end)
507
adjstart = rle->end;
508
else
509
adjstart = start;
510
511
if (end < rle->start)
512
adjend = rle->start;
513
else if (end > rle->end)
514
adjend = rle->end;
515
else
516
adjend = end;
517
518
adjcount = adjend - adjstart;
519
520
return (bus_generic_rman_alloc_resource(bus, child,
521
SYS_RES_MEMORY, rid, adjstart, adjend, adjcount, flags));
522
case SYS_RES_IRQ:
523
/* Check for passthrough from subattachments. */
524
if (device_get_parent(child) != bus)
525
return BUS_ALLOC_RESOURCE(device_get_parent(bus), child,
526
type, rid, start, end, count,
527
flags);
528
529
rle = resource_list_find(&dinfo->udi_resources, SYS_RES_IRQ,
530
*rid);
531
if (rle == NULL) {
532
if (dinfo->udi_ninterrupts >= 6) {
533
device_printf(bus,
534
"%s has more than 6 interrupts\n",
535
device_get_nameunit(child));
536
return (NULL);
537
}
538
resource_list_add(&dinfo->udi_resources, SYS_RES_IRQ,
539
dinfo->udi_ninterrupts, start, start,
540
1);
541
542
dinfo->udi_interrupts[dinfo->udi_ninterrupts] = start;
543
dinfo->udi_ninterrupts++;
544
}
545
546
return (resource_list_alloc(&dinfo->udi_resources, bus, child,
547
type, rid, start, end, count,
548
flags));
549
default:
550
device_printf(bus, "unknown resource request from %s\n",
551
device_get_nameunit(child));
552
return (NULL);
553
}
554
}
555
556
static int
557
unin_chip_adjust_resource(device_t bus, device_t child, struct resource *r,
558
rman_res_t start, rman_res_t end)
559
{
560
switch (rman_get_type(r)) {
561
case SYS_RES_IOPORT:
562
case SYS_RES_MEMORY:
563
return (bus_generic_rman_adjust_resource(bus, child, r, start,
564
end));
565
case SYS_RES_IRQ:
566
return (bus_generic_adjust_resource(bus, child, r, start, end));
567
default:
568
return (EINVAL);
569
}
570
}
571
572
static int
573
unin_chip_release_resource(device_t bus, device_t child, struct resource *res)
574
{
575
switch (rman_get_type(res)) {
576
case SYS_RES_IOPORT:
577
case SYS_RES_MEMORY:
578
return (bus_generic_rman_release_resource(bus, child, res));
579
case SYS_RES_IRQ:
580
return (bus_generic_rl_release_resource(bus, child, res));
581
default:
582
return (EINVAL);
583
}
584
}
585
586
static int
587
unin_chip_activate_resource(device_t bus, device_t child, struct resource *res)
588
{
589
switch (rman_get_type(res)) {
590
case SYS_RES_IOPORT:
591
case SYS_RES_MEMORY:
592
return (bus_generic_rman_activate_resource(bus, child, res));
593
case SYS_RES_IRQ:
594
return (bus_generic_activate_resource(bus, child, res));
595
default:
596
return (EINVAL);
597
}
598
}
599
600
static int
601
unin_chip_deactivate_resource(device_t bus, device_t child,
602
struct resource *res)
603
{
604
switch (rman_get_type(res)) {
605
case SYS_RES_IOPORT:
606
case SYS_RES_MEMORY:
607
return (bus_generic_rman_deactivate_resource(bus, child, res));
608
case SYS_RES_IRQ:
609
return (bus_generic_deactivate_resource(bus, child, res));
610
default:
611
return (EINVAL);
612
}
613
}
614
615
static int
616
unin_chip_map_resource(device_t bus, device_t child, struct resource *r,
617
struct resource_map_request *argsp, struct resource_map *map)
618
{
619
struct resource_map_request args;
620
rman_res_t length, start;
621
int error;
622
623
/* Resources must be active to be mapped. */
624
if (!(rman_get_flags(r) & RF_ACTIVE))
625
return (ENXIO);
626
627
/* Mappings are only supported on I/O and memory resources. */
628
switch (rman_get_type(r)) {
629
case SYS_RES_IOPORT:
630
case SYS_RES_MEMORY:
631
break;
632
default:
633
return (EINVAL);
634
}
635
636
resource_init_map_request(&args);
637
error = resource_validate_map_request(r, argsp, &args, &start, &length);
638
if (error)
639
return (error);
640
641
if (bootverbose)
642
printf("nexus mapdev: start %jx, len %jd\n",
643
(uintmax_t)start, (uintmax_t)length);
644
645
map->r_vaddr = pmap_mapdev_attr(start, length, args.memattr);
646
if (map->r_vaddr == NULL)
647
return (ENOMEM);
648
map->r_bustag = &bs_be_tag;
649
map->r_size = length;
650
map->r_bushandle = (bus_space_handle_t)map->r_vaddr;
651
return (0);
652
}
653
654
static int
655
unin_chip_unmap_resource(device_t bus, device_t child, struct resource *r,
656
struct resource_map *map)
657
{
658
/*
659
* If this is a memory resource, unmap it.
660
*/
661
switch (rman_get_type(r)) {
662
case SYS_RES_IOPORT:
663
case SYS_RES_MEMORY:
664
pmap_unmapdev(map->r_vaddr, map->r_size);
665
break;
666
default:
667
return (EINVAL);
668
}
669
return (0);
670
}
671
672
static struct resource_list *
673
unin_chip_get_resource_list (device_t dev, device_t child)
674
{
675
struct unin_chip_devinfo *dinfo;
676
677
dinfo = device_get_ivars(child);
678
return (&dinfo->udi_resources);
679
}
680
681
static const struct ofw_bus_devinfo *
682
unin_chip_get_devinfo(device_t dev, device_t child)
683
{
684
struct unin_chip_devinfo *dinfo;
685
686
dinfo = device_get_ivars(child);
687
return (&dinfo->udi_obdinfo);
688
}
689
690
int
691
unin_chip_wake(device_t dev)
692
{
693
694
if (dev == NULL)
695
dev = unin_chip;
696
unin_update_reg(dev, UNIN_PWR_MGMT, UNIN_PWR_NORMAL, UNIN_PWR_MASK);
697
DELAY(10);
698
unin_update_reg(dev, UNIN_HWINIT_STATE, UNIN_RUNNING, 0);
699
DELAY(100);
700
701
return (0);
702
}
703
704
int
705
unin_chip_sleep(device_t dev, int idle)
706
{
707
if (dev == NULL)
708
dev = unin_chip;
709
710
unin_update_reg(dev, UNIN_HWINIT_STATE, UNIN_SLEEPING, 0);
711
DELAY(10);
712
if (idle)
713
unin_update_reg(dev, UNIN_PWR_MGMT, UNIN_PWR_IDLE2, UNIN_PWR_MASK);
714
else
715
unin_update_reg(dev, UNIN_PWR_MGMT, UNIN_PWR_SLEEP, UNIN_PWR_MASK);
716
DELAY(10);
717
718
return (0);
719
}
720
721