econa.c revision 271398
1/*- 2 * Copyright (c) 2009 Yohanes Nugroho <yohanes@gmail.com> 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 * 14 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: head/sys/arm/cavium/cns11xx/econa.c 271398 2014-09-10 15:25:15Z andrew $"); 29 30#include <sys/param.h> 31#include <sys/systm.h> 32#include <sys/bus.h> 33#include <sys/types.h> 34#include <sys/kernel.h> 35#include <sys/malloc.h> 36#include <sys/module.h> 37#include <sys/rman.h> 38#include <vm/vm.h> 39#include <vm/vm_kern.h> 40#include <vm/pmap.h> 41#include <vm/vm_page.h> 42#include <vm/vm_extern.h> 43 44#define _ARM32_BUS_DMA_PRIVATE 45#include <machine/armreg.h> 46#include <machine/bus.h> 47#include <machine/intr.h> 48#include <machine/resource.h> 49 50#include "econa_reg.h" 51#include "econa_var.h" 52 53static struct econa_softc *econa_softc; 54 55unsigned int CPU_clock = 200000000; 56unsigned int AHB_clock; 57unsigned int APB_clock; 58 59bs_protos(generic); 60bs_protos(generic_armv4); 61 62struct bus_space econa_bs_tag = { 63 /* cookie */ 64 (void *) 0, 65 66 /* mapping/unmapping */ 67 generic_bs_map, 68 generic_bs_unmap, 69 generic_bs_subregion, 70 71 /* allocation/deallocation */ 72 generic_bs_alloc, 73 generic_bs_free, 74 75 /* barrier */ 76 generic_bs_barrier, 77 78 /* read (single) */ 79 generic_bs_r_1, 80 generic_armv4_bs_r_2, 81 generic_bs_r_4, 82 NULL, 83 84 /* read multiple */ 85 generic_bs_rm_1, 86 generic_armv4_bs_rm_2, 87 generic_bs_rm_4, 88 NULL, 89 90 /* read region */ 91 generic_bs_rr_1, 92 generic_armv4_bs_rr_2, 93 generic_bs_rr_4, 94 NULL, 95 96 /* write (single) */ 97 generic_bs_w_1, 98 generic_armv4_bs_w_2, 99 generic_bs_w_4, 100 NULL, 101 102 /* write multiple */ 103 generic_bs_wm_1, 104 generic_armv4_bs_wm_2, 105 generic_bs_wm_4, 106 NULL, 107 108 /* write region */ 109 NULL, 110 NULL, 111 NULL, 112 NULL, 113 114 /* set multiple */ 115 NULL, 116 NULL, 117 NULL, 118 NULL, 119 120 /* set region */ 121 NULL, 122 NULL, 123 NULL, 124 NULL, 125 126 /* copy */ 127 NULL, 128 NULL, 129 NULL, 130 NULL, 131 132 /* read (single) stream */ 133 NULL, 134 NULL, 135 NULL, 136 NULL, 137 138 /* read multiple stream */ 139 NULL, 140 generic_armv4_bs_rm_2, 141 NULL, 142 NULL, 143 144 /* read region stream */ 145 NULL, 146 NULL, 147 NULL, 148 NULL, 149 150 /* write (single) stream */ 151 NULL, 152 NULL, 153 NULL, 154 NULL, 155 156 /* write multiple stream */ 157 NULL, 158 generic_armv4_bs_wm_2, 159 NULL, 160 NULL, 161 162 /* write region stream */ 163 NULL, 164 NULL, 165 NULL, 166 NULL 167}; 168 169bus_space_tag_t obio_tag = &econa_bs_tag; 170 171static int 172econa_probe(device_t dev) 173{ 174 175 device_set_desc(dev, "ECONA device bus"); 176 return (BUS_PROBE_NOWILDCARD); 177} 178 179static void 180econa_identify(driver_t *drv, device_t parent) 181{ 182 183 BUS_ADD_CHILD(parent, 0, "econaarm", 0); 184} 185 186struct arm32_dma_range * 187bus_dma_get_range(void) 188{ 189 190 return (NULL); 191} 192 193int 194bus_dma_get_range_nb(void) 195{ 196 197 return (0); 198} 199 200extern void irq_entry(void); 201 202static void 203econa_add_child(device_t dev, int prio, const char *name, int unit, 204 bus_addr_t addr, bus_size_t size, 205 int irq0, int irq1, 206 int irq2, int irq3, int irq4) 207{ 208 device_t kid; 209 struct econa_ivar *ivar; 210 211 kid = device_add_child_ordered(dev, prio, name, unit); 212 if (kid == NULL) { 213 printf("Can't add child %s%d ordered\n", name, unit); 214 return; 215 } 216 ivar = malloc(sizeof(*ivar), M_DEVBUF, M_NOWAIT | M_ZERO); 217 if (ivar == NULL) { 218 device_delete_child(dev, kid); 219 return; 220 } 221 device_set_ivars(kid, ivar); 222 resource_list_init(&ivar->resources); 223 if (irq0 != -1) 224 bus_set_resource(kid, SYS_RES_IRQ, 0, irq0, 1); 225 if (irq1 != 0) 226 bus_set_resource(kid, SYS_RES_IRQ, 1, irq1, 1); 227 if (irq2 != 0) 228 bus_set_resource(kid, SYS_RES_IRQ, 2, irq2, 1); 229 if (irq3 != 0) 230 bus_set_resource(kid, SYS_RES_IRQ, 3, irq3, 1); 231 if (irq4 != 0) 232 bus_set_resource(kid, SYS_RES_IRQ, 4, irq4, 1); 233 234 if (addr != 0) 235 bus_set_resource(kid, SYS_RES_MEMORY, 0, addr, size); 236 237} 238 239struct cpu_devs 240{ 241 const char *name; 242 int unit; 243 bus_addr_t mem_base; 244 bus_size_t mem_len; 245 int irq0; 246 int irq1; 247 int irq2; 248 int irq3; 249 int irq4; 250}; 251 252struct cpu_devs econarm_devs[] = 253{ 254 { 255 "econa_ic", 0, 256 ECONA_IO_BASE + ECONA_PIC_BASE, ECONA_PIC_SIZE, 257 0 258 }, 259 { 260 "system", 0, 261 ECONA_IO_BASE + ECONA_SYSTEM_BASE, ECONA_SYSTEM_SIZE, 262 0 263 }, 264 { 265 "uart", 0, 266 ECONA_IO_BASE + ECONA_UART_BASE, ECONA_UART_SIZE, 267 ECONA_IRQ_UART 268 }, 269 { 270 "timer", 0, 271 ECONA_IO_BASE + ECONA_TIMER_BASE, ECONA_TIMER_SIZE, 272 ECONA_IRQ_TIMER_1, ECONA_IRQ_TIMER_2 273 }, 274 { 275 "ohci", 0, 276 ECONA_OHCI_VBASE, ECONA_OHCI_SIZE, 277 ECONA_IRQ_OHCI 278 }, 279 { 280 "ehci", 0, 281 ECONA_EHCI_VBASE, ECONA_EHCI_SIZE, 282 ECONA_IRQ_EHCI 283 }, 284 { 285 "cfi", 0, 286 ECONA_CFI_VBASE, ECONA_CFI_SIZE, 287 0 288 }, 289 { 290 "ece", 0, 291 ECONA_IO_BASE + ECONA_NET_BASE, ECONA_NET_SIZE, 292 ECONA_IRQ_STATUS, 293 ECONA_IRQ_TSTC, ECONA_IRQ_FSRC, 294 ECONA_IRQ_TSQE, ECONA_IRQ_FSQF, 295 }, 296 { 0, 0, 0, 0, 0, 0, 0, 0, 0 } 297}; 298 299static void 300econa_cpu_add_builtin_children(device_t dev, struct econa_softc *sc) 301{ 302 int i; 303 struct cpu_devs *walker; 304 305 for (i = 0, walker = econarm_devs; walker->name; i++, walker++) { 306 econa_add_child(dev, i, walker->name, walker->unit, 307 walker->mem_base, walker->mem_len, 308 walker->irq0,walker->irq1, walker->irq2, 309 walker->irq3, walker->irq4); 310 } 311 312} 313 314struct intc_trigger_t { 315 int mode; 316 int level; 317}; 318 319static struct intc_trigger_t intc_trigger_table[] = { 320 {INTC_EDGE_TRIGGER, INTC_RISING_EDGE}, 321 {INTC_EDGE_TRIGGER, INTC_RISING_EDGE}, 322 {INTC_EDGE_TRIGGER, INTC_FALLING_EDGE}, 323 {INTC_EDGE_TRIGGER, INTC_RISING_EDGE}, 324 {INTC_TRIGGER_UNKNOWN, INTC_TRIGGER_UNKNOWN}, 325 {INTC_LEVEL_TRIGGER, INTC_ACTIVE_LOW}, 326 {INTC_LEVEL_TRIGGER, INTC_ACTIVE_LOW}, 327 {INTC_LEVEL_TRIGGER, INTC_ACTIVE_HIGH}, 328 {INTC_TRIGGER_UNKNOWN, INTC_TRIGGER_UNKNOWN}, 329 {INTC_LEVEL_TRIGGER, INTC_ACTIVE_HIGH}, 330 {INTC_LEVEL_TRIGGER, INTC_ACTIVE_HIGH}, 331 {INTC_LEVEL_TRIGGER, INTC_ACTIVE_HIGH}, 332 {INTC_LEVEL_TRIGGER, INTC_ACTIVE_HIGH}, 333 {INTC_TRIGGER_UNKNOWN, INTC_TRIGGER_UNKNOWN}, 334 {INTC_LEVEL_TRIGGER, INTC_ACTIVE_HIGH}, 335 {INTC_EDGE_TRIGGER, INTC_FALLING_EDGE}, 336 {INTC_TRIGGER_UNKNOWN, INTC_TRIGGER_UNKNOWN}, 337 {INTC_TRIGGER_UNKNOWN, INTC_TRIGGER_UNKNOWN}, 338 {INTC_LEVEL_TRIGGER, INTC_ACTIVE_HIGH}, 339 {INTC_EDGE_TRIGGER, INTC_RISING_EDGE}, 340 {INTC_EDGE_TRIGGER, INTC_RISING_EDGE}, 341 {INTC_EDGE_TRIGGER, INTC_RISING_EDGE}, 342 {INTC_EDGE_TRIGGER, INTC_RISING_EDGE}, 343 {INTC_LEVEL_TRIGGER, INTC_ACTIVE_LOW}, 344 {INTC_LEVEL_TRIGGER, INTC_ACTIVE_LOW}, 345}; 346 347static inline uint32_t 348read_4(struct econa_softc *sc, bus_size_t off) 349{ 350 351 return bus_space_read_4(sc->ec_st, sc->ec_sys_sh, off); 352} 353 354static inline void 355write_4(struct econa_softc *sc, bus_size_t off, uint32_t val) 356{ 357 358 return bus_space_write_4(sc->ec_st, sc->ec_sys_sh, off, val); 359} 360 361static inline uint32_t 362system_read_4(struct econa_softc *sc, bus_size_t off) 363{ 364 365 return bus_space_read_4(sc->ec_st, sc->ec_system_sh, off); 366} 367 368static inline void 369system_write_4(struct econa_softc *sc, bus_size_t off, uint32_t val) 370{ 371 372 return bus_space_write_4(sc->ec_st, sc->ec_system_sh, off, val); 373} 374 375 376 377static inline void 378econa_set_irq_mode(struct econa_softc * sc, unsigned int irq, 379 unsigned int mode) 380{ 381 unsigned int val; 382 383 if ((mode != INTC_LEVEL_TRIGGER) && (mode != INTC_EDGE_TRIGGER)) 384 return; 385 386 val = read_4(sc, INTC_INTERRUPT_TRIGGER_MODE_REG_OFFSET); 387 388 if (mode == INTC_LEVEL_TRIGGER) { 389 if (val & (1UL << irq)) { 390 val &= ~(1UL << irq); 391 write_4(sc, INTC_INTERRUPT_TRIGGER_MODE_REG_OFFSET, 392 val); 393 } 394 } else { 395 if (!(val & (1UL << irq))) { 396 val |= (1UL << irq); 397 write_4(sc, INTC_INTERRUPT_TRIGGER_MODE_REG_OFFSET, 398 val); 399 } 400 } 401} 402 403/* 404 * Configure interrupt trigger level to be Active High/Low 405 * or Rising/Falling Edge 406 */ 407static inline void 408econa_set_irq_level(struct econa_softc * sc, 409 unsigned int irq, unsigned int level) 410{ 411 unsigned int val; 412 413 if ((level != INTC_ACTIVE_HIGH) && 414 (level != INTC_ACTIVE_LOW) && 415 (level != INTC_RISING_EDGE) && 416 (level != INTC_FALLING_EDGE)) { 417 return; 418 } 419 420 val = read_4(sc, INTC_INTERRUPT_TRIGGER_LEVEL_REG_OFFSET); 421 422 if ((level == INTC_ACTIVE_HIGH) || (level == INTC_RISING_EDGE)) { 423 if (val & (1UL << irq)) { 424 val &= ~(1UL << irq); 425 write_4(sc, INTC_INTERRUPT_TRIGGER_LEVEL_REG_OFFSET, 426 val); 427 } 428 } else { 429 if (!(val & (1UL << irq))) { 430 val |= (1UL << irq); 431 write_4(sc, INTC_INTERRUPT_TRIGGER_LEVEL_REG_OFFSET, 432 val); 433 } 434 } 435} 436 437static void 438get_system_clock(void) 439{ 440 uint32_t sclock = system_read_4(econa_softc, SYSTEM_CLOCK); 441 442 sclock = (sclock >> 6) & 0x03; 443 444 switch (sclock) { 445 case 0: 446 CPU_clock = 175000000; 447 break; 448 case 1: 449 CPU_clock = 200000000; 450 break; 451 case 2: 452 CPU_clock = 225000000; 453 break; 454 case 3: 455 CPU_clock = 250000000; 456 break; 457 } 458 AHB_clock = CPU_clock >> 1; 459 APB_clock = AHB_clock >> 1; 460} 461 462static int 463econa_attach(device_t dev) 464{ 465 struct econa_softc *sc = device_get_softc(dev); 466 int i; 467 468 econa_softc = sc; 469 sc->ec_st = &econa_bs_tag; 470 sc->ec_sh = ECONA_IO_BASE; 471 sc->dev = dev; 472 if (bus_space_subregion(sc->ec_st, sc->ec_sh, ECONA_PIC_BASE, 473 ECONA_PIC_SIZE, &sc->ec_sys_sh) != 0) 474 panic("Unable to map IRQ registers"); 475 476 if (bus_space_subregion(sc->ec_st, sc->ec_sh, ECONA_SYSTEM_BASE, 477 ECONA_SYSTEM_SIZE, &sc->ec_system_sh) != 0) 478 panic("Unable to map IRQ registers"); 479 480 sc->ec_irq_rman.rm_type = RMAN_ARRAY; 481 sc->ec_irq_rman.rm_descr = "ECONA IRQs"; 482 sc->ec_mem_rman.rm_type = RMAN_ARRAY; 483 sc->ec_mem_rman.rm_descr = "ECONA Memory"; 484 if (rman_init(&sc->ec_irq_rman) != 0 || 485 rman_manage_region(&sc->ec_irq_rman, 0, 31) != 0) 486 panic("econa_attach: failed to set up IRQ rman"); 487 if (rman_init(&sc->ec_mem_rman) != 0 || 488 rman_manage_region(&sc->ec_mem_rman, 0, 489 ~0) != 0) 490 panic("econa_attach: failed to set up memory rman"); 491 492 write_4(sc, INTC_INTERRUPT_CLEAR_EDGE_TRIGGER_REG_OFFSET, 0xffffffff); 493 494 write_4(sc, INTC_INTERRUPT_MASK_REG_OFFSET, 0xffffffff); 495 496 write_4(sc, INTC_FIQ_MODE_SELECT_REG_OFFSET, 0); 497 498 /*initialize irq*/ 499 for (i = 0; i < 32; i++) { 500 if (intc_trigger_table[i].mode != INTC_TRIGGER_UNKNOWN) { 501 econa_set_irq_mode(sc,i, intc_trigger_table[i].mode); 502 econa_set_irq_level(sc, i, intc_trigger_table[i].level); 503 } 504 } 505 506 get_system_clock(); 507 508 econa_cpu_add_builtin_children(dev, sc); 509 510 bus_generic_probe(dev); 511 bus_generic_attach(dev); 512 enable_interrupts(PSR_I | PSR_F); 513 514 return (0); 515} 516 517static struct resource * 518econa_alloc_resource(device_t dev, device_t child, int type, int *rid, 519 u_long start, u_long end, u_long count, u_int flags) 520{ 521 struct econa_softc *sc = device_get_softc(dev); 522 struct resource_list_entry *rle; 523 struct econa_ivar *ivar = device_get_ivars(child); 524 struct resource_list *rl = &ivar->resources; 525 526 if (device_get_parent(child) != dev) 527 return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child, 528 type, rid, start, end, count, flags)); 529 530 rle = resource_list_find(rl, type, *rid); 531 if (rle == NULL) { 532 return (NULL); 533 } 534 if (rle->res) 535 panic("Resource rid %d type %d already in use", *rid, type); 536 if (start == 0UL && end == ~0UL) { 537 start = rle->start; 538 count = ulmax(count, rle->count); 539 end = ulmax(rle->end, start + count - 1); 540 } 541 switch (type) 542 { 543 case SYS_RES_IRQ: 544 rle->res = rman_reserve_resource(&sc->ec_irq_rman, 545 start, end, count, flags, child); 546 break; 547 case SYS_RES_MEMORY: 548 rle->res = rman_reserve_resource(&sc->ec_mem_rman, 549 start, end, count, flags, child); 550 if (rle->res != NULL) { 551 rman_set_bustag(rle->res, &econa_bs_tag); 552 rman_set_bushandle(rle->res, start); 553 } 554 break; 555 } 556 if (rle->res) { 557 rle->start = rman_get_start(rle->res); 558 rle->end = rman_get_end(rle->res); 559 rle->count = count; 560 rman_set_rid(rle->res, *rid); 561 } 562 return (rle->res); 563} 564 565static struct resource_list * 566econa_get_resource_list(device_t dev, device_t child) 567{ 568 struct econa_ivar *ivar; 569 ivar = device_get_ivars(child); 570 return (&(ivar->resources)); 571} 572 573static int 574econa_release_resource(device_t dev, device_t child, int type, 575 int rid, struct resource *r) 576{ 577 struct resource_list *rl; 578 struct resource_list_entry *rle; 579 580 rl = econa_get_resource_list(dev, child); 581 if (rl == NULL) 582 return (EINVAL); 583 rle = resource_list_find(rl, type, rid); 584 if (rle == NULL) 585 return (EINVAL); 586 rman_release_resource(r); 587 rle->res = NULL; 588 return (0); 589} 590 591static int 592econa_setup_intr(device_t dev, device_t child, 593 struct resource *ires, int flags, driver_filter_t *filt, 594 driver_intr_t *intr, void *arg, void **cookiep) 595{ 596 int error; 597 598 if (rman_get_start(ires) == ECONA_IRQ_SYSTEM && filt == NULL) 599 panic("All system interrupt ISRs must be FILTER"); 600 601 error = BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, 602 filt, intr, arg, cookiep); 603 if (error) 604 return (error); 605 606 return (0); 607} 608 609static int 610econa_teardown_intr(device_t dev, device_t child, struct resource *res, 611 void *cookie) 612{ 613 614 return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie)); 615} 616 617static int 618econa_activate_resource(device_t bus, device_t child, int type, int rid, 619 struct resource *r) 620{ 621 622 return (rman_activate_resource(r)); 623} 624 625static int 626econa_print_child(device_t dev, device_t child) 627{ 628 struct econa_ivar *ivars; 629 struct resource_list *rl; 630 int retval = 0; 631 632 ivars = device_get_ivars(child); 633 rl = &ivars->resources; 634 635 retval += bus_print_child_header(dev, child); 636 637 retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#lx"); 638 retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx"); 639 retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld"); 640 if (device_get_flags(dev)) 641 retval += printf(" flags %#x", device_get_flags(dev)); 642 643 retval += bus_print_child_footer(dev, child); 644 645 return (retval); 646} 647 648void 649arm_mask_irq(uintptr_t nb) 650{ 651 unsigned int value; 652 653 value = read_4(econa_softc,INTC_INTERRUPT_MASK_REG_OFFSET) | 1<<nb; 654 write_4(econa_softc, INTC_INTERRUPT_MASK_REG_OFFSET, value); 655} 656 657void 658arm_unmask_irq(uintptr_t nb) 659{ 660 unsigned int value; 661 662 value = read_4(econa_softc, 663 INTC_INTERRUPT_CLEAR_EDGE_TRIGGER_REG_OFFSET) | (1 << nb); 664 write_4(econa_softc, 665 INTC_INTERRUPT_CLEAR_EDGE_TRIGGER_REG_OFFSET, value); 666 value = read_4(econa_softc, INTC_INTERRUPT_MASK_REG_OFFSET)& ~(1 << nb); 667 write_4(econa_softc, INTC_INTERRUPT_MASK_REG_OFFSET, value); 668} 669 670int 671arm_get_next_irq(int x) 672{ 673 int irq; 674 675 irq = read_4(econa_softc, INTC_INTERRUPT_STATUS_REG_OFFSET) & 676 ~(read_4(econa_softc, INTC_INTERRUPT_MASK_REG_OFFSET)); 677 678 if (irq!=0) { 679 return (ffs(irq) - 1); 680 } 681 682 return (-1); 683} 684 685void 686cpu_reset(void) 687{ 688 uint32_t control; 689 690 control = system_read_4(econa_softc, RESET_CONTROL); 691 control |= GLOBAL_RESET; 692 system_write_4(econa_softc, RESET_CONTROL, control); 693 control = system_read_4(econa_softc, RESET_CONTROL); 694 control &= (~(GLOBAL_RESET)); 695 system_write_4(econa_softc, RESET_CONTROL, control); 696 while (1); 697} 698 699 700 701void 702power_on_network_interface(void) 703{ 704 uint32_t cfg_reg; 705 int ii; 706 707 cfg_reg = system_read_4(econa_softc, RESET_CONTROL); 708 cfg_reg |= NET_INTERFACE_RESET; 709 /* set reset bit to HIGH active; */ 710 system_write_4(econa_softc, RESET_CONTROL, cfg_reg); 711 712 /*pulse delay */ 713 for (ii = 0; ii < 0xFFF; ii++) 714 DELAY(100); 715 /* set reset bit to LOW active; */ 716 cfg_reg = system_read_4(econa_softc, RESET_CONTROL); 717 cfg_reg &= ~(NET_INTERFACE_RESET); 718 system_write_4(econa_softc, RESET_CONTROL, cfg_reg); 719 720 /*pulse delay */ 721 for (ii = 0; ii < 0xFFF; ii++) 722 DELAY(100); 723 cfg_reg = system_read_4(econa_softc, RESET_CONTROL); 724 cfg_reg |= NET_INTERFACE_RESET; 725 /* set reset bit to HIGH active; */ 726 system_write_4(econa_softc, RESET_CONTROL, cfg_reg); 727} 728 729unsigned int 730get_tclk(void) 731{ 732 733 return CPU_clock; 734} 735 736static device_method_t econa_methods[] = { 737 DEVMETHOD(device_probe, econa_probe), 738 DEVMETHOD(device_attach, econa_attach), 739 DEVMETHOD(device_identify, econa_identify), 740 DEVMETHOD(bus_alloc_resource, econa_alloc_resource), 741 DEVMETHOD(bus_setup_intr, econa_setup_intr), 742 DEVMETHOD(bus_teardown_intr, econa_teardown_intr), 743 DEVMETHOD(bus_activate_resource, econa_activate_resource), 744 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 745 DEVMETHOD(bus_get_resource_list, econa_get_resource_list), 746 DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource), 747 DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), 748 DEVMETHOD(bus_release_resource, econa_release_resource), 749 DEVMETHOD(bus_print_child, econa_print_child), 750 {0, 0}, 751}; 752 753static driver_t econa_driver = { 754 "econaarm", 755 econa_methods, 756 sizeof(struct econa_softc), 757}; 758static devclass_t econa_devclass; 759 760DRIVER_MODULE(econaarm, nexus, econa_driver, econa_devclass, 0, 0); 761