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