macio.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696
  1. /*-
  2. * SPDX-License-Identifier: BSD-3-Clause
  3. *
  4. * Copyright 2002 by Peter Grehan. All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. The name of the author may not be used to endorse or promote products
  15. * derived from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  22. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  23. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  24. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  25. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27. * SUCH DAMAGE.
  28. *
  29. * $FreeBSD$
  30. */
  31. /*
  32. * Driver for KeyLargo/Pangea, the MacPPC south bridge ASIC.
  33. */
  34. #include <sys/param.h>
  35. #include <sys/systm.h>
  36. #include <sys/kernel.h>
  37. #include <sys/malloc.h>
  38. #include <sys/module.h>
  39. #include <sys/bus.h>
  40. #include <sys/rman.h>
  41. #include <vm/vm.h>
  42. #include <vm/pmap.h>
  43. #include <machine/bus.h>
  44. #include <machine/intr_machdep.h>
  45. #include <machine/resource.h>
  46. #include <machine/vmparam.h>
  47. #include <dev/ofw/ofw_bus.h>
  48. #include <dev/ofw/ofw_bus_subr.h>
  49. #include <dev/ofw/openfirm.h>
  50. #include <powerpc/powermac/maciovar.h>
  51. #include <dev/pci/pcivar.h>
  52. #include <dev/pci/pcireg.h>
  53. /*
  54. * Macio softc
  55. */
  56. struct macio_softc {
  57. phandle_t sc_node;
  58. vm_offset_t sc_base;
  59. vm_offset_t sc_size;
  60. struct rman sc_mem_rman;
  61. /* FCR registers */
  62. int sc_memrid;
  63. struct resource *sc_memr;
  64. };
  65. static MALLOC_DEFINE(M_MACIO, "macio", "macio device information");
  66. static int macio_probe(device_t);
  67. static int macio_attach(device_t);
  68. static int macio_print_child(device_t dev, device_t child);
  69. static void macio_probe_nomatch(device_t, device_t);
  70. static struct resource *macio_alloc_resource(device_t, device_t, int, int *,
  71. rman_res_t, rman_res_t, rman_res_t,
  72. u_int);
  73. static int macio_activate_resource(device_t, device_t, int, int,
  74. struct resource *);
  75. static int macio_deactivate_resource(device_t, device_t, int, int,
  76. struct resource *);
  77. static int macio_release_resource(device_t, device_t, int, int,
  78. struct resource *);
  79. static struct resource_list *macio_get_resource_list (device_t, device_t);
  80. static ofw_bus_get_devinfo_t macio_get_devinfo;
  81. /*
  82. * Bus interface definition
  83. */
  84. static device_method_t macio_methods[] = {
  85. /* Device interface */
  86. DEVMETHOD(device_probe, macio_probe),
  87. DEVMETHOD(device_attach, macio_attach),
  88. DEVMETHOD(device_detach, bus_generic_detach),
  89. DEVMETHOD(device_shutdown, bus_generic_shutdown),
  90. DEVMETHOD(device_suspend, bus_generic_suspend),
  91. DEVMETHOD(device_resume, bus_generic_resume),
  92. /* Bus interface */
  93. DEVMETHOD(bus_print_child, macio_print_child),
  94. DEVMETHOD(bus_probe_nomatch, macio_probe_nomatch),
  95. DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
  96. DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
  97. DEVMETHOD(bus_alloc_resource, macio_alloc_resource),
  98. DEVMETHOD(bus_release_resource, macio_release_resource),
  99. DEVMETHOD(bus_activate_resource, macio_activate_resource),
  100. DEVMETHOD(bus_deactivate_resource, macio_deactivate_resource),
  101. DEVMETHOD(bus_get_resource_list, macio_get_resource_list),
  102. DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str),
  103. /* ofw_bus interface */
  104. DEVMETHOD(ofw_bus_get_devinfo, macio_get_devinfo),
  105. DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat),
  106. DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model),
  107. DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name),
  108. DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
  109. DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
  110. { 0, 0 }
  111. };
  112. static driver_t macio_pci_driver = {
  113. "macio",
  114. macio_methods,
  115. sizeof(struct macio_softc)
  116. };
  117. devclass_t macio_devclass;
  118. EARLY_DRIVER_MODULE(macio, pci, macio_pci_driver, macio_devclass, 0, 0,
  119. BUS_PASS_BUS);
  120. /*
  121. * PCI ID search table
  122. */
  123. static struct macio_pci_dev {
  124. u_int32_t mpd_devid;
  125. char *mpd_desc;
  126. } macio_pci_devlist[] = {
  127. { 0x0017106b, "Paddington I/O Controller" },
  128. { 0x0022106b, "KeyLargo I/O Controller" },
  129. { 0x0025106b, "Pangea I/O Controller" },
  130. { 0x003e106b, "Intrepid I/O Controller" },
  131. { 0x0041106b, "K2 KeyLargo I/O Controller" },
  132. { 0x004f106b, "Shasta I/O Controller" },
  133. { 0, NULL }
  134. };
  135. /*
  136. * Devices to exclude from the probe
  137. * XXX some of these may be required in the future...
  138. */
  139. #define MACIO_QUIRK_IGNORE 0x00000001
  140. #define MACIO_QUIRK_CHILD_HAS_INTR 0x00000002
  141. #define MACIO_QUIRK_USE_CHILD_REG 0x00000004
  142. struct macio_quirk_entry {
  143. const char *mq_name;
  144. int mq_quirks;
  145. };
  146. static struct macio_quirk_entry macio_quirks[] = {
  147. { "escc-legacy", MACIO_QUIRK_IGNORE },
  148. { "timer", MACIO_QUIRK_IGNORE },
  149. { "escc", MACIO_QUIRK_CHILD_HAS_INTR },
  150. { "i2s", MACIO_QUIRK_CHILD_HAS_INTR |
  151. MACIO_QUIRK_USE_CHILD_REG },
  152. { NULL, 0 }
  153. };
  154. static int
  155. macio_get_quirks(const char *name)
  156. {
  157. struct macio_quirk_entry *mqe;
  158. for (mqe = macio_quirks; mqe->mq_name != NULL; mqe++)
  159. if (strcmp(name, mqe->mq_name) == 0)
  160. return (mqe->mq_quirks);
  161. return (0);
  162. }
  163. /*
  164. * Add an interrupt to the dev's resource list if present
  165. */
  166. static void
  167. macio_add_intr(phandle_t devnode, struct macio_devinfo *dinfo)
  168. {
  169. phandle_t iparent;
  170. int *intr;
  171. int i, nintr;
  172. int icells;
  173. if (dinfo->mdi_ninterrupts >= 6) {
  174. printf("macio: device has more than 6 interrupts\n");
  175. return;
  176. }
  177. nintr = OF_getprop_alloc_multi(devnode, "interrupts", sizeof(*intr),
  178. (void **)&intr);
  179. if (nintr == -1) {
  180. nintr = OF_getprop_alloc_multi(devnode, "AAPL,interrupts",
  181. sizeof(*intr), (void **)&intr);
  182. if (nintr == -1)
  183. return;
  184. }
  185. if (intr[0] == -1)
  186. return;
  187. if (OF_getprop(devnode, "interrupt-parent", &iparent, sizeof(iparent))
  188. <= 0)
  189. panic("Interrupt but no interrupt parent!\n");
  190. if (OF_getprop(OF_node_from_xref(iparent), "#interrupt-cells", &icells,
  191. sizeof(icells)) <= 0)
  192. icells = 1;
  193. for (i = 0; i < nintr; i+=icells) {
  194. u_int irq = MAP_IRQ(iparent, intr[i]);
  195. resource_list_add(&dinfo->mdi_resources, SYS_RES_IRQ,
  196. dinfo->mdi_ninterrupts, irq, irq, 1);
  197. dinfo->mdi_interrupts[dinfo->mdi_ninterrupts] = irq;
  198. dinfo->mdi_ninterrupts++;
  199. }
  200. }
  201. static void
  202. macio_add_reg(phandle_t devnode, struct macio_devinfo *dinfo)
  203. {
  204. struct macio_reg *reg, *regp;
  205. phandle_t child;
  206. char buf[8];
  207. int i, layout_id = 0, nreg, res;
  208. nreg = OF_getprop_alloc_multi(devnode, "reg", sizeof(*reg), (void **)&reg);
  209. if (nreg == -1)
  210. return;
  211. /*
  212. * Some G5's have broken properties in the i2s-a area. If so we try
  213. * to fix it. Right now we know of two different cases, one for
  214. * sound layout-id 36 and the other one for sound layout-id 76.
  215. * What is missing is the base address for the memory addresses.
  216. * We take them from the parent node (i2s) and use the size
  217. * information from the child.
  218. */
  219. if (reg[0].mr_base == 0) {
  220. child = OF_child(devnode);
  221. while (child != 0) {
  222. res = OF_getprop(child, "name", buf, sizeof(buf));
  223. if (res > 0 && strcmp(buf, "sound") == 0)
  224. break;
  225. child = OF_peer(child);
  226. }
  227. res = OF_getprop(child, "layout-id", &layout_id,
  228. sizeof(layout_id));
  229. if (res > 0 && (layout_id == 36 || layout_id == 76)) {
  230. res = OF_getprop_alloc_multi(OF_parent(devnode), "reg",
  231. sizeof(*regp), (void **)&regp);
  232. reg[0] = regp[0];
  233. reg[1].mr_base = regp[1].mr_base;
  234. reg[2].mr_base = regp[1].mr_base + reg[1].mr_size;
  235. }
  236. }
  237. for (i = 0; i < nreg; i++) {
  238. resource_list_add(&dinfo->mdi_resources, SYS_RES_MEMORY, i,
  239. reg[i].mr_base, reg[i].mr_base + reg[i].mr_size,
  240. reg[i].mr_size);
  241. }
  242. }
  243. /*
  244. * PCI probe
  245. */
  246. static int
  247. macio_probe(device_t dev)
  248. {
  249. int i;
  250. u_int32_t devid;
  251. devid = pci_get_devid(dev);
  252. for (i = 0; macio_pci_devlist[i].mpd_desc != NULL; i++) {
  253. if (devid == macio_pci_devlist[i].mpd_devid) {
  254. device_set_desc(dev, macio_pci_devlist[i].mpd_desc);
  255. return (0);
  256. }
  257. }
  258. return (ENXIO);
  259. }
  260. /*
  261. * PCI attach: scan Open Firmware child nodes, and attach these as children
  262. * of the macio bus
  263. */
  264. static int
  265. macio_attach(device_t dev)
  266. {
  267. struct macio_softc *sc;
  268. struct macio_devinfo *dinfo;
  269. phandle_t root;
  270. phandle_t child;
  271. phandle_t subchild;
  272. device_t cdev;
  273. u_int reg[3];
  274. char compat[32];
  275. int error, quirks;
  276. sc = device_get_softc(dev);
  277. root = sc->sc_node = ofw_bus_get_node(dev);
  278. /*
  279. * Locate the device node and it's base address
  280. */
  281. if (OF_getprop(root, "assigned-addresses",
  282. reg, sizeof(reg)) < (ssize_t)sizeof(reg)) {
  283. return (ENXIO);
  284. }
  285. /* Used later to see if we have to enable the I2S part. */
  286. OF_getprop(root, "compatible", compat, sizeof(compat));
  287. sc->sc_base = reg[2];
  288. sc->sc_size = MACIO_REG_SIZE;
  289. sc->sc_memrid = PCIR_BAR(0);
  290. sc->sc_memr = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
  291. &sc->sc_memrid, RF_ACTIVE);
  292. sc->sc_mem_rman.rm_type = RMAN_ARRAY;
  293. sc->sc_mem_rman.rm_descr = "MacIO Device Memory";
  294. error = rman_init(&sc->sc_mem_rman);
  295. if (error) {
  296. device_printf(dev, "rman_init() failed. error = %d\n", error);
  297. return (error);
  298. }
  299. error = rman_manage_region(&sc->sc_mem_rman, 0, sc->sc_size);
  300. if (error) {
  301. device_printf(dev,
  302. "rman_manage_region() failed. error = %d\n", error);
  303. return (error);
  304. }
  305. /*
  306. * Iterate through the sub-devices
  307. */
  308. for (child = OF_child(root); child != 0; child = OF_peer(child)) {
  309. dinfo = malloc(sizeof(*dinfo), M_MACIO, M_WAITOK | M_ZERO);
  310. if (ofw_bus_gen_setup_devinfo(&dinfo->mdi_obdinfo, child) !=
  311. 0) {
  312. free(dinfo, M_MACIO);
  313. continue;
  314. }
  315. quirks = macio_get_quirks(dinfo->mdi_obdinfo.obd_name);
  316. if ((quirks & MACIO_QUIRK_IGNORE) != 0) {
  317. ofw_bus_gen_destroy_devinfo(&dinfo->mdi_obdinfo);
  318. free(dinfo, M_MACIO);
  319. continue;
  320. }
  321. resource_list_init(&dinfo->mdi_resources);
  322. dinfo->mdi_ninterrupts = 0;
  323. macio_add_intr(child, dinfo);
  324. if ((quirks & MACIO_QUIRK_USE_CHILD_REG) != 0)
  325. macio_add_reg(OF_child(child), dinfo);
  326. else
  327. macio_add_reg(child, dinfo);
  328. if ((quirks & MACIO_QUIRK_CHILD_HAS_INTR) != 0)
  329. for (subchild = OF_child(child); subchild != 0;
  330. subchild = OF_peer(subchild))
  331. macio_add_intr(subchild, dinfo);
  332. cdev = device_add_child(dev, NULL, -1);
  333. if (cdev == NULL) {
  334. device_printf(dev, "<%s>: device_add_child failed\n",
  335. dinfo->mdi_obdinfo.obd_name);
  336. resource_list_free(&dinfo->mdi_resources);
  337. ofw_bus_gen_destroy_devinfo(&dinfo->mdi_obdinfo);
  338. free(dinfo, M_MACIO);
  339. continue;
  340. }
  341. device_set_ivars(cdev, dinfo);
  342. /* Set FCRs to enable some devices */
  343. if (sc->sc_memr == NULL)
  344. continue;
  345. if (strcmp(ofw_bus_get_name(cdev), "bmac") == 0 ||
  346. (ofw_bus_get_compat(cdev) != NULL &&
  347. strcmp(ofw_bus_get_compat(cdev), "bmac+") == 0)) {
  348. uint32_t fcr;
  349. fcr = bus_read_4(sc->sc_memr, HEATHROW_FCR);
  350. fcr |= FCR_ENET_ENABLE & ~FCR_ENET_RESET;
  351. bus_write_4(sc->sc_memr, HEATHROW_FCR, fcr);
  352. DELAY(50000);
  353. fcr |= FCR_ENET_RESET;
  354. bus_write_4(sc->sc_memr, HEATHROW_FCR, fcr);
  355. DELAY(50000);
  356. fcr &= ~FCR_ENET_RESET;
  357. bus_write_4(sc->sc_memr, HEATHROW_FCR, fcr);
  358. DELAY(50000);
  359. bus_write_4(sc->sc_memr, HEATHROW_FCR, fcr);
  360. }
  361. /*
  362. * Make sure the I2S0 and the I2S0_CLK are enabled.
  363. * On certain G5's they are not.
  364. */
  365. if ((strcmp(ofw_bus_get_name(cdev), "i2s") == 0) &&
  366. (strcmp(compat, "K2-Keylargo") == 0)) {
  367. uint32_t fcr1;
  368. fcr1 = bus_read_4(sc->sc_memr, KEYLARGO_FCR1);
  369. fcr1 |= FCR1_I2S0_CLK_ENABLE | FCR1_I2S0_ENABLE;
  370. bus_write_4(sc->sc_memr, KEYLARGO_FCR1, fcr1);
  371. }
  372. }
  373. return (bus_generic_attach(dev));
  374. }
  375. static int
  376. macio_print_child(device_t dev, device_t child)
  377. {
  378. struct macio_devinfo *dinfo;
  379. struct resource_list *rl;
  380. int retval = 0;
  381. dinfo = device_get_ivars(child);
  382. rl = &dinfo->mdi_resources;
  383. retval += bus_print_child_header(dev, child);
  384. retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx");
  385. retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd");
  386. retval += bus_print_child_footer(dev, child);
  387. return (retval);
  388. }
  389. static void
  390. macio_probe_nomatch(device_t dev, device_t child)
  391. {
  392. struct macio_devinfo *dinfo;
  393. struct resource_list *rl;
  394. const char *type;
  395. if (bootverbose) {
  396. dinfo = device_get_ivars(child);
  397. rl = &dinfo->mdi_resources;
  398. if ((type = ofw_bus_get_type(child)) == NULL)
  399. type = "(unknown)";
  400. device_printf(dev, "<%s, %s>", type, ofw_bus_get_name(child));
  401. resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx");
  402. resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd");
  403. printf(" (no driver attached)\n");
  404. }
  405. }
  406. static struct resource *
  407. macio_alloc_resource(device_t bus, device_t child, int type, int *rid,
  408. rman_res_t start, rman_res_t end, rman_res_t count,
  409. u_int flags)
  410. {
  411. struct macio_softc *sc;
  412. int needactivate;
  413. struct resource *rv;
  414. struct rman *rm;
  415. u_long adjstart, adjend, adjcount;
  416. struct macio_devinfo *dinfo;
  417. struct resource_list_entry *rle;
  418. sc = device_get_softc(bus);
  419. dinfo = device_get_ivars(child);
  420. needactivate = flags & RF_ACTIVE;
  421. flags &= ~RF_ACTIVE;
  422. switch (type) {
  423. case SYS_RES_MEMORY:
  424. case SYS_RES_IOPORT:
  425. rle = resource_list_find(&dinfo->mdi_resources, SYS_RES_MEMORY,
  426. *rid);
  427. if (rle == NULL) {
  428. device_printf(bus, "no rle for %s memory %d\n",
  429. device_get_nameunit(child), *rid);
  430. return (NULL);
  431. }
  432. if (start < rle->start)
  433. adjstart = rle->start;
  434. else if (start > rle->end)
  435. adjstart = rle->end;
  436. else
  437. adjstart = start;
  438. if (end < rle->start)
  439. adjend = rle->start;
  440. else if (end > rle->end)
  441. adjend = rle->end;
  442. else
  443. adjend = end;
  444. adjcount = adjend - adjstart;
  445. rm = &sc->sc_mem_rman;
  446. break;
  447. case SYS_RES_IRQ:
  448. /* Check for passthrough from subattachments like macgpio */
  449. if (device_get_parent(child) != bus)
  450. return BUS_ALLOC_RESOURCE(device_get_parent(bus), child,
  451. type, rid, start, end, count, flags);
  452. rle = resource_list_find(&dinfo->mdi_resources, SYS_RES_IRQ,
  453. *rid);
  454. if (rle == NULL) {
  455. if (dinfo->mdi_ninterrupts >= 6) {
  456. device_printf(bus,
  457. "%s has more than 6 interrupts\n",
  458. device_get_nameunit(child));
  459. return (NULL);
  460. }
  461. resource_list_add(&dinfo->mdi_resources, SYS_RES_IRQ,
  462. dinfo->mdi_ninterrupts, start, start, 1);
  463. dinfo->mdi_interrupts[dinfo->mdi_ninterrupts] = start;
  464. dinfo->mdi_ninterrupts++;
  465. }
  466. return (resource_list_alloc(&dinfo->mdi_resources, bus, child,
  467. type, rid, start, end, count, flags));
  468. default:
  469. device_printf(bus, "unknown resource request from %s\n",
  470. device_get_nameunit(child));
  471. return (NULL);
  472. }
  473. rv = rman_reserve_resource(rm, adjstart, adjend, adjcount, flags,
  474. child);
  475. if (rv == NULL) {
  476. device_printf(bus,
  477. "failed to reserve resource %#lx - %#lx (%#lx) for %s\n",
  478. adjstart, adjend, adjcount, device_get_nameunit(child));
  479. return (NULL);
  480. }
  481. rman_set_rid(rv, *rid);
  482. if (needactivate) {
  483. if (bus_activate_resource(child, type, *rid, rv) != 0) {
  484. device_printf(bus,
  485. "failed to activate resource for %s\n",
  486. device_get_nameunit(child));
  487. rman_release_resource(rv);
  488. return (NULL);
  489. }
  490. }
  491. return (rv);
  492. }
  493. static int
  494. macio_release_resource(device_t bus, device_t child, int type, int rid,
  495. struct resource *res)
  496. {
  497. if (rman_get_flags(res) & RF_ACTIVE) {
  498. int error = bus_deactivate_resource(child, type, rid, res);
  499. if (error)
  500. return error;
  501. }
  502. return (rman_release_resource(res));
  503. }
  504. static int
  505. macio_activate_resource(device_t bus, device_t child, int type, int rid,
  506. struct resource *res)
  507. {
  508. struct macio_softc *sc;
  509. void *p;
  510. sc = device_get_softc(bus);
  511. if (type == SYS_RES_IRQ)
  512. return (bus_activate_resource(bus, type, rid, res));
  513. if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) {
  514. p = pmap_mapdev((vm_offset_t)rman_get_start(res) + sc->sc_base,
  515. (vm_size_t)rman_get_size(res));
  516. if (p == NULL)
  517. return (ENOMEM);
  518. rman_set_virtual(res, p);
  519. rman_set_bustag(res, &bs_le_tag);
  520. rman_set_bushandle(res, (u_long)p);
  521. }
  522. return (rman_activate_resource(res));
  523. }
  524. static int
  525. macio_deactivate_resource(device_t bus, device_t child, int type, int rid,
  526. struct resource *res)
  527. {
  528. /*
  529. * If this is a memory resource, unmap it.
  530. */
  531. if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) {
  532. u_int32_t psize;
  533. psize = rman_get_size(res);
  534. pmap_unmapdev((vm_offset_t)rman_get_virtual(res), psize);
  535. }
  536. return (rman_deactivate_resource(res));
  537. }
  538. static struct resource_list *
  539. macio_get_resource_list (device_t dev, device_t child)
  540. {
  541. struct macio_devinfo *dinfo;
  542. dinfo = device_get_ivars(child);
  543. return (&dinfo->mdi_resources);
  544. }
  545. static const struct ofw_bus_devinfo *
  546. macio_get_devinfo(device_t dev, device_t child)
  547. {
  548. struct macio_devinfo *dinfo;
  549. dinfo = device_get_ivars(child);
  550. return (&dinfo->mdi_obdinfo);
  551. }
  552. int
  553. macio_enable_wireless(device_t dev, bool enable)
  554. {
  555. struct macio_softc *sc = device_get_softc(dev);
  556. uint32_t x;
  557. if (enable) {
  558. x = bus_read_4(sc->sc_memr, KEYLARGO_FCR2);
  559. x |= 0x4;
  560. bus_write_4(sc->sc_memr, KEYLARGO_FCR2, x);
  561. /* Enable card slot. */
  562. bus_write_1(sc->sc_memr, KEYLARGO_GPIO_BASE + 0x0f, 5);
  563. DELAY(1000);
  564. bus_write_1(sc->sc_memr, KEYLARGO_GPIO_BASE + 0x0f, 4);
  565. DELAY(1000);
  566. x = bus_read_4(sc->sc_memr, KEYLARGO_FCR2);
  567. x &= ~0x80000000;
  568. bus_write_4(sc->sc_memr, KEYLARGO_FCR2, x);
  569. /* out8(gpio + 0x10, 4); */
  570. bus_write_1(sc->sc_memr, KEYLARGO_EXTINT_GPIO_REG_BASE + 0x0b, 0);
  571. bus_write_1(sc->sc_memr, KEYLARGO_EXTINT_GPIO_REG_BASE + 0x0a, 0x28);
  572. bus_write_1(sc->sc_memr, KEYLARGO_EXTINT_GPIO_REG_BASE + 0x0d, 0x28);
  573. bus_write_1(sc->sc_memr, KEYLARGO_GPIO_BASE + 0x0d, 0x28);
  574. bus_write_1(sc->sc_memr, KEYLARGO_GPIO_BASE + 0x0e, 0x28);
  575. bus_write_4(sc->sc_memr, 0x1c000, 0);
  576. /* Initialize the card. */
  577. bus_write_4(sc->sc_memr, 0x1a3e0, 0x41);
  578. x = bus_read_4(sc->sc_memr, KEYLARGO_FCR2);
  579. x |= 0x80000000;
  580. bus_write_4(sc->sc_memr, KEYLARGO_FCR2, x);
  581. } else {
  582. x = bus_read_4(sc->sc_memr, KEYLARGO_FCR2);
  583. x &= ~0x4;
  584. bus_write_4(sc->sc_memr, KEYLARGO_FCR2, x);
  585. /* out8(gpio + 0x10, 0); */
  586. }
  587. return (0);
  588. }