1/*- 2 * Copyright (c) 2006-2008, Juniper Networks, Inc.
| 1/*- 2 * Copyright (c) 2006-2008, Juniper Networks, Inc.
|
| 3 * Copyright (c) 2008 Semihalf, Rafal Czubak
|
3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29#include <sys/cdefs.h>
| 4 * 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 30#include <sys/cdefs.h>
|
30__FBSDID("$FreeBSD: head/sys/powerpc/mpc85xx/lbc.c 184250 2008-10-25 06:03:40Z marcel $");
| 31__FBSDID("$FreeBSD: head/sys/powerpc/mpc85xx/lbc.c 186288 2008-12-18 18:27:12Z raj $");
|
31 32#include <sys/param.h> 33#include <sys/systm.h> 34#include <sys/ktr.h> 35#include <sys/kernel.h> 36#include <sys/malloc.h> 37#include <sys/module.h> 38#include <sys/bus.h> 39#include <sys/rman.h> 40#include <machine/bus.h> 41#include <machine/ocpbus.h> 42 43#include <vm/vm.h> 44#include <vm/pmap.h> 45 46#include <powerpc/mpc85xx/lbc.h>
| 32 33#include <sys/param.h> 34#include <sys/systm.h> 35#include <sys/ktr.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 <machine/bus.h> 42#include <machine/ocpbus.h> 43 44#include <vm/vm.h> 45#include <vm/pmap.h> 46 47#include <powerpc/mpc85xx/lbc.h>
|
| 48#include <powerpc/mpc85xx/mpc85xx.h> 49#include <powerpc/mpc85xx/ocpbus.h>
|
47 48struct lbc_softc { 49 device_t sc_dev; 50 51 struct resource *sc_res; 52 bus_space_handle_t sc_bsh; 53 bus_space_tag_t sc_bst; 54 int sc_rid; 55 56 struct rman sc_rman;
| 50 51struct lbc_softc { 52 device_t sc_dev; 53 54 struct resource *sc_res; 55 bus_space_handle_t sc_bsh; 56 bus_space_tag_t sc_bst; 57 int sc_rid; 58 59 struct rman sc_rman;
|
57 uintptr_t sc_kva;
| 60 vm_offset_t sc_kva[LBC_DEV_MAX];
|
58}; 59 60struct lbc_devinfo { 61 int lbc_devtype;
| 61}; 62 63struct lbc_devinfo { 64 int lbc_devtype;
|
62 int lbc_memtype; 63 /* Also the BAR number */
| 65 /* LBC child unit. It also represents resource table entry number */
|
64 int lbc_unit; 65}; 66
| 66 int lbc_unit; 67}; 68
|
| 69/* Resources for MPC8555CDS system */ 70const struct lbc_resource mpc85xx_lbc_resources[] = { 71 /* Boot flash bank */ 72 { 73 LBC_DEVTYPE_CFI, 0, 0xff800000, 0x00800000, 16, 74 LBCRES_MSEL_GPCM, LBCRES_DECC_DISABLED, 75 LBCRES_ATOM_DISABLED, 0 76 }, 77 78 /* Second flash bank */ 79 { 80 LBC_DEVTYPE_CFI, 1, 0xff000000, 0x00800000, 16, 81 LBCRES_MSEL_GPCM, LBCRES_DECC_DISABLED, 82 LBCRES_ATOM_DISABLED, 0 83 }, 84 85 /* DS1553 RTC/NVRAM */ 86 { 87 LBC_DEVTYPE_RTC, 2, 0xf8000000, 0x8000, 8, 88 LBCRES_MSEL_GPCM, LBCRES_DECC_DISABLED, 89 LBCRES_ATOM_DISABLED, 0 90 }, 91 92 {0} 93}; 94
|
67static int lbc_probe(device_t); 68static int lbc_attach(device_t); 69static int lbc_shutdown(device_t); 70static int lbc_get_resource(device_t, device_t, int, int, u_long *, 71 u_long *); 72static struct resource *lbc_alloc_resource(device_t, device_t, int, int *, 73 u_long, u_long, u_long, u_int); 74static int lbc_print_child(device_t, device_t); 75static int lbc_release_resource(device_t, device_t, int, int, 76 struct resource *); 77static int lbc_read_ivar(device_t, device_t, int, uintptr_t *); 78 79/* 80 * Bus interface definition 81 */ 82static device_method_t lbc_methods[] = { 83 /* Device interface */ 84 DEVMETHOD(device_probe, lbc_probe), 85 DEVMETHOD(device_attach, lbc_attach), 86 DEVMETHOD(device_shutdown, lbc_shutdown), 87 88 /* Bus interface */ 89 DEVMETHOD(bus_print_child, lbc_print_child), 90 DEVMETHOD(bus_read_ivar, lbc_read_ivar), 91 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 92 DEVMETHOD(bus_teardown_intr, NULL), 93 94 DEVMETHOD(bus_get_resource, NULL), 95 DEVMETHOD(bus_alloc_resource, lbc_alloc_resource), 96 DEVMETHOD(bus_release_resource, lbc_release_resource), 97 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 98 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 99 100 { 0, 0 } 101}; 102 103static driver_t lbc_driver = { 104 "lbc", 105 lbc_methods, 106 sizeof(struct lbc_softc) 107}; 108devclass_t lbc_devclass; 109DRIVER_MODULE(lbc, ocpbus, lbc_driver, lbc_devclass, 0, 0); 110
| 95static int lbc_probe(device_t); 96static int lbc_attach(device_t); 97static int lbc_shutdown(device_t); 98static int lbc_get_resource(device_t, device_t, int, int, u_long *, 99 u_long *); 100static struct resource *lbc_alloc_resource(device_t, device_t, int, int *, 101 u_long, u_long, u_long, u_int); 102static int lbc_print_child(device_t, device_t); 103static int lbc_release_resource(device_t, device_t, int, int, 104 struct resource *); 105static int lbc_read_ivar(device_t, device_t, int, uintptr_t *); 106 107/* 108 * Bus interface definition 109 */ 110static device_method_t lbc_methods[] = { 111 /* Device interface */ 112 DEVMETHOD(device_probe, lbc_probe), 113 DEVMETHOD(device_attach, lbc_attach), 114 DEVMETHOD(device_shutdown, lbc_shutdown), 115 116 /* Bus interface */ 117 DEVMETHOD(bus_print_child, lbc_print_child), 118 DEVMETHOD(bus_read_ivar, lbc_read_ivar), 119 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 120 DEVMETHOD(bus_teardown_intr, NULL), 121 122 DEVMETHOD(bus_get_resource, NULL), 123 DEVMETHOD(bus_alloc_resource, lbc_alloc_resource), 124 DEVMETHOD(bus_release_resource, lbc_release_resource), 125 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 126 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 127 128 { 0, 0 } 129}; 130 131static driver_t lbc_driver = { 132 "lbc", 133 lbc_methods, 134 sizeof(struct lbc_softc) 135}; 136devclass_t lbc_devclass; 137DRIVER_MODULE(lbc, ocpbus, lbc_driver, lbc_devclass, 0, 0); 138
|
| 139static __inline void 140lbc_write_reg(struct lbc_softc *sc, bus_size_t off, uint32_t val) 141{ 142 143 bus_space_write_4(sc->sc_bst, sc->sc_bsh, off, val); 144} 145 146static __inline uint32_t 147lbc_read_reg(struct lbc_softc *sc, bus_size_t off) 148{ 149 150 return (bus_space_read_4(sc->sc_bst, sc->sc_bsh, off)); 151} 152 153/* 154 * Calculate address mask used by OR(n) registers. Use memory region size to 155 * determine mask value. The size must be a power of two and within the range 156 * of 32KB - 4GB. Otherwise error code is returned. Value representing 157 * 4GB size can be passed as 0xffffffff. 158 */ 159static uint32_t 160lbc_address_mask(uint32_t size) 161{ 162 int n = 15; 163 164 if (size == ~0UL) 165 return (0); 166 167 while (n < 32) { 168 if (size == (1UL << n)) 169 break; 170 n++; 171 } 172 173 if (n == 32) 174 return (EINVAL); 175 176 return (0xffff8000 << (n - 15)); 177} 178
|
111static device_t
| 179static device_t
|
112lbc_mk_child(device_t dev, int type, int mtype, int unit)
| 180lbc_mk_child(device_t dev, const struct lbc_resource *lbcres)
|
113{ 114 struct lbc_devinfo *dinfo; 115 device_t child; 116
| 181{ 182 struct lbc_devinfo *dinfo; 183 device_t child; 184
|
| 185 if (lbcres->lbr_unit > LBC_DEV_MAX - 1) 186 return (NULL); 187
|
117 child = device_add_child(dev, NULL, -1); 118 if (child == NULL) {
| 188 child = device_add_child(dev, NULL, -1); 189 if (child == NULL) {
|
119 device_printf(dev, "could not add child device\n");
| 190 device_printf(dev, "could not add LBC child device\n");
|
120 return (NULL); 121 } 122 dinfo = malloc(sizeof(struct lbc_devinfo), M_DEVBUF, M_WAITOK | M_ZERO);
| 191 return (NULL); 192 } 193 dinfo = malloc(sizeof(struct lbc_devinfo), M_DEVBUF, M_WAITOK | M_ZERO);
|
123 dinfo->lbc_devtype = type; 124 dinfo->lbc_memtype = mtype; 125 dinfo->lbc_unit = unit;
| 194 dinfo->lbc_devtype = lbcres->lbr_devtype; 195 dinfo->lbc_unit = lbcres->lbr_unit;
|
126 device_set_ivars(child, dinfo); 127 return (child); 128} 129 130static int
| 196 device_set_ivars(child, dinfo); 197 return (child); 198} 199 200static int
|
| 201lbc_init_child(device_t dev, device_t child) 202{ 203 struct lbc_softc *sc; 204 struct lbc_devinfo *dinfo; 205 const struct lbc_resource *res; 206 u_long start, size; 207 uint32_t regbuff; 208 int error, unit; 209 210 sc = device_get_softc(dev); 211 dinfo = device_get_ivars(child); 212 213 res = mpc85xx_lbc_resources; 214 215 regbuff = 0; 216 unit = -1; 217 for (; res->lbr_devtype; res++) { 218 if (res->lbr_unit != dinfo->lbc_unit) 219 continue; 220 221 start = res->lbr_base_addr; 222 size = res->lbr_size; 223 unit = res->lbr_unit; 224 225 /* 226 * Configure LAW for this LBC device and map its physical 227 * memory region into KVA 228 */ 229 error = law_enable(OCP85XX_TGTIF_LBC, start, size); 230 if (error) 231 return (error); 232 233 sc->sc_kva[unit] = (vm_offset_t)pmap_mapdev(start, size); 234 if (sc->sc_kva[unit] == 0) { 235 law_disable(OCP85XX_TGTIF_LBC, start, size); 236 return (ENOSPC); 237 } 238 239 /* 240 * Compute and program BR value 241 */ 242 regbuff |= start; 243 244 switch (res->lbr_port_size) { 245 case 8: 246 regbuff |= (1 << 11); 247 break; 248 case 16: 249 regbuff |= (2 << 11); 250 break; 251 case 32: 252 regbuff |= (3 << 11); 253 break; 254 default: 255 error = EINVAL; 256 goto fail; 257 } 258 regbuff |= (res->lbr_decc << 9); 259 regbuff |= (res->lbr_wp << 8); 260 regbuff |= (res->lbr_msel << 5); 261 regbuff |= (res->lbr_atom << 2); 262 regbuff |= 1; 263 264 lbc_write_reg(sc, LBC85XX_BR(unit), regbuff); 265 266 /* 267 * Compute and program OR value 268 */ 269 regbuff = 0; 270 regbuff |= lbc_address_mask(size); 271 272 switch (res->lbr_msel) { 273 case LBCRES_MSEL_GPCM: 274 /* TODO Add flag support for option registers */ 275 regbuff |= 0x00000ff7; 276 break; 277 case LBCRES_MSEL_FCM: 278 printf("FCM mode not supported yet!"); 279 error = ENOSYS; 280 goto fail; 281 case LBCRES_MSEL_UPMA: 282 case LBCRES_MSEL_UPMB: 283 case LBCRES_MSEL_UPMC: 284 printf("UPM mode not supported yet!"); 285 error = ENOSYS; 286 goto fail; 287 } 288 289 lbc_write_reg(sc, LBC85XX_OR(unit), regbuff); 290 291 return (0); 292 } 293fail: 294 if (unit != -1) { 295 law_disable(OCP85XX_TGTIF_LBC, start, size); 296 pmap_unmapdev(sc->sc_kva[unit], size); 297 return (error); 298 } else 299 return (ENOENT); 300} 301 302static int
|
131lbc_probe(device_t dev) 132{ 133 device_t parent; 134 uintptr_t devtype; 135 int error; 136 137 parent = device_get_parent(dev); 138 error = BUS_READ_IVAR(parent, dev, OCPBUS_IVAR_DEVTYPE, &devtype); 139 if (error) 140 return (error); 141 if (devtype != OCPBUS_DEVTYPE_LBC) 142 return (ENXIO); 143 144 device_set_desc(dev, "Freescale MPC85xx Local Bus Controller"); 145 return (BUS_PROBE_DEFAULT); 146} 147 148static int 149lbc_attach(device_t dev) 150{ 151 struct lbc_softc *sc; 152 struct rman *rm;
| 303lbc_probe(device_t dev) 304{ 305 device_t parent; 306 uintptr_t devtype; 307 int error; 308 309 parent = device_get_parent(dev); 310 error = BUS_READ_IVAR(parent, dev, OCPBUS_IVAR_DEVTYPE, &devtype); 311 if (error) 312 return (error); 313 if (devtype != OCPBUS_DEVTYPE_LBC) 314 return (ENXIO); 315 316 device_set_desc(dev, "Freescale MPC85xx Local Bus Controller"); 317 return (BUS_PROBE_DEFAULT); 318} 319 320static int 321lbc_attach(device_t dev) 322{ 323 struct lbc_softc *sc; 324 struct rman *rm;
|
153 u_long start, size;
| 325 const struct lbc_resource *lbcres;
|
154 int error; 155 156 sc = device_get_softc(dev); 157 sc->sc_dev = dev; 158 159 sc->sc_rid = 0; 160 sc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rid, 161 RF_ACTIVE); 162 if (sc->sc_res == NULL) 163 return (ENXIO); 164 165 sc->sc_bst = rman_get_bustag(sc->sc_res); 166 sc->sc_bsh = rman_get_bushandle(sc->sc_res); 167
| 326 int error; 327 328 sc = device_get_softc(dev); 329 sc->sc_dev = dev; 330 331 sc->sc_rid = 0; 332 sc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rid, 333 RF_ACTIVE); 334 if (sc->sc_res == NULL) 335 return (ENXIO); 336 337 sc->sc_bst = rman_get_bustag(sc->sc_res); 338 sc->sc_bsh = rman_get_bushandle(sc->sc_res); 339
|
168 error = bus_get_resource(dev, SYS_RES_MEMORY, 1, &start, &size); 169 if (error) 170 goto fail; 171
| |
172 rm = &sc->sc_rman; 173 rm->rm_type = RMAN_ARRAY; 174 rm->rm_descr = "MPC85XX Local Bus Space";
| 340 rm = &sc->sc_rman; 341 rm->rm_type = RMAN_ARRAY; 342 rm->rm_descr = "MPC85XX Local Bus Space";
|
175 rm->rm_start = start; 176 rm->rm_end = start + size - 1;
| 343 rm->rm_start = 0UL; 344 rm->rm_end = ~0UL;
|
177 error = rman_init(rm); 178 if (error) 179 goto fail; 180 181 error = rman_manage_region(rm, rm->rm_start, rm->rm_end); 182 if (error) { 183 rman_fini(rm); 184 goto fail; 185 } 186
| 345 error = rman_init(rm); 346 if (error) 347 goto fail; 348 349 error = rman_manage_region(rm, rm->rm_start, rm->rm_end); 350 if (error) { 351 rman_fini(rm); 352 goto fail; 353 } 354
|
187 sc->sc_kva = (uintptr_t)pmap_mapdev(start, size);
| 355 /* 356 * Initialize configuration register: 357 * - enable Local Bus 358 * - set data buffer control signal function 359 * - disable parity byte select 360 * - set ECC parity type 361 * - set bus monitor timing and timer prescale 362 */ 363 lbc_write_reg(sc, LBC85XX_LBCR, 0x00000000);
|
188
| 364
|
189 lbc_mk_child(dev, LBC_DEVTYPE_CFI, 0, 0);
| 365 /* 366 * Initialize clock ratio register: 367 * - disable PLL bypass mode 368 * - configure LCLK delay cycles for the assertion of LALE 369 * - set system clock divider 370 */ 371 lbc_write_reg(sc, LBC85XX_LCRR, 0x00030008);
|
190
| 372
|
| 373 lbcres = mpc85xx_lbc_resources; 374 375 for (; lbcres->lbr_devtype; lbcres++) 376 if (!lbc_mk_child(dev, lbcres)) { 377 error = ENXIO; 378 goto fail; 379 } 380
|
191 return (bus_generic_attach(dev)); 192
| 381 return (bus_generic_attach(dev)); 382
|
193 fail:
| 383fail:
|
194 bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rid, sc->sc_res); 195 return (error); 196} 197 198static int 199lbc_shutdown(device_t dev) 200{ 201 202 /* TODO */ 203 return(0); 204} 205 206static struct resource * 207lbc_alloc_resource(device_t dev, device_t child, int type, int *rid, 208 u_long start, u_long end, u_long count, u_int flags) 209{ 210 struct lbc_softc *sc;
| 384 bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rid, sc->sc_res); 385 return (error); 386} 387 388static int 389lbc_shutdown(device_t dev) 390{ 391 392 /* TODO */ 393 return(0); 394} 395 396static struct resource * 397lbc_alloc_resource(device_t dev, device_t child, int type, int *rid, 398 u_long start, u_long end, u_long count, u_int flags) 399{ 400 struct lbc_softc *sc;
|
| 401 struct lbc_devinfo *dinfo;
|
211 struct resource *rv; 212 struct rman *rm; 213 int error; 214 215 sc = device_get_softc(dev);
| 402 struct resource *rv; 403 struct rman *rm; 404 int error; 405 406 sc = device_get_softc(dev);
|
| 407 dinfo = device_get_ivars(child);
|
216 217 if (type != SYS_RES_MEMORY && type != SYS_RES_IRQ) 218 return (NULL); 219 220 /* We only support default allocations. */ 221 if (start != 0ul || end != ~0ul) 222 return (NULL); 223 224 if (type == SYS_RES_IRQ) 225 return (bus_alloc_resource(dev, type, rid, start, end, count, 226 flags)); 227
| 408 409 if (type != SYS_RES_MEMORY && type != SYS_RES_IRQ) 410 return (NULL); 411 412 /* We only support default allocations. */ 413 if (start != 0ul || end != ~0ul) 414 return (NULL); 415 416 if (type == SYS_RES_IRQ) 417 return (bus_alloc_resource(dev, type, rid, start, end, count, 418 flags)); 419
|
| 420 if (!sc->sc_kva[dinfo->lbc_unit]) { 421 error = lbc_init_child(dev, child); 422 if (error) 423 return (NULL); 424 } 425
|
228 error = lbc_get_resource(dev, child, type, *rid, &start, &count); 229 if (error) 230 return (NULL); 231 232 rm = &sc->sc_rman; 233 end = start + count - 1; 234 rv = rman_reserve_resource(rm, start, end, count, flags, child); 235 if (rv != NULL) { 236 rman_set_bustag(rv, &bs_be_tag);
| 426 error = lbc_get_resource(dev, child, type, *rid, &start, &count); 427 if (error) 428 return (NULL); 429 430 rm = &sc->sc_rman; 431 end = start + count - 1; 432 rv = rman_reserve_resource(rm, start, end, count, flags, child); 433 if (rv != NULL) { 434 rman_set_bustag(rv, &bs_be_tag);
|
237 rman_set_bushandle(rv, sc->sc_kva + rman_get_start(rv) - 238 rm->rm_start);
| 435 rman_set_bushandle(rv, rman_get_start(rv));
|
239 } 240 return (rv); 241} 242 243static int 244lbc_print_child(device_t dev, device_t child) 245{ 246 u_long size, start; 247 int error, retval, rid; 248 249 retval = bus_print_child_header(dev, child); 250 251 rid = 0; 252 while (1) { 253 error = lbc_get_resource(dev, child, SYS_RES_MEMORY, rid, 254 &start, &size); 255 if (error) 256 break; 257 retval += (rid == 0) ? printf(" iomem ") : printf(","); 258 retval += printf("%#lx", start); 259 if (size > 1) 260 retval += printf("-%#lx", start + size - 1); 261 rid++; 262 } 263 264 retval += bus_print_child_footer(dev, child); 265 return (retval); 266} 267 268static int 269lbc_read_ivar(device_t dev, device_t child, int index, uintptr_t *result) 270{ 271 struct lbc_devinfo *dinfo; 272 273 if (device_get_parent(child) != dev) 274 return (EINVAL); 275 276 dinfo = device_get_ivars(child); 277 278 switch (index) { 279 case LBC_IVAR_DEVTYPE: 280 *result = dinfo->lbc_devtype; 281 return (0);
| 436 } 437 return (rv); 438} 439 440static int 441lbc_print_child(device_t dev, device_t child) 442{ 443 u_long size, start; 444 int error, retval, rid; 445 446 retval = bus_print_child_header(dev, child); 447 448 rid = 0; 449 while (1) { 450 error = lbc_get_resource(dev, child, SYS_RES_MEMORY, rid, 451 &start, &size); 452 if (error) 453 break; 454 retval += (rid == 0) ? printf(" iomem ") : printf(","); 455 retval += printf("%#lx", start); 456 if (size > 1) 457 retval += printf("-%#lx", start + size - 1); 458 rid++; 459 } 460 461 retval += bus_print_child_footer(dev, child); 462 return (retval); 463} 464 465static int 466lbc_read_ivar(device_t dev, device_t child, int index, uintptr_t *result) 467{ 468 struct lbc_devinfo *dinfo; 469 470 if (device_get_parent(child) != dev) 471 return (EINVAL); 472 473 dinfo = device_get_ivars(child); 474 475 switch (index) { 476 case LBC_IVAR_DEVTYPE: 477 *result = dinfo->lbc_devtype; 478 return (0);
|
282 case LBC_IVAR_CLOCK: 283 *result = 1843200; 284 return (0); 285 case LBC_IVAR_REGSHIFT: 286 *result = 0; 287 return (0);
| |
288 default: 289 break; 290 } 291 return (EINVAL); 292} 293 294static int 295lbc_release_resource(device_t dev, device_t child, int type, int rid, 296 struct resource *res) 297{ 298 299 return (rman_release_resource(res)); 300} 301 302static int 303lbc_get_resource(device_t dev, device_t child, int type, int rid, 304 u_long *startp, u_long *countp) 305{ 306 struct lbc_softc *sc; 307 struct lbc_devinfo *dinfo;
| 479 default: 480 break; 481 } 482 return (EINVAL); 483} 484 485static int 486lbc_release_resource(device_t dev, device_t child, int type, int rid, 487 struct resource *res) 488{ 489 490 return (rman_release_resource(res)); 491} 492 493static int 494lbc_get_resource(device_t dev, device_t child, int type, int rid, 495 u_long *startp, u_long *countp) 496{ 497 struct lbc_softc *sc; 498 struct lbc_devinfo *dinfo;
|
| 499 const struct lbc_resource *lbcres;
|
308 309 if (type != SYS_RES_MEMORY) 310 return (ENOENT); 311
| 500 501 if (type != SYS_RES_MEMORY) 502 return (ENOENT); 503
|
312 /* Currently all devices have a single RID per type. */
| 504 /* Currently all LBC devices have a single RID per type. */
|
313 if (rid != 0) 314 return (ENOENT); 315 316 sc = device_get_softc(dev); 317 dinfo = device_get_ivars(child); 318
| 505 if (rid != 0) 506 return (ENOENT); 507 508 sc = device_get_softc(dev); 509 dinfo = device_get_ivars(child); 510
|
| 511 if ((dinfo->lbc_unit < 0) || (dinfo->lbc_unit > (LBC_DEV_MAX - 1))) 512 return (EINVAL); 513 514 lbcres = mpc85xx_lbc_resources; 515
|
319 switch (dinfo->lbc_devtype) { 320 case LBC_DEVTYPE_CFI:
| 516 switch (dinfo->lbc_devtype) { 517 case LBC_DEVTYPE_CFI:
|
321 *startp = sc->sc_rman.rm_start; 322 *countp = sc->sc_rman.rm_end - sc->sc_rman.rm_start + 1; 323 break;
| 518 case LBC_DEVTYPE_RTC: 519 for (; lbcres->lbr_devtype; lbcres++) { 520 if (dinfo->lbc_unit == lbcres->lbr_unit) { 521 *startp = sc->sc_kva[lbcres->lbr_unit]; 522 *countp = lbcres->lbr_size; 523 return (0); 524 } 525 }
|
324 default:
| 526 default:
|
325 return(EDOOFUS);
| 527 return (EDOOFUS);
|
326 }
| 528 }
|
327 return(0);
| 529 return (0);
|
328}
| 530}
|