lbc.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859
  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. #include "opt_platform.h"
  36. #include <sys/cdefs.h>
  37. __FBSDID("$FreeBSD$");
  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. #include <vm/vm.h>
  48. #include <vm/pmap.h>
  49. #include <dev/fdt/fdt_common.h>
  50. #include <dev/ofw/ofw_bus.h>
  51. #include <dev/ofw/ofw_bus_subr.h>
  52. #include <powerpc/mpc85xx/mpc85xx.h>
  53. #include "ofw_bus_if.h"
  54. #include "lbc.h"
  55. #ifdef DEBUG
  56. #define debugf(fmt, args...) do { printf("%s(): ", __func__); \
  57. printf(fmt,##args); } while (0)
  58. #else
  59. #define debugf(fmt, args...)
  60. #endif
  61. static MALLOC_DEFINE(M_LBC, "localbus", "localbus devices information");
  62. static int lbc_probe(device_t);
  63. static int lbc_attach(device_t);
  64. static int lbc_shutdown(device_t);
  65. static int lbc_activate_resource(device_t bus __unused, device_t child __unused,
  66. int type, int rid __unused, struct resource *r);
  67. static int lbc_deactivate_resource(device_t bus __unused,
  68. device_t child __unused, int type __unused, int rid __unused,
  69. struct resource *r);
  70. static struct resource *lbc_alloc_resource(device_t, device_t, int, int *,
  71. rman_res_t, rman_res_t, rman_res_t, u_int);
  72. static int lbc_print_child(device_t, device_t);
  73. static int lbc_release_resource(device_t, device_t, int, int,
  74. struct resource *);
  75. static const struct ofw_bus_devinfo *lbc_get_devinfo(device_t, device_t);
  76. /*
  77. * Bus interface definition
  78. */
  79. static device_method_t lbc_methods[] = {
  80. /* Device interface */
  81. DEVMETHOD(device_probe, lbc_probe),
  82. DEVMETHOD(device_attach, lbc_attach),
  83. DEVMETHOD(device_shutdown, lbc_shutdown),
  84. /* Bus interface */
  85. DEVMETHOD(bus_print_child, lbc_print_child),
  86. DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
  87. DEVMETHOD(bus_teardown_intr, NULL),
  88. DEVMETHOD(bus_alloc_resource, lbc_alloc_resource),
  89. DEVMETHOD(bus_release_resource, lbc_release_resource),
  90. DEVMETHOD(bus_activate_resource, lbc_activate_resource),
  91. DEVMETHOD(bus_deactivate_resource, lbc_deactivate_resource),
  92. /* OFW bus interface */
  93. DEVMETHOD(ofw_bus_get_devinfo, lbc_get_devinfo),
  94. DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat),
  95. DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model),
  96. DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name),
  97. DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
  98. DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
  99. { 0, 0 }
  100. };
  101. static driver_t lbc_driver = {
  102. "lbc",
  103. lbc_methods,
  104. sizeof(struct lbc_softc)
  105. };
  106. devclass_t lbc_devclass;
  107. EARLY_DRIVER_MODULE(lbc, ofwbus, lbc_driver, lbc_devclass,
  108. 0, 0, BUS_PASS_BUS);
  109. /*
  110. * Calculate address mask used by OR(n) registers. Use memory region size to
  111. * determine mask value. The size must be a power of two and within the range
  112. * of 32KB - 4GB. Otherwise error code is returned. Value representing
  113. * 4GB size can be passed as 0xffffffff.
  114. */
  115. static uint32_t
  116. lbc_address_mask(uint32_t size)
  117. {
  118. int n = 15;
  119. if (size == ~0)
  120. return (0);
  121. while (n < 32) {
  122. if (size == (1U << n))
  123. break;
  124. n++;
  125. }
  126. if (n == 32)
  127. return (EINVAL);
  128. return (0xffff8000 << (n - 15));
  129. }
  130. static void
  131. lbc_banks_unmap(struct lbc_softc *sc)
  132. {
  133. int r;
  134. r = 0;
  135. while (r < LBC_DEV_MAX) {
  136. if (sc->sc_range[r].size == 0)
  137. return;
  138. pmap_unmapdev(sc->sc_range[r].kva, sc->sc_range[r].size);
  139. law_disable(OCP85XX_TGTIF_LBC, sc->sc_range[r].addr,
  140. sc->sc_range[r].size);
  141. r++;
  142. }
  143. }
  144. static int
  145. lbc_banks_map(struct lbc_softc *sc)
  146. {
  147. vm_paddr_t end, start;
  148. vm_size_t size;
  149. u_int i, r, ranges, s;
  150. int error;
  151. bzero(sc->sc_range, sizeof(sc->sc_range));
  152. /*
  153. * Determine number of discontiguous address ranges to program.
  154. */
  155. ranges = 0;
  156. for (i = 0; i < LBC_DEV_MAX; i++) {
  157. size = sc->sc_banks[i].size;
  158. if (size == 0)
  159. continue;
  160. start = sc->sc_banks[i].addr;
  161. for (r = 0; r < ranges; r++) {
  162. /* Avoid wrap-around bugs. */
  163. end = sc->sc_range[r].addr - 1 + sc->sc_range[r].size;
  164. if (start > 0 && end == start - 1) {
  165. sc->sc_range[r].size += size;
  166. break;
  167. }
  168. /* Avoid wrap-around bugs. */
  169. end = start - 1 + size;
  170. if (sc->sc_range[r].addr > 0 &&
  171. end == sc->sc_range[r].addr - 1) {
  172. sc->sc_range[r].addr = start;
  173. sc->sc_range[r].size += size;
  174. break;
  175. }
  176. }
  177. if (r == ranges) {
  178. /* New range; add using insertion sort */
  179. r = 0;
  180. while (r < ranges && sc->sc_range[r].addr < start)
  181. r++;
  182. for (s = ranges; s > r; s--)
  183. sc->sc_range[s] = sc->sc_range[s-1];
  184. sc->sc_range[r].addr = start;
  185. sc->sc_range[r].size = size;
  186. ranges++;
  187. }
  188. }
  189. /*
  190. * Ranges are sorted so quickly go over the list to merge ranges
  191. * that grew toward each other while building the ranges.
  192. */
  193. r = 0;
  194. while (r < ranges - 1) {
  195. end = sc->sc_range[r].addr + sc->sc_range[r].size;
  196. if (end != sc->sc_range[r+1].addr) {
  197. r++;
  198. continue;
  199. }
  200. sc->sc_range[r].size += sc->sc_range[r+1].size;
  201. for (s = r + 1; s < ranges - 1; s++)
  202. sc->sc_range[s] = sc->sc_range[s+1];
  203. bzero(&sc->sc_range[s], sizeof(sc->sc_range[s]));
  204. ranges--;
  205. }
  206. /*
  207. * Configure LAW for the LBC ranges and map the physical memory
  208. * range into KVA.
  209. */
  210. for (r = 0; r < ranges; r++) {
  211. start = sc->sc_range[r].addr;
  212. size = sc->sc_range[r].size;
  213. error = law_enable(OCP85XX_TGTIF_LBC, start, size);
  214. if (error)
  215. return (error);
  216. sc->sc_range[r].kva = (vm_offset_t)pmap_mapdev(start, size);
  217. }
  218. /* XXX: need something better here? */
  219. if (ranges == 0)
  220. return (EINVAL);
  221. /* Assign KVA to banks based on the enclosing range. */
  222. for (i = 0; i < LBC_DEV_MAX; i++) {
  223. size = sc->sc_banks[i].size;
  224. if (size == 0)
  225. continue;
  226. start = sc->sc_banks[i].addr;
  227. for (r = 0; r < ranges; r++) {
  228. end = sc->sc_range[r].addr - 1 + sc->sc_range[r].size;
  229. if (start >= sc->sc_range[r].addr &&
  230. start - 1 + size <= end)
  231. break;
  232. }
  233. if (r < ranges) {
  234. sc->sc_banks[i].kva = sc->sc_range[r].kva +
  235. (start - sc->sc_range[r].addr);
  236. }
  237. }
  238. return (0);
  239. }
  240. static int
  241. lbc_banks_enable(struct lbc_softc *sc)
  242. {
  243. uint32_t size;
  244. uint32_t regval;
  245. int error, i;
  246. for (i = 0; i < LBC_DEV_MAX; i++) {
  247. size = sc->sc_banks[i].size;
  248. if (size == 0)
  249. continue;
  250. /*
  251. * Compute and program BR value.
  252. */
  253. regval = sc->sc_banks[i].addr;
  254. switch (sc->sc_banks[i].width) {
  255. case 8:
  256. regval |= (1 << 11);
  257. break;
  258. case 16:
  259. regval |= (2 << 11);
  260. break;
  261. case 32:
  262. regval |= (3 << 11);
  263. break;
  264. default:
  265. error = EINVAL;
  266. goto fail;
  267. }
  268. regval |= (sc->sc_banks[i].decc << 9);
  269. regval |= (sc->sc_banks[i].wp << 8);
  270. regval |= (sc->sc_banks[i].msel << 5);
  271. regval |= (sc->sc_banks[i].atom << 2);
  272. regval |= 1;
  273. bus_space_write_4(sc->sc_bst, sc->sc_bsh,
  274. LBC85XX_BR(i), regval);
  275. /*
  276. * Compute and program OR value.
  277. */
  278. regval = lbc_address_mask(size);
  279. switch (sc->sc_banks[i].msel) {
  280. case LBCRES_MSEL_GPCM:
  281. /* TODO Add flag support for option registers */
  282. regval |= 0x0ff7;
  283. break;
  284. case LBCRES_MSEL_FCM:
  285. /* TODO Add flag support for options register */
  286. regval |= 0x0796;
  287. break;
  288. case LBCRES_MSEL_UPMA:
  289. case LBCRES_MSEL_UPMB:
  290. case LBCRES_MSEL_UPMC:
  291. printf("UPM mode not supported yet!");
  292. error = ENOSYS;
  293. goto fail;
  294. }
  295. bus_space_write_4(sc->sc_bst, sc->sc_bsh,
  296. LBC85XX_OR(i), regval);
  297. }
  298. return (0);
  299. fail:
  300. lbc_banks_unmap(sc);
  301. return (error);
  302. }
  303. static void
  304. fdt_lbc_fixup(phandle_t node, struct lbc_softc *sc, struct lbc_devinfo *di)
  305. {
  306. pcell_t width;
  307. int bank;
  308. if (OF_getprop(node, "bank-width", (void *)&width, sizeof(width)) <= 0)
  309. return;
  310. bank = di->di_bank;
  311. if (sc->sc_banks[bank].size == 0)
  312. return;
  313. /* Express width in bits. */
  314. sc->sc_banks[bank].width = width * 8;
  315. }
  316. static int
  317. fdt_lbc_reg_decode(phandle_t node, struct lbc_softc *sc,
  318. struct lbc_devinfo *di)
  319. {
  320. rman_res_t start, end, count;
  321. pcell_t *reg, *regptr;
  322. pcell_t addr_cells, size_cells;
  323. int tuple_size, tuples;
  324. int i, j, rv, bank;
  325. if (fdt_addrsize_cells(OF_parent(node), &addr_cells, &size_cells) != 0)
  326. return (ENXIO);
  327. tuple_size = sizeof(pcell_t) * (addr_cells + size_cells);
  328. tuples = OF_getencprop_alloc_multi(node, "reg", tuple_size,
  329. (void **)&reg);
  330. debugf("addr_cells = %d, size_cells = %d\n", addr_cells, size_cells);
  331. debugf("tuples = %d, tuple size = %d\n", tuples, tuple_size);
  332. if (tuples <= 0)
  333. /* No 'reg' property in this node. */
  334. return (0);
  335. regptr = reg;
  336. for (i = 0; i < tuples; i++) {
  337. bank = fdt_data_get((void *)reg, 1);
  338. di->di_bank = bank;
  339. reg += 1;
  340. /* Get address/size. */
  341. start = count = 0;
  342. for (j = 0; j < addr_cells - 1; j++) {
  343. start <<= 32;
  344. start |= reg[j];
  345. }
  346. for (j = 0; j < size_cells; j++) {
  347. count <<= 32;
  348. count |= reg[addr_cells + j - 1];
  349. }
  350. reg += addr_cells - 1 + size_cells;
  351. /* Calculate address range relative to VA base. */
  352. start = sc->sc_banks[bank].kva + start;
  353. end = start + count - 1;
  354. debugf("reg addr bank = %d, start = %jx, end = %jx, "
  355. "count = %jx\n", bank, start, end, count);
  356. /* Use bank (CS) cell as rid. */
  357. resource_list_add(&di->di_res, SYS_RES_MEMORY, bank, start,
  358. end, count);
  359. }
  360. rv = 0;
  361. OF_prop_free(regptr);
  362. return (rv);
  363. }
  364. static void
  365. lbc_intr(void *arg)
  366. {
  367. struct lbc_softc *sc = arg;
  368. uint32_t ltesr;
  369. ltesr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTESR);
  370. sc->sc_ltesr = ltesr;
  371. bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTESR, ltesr);
  372. wakeup(sc->sc_dev);
  373. }
  374. static int
  375. lbc_probe(device_t dev)
  376. {
  377. if (!(ofw_bus_is_compatible(dev, "fsl,lbc") ||
  378. ofw_bus_is_compatible(dev, "fsl,elbc")))
  379. return (ENXIO);
  380. device_set_desc(dev, "Freescale Local Bus Controller");
  381. return (BUS_PROBE_DEFAULT);
  382. }
  383. static int
  384. lbc_attach(device_t dev)
  385. {
  386. struct lbc_softc *sc;
  387. struct lbc_devinfo *di;
  388. struct rman *rm;
  389. uintmax_t offset, size;
  390. vm_paddr_t start;
  391. device_t cdev;
  392. phandle_t node, child;
  393. pcell_t *ranges, *rangesptr;
  394. int tuple_size, tuples;
  395. int par_addr_cells;
  396. int bank, error, i, j;
  397. sc = device_get_softc(dev);
  398. sc->sc_dev = dev;
  399. sc->sc_mrid = 0;
  400. sc->sc_mres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_mrid,
  401. RF_ACTIVE);
  402. if (sc->sc_mres == NULL)
  403. return (ENXIO);
  404. sc->sc_bst = rman_get_bustag(sc->sc_mres);
  405. sc->sc_bsh = rman_get_bushandle(sc->sc_mres);
  406. for (bank = 0; bank < LBC_DEV_MAX; bank++) {
  407. bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_BR(bank), 0);
  408. bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_OR(bank), 0);
  409. }
  410. /*
  411. * Initialize configuration register:
  412. * - enable Local Bus
  413. * - set data buffer control signal function
  414. * - disable parity byte select
  415. * - set ECC parity type
  416. * - set bus monitor timing and timer prescale
  417. */
  418. bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LBCR, 0);
  419. /*
  420. * Initialize clock ratio register:
  421. * - disable PLL bypass mode
  422. * - configure LCLK delay cycles for the assertion of LALE
  423. * - set system clock divider
  424. */
  425. bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LCRR, 0x00030008);
  426. bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTEDR, 0);
  427. bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTESR, ~0);
  428. bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTEIR, 0x64080001);
  429. sc->sc_irid = 0;
  430. sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irid,
  431. RF_ACTIVE | RF_SHAREABLE);
  432. if (sc->sc_ires != NULL) {
  433. error = bus_setup_intr(dev, sc->sc_ires,
  434. INTR_TYPE_MISC | INTR_MPSAFE, NULL, lbc_intr, sc,
  435. &sc->sc_icookie);
  436. if (error) {
  437. device_printf(dev, "could not activate interrupt\n");
  438. bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid,
  439. sc->sc_ires);
  440. sc->sc_ires = NULL;
  441. }
  442. }
  443. sc->sc_ltesr = ~0;
  444. rangesptr = NULL;
  445. rm = &sc->sc_rman;
  446. rm->rm_type = RMAN_ARRAY;
  447. rm->rm_descr = "Local Bus Space";
  448. error = rman_init(rm);
  449. if (error)
  450. goto fail;
  451. error = rman_manage_region(rm, rm->rm_start, rm->rm_end);
  452. if (error) {
  453. rman_fini(rm);
  454. goto fail;
  455. }
  456. /*
  457. * Process 'ranges' property.
  458. */
  459. node = ofw_bus_get_node(dev);
  460. if ((fdt_addrsize_cells(node, &sc->sc_addr_cells,
  461. &sc->sc_size_cells)) != 0) {
  462. error = ENXIO;
  463. goto fail;
  464. }
  465. par_addr_cells = fdt_parent_addr_cells(node);
  466. if (par_addr_cells > 2) {
  467. device_printf(dev, "unsupported parent #addr-cells\n");
  468. error = ERANGE;
  469. goto fail;
  470. }
  471. tuple_size = sizeof(pcell_t) * (sc->sc_addr_cells + par_addr_cells +
  472. sc->sc_size_cells);
  473. tuples = OF_getencprop_alloc_multi(node, "ranges", tuple_size,
  474. (void **)&ranges);
  475. if (tuples < 0) {
  476. device_printf(dev, "could not retrieve 'ranges' property\n");
  477. error = ENXIO;
  478. goto fail;
  479. }
  480. rangesptr = ranges;
  481. debugf("par addr_cells = %d, addr_cells = %d, size_cells = %d, "
  482. "tuple_size = %d, tuples = %d\n", par_addr_cells,
  483. sc->sc_addr_cells, sc->sc_size_cells, tuple_size, tuples);
  484. start = 0;
  485. size = 0;
  486. for (i = 0; i < tuples; i++) {
  487. /* The first cell is the bank (chip select) number. */
  488. bank = fdt_data_get(ranges, 1);
  489. if (bank < 0 || bank > LBC_DEV_MAX) {
  490. device_printf(dev, "bank out of range: %d\n", bank);
  491. error = ERANGE;
  492. goto fail;
  493. }
  494. ranges += 1;
  495. /*
  496. * Remaining cells of the child address define offset into
  497. * this CS.
  498. */
  499. offset = 0;
  500. for (j = 0; j < sc->sc_addr_cells - 1; j++) {
  501. offset <<= sizeof(pcell_t) * 8;
  502. offset |= *ranges;
  503. ranges++;
  504. }
  505. /* Parent bus start address of this bank. */
  506. start = 0;
  507. for (j = 0; j < par_addr_cells; j++) {
  508. start <<= sizeof(pcell_t) * 8;
  509. start |= *ranges;
  510. ranges++;
  511. }
  512. size = fdt_data_get((void *)ranges, sc->sc_size_cells);
  513. ranges += sc->sc_size_cells;
  514. debugf("bank = %d, start = %jx, size = %jx\n", bank,
  515. (uintmax_t)start, size);
  516. sc->sc_banks[bank].addr = start + offset;
  517. sc->sc_banks[bank].size = size;
  518. /*
  519. * Attributes for the bank.
  520. *
  521. * XXX Note there are no DT bindings defined for them at the
  522. * moment, so we need to provide some defaults.
  523. */
  524. sc->sc_banks[bank].width = 16;
  525. sc->sc_banks[bank].msel = LBCRES_MSEL_GPCM;
  526. sc->sc_banks[bank].decc = LBCRES_DECC_DISABLED;
  527. sc->sc_banks[bank].atom = LBCRES_ATOM_DISABLED;
  528. sc->sc_banks[bank].wp = 0;
  529. }
  530. /*
  531. * Initialize mem-mappings for the LBC banks (i.e. chip selects).
  532. */
  533. error = lbc_banks_map(sc);
  534. if (error)
  535. goto fail;
  536. /*
  537. * Walk the localbus and add direct subordinates as our children.
  538. */
  539. for (child = OF_child(node); child != 0; child = OF_peer(child)) {
  540. di = malloc(sizeof(*di), M_LBC, M_WAITOK | M_ZERO);
  541. if (ofw_bus_gen_setup_devinfo(&di->di_ofw, child) != 0) {
  542. free(di, M_LBC);
  543. device_printf(dev, "could not set up devinfo\n");
  544. continue;
  545. }
  546. resource_list_init(&di->di_res);
  547. if (fdt_lbc_reg_decode(child, sc, di)) {
  548. device_printf(dev, "could not process 'reg' "
  549. "property\n");
  550. ofw_bus_gen_destroy_devinfo(&di->di_ofw);
  551. free(di, M_LBC);
  552. continue;
  553. }
  554. fdt_lbc_fixup(child, sc, di);
  555. /* Add newbus device for this FDT node */
  556. cdev = device_add_child(dev, NULL, -1);
  557. if (cdev == NULL) {
  558. device_printf(dev, "could not add child: %s\n",
  559. di->di_ofw.obd_name);
  560. resource_list_free(&di->di_res);
  561. ofw_bus_gen_destroy_devinfo(&di->di_ofw);
  562. free(di, M_LBC);
  563. continue;
  564. }
  565. debugf("added child name='%s', node=%x\n", di->di_ofw.obd_name,
  566. child);
  567. device_set_ivars(cdev, di);
  568. }
  569. /*
  570. * Enable the LBC.
  571. */
  572. lbc_banks_enable(sc);
  573. OF_prop_free(rangesptr);
  574. return (bus_generic_attach(dev));
  575. fail:
  576. OF_prop_free(rangesptr);
  577. bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_mrid, sc->sc_mres);
  578. return (error);
  579. }
  580. static int
  581. lbc_shutdown(device_t dev)
  582. {
  583. /* TODO */
  584. return(0);
  585. }
  586. static struct resource *
  587. lbc_alloc_resource(device_t bus, device_t child, int type, int *rid,
  588. rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
  589. {
  590. struct lbc_softc *sc;
  591. struct lbc_devinfo *di;
  592. struct resource_list_entry *rle;
  593. struct resource *res;
  594. struct rman *rm;
  595. int needactivate;
  596. /* We only support default allocations. */
  597. if (!RMAN_IS_DEFAULT_RANGE(start, end))
  598. return (NULL);
  599. sc = device_get_softc(bus);
  600. if (type == SYS_RES_IRQ)
  601. return (bus_alloc_resource(bus, type, rid, start, end, count,
  602. flags));
  603. /*
  604. * Request for the default allocation with a given rid: use resource
  605. * list stored in the local device info.
  606. */
  607. if ((di = device_get_ivars(child)) == NULL)
  608. return (NULL);
  609. if (type == SYS_RES_IOPORT)
  610. type = SYS_RES_MEMORY;
  611. rid = &di->di_bank;
  612. rle = resource_list_find(&di->di_res, type, *rid);
  613. if (rle == NULL) {
  614. device_printf(bus, "no default resources for "
  615. "rid = %d, type = %d\n", *rid, type);
  616. return (NULL);
  617. }
  618. start = rle->start;
  619. count = rle->count;
  620. end = start + count - 1;
  621. sc = device_get_softc(bus);
  622. needactivate = flags & RF_ACTIVE;
  623. flags &= ~RF_ACTIVE;
  624. rm = &sc->sc_rman;
  625. res = rman_reserve_resource(rm, start, end, count, flags, child);
  626. if (res == NULL) {
  627. device_printf(bus, "failed to reserve resource %#jx - %#jx "
  628. "(%#jx)\n", start, end, count);
  629. return (NULL);
  630. }
  631. rman_set_rid(res, *rid);
  632. rman_set_bustag(res, &bs_be_tag);
  633. rman_set_bushandle(res, rman_get_start(res));
  634. if (needactivate)
  635. if (bus_activate_resource(child, type, *rid, res)) {
  636. device_printf(child, "resource activation failed\n");
  637. rman_release_resource(res);
  638. return (NULL);
  639. }
  640. return (res);
  641. }
  642. static int
  643. lbc_print_child(device_t dev, device_t child)
  644. {
  645. struct lbc_devinfo *di;
  646. struct resource_list *rl;
  647. int rv;
  648. di = device_get_ivars(child);
  649. rl = &di->di_res;
  650. rv = 0;
  651. rv += bus_print_child_header(dev, child);
  652. rv += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx");
  653. rv += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd");
  654. rv += bus_print_child_footer(dev, child);
  655. return (rv);
  656. }
  657. static int
  658. lbc_release_resource(device_t dev, device_t child, int type, int rid,
  659. struct resource *res)
  660. {
  661. int err;
  662. if (rman_get_flags(res) & RF_ACTIVE) {
  663. err = bus_deactivate_resource(child, type, rid, res);
  664. if (err)
  665. return (err);
  666. }
  667. return (rman_release_resource(res));
  668. }
  669. static int
  670. lbc_activate_resource(device_t bus __unused, device_t child __unused,
  671. int type __unused, int rid __unused, struct resource *r)
  672. {
  673. /* Child resources were already mapped, just activate. */
  674. return (rman_activate_resource(r));
  675. }
  676. static int
  677. lbc_deactivate_resource(device_t bus __unused, device_t child __unused,
  678. int type __unused, int rid __unused, struct resource *r)
  679. {
  680. return (rman_deactivate_resource(r));
  681. }
  682. static const struct ofw_bus_devinfo *
  683. lbc_get_devinfo(device_t bus, device_t child)
  684. {
  685. struct lbc_devinfo *di;
  686. di = device_get_ivars(child);
  687. return (&di->di_ofw);
  688. }
  689. void
  690. lbc_write_reg(device_t child, u_int off, uint32_t val)
  691. {
  692. device_t dev;
  693. struct lbc_softc *sc;
  694. dev = device_get_parent(child);
  695. if (off >= 0x1000) {
  696. device_printf(dev, "%s(%s): invalid offset %#x\n",
  697. __func__, device_get_nameunit(child), off);
  698. return;
  699. }
  700. sc = device_get_softc(dev);
  701. if (off == LBC85XX_LTESR && sc->sc_ltesr != ~0u) {
  702. sc->sc_ltesr ^= (val & sc->sc_ltesr);
  703. return;
  704. }
  705. if (off == LBC85XX_LTEATR && (val & 1) == 0)
  706. sc->sc_ltesr = ~0u;
  707. bus_space_write_4(sc->sc_bst, sc->sc_bsh, off, val);
  708. }
  709. uint32_t
  710. lbc_read_reg(device_t child, u_int off)
  711. {
  712. device_t dev;
  713. struct lbc_softc *sc;
  714. uint32_t val;
  715. dev = device_get_parent(child);
  716. if (off >= 0x1000) {
  717. device_printf(dev, "%s(%s): invalid offset %#x\n",
  718. __func__, device_get_nameunit(child), off);
  719. return (~0U);
  720. }
  721. sc = device_get_softc(dev);
  722. if (off == LBC85XX_LTESR && sc->sc_ltesr != ~0U)
  723. val = sc->sc_ltesr;
  724. else
  725. val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, off);
  726. return (val);
  727. }