uninorth.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673
  1. /*-
  2. * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
  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. * $FreeBSD$
  28. */
  29. #include <sys/param.h>
  30. #include <sys/systm.h>
  31. #include <sys/module.h>
  32. #include <sys/bus.h>
  33. #include <sys/conf.h>
  34. #include <sys/kernel.h>
  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. #include <dev/pci/pcivar.h>
  40. #include <dev/pci/pcireg.h>
  41. #include <machine/bus.h>
  42. #include <machine/intr_machdep.h>
  43. #include <machine/md_var.h>
  44. #include <machine/pio.h>
  45. #include <machine/resource.h>
  46. #include <sys/rman.h>
  47. #include <powerpc/powermac/uninorthvar.h>
  48. #include <vm/vm.h>
  49. #include <vm/pmap.h>
  50. /*
  51. * Driver for the Uninorth chip itself.
  52. */
  53. static MALLOC_DEFINE(M_UNIN, "unin", "unin device information");
  54. /*
  55. * Device interface.
  56. */
  57. static int unin_chip_probe(device_t);
  58. static int unin_chip_attach(device_t);
  59. /*
  60. * Bus interface.
  61. */
  62. static int unin_chip_print_child(device_t dev, device_t child);
  63. static void unin_chip_probe_nomatch(device_t, device_t);
  64. static struct resource *unin_chip_alloc_resource(device_t, device_t, int, int *,
  65. rman_res_t, rman_res_t,
  66. rman_res_t, u_int);
  67. static int unin_chip_activate_resource(device_t, device_t, int, int,
  68. struct resource *);
  69. static int unin_chip_deactivate_resource(device_t, device_t, int, int,
  70. struct resource *);
  71. static int unin_chip_release_resource(device_t, device_t, int, int,
  72. struct resource *);
  73. static struct resource_list *unin_chip_get_resource_list (device_t, device_t);
  74. /*
  75. * OFW Bus interface
  76. */
  77. static ofw_bus_get_devinfo_t unin_chip_get_devinfo;
  78. /*
  79. * Local routines
  80. */
  81. static void unin_enable_gmac(device_t dev);
  82. static void unin_enable_mpic(device_t dev);
  83. /*
  84. * Driver methods.
  85. */
  86. static device_method_t unin_chip_methods[] = {
  87. /* Device interface */
  88. DEVMETHOD(device_probe, unin_chip_probe),
  89. DEVMETHOD(device_attach, unin_chip_attach),
  90. /* Bus interface */
  91. DEVMETHOD(bus_print_child, unin_chip_print_child),
  92. DEVMETHOD(bus_probe_nomatch, unin_chip_probe_nomatch),
  93. DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
  94. DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
  95. DEVMETHOD(bus_alloc_resource, unin_chip_alloc_resource),
  96. DEVMETHOD(bus_release_resource, unin_chip_release_resource),
  97. DEVMETHOD(bus_activate_resource, unin_chip_activate_resource),
  98. DEVMETHOD(bus_deactivate_resource, unin_chip_deactivate_resource),
  99. DEVMETHOD(bus_get_resource_list, unin_chip_get_resource_list),
  100. DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str),
  101. /* ofw_bus interface */
  102. DEVMETHOD(ofw_bus_get_devinfo, unin_chip_get_devinfo),
  103. DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat),
  104. DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model),
  105. DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name),
  106. DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
  107. DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
  108. { 0, 0 }
  109. };
  110. static driver_t unin_chip_driver = {
  111. "unin",
  112. unin_chip_methods,
  113. sizeof(struct unin_chip_softc)
  114. };
  115. static devclass_t unin_chip_devclass;
  116. /*
  117. * Assume there is only one unin chip in a PowerMac, so that pmu.c functions can
  118. * suspend the chip after the whole rest of the device tree is suspended, not
  119. * earlier.
  120. */
  121. static device_t unin_chip;
  122. EARLY_DRIVER_MODULE(unin, ofwbus, unin_chip_driver, unin_chip_devclass, 0, 0,
  123. BUS_PASS_BUS);
  124. /*
  125. * Add an interrupt to the dev's resource list if present
  126. */
  127. static void
  128. unin_chip_add_intr(phandle_t devnode, struct unin_chip_devinfo *dinfo)
  129. {
  130. phandle_t iparent;
  131. int *intr;
  132. int i, nintr;
  133. int icells;
  134. if (dinfo->udi_ninterrupts >= 6) {
  135. printf("unin: device has more than 6 interrupts\n");
  136. return;
  137. }
  138. nintr = OF_getprop_alloc_multi(devnode, "interrupts", sizeof(*intr),
  139. (void **)&intr);
  140. if (nintr == -1) {
  141. nintr = OF_getprop_alloc_multi(devnode, "AAPL,interrupts",
  142. sizeof(*intr), (void **)&intr);
  143. if (nintr == -1)
  144. return;
  145. }
  146. if (intr[0] == -1)
  147. return;
  148. if (OF_getprop(devnode, "interrupt-parent", &iparent, sizeof(iparent))
  149. <= 0)
  150. panic("Interrupt but no interrupt parent!\n");
  151. if (OF_searchprop(iparent, "#interrupt-cells", &icells, sizeof(icells))
  152. <= 0)
  153. icells = 1;
  154. for (i = 0; i < nintr; i+=icells) {
  155. u_int irq = MAP_IRQ(iparent, intr[i]);
  156. resource_list_add(&dinfo->udi_resources, SYS_RES_IRQ,
  157. dinfo->udi_ninterrupts, irq, irq, 1);
  158. if (icells > 1) {
  159. powerpc_config_intr(irq,
  160. (intr[i+1] & 1) ? INTR_TRIGGER_LEVEL :
  161. INTR_TRIGGER_EDGE, INTR_POLARITY_LOW);
  162. }
  163. dinfo->udi_interrupts[dinfo->udi_ninterrupts] = irq;
  164. dinfo->udi_ninterrupts++;
  165. }
  166. }
  167. static void
  168. unin_chip_add_reg(phandle_t devnode, struct unin_chip_devinfo *dinfo)
  169. {
  170. struct unin_chip_reg *reg;
  171. int i, nreg;
  172. nreg = OF_getprop_alloc_multi(devnode, "reg", sizeof(*reg), (void **)&reg);
  173. if (nreg == -1)
  174. return;
  175. for (i = 0; i < nreg; i++) {
  176. resource_list_add(&dinfo->udi_resources, SYS_RES_MEMORY, i,
  177. reg[i].mr_base,
  178. reg[i].mr_base + reg[i].mr_size,
  179. reg[i].mr_size);
  180. }
  181. }
  182. static void
  183. unin_update_reg(device_t dev, uint32_t regoff, uint32_t set, uint32_t clr)
  184. {
  185. volatile u_int *reg;
  186. struct unin_chip_softc *sc;
  187. u_int32_t tmpl;
  188. sc = device_get_softc(dev);
  189. reg = (void *)(sc->sc_addr + regoff);
  190. tmpl = inl(reg);
  191. tmpl &= ~clr;
  192. tmpl |= set;
  193. outl(reg, tmpl);
  194. }
  195. static void
  196. unin_enable_gmac(device_t dev)
  197. {
  198. unin_update_reg(dev, UNIN_CLOCKCNTL, UNIN_CLOCKCNTL_GMAC, 0);
  199. }
  200. static void
  201. unin_enable_mpic(device_t dev)
  202. {
  203. unin_update_reg(dev, UNIN_TOGGLE_REG, UNIN_MPIC_RESET | UNIN_MPIC_OUTPUT_ENABLE, 0);
  204. }
  205. static int
  206. unin_chip_probe(device_t dev)
  207. {
  208. const char *name;
  209. name = ofw_bus_get_name(dev);
  210. if (name == NULL)
  211. return (ENXIO);
  212. if (strcmp(name, "uni-n") != 0 && strcmp(name, "u3") != 0
  213. && strcmp(name, "u4") != 0)
  214. return (ENXIO);
  215. device_set_desc(dev, "Apple UniNorth System Controller");
  216. return (0);
  217. }
  218. static int
  219. unin_chip_attach(device_t dev)
  220. {
  221. struct unin_chip_softc *sc;
  222. struct unin_chip_devinfo *dinfo;
  223. phandle_t root;
  224. phandle_t child;
  225. phandle_t iparent;
  226. device_t cdev;
  227. cell_t acells, scells;
  228. char compat[32];
  229. char name[32];
  230. u_int irq, reg[3];
  231. int error, i = 0;
  232. sc = device_get_softc(dev);
  233. root = ofw_bus_get_node(dev);
  234. if (OF_getprop(root, "reg", reg, sizeof(reg)) < 8)
  235. return (ENXIO);
  236. acells = scells = 1;
  237. OF_getprop(OF_parent(root), "#address-cells", &acells, sizeof(acells));
  238. OF_getprop(OF_parent(root), "#size-cells", &scells, sizeof(scells));
  239. i = 0;
  240. sc->sc_physaddr = reg[i++];
  241. if (acells == 2) {
  242. sc->sc_physaddr <<= 32;
  243. sc->sc_physaddr |= reg[i++];
  244. }
  245. sc->sc_size = reg[i++];
  246. if (scells == 2) {
  247. sc->sc_size <<= 32;
  248. sc->sc_size |= reg[i++];
  249. }
  250. sc->sc_mem_rman.rm_type = RMAN_ARRAY;
  251. sc->sc_mem_rman.rm_descr = "UniNorth Device Memory";
  252. error = rman_init(&sc->sc_mem_rman);
  253. if (error) {
  254. device_printf(dev, "rman_init() failed. error = %d\n", error);
  255. return (error);
  256. }
  257. error = rman_manage_region(&sc->sc_mem_rman, sc->sc_physaddr,
  258. sc->sc_physaddr + sc->sc_size - 1);
  259. if (error) {
  260. device_printf(dev,
  261. "rman_manage_region() failed. error = %d\n",
  262. error);
  263. return (error);
  264. }
  265. if (unin_chip == NULL)
  266. unin_chip = dev;
  267. /*
  268. * Iterate through the sub-devices
  269. */
  270. for (child = OF_child(root); child != 0; child = OF_peer(child)) {
  271. dinfo = malloc(sizeof(*dinfo), M_UNIN, M_WAITOK | M_ZERO);
  272. if (ofw_bus_gen_setup_devinfo(&dinfo->udi_obdinfo, child)
  273. != 0)
  274. {
  275. free(dinfo, M_UNIN);
  276. continue;
  277. }
  278. resource_list_init(&dinfo->udi_resources);
  279. dinfo->udi_ninterrupts = 0;
  280. unin_chip_add_intr(child, dinfo);
  281. /*
  282. * Some Apple machines do have a bug in OF, they miss
  283. * the interrupt entries on the U3 I2C node. That means they
  284. * do not have an entry with number of interrupts nor the
  285. * entry of the interrupt parent handle.
  286. * We define an interrupt and hardwire it to the /u3/mpic
  287. * handle.
  288. */
  289. if (OF_getprop(child, "name", name, sizeof(name)) <= 0)
  290. device_printf(dev, "device has no name!\n");
  291. if (dinfo->udi_ninterrupts == 0 &&
  292. (strcmp(name, "i2c-bus") == 0 ||
  293. strcmp(name, "i2c") == 0)) {
  294. if (OF_getprop(child, "interrupt-parent", &iparent,
  295. sizeof(iparent)) <= 0) {
  296. iparent = OF_finddevice("/u3/mpic");
  297. device_printf(dev, "Set /u3/mpic as iparent!\n");
  298. }
  299. /* Add an interrupt number 0 to the parent. */
  300. irq = MAP_IRQ(iparent, 0);
  301. resource_list_add(&dinfo->udi_resources, SYS_RES_IRQ,
  302. dinfo->udi_ninterrupts, irq, irq, 1);
  303. dinfo->udi_interrupts[dinfo->udi_ninterrupts] = irq;
  304. dinfo->udi_ninterrupts++;
  305. }
  306. unin_chip_add_reg(child, dinfo);
  307. cdev = device_add_child(dev, NULL, -1);
  308. if (cdev == NULL) {
  309. device_printf(dev, "<%s>: device_add_child failed\n",
  310. dinfo->udi_obdinfo.obd_name);
  311. resource_list_free(&dinfo->udi_resources);
  312. ofw_bus_gen_destroy_devinfo(&dinfo->udi_obdinfo);
  313. free(dinfo, M_UNIN);
  314. continue;
  315. }
  316. device_set_ivars(cdev, dinfo);
  317. }
  318. /*
  319. * Only map the first page, since that is where the registers
  320. * of interest lie.
  321. */
  322. sc->sc_addr = (vm_offset_t)pmap_mapdev(sc->sc_physaddr, PAGE_SIZE);
  323. sc->sc_version = *(u_int *)sc->sc_addr;
  324. device_printf(dev, "Version %d\n", sc->sc_version);
  325. /*
  326. * Enable the GMAC Ethernet cell and the integrated OpenPIC
  327. * if Open Firmware says they are used.
  328. */
  329. for (child = OF_child(root); child; child = OF_peer(child)) {
  330. memset(compat, 0, sizeof(compat));
  331. OF_getprop(child, "compatible", compat, sizeof(compat));
  332. if (strcmp(compat, "gmac") == 0)
  333. unin_enable_gmac(dev);
  334. if (strcmp(compat, "chrp,open-pic") == 0)
  335. unin_enable_mpic(dev);
  336. }
  337. /*
  338. * GMAC lives under the PCI bus, so just check if enet is gmac.
  339. */
  340. child = OF_finddevice("enet");
  341. memset(compat, 0, sizeof(compat));
  342. OF_getprop(child, "compatible", compat, sizeof(compat));
  343. if (strcmp(compat, "gmac") == 0)
  344. unin_enable_gmac(dev);
  345. return (bus_generic_attach(dev));
  346. }
  347. static int
  348. unin_chip_print_child(device_t dev, device_t child)
  349. {
  350. struct unin_chip_devinfo *dinfo;
  351. struct resource_list *rl;
  352. int retval = 0;
  353. dinfo = device_get_ivars(child);
  354. rl = &dinfo->udi_resources;
  355. retval += bus_print_child_header(dev, child);
  356. retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx");
  357. retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd");
  358. retval += bus_print_child_footer(dev, child);
  359. return (retval);
  360. }
  361. static void
  362. unin_chip_probe_nomatch(device_t dev, device_t child)
  363. {
  364. struct unin_chip_devinfo *dinfo;
  365. struct resource_list *rl;
  366. const char *type;
  367. if (bootverbose) {
  368. dinfo = device_get_ivars(child);
  369. rl = &dinfo->udi_resources;
  370. if ((type = ofw_bus_get_type(child)) == NULL)
  371. type = "(unknown)";
  372. device_printf(dev, "<%s, %s>", type, ofw_bus_get_name(child));
  373. resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx");
  374. resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd");
  375. printf(" (no driver attached)\n");
  376. }
  377. }
  378. static struct resource *
  379. unin_chip_alloc_resource(device_t bus, device_t child, int type, int *rid,
  380. rman_res_t start, rman_res_t end, rman_res_t count,
  381. u_int flags)
  382. {
  383. struct unin_chip_softc *sc;
  384. int needactivate;
  385. struct resource *rv;
  386. struct rman *rm;
  387. u_long adjstart, adjend, adjcount;
  388. struct unin_chip_devinfo *dinfo;
  389. struct resource_list_entry *rle;
  390. sc = device_get_softc(bus);
  391. dinfo = device_get_ivars(child);
  392. needactivate = flags & RF_ACTIVE;
  393. flags &= ~RF_ACTIVE;
  394. switch (type) {
  395. case SYS_RES_MEMORY:
  396. case SYS_RES_IOPORT:
  397. rle = resource_list_find(&dinfo->udi_resources, SYS_RES_MEMORY,
  398. *rid);
  399. if (rle == NULL) {
  400. device_printf(bus, "no rle for %s memory %d\n",
  401. device_get_nameunit(child), *rid);
  402. return (NULL);
  403. }
  404. rle->end = rle->end - 1; /* Hack? */
  405. if (start < rle->start)
  406. adjstart = rle->start;
  407. else if (start > rle->end)
  408. adjstart = rle->end;
  409. else
  410. adjstart = start;
  411. if (end < rle->start)
  412. adjend = rle->start;
  413. else if (end > rle->end)
  414. adjend = rle->end;
  415. else
  416. adjend = end;
  417. adjcount = adjend - adjstart;
  418. rm = &sc->sc_mem_rman;
  419. break;
  420. case SYS_RES_IRQ:
  421. /* Check for passthrough from subattachments. */
  422. if (device_get_parent(child) != bus)
  423. return BUS_ALLOC_RESOURCE(device_get_parent(bus), child,
  424. type, rid, start, end, count,
  425. flags);
  426. rle = resource_list_find(&dinfo->udi_resources, SYS_RES_IRQ,
  427. *rid);
  428. if (rle == NULL) {
  429. if (dinfo->udi_ninterrupts >= 6) {
  430. device_printf(bus,
  431. "%s has more than 6 interrupts\n",
  432. device_get_nameunit(child));
  433. return (NULL);
  434. }
  435. resource_list_add(&dinfo->udi_resources, SYS_RES_IRQ,
  436. dinfo->udi_ninterrupts, start, start,
  437. 1);
  438. dinfo->udi_interrupts[dinfo->udi_ninterrupts] = start;
  439. dinfo->udi_ninterrupts++;
  440. }
  441. return (resource_list_alloc(&dinfo->udi_resources, bus, child,
  442. type, rid, start, end, count,
  443. flags));
  444. default:
  445. device_printf(bus, "unknown resource request from %s\n",
  446. device_get_nameunit(child));
  447. return (NULL);
  448. }
  449. rv = rman_reserve_resource(rm, adjstart, adjend, adjcount, flags,
  450. child);
  451. if (rv == NULL) {
  452. device_printf(bus,
  453. "failed to reserve resource %#lx - %#lx (%#lx)"
  454. " for %s\n", adjstart, adjend, adjcount,
  455. device_get_nameunit(child));
  456. return (NULL);
  457. }
  458. rman_set_rid(rv, *rid);
  459. if (needactivate) {
  460. if (bus_activate_resource(child, type, *rid, rv) != 0) {
  461. device_printf(bus,
  462. "failed to activate resource for %s\n",
  463. device_get_nameunit(child));
  464. rman_release_resource(rv);
  465. return (NULL);
  466. }
  467. }
  468. return (rv);
  469. }
  470. static int
  471. unin_chip_release_resource(device_t bus, device_t child, int type, int rid,
  472. struct resource *res)
  473. {
  474. if (rman_get_flags(res) & RF_ACTIVE) {
  475. int error = bus_deactivate_resource(child, type, rid, res);
  476. if (error)
  477. return error;
  478. }
  479. return (rman_release_resource(res));
  480. }
  481. static int
  482. unin_chip_activate_resource(device_t bus, device_t child, int type, int rid,
  483. struct resource *res)
  484. {
  485. void *p;
  486. if (type == SYS_RES_IRQ)
  487. return (bus_activate_resource(bus, type, rid, res));
  488. if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) {
  489. vm_offset_t start;
  490. start = (vm_offset_t) rman_get_start(res);
  491. if (bootverbose)
  492. printf("unin mapdev: start %zx, len %jd\n", start,
  493. rman_get_size(res));
  494. p = pmap_mapdev(start, (vm_size_t) rman_get_size(res));
  495. if (p == NULL)
  496. return (ENOMEM);
  497. rman_set_virtual(res, p);
  498. rman_set_bustag(res, &bs_be_tag);
  499. rman_set_bushandle(res, (u_long)p);
  500. }
  501. return (rman_activate_resource(res));
  502. }
  503. static int
  504. unin_chip_deactivate_resource(device_t bus, device_t child, int type, int rid,
  505. struct resource *res)
  506. {
  507. /*
  508. * If this is a memory resource, unmap it.
  509. */
  510. if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) {
  511. u_int32_t psize;
  512. psize = rman_get_size(res);
  513. pmap_unmapdev((vm_offset_t)rman_get_virtual(res), psize);
  514. }
  515. return (rman_deactivate_resource(res));
  516. }
  517. static struct resource_list *
  518. unin_chip_get_resource_list (device_t dev, device_t child)
  519. {
  520. struct unin_chip_devinfo *dinfo;
  521. dinfo = device_get_ivars(child);
  522. return (&dinfo->udi_resources);
  523. }
  524. static const struct ofw_bus_devinfo *
  525. unin_chip_get_devinfo(device_t dev, device_t child)
  526. {
  527. struct unin_chip_devinfo *dinfo;
  528. dinfo = device_get_ivars(child);
  529. return (&dinfo->udi_obdinfo);
  530. }
  531. int
  532. unin_chip_wake(device_t dev)
  533. {
  534. if (dev == NULL)
  535. dev = unin_chip;
  536. unin_update_reg(dev, UNIN_PWR_MGMT, UNIN_PWR_NORMAL, UNIN_PWR_MASK);
  537. DELAY(10);
  538. unin_update_reg(dev, UNIN_HWINIT_STATE, UNIN_RUNNING, 0);
  539. DELAY(100);
  540. return (0);
  541. }
  542. int
  543. unin_chip_sleep(device_t dev, int idle)
  544. {
  545. if (dev == NULL)
  546. dev = unin_chip;
  547. unin_update_reg(dev, UNIN_HWINIT_STATE, UNIN_SLEEPING, 0);
  548. DELAY(10);
  549. if (idle)
  550. unin_update_reg(dev, UNIN_PWR_MGMT, UNIN_PWR_IDLE2, UNIN_PWR_MASK);
  551. else
  552. unin_update_reg(dev, UNIN_PWR_MGMT, UNIN_PWR_SLEEP, UNIN_PWR_MASK);
  553. DELAY(10);
  554. return (0);
  555. }