The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/arm/econa/econa.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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: releng/9.0/sys/arm/econa/econa.c 201468 2010-01-04 03:35:45Z rpaulo $");
   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 
   52 static struct econa_softc *econa_softc;
   53 
   54 unsigned int CPU_clock = 200000000;
   55 unsigned int AHB_clock;
   56 unsigned int APB_clock;
   57 
   58 bs_protos(generic);
   59 bs_protos(generic_armv4);
   60 
   61 struct 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 
  168 bus_space_tag_t obio_tag = &econa_bs_tag;
  169 
  170 static int
  171 econa_probe(device_t dev)
  172 {
  173 
  174         device_set_desc(dev, "ECONA device bus");
  175         return (0);
  176 }
  177 
  178 static void
  179 econa_identify(driver_t *drv, device_t parent)
  180 {
  181 
  182         BUS_ADD_CHILD(parent, 0, "econaarm", 0);
  183 }
  184 
  185 struct arm32_dma_range *
  186 bus_dma_get_range(void)
  187 {
  188 
  189         return (NULL);
  190 }
  191 
  192 int
  193 bus_dma_get_range_nb(void)
  194 {
  195 
  196         return (0);
  197 }
  198 
  199 extern void irq_entry(void);
  200 
  201 static void
  202 econa_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 
  238 struct 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 
  251 struct 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 
  298 static void
  299 econa_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 
  313 struct intc_trigger_t {
  314         int mode;
  315         int level;
  316 };
  317 
  318 static 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 
  346 static inline uint32_t
  347 read_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 
  353 static inline void
  354 write_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 
  360 static inline uint32_t
  361 system_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 
  367 static inline void
  368 system_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 
  376 static inline void
  377 econa_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  */
  406 static inline void
  407 econa_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 
  436 static void
  437 get_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 
  461 static int
  462 econa_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 
  516 static struct resource *
  517 econa_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 
  564 static struct resource_list *
  565 econa_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 
  572 static int
  573 econa_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 
  590 static int
  591 econa_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 
  596         if (rman_get_start(ires) == ECONA_IRQ_SYSTEM && filt == NULL)
  597                 panic("All system interrupt ISRs must be FILTER");
  598 
  599         BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, filt,
  600             intr, arg, cookiep);
  601 
  602         arm_unmask_irq(rman_get_start(ires));
  603 
  604         return (0);
  605 }
  606 
  607 static int
  608 econa_teardown_intr(device_t dev, device_t child, struct resource *res,
  609     void *cookie)
  610 {
  611 
  612         return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie));
  613 }
  614 
  615 static int
  616 econa_activate_resource(device_t bus, device_t child, int type, int rid,
  617     struct resource *r)
  618 {
  619 
  620         return (rman_activate_resource(r));
  621 }
  622 
  623 static int
  624 econa_print_child(device_t dev, device_t child)
  625 {
  626         struct econa_ivar *ivars;
  627         struct resource_list *rl;
  628         int retval = 0;
  629 
  630         ivars = device_get_ivars(child);
  631         rl = &ivars->resources;
  632 
  633         retval += bus_print_child_header(dev, child);
  634 
  635         retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#lx");
  636         retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
  637         retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
  638         if (device_get_flags(dev))
  639                 retval += printf(" flags %#x", device_get_flags(dev));
  640 
  641         retval += bus_print_child_footer(dev, child);
  642 
  643         return (retval);
  644 }
  645 
  646 void
  647 arm_mask_irq(uintptr_t nb)
  648 {
  649         unsigned int value;
  650 
  651         value = read_4(econa_softc,INTC_INTERRUPT_MASK_REG_OFFSET) | 1<<nb;
  652         write_4(econa_softc, INTC_INTERRUPT_MASK_REG_OFFSET, value);
  653 }
  654 
  655 void
  656 arm_unmask_irq(uintptr_t nb)
  657 {
  658         unsigned int value;
  659 
  660         value = read_4(econa_softc,
  661             INTC_INTERRUPT_CLEAR_EDGE_TRIGGER_REG_OFFSET) | (1 << nb);
  662         write_4(econa_softc,
  663             INTC_INTERRUPT_CLEAR_EDGE_TRIGGER_REG_OFFSET, value);
  664         value = read_4(econa_softc, INTC_INTERRUPT_MASK_REG_OFFSET)& ~(1 << nb);
  665         write_4(econa_softc, INTC_INTERRUPT_MASK_REG_OFFSET, value);
  666 }
  667 
  668 int
  669 arm_get_next_irq(int x)
  670 {
  671         int irq;
  672 
  673         irq = read_4(econa_softc, INTC_INTERRUPT_STATUS_REG_OFFSET) &
  674             ~(read_4(econa_softc, INTC_INTERRUPT_MASK_REG_OFFSET));
  675 
  676         if (irq!=0) {
  677                 return (ffs(irq) - 1);
  678         }
  679 
  680         return (-1);
  681 }
  682 
  683 void
  684 cpu_reset(void)
  685 {
  686         uint32_t control;
  687 
  688         control = system_read_4(econa_softc, RESET_CONTROL);
  689         control |= GLOBAL_RESET;
  690         system_write_4(econa_softc, RESET_CONTROL, control);
  691         control = system_read_4(econa_softc, RESET_CONTROL);
  692         control &= (~(GLOBAL_RESET));
  693         system_write_4(econa_softc, RESET_CONTROL, control);
  694         while (1);
  695 }
  696 
  697 
  698 
  699 void
  700 power_on_network_interface(void)
  701 {
  702         uint32_t cfg_reg;
  703         int ii;
  704 
  705         cfg_reg =  system_read_4(econa_softc, RESET_CONTROL);
  706         cfg_reg |= NET_INTERFACE_RESET;
  707         /* set reset bit to HIGH active; */
  708         system_write_4(econa_softc, RESET_CONTROL, cfg_reg);
  709 
  710         /*pulse delay */
  711         for (ii = 0; ii < 0xFFF; ii++)
  712                 DELAY(100);
  713         /* set reset bit to LOW active; */
  714         cfg_reg =  system_read_4(econa_softc, RESET_CONTROL);
  715         cfg_reg &= ~(NET_INTERFACE_RESET);
  716         system_write_4(econa_softc, RESET_CONTROL, cfg_reg);
  717 
  718         /*pulse delay */
  719         for (ii = 0; ii < 0xFFF; ii++)
  720                 DELAY(100);
  721         cfg_reg = system_read_4(econa_softc, RESET_CONTROL);
  722         cfg_reg |= NET_INTERFACE_RESET;
  723         /* set reset bit to HIGH active; */
  724         system_write_4(econa_softc, RESET_CONTROL, cfg_reg);
  725 }
  726 
  727 unsigned int
  728 get_tclk(void)
  729 {
  730 
  731         return CPU_clock;
  732 }
  733 
  734 static device_method_t econa_methods[] = {
  735         DEVMETHOD(device_probe,         econa_probe),
  736         DEVMETHOD(device_attach,                econa_attach),
  737         DEVMETHOD(device_identify,              econa_identify),
  738         DEVMETHOD(bus_alloc_resource,           econa_alloc_resource),
  739         DEVMETHOD(bus_setup_intr,               econa_setup_intr),
  740         DEVMETHOD(bus_teardown_intr,            econa_teardown_intr),
  741         DEVMETHOD(bus_activate_resource,        econa_activate_resource),
  742         DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
  743         DEVMETHOD(bus_get_resource_list,        econa_get_resource_list),
  744         DEVMETHOD(bus_set_resource,             bus_generic_rl_set_resource),
  745         DEVMETHOD(bus_get_resource,             bus_generic_rl_get_resource),
  746         DEVMETHOD(bus_release_resource, econa_release_resource),
  747         DEVMETHOD(bus_print_child,              econa_print_child),
  748         {0, 0},
  749 };
  750 
  751 static driver_t econa_driver = {
  752         "econaarm",
  753         econa_methods,
  754         sizeof(struct econa_softc),
  755 };
  756 static devclass_t econa_devclass;
  757 
  758 DRIVER_MODULE(econaarm, nexus, econa_driver, econa_devclass, 0, 0);

Cache object: a04079c6b149499d9930382d4c9b6860


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.