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/at91/at91rm9200.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) 2005 Olivier Houchard.  All rights reserved.
    3  * Copyright (c) 2010 Greg Ansley.  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/at91/at91rm9200.c 217036 2011-01-05 23:45:07Z imp $");
   29 
   30 #include <sys/param.h>
   31 #include <sys/systm.h>
   32 #include <sys/bus.h>
   33 #include <sys/kernel.h>
   34 #include <sys/malloc.h>
   35 #include <sys/module.h>
   36 
   37 #define _ARM32_BUS_DMA_PRIVATE
   38 #include <machine/bus.h>
   39 
   40 #include <arm/at91/at91var.h>
   41 #include <arm/at91/at91rm92reg.h>
   42 #include <arm/at91/at91_aicreg.h>
   43 #include <arm/at91/at91_pmcreg.h>
   44 #include <arm/at91/at91_pmcvar.h>
   45 
   46 struct at91rm92_softc {
   47         device_t dev;
   48         bus_space_tag_t sc_st;
   49         bus_space_handle_t sc_sh;
   50         bus_space_handle_t sc_sys_sh;
   51         bus_space_handle_t sc_aic_sh;
   52         bus_space_handle_t sc_dbg_sh;
   53         bus_space_handle_t sc_matrix_sh;
   54 };
   55 /*
   56  * Standard priority levels for the system.  0 is lowest and 7 is highest.
   57  * These values are the ones Atmel uses for its Linux port, which differ
   58  * a little form the ones that are in the standard distribution.  Also,
   59  * the ones marked with 'TWEEK' are different based on experience.
   60  */
   61 static const int at91_irq_prio[32] =
   62 {
   63         7,      /* Advanced Interrupt Controller (FIQ) */
   64         7,      /* System Peripherals */
   65         1,      /* Parallel IO Controller A */
   66         1,      /* Parallel IO Controller B */
   67         1,      /* Parallel IO Controller C */
   68         1,      /* Parallel IO Controller D */
   69         5,      /* USART 0 */
   70         5,      /* USART 1 */
   71         5,      /* USART 2 */
   72         5,      /* USART 3 */
   73         0,      /* Multimedia Card Interface */
   74         2,      /* USB Device Port */
   75         4,      /* Two-Wire Interface */                /* TWEEK */
   76         5,      /* Serial Peripheral Interface */
   77         4,      /* Serial Synchronous Controller 0 */
   78         6,      /* Serial Synchronous Controller 1 */   /* TWEEK */
   79         4,      /* Serial Synchronous Controller 2 */
   80         0,      /* Timer Counter 0 */
   81         6,      /* Timer Counter 1 */                   /* TWEEK */
   82         0,      /* Timer Counter 2 */
   83         0,      /* Timer Counter 3 */
   84         0,      /* Timer Counter 4 */
   85         0,      /* Timer Counter 5 */
   86         2,      /* USB Host port */
   87         3,      /* Ethernet MAC */
   88         0,      /* Advanced Interrupt Controller (IRQ0) */
   89         0,      /* Advanced Interrupt Controller (IRQ1) */
   90         0,      /* Advanced Interrupt Controller (IRQ2) */
   91         0,      /* Advanced Interrupt Controller (IRQ3) */
   92         0,      /* Advanced Interrupt Controller (IRQ4) */
   93         0,      /* Advanced Interrupt Controller (IRQ5) */
   94         0       /* Advanced Interrupt Controller (IRQ6) */
   95 };
   96 
   97 #define DEVICE(_name, _id, _unit)               \
   98         {                                       \
   99                 _name, _unit,                   \
  100                 AT91RM92_ ## _id ##_BASE,       \
  101                 AT91RM92_ ## _id ## _SIZE,      \
  102                 AT91RM92_IRQ_ ## _id            \
  103         }
  104 
  105 static const struct cpu_devs at91_devs[] =
  106 {
  107         DEVICE("at91_pmc",   PMC,    0),
  108         DEVICE("at91_st",    ST,     0),
  109         DEVICE("at91_pio",   PIOA,   0),
  110         DEVICE("at91_pio",   PIOB,   1),
  111         DEVICE("at91_pio",   PIOC,   2),
  112         DEVICE("at91_pio",   PIOD,   3),
  113         DEVICE("at91_rtc",   RTC,    0),
  114 
  115         DEVICE("at91_mci",   MCI,    0),
  116         DEVICE("at91_twi",   TWI,    0),
  117         DEVICE("at91_udp",   UDP,    0),
  118         DEVICE("ate",        EMAC,   0),
  119         DEVICE("at91_ssc",   SSC0,   0),
  120         DEVICE("at91_ssc",   SSC1,   1),
  121         DEVICE("at91_ssc",   SSC2,   2),
  122         DEVICE("spi",        SPI,    0),
  123 
  124         DEVICE("uart",       DBGU,   0),
  125         DEVICE("uart",       USART0, 1),
  126         DEVICE("uart",       USART1, 2),
  127         DEVICE("uart",       USART2, 3),
  128         DEVICE("uart",       USART3, 4),
  129         DEVICE("at91_aic",   AIC,    0),
  130         DEVICE("at91_mc",    MC,     0),
  131         DEVICE("at91_tc",    TC0,    0),
  132         DEVICE("at91_tc",    TC1,    1),
  133         DEVICE("ohci",       OHCI,   0),
  134         DEVICE("af91_cfata", CF,     0),
  135         {       0, 0, 0, 0, 0 }
  136 };
  137 
  138 static void
  139 at91_add_child(device_t dev, int prio, const char *name, int unit,
  140     bus_addr_t addr, bus_size_t size, int irq0, int irq1, int irq2)
  141 {
  142         device_t kid;
  143         struct at91_ivar *ivar;
  144 
  145         kid = device_add_child_ordered(dev, prio, name, unit);
  146         if (kid == NULL) {
  147             printf("Can't add child %s%d ordered\n", name, unit);
  148             return;
  149         }
  150         ivar = malloc(sizeof(*ivar), M_DEVBUF, M_NOWAIT | M_ZERO);
  151         if (ivar == NULL) {
  152                 device_delete_child(dev, kid);
  153                 printf("Can't add alloc ivar\n");
  154                 return;
  155         }
  156         device_set_ivars(kid, ivar);
  157         resource_list_init(&ivar->resources);
  158         if (irq0 != -1) {
  159                 bus_set_resource(kid, SYS_RES_IRQ, 0, irq0, 1);
  160                 if (irq0 != AT91RM92_IRQ_SYSTEM)
  161                         at91_pmc_clock_add(device_get_nameunit(kid), irq0, 0);
  162         }
  163         if (irq1 != 0)
  164                 bus_set_resource(kid, SYS_RES_IRQ, 1, irq1, 1);
  165         if (irq2 != 0)
  166                 bus_set_resource(kid, SYS_RES_IRQ, 2, irq2, 1);
  167         if (addr != 0 && addr < AT91RM92_BASE) 
  168                 addr += AT91RM92_BASE;
  169         if (addr != 0)
  170                 bus_set_resource(kid, SYS_RES_MEMORY, 0, addr, size);
  171 }
  172 
  173 static void
  174 at91_cpu_add_builtin_children(device_t dev)
  175 {
  176         int i;
  177         const struct cpu_devs *walker;
  178         
  179         for (i = 1, walker = at91_devs; walker->name; i++, walker++) {
  180                 at91_add_child(dev, i, walker->name, walker->unit,
  181                     walker->mem_base, walker->mem_len, walker->irq0,
  182                     walker->irq1, walker->irq2);
  183         }
  184 }
  185 
  186 static uint32_t
  187 at91_pll_outb(int freq)
  188 {
  189 
  190         if (freq > 155000000)
  191                 return (0x0000);
  192         else 
  193                 return (0x8000);
  194 }
  195 
  196 static void
  197 at91_identify(driver_t *drv, device_t parent)
  198 {
  199 
  200         if (at91_cpu_is(AT91_CPU_RM9200)) {
  201                 at91_add_child(parent, 0, "at91rm920", 0, 0, 0, -1, 0, 0);
  202                 at91_cpu_add_builtin_children(parent);
  203         }
  204 }
  205 
  206 static int
  207 at91_probe(device_t dev)
  208 {
  209 
  210         if (at91_cpu_is(AT91_CPU_RM9200)) {
  211                 device_set_desc(dev, "AT91RM9200");
  212                 return (0);
  213         }
  214         return (ENXIO);
  215 }
  216 
  217 static int
  218 at91_attach(device_t dev)
  219 {
  220         struct at91_pmc_clock *clk;
  221         struct at91rm92_softc *sc = device_get_softc(dev);
  222         int i;
  223 
  224         struct at91_softc *at91sc = device_get_softc(device_get_parent(dev));
  225 
  226         sc->sc_st = at91sc->sc_st;
  227         sc->sc_sh = at91sc->sc_sh;
  228         sc->dev = dev;
  229 
  230         if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91RM92_SYS_BASE,
  231             AT91RM92_SYS_SIZE, &sc->sc_sys_sh) != 0)
  232                 panic("Enable to map system registers");
  233 
  234         if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91RM92_DBGU_BASE,
  235             AT91RM92_DBGU_SIZE, &sc->sc_dbg_sh) != 0)
  236                 panic("Enable to map DBGU registers");
  237 
  238         if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91RM92_AIC_BASE,
  239             AT91RM92_AIC_SIZE, &sc->sc_aic_sh) != 0)
  240                 panic("Enable to map system registers");
  241 
  242         /* XXX Hack to tell atmelarm about the AIC */
  243         at91sc->sc_aic_sh = sc->sc_aic_sh;
  244         at91sc->sc_irq_system = AT91RM92_IRQ_SYSTEM;
  245 
  246         for (i = 0; i < 32; i++) {
  247                 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SVR + 
  248                     i * 4, i);
  249                 /* Priority. */
  250                 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SMR + i * 4,
  251                     at91_irq_prio[i]);
  252                 if (i < 8)
  253                         bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_EOICR,
  254                             1);
  255         }
  256 
  257         bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SPU, 32);
  258         /* No debug. */
  259         bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_DCR, 0);
  260         /* Disable and clear all interrupts. */
  261         bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_IDCR, 0xffffffff);
  262         bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_ICCR, 0xffffffff);
  263 
  264         /* Disable all interrupts for RTC (0xe24 == RTC_IDR) */
  265         bus_space_write_4(sc->sc_st, sc->sc_sys_sh, 0xe24, 0xffffffff);
  266 
  267         /* Disable all interrupts for the SDRAM controller */
  268         bus_space_write_4(sc->sc_st, sc->sc_sys_sh, 0xfa8, 0xffffffff);
  269 
  270         /* Disable all interrupts for DBGU */
  271         bus_space_write_4(sc->sc_st, sc->sc_dbg_sh, 0x0c, 0xffffffff);
  272 
  273         /* Update USB device port clock info */
  274         clk = at91_pmc_clock_ref("udpck");
  275         clk->pmc_mask  = PMC_SCER_UDP;
  276         at91_pmc_clock_deref(clk);
  277 
  278         /* Update USB host port clock info */
  279         clk = at91_pmc_clock_ref("uhpck");
  280         clk->pmc_mask  = PMC_SCER_UHP;
  281         at91_pmc_clock_deref(clk);
  282 
  283         /* Each SOC has different PLL contraints */
  284         clk = at91_pmc_clock_ref("plla");
  285         clk->pll_min_in    = RM9200_PLL_A_MIN_IN_FREQ;          /*   1 MHz */
  286         clk->pll_max_in    = RM9200_PLL_A_MAX_IN_FREQ;          /*  32 MHz */
  287         clk->pll_min_out   = RM9200_PLL_A_MIN_OUT_FREQ;         /*  80 MHz */
  288         clk->pll_max_out   = RM9200_PLL_A_MAX_OUT_FREQ;         /* 180 MHz */
  289         clk->pll_mul_shift = RM9200_PLL_A_MUL_SHIFT;
  290         clk->pll_mul_mask  = RM9200_PLL_A_MUL_MASK;
  291         clk->pll_div_shift = RM9200_PLL_A_DIV_SHIFT;
  292         clk->pll_div_mask  = RM9200_PLL_A_DIV_MASK;
  293         clk->set_outb      = at91_pll_outb;
  294         at91_pmc_clock_deref(clk);
  295 
  296         clk = at91_pmc_clock_ref("pllb");
  297         clk->pll_min_in    = RM9200_PLL_B_MIN_IN_FREQ;          /* 100 KHz */
  298         clk->pll_max_in    = RM9200_PLL_B_MAX_IN_FREQ;          /*  32 MHz */
  299         clk->pll_min_out   = RM9200_PLL_B_MIN_OUT_FREQ;         /*  30 MHz */
  300         clk->pll_max_out   = RM9200_PLL_B_MAX_OUT_FREQ;         /* 240 MHz */
  301         clk->pll_mul_shift = RM9200_PLL_B_MUL_SHIFT;
  302         clk->pll_mul_mask  = RM9200_PLL_B_MUL_MASK;
  303         clk->pll_div_shift = RM9200_PLL_B_DIV_SHIFT;
  304         clk->pll_div_mask  = RM9200_PLL_B_DIV_MASK;
  305         clk->set_outb      = at91_pll_outb;
  306         at91_pmc_clock_deref(clk);
  307 
  308         return (0);
  309 }
  310 
  311 static device_method_t at91_methods[] = {
  312         DEVMETHOD(device_probe, at91_probe),
  313         DEVMETHOD(device_attach, at91_attach),
  314         DEVMETHOD(device_identify, at91_identify),
  315         {0, 0},
  316 };
  317 
  318 static driver_t at91rm92_driver = {
  319         "at91rm920",
  320         at91_methods,
  321         sizeof(struct at91rm92_softc),
  322 };
  323 
  324 static devclass_t at91rm92_devclass;
  325 
  326 DRIVER_MODULE(at91rm920, atmelarm, at91rm92_driver, at91rm92_devclass, 0, 0);

Cache object: 3b6645dba71626369f186537a22a7274


[ 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.