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/at91sam9260.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/at91sam9260.c 213498 2010-10-06 22:40:27Z cognet $");
   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/at91_aicreg.h>
   42 #include <arm/at91/at91sam9260reg.h>
   43 #include <arm/at91/at91_pmcreg.h>
   44 #include <arm/at91/at91_pmcvar.h>
   45 
   46 struct at91sam9_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 /*
   57  * Standard priority levels for the system.  0 is lowest and 7 is highest.
   58  * These values are the ones Atmel uses for its Linux port
   59  */
   60 static const int at91_irq_prio[32] =
   61 {
   62         7,      /* Advanced Interrupt Controller */
   63         7,      /* System Peripherals */
   64         1,      /* Parallel IO Controller A */
   65         1,      /* Parallel IO Controller B */
   66         1,      /* Parallel IO Controller C */
   67         0,      /* Analog-to-Digital Converter */
   68         5,      /* USART 0 */
   69         5,      /* USART 1 */
   70         5,      /* USART 2 */
   71         0,      /* Multimedia Card Interface */
   72         2,      /* USB Device Port */
   73         6,      /* Two-Wire Interface */
   74         5,      /* Serial Peripheral Interface 0 */
   75         5,      /* Serial Peripheral Interface 1 */
   76         5,      /* Serial Synchronous Controller */
   77         0,      /* (reserved) */
   78         0,      /* (reserved) */
   79         0,      /* Timer Counter 0 */
   80         0,      /* Timer Counter 1 */
   81         0,      /* Timer Counter 2 */
   82         2,      /* USB Host port */
   83         3,      /* Ethernet */
   84         0,      /* Image Sensor Interface */
   85         5,      /* USART 3 */
   86         5,      /* USART 4 */
   87         5,      /* USART 5 */
   88         0,      /* Timer Counter 3 */
   89         0,      /* Timer Counter 4 */
   90         0,      /* Timer Counter 5 */
   91         0,      /* Advanced Interrupt Controller IRQ0 */
   92         0,      /* Advanced Interrupt Controller IRQ1 */
   93         0,      /* Advanced Interrupt Controller IRQ2 */
   94 };
   95 
   96 #define DEVICE(_name, _id, _unit)               \
   97         {                                       \
   98                 _name, _unit,                   \
   99                 AT91SAM9260_ ## _id ##_BASE,    \
  100                 AT91SAM9260_ ## _id ## _SIZE,   \
  101                 AT91SAM9260_IRQ_ ## _id         \
  102         }
  103 
  104 static const struct cpu_devs at91_devs[] =
  105 {
  106         DEVICE("at91_pmc", PMC,  0),
  107         DEVICE("at91_wdt", WDT,  0),
  108         DEVICE("at91_rst", RSTC, 0),
  109         DEVICE("at91_pit", PIT,  0),
  110         DEVICE("at91_pio", PIOA, 0),
  111         DEVICE("at91_pio", PIOB, 1),
  112         DEVICE("at91_pio", PIOC, 2),
  113         DEVICE("at91_twi", TWI, 0),
  114         DEVICE("at91_mci", MCI, 0),
  115         DEVICE("uart", DBGU,   0),
  116         DEVICE("uart", USART0, 1),
  117         DEVICE("uart", USART1, 2),
  118         DEVICE("uart", USART2, 3),
  119         DEVICE("uart", USART3, 4),
  120         DEVICE("uart", USART4, 5),
  121         DEVICE("uart", USART5, 6),
  122         DEVICE("spi",  SPI0,   0),
  123         DEVICE("spi",  SPI1,   1),
  124         DEVICE("ate",  EMAC,   0),
  125         DEVICE("macb", EMAC,   0),
  126         DEVICE("nand", NAND,   0),
  127         DEVICE("ohci", OHCI,   0),
  128         { 0, 0, 0, 0, 0 }
  129 };
  130 
  131 static void
  132 at91_add_child(device_t dev, int prio, const char *name, int unit,
  133     bus_addr_t addr, bus_size_t size, int irq0, int irq1, int irq2)
  134 {
  135         device_t kid;
  136         struct at91_ivar *ivar;
  137 
  138         kid = device_add_child_ordered(dev, prio, name, unit);
  139         if (kid == NULL) {
  140             printf("Can't add child %s%d ordered\n", name, unit);
  141             return;
  142         }
  143         ivar = malloc(sizeof(*ivar), M_DEVBUF, M_NOWAIT | M_ZERO);
  144         if (ivar == NULL) {
  145                 device_delete_child(dev, kid);
  146                 printf("Can't add alloc ivar\n");
  147                 return;
  148         }
  149         device_set_ivars(kid, ivar);
  150         resource_list_init(&ivar->resources);
  151         if (irq0 != -1) {
  152                 bus_set_resource(kid, SYS_RES_IRQ, 0, irq0, 1);
  153                 if (irq0 != AT91SAM9260_IRQ_SYSTEM)
  154                         at91_pmc_clock_add(device_get_nameunit(kid), irq0, 0);
  155         }
  156         if (irq1 != 0)
  157                 bus_set_resource(kid, SYS_RES_IRQ, 1, irq1, 1);
  158         if (irq2 != 0)
  159                 bus_set_resource(kid, SYS_RES_IRQ, 2, irq2, 1);
  160         if (addr != 0 && addr < AT91SAM9260_BASE) 
  161                 addr += AT91SAM9260_BASE;
  162         if (addr != 0)
  163                 bus_set_resource(kid, SYS_RES_MEMORY, 0, addr, size);
  164 }
  165 
  166 static void
  167 at91_cpu_add_builtin_children(device_t dev)
  168 {
  169         int i;
  170         const struct cpu_devs *walker;
  171 
  172         for (i = 1, walker = at91_devs; walker->name; i++, walker++) {
  173                 at91_add_child(dev, i, walker->name, walker->unit,
  174                     walker->mem_base, walker->mem_len, walker->irq0,
  175                     walker->irq1, walker->irq2);
  176         }
  177 }
  178 
  179 static uint32_t
  180 at91_pll_outa(int freq)
  181 {
  182 
  183         if (freq > 195000000)
  184                 return (0x20000000);
  185         else 
  186                 return (0x20008000);
  187 }
  188 
  189 static uint32_t
  190 at91_pll_outb(int freq)
  191 {
  192         return (0x4000);
  193 }
  194 
  195 static void
  196 at91_identify(driver_t *drv, device_t parent)
  197 {
  198 
  199         if (at91_cpu_is(AT91_CPU_SAM9260)) {
  200                 at91_add_child(parent, 0, "at91sam9260", 0, 0, 0, -1, 0, 0);
  201                 at91_cpu_add_builtin_children(parent);
  202         }
  203 }
  204 
  205 static int
  206 at91_probe(device_t dev)
  207 {
  208 
  209         if (at91_cpu_is(AT91_CPU_SAM9260)) {
  210                 device_set_desc(dev, "AT91SAM9260");
  211                 return (0);
  212         }
  213         return (ENXIO);
  214 }
  215 
  216 static int
  217 at91_attach(device_t dev)
  218 {
  219         struct at91_pmc_clock *clk;
  220         struct at91sam9_softc *sc = device_get_softc(dev);
  221         int i;
  222 
  223         struct at91_softc *at91sc = device_get_softc(device_get_parent(dev));
  224 
  225         sc->sc_st = at91sc->sc_st;
  226         sc->sc_sh = at91sc->sc_sh;
  227         sc->dev = dev;
  228 
  229         /* 
  230          * XXX These values work for the RM9200, SAM926[01], and SAM9260
  231          * will have to fix this when we want to support anything else. XXX
  232          */
  233         if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91SAM9260_SYS_BASE,
  234             AT91SAM9260_SYS_SIZE, &sc->sc_sys_sh) != 0)
  235                 panic("Enable to map system registers");
  236 
  237         if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91SAM9260_DBGU_BASE,
  238             AT91SAM9260_DBGU_SIZE, &sc->sc_dbg_sh) != 0)
  239                 panic("Enable to map DBGU registers");
  240 
  241         if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91SAM9260_AIC_BASE,
  242             AT91SAM9260_AIC_SIZE, &sc->sc_aic_sh) != 0)
  243                 panic("Enable to map system registers");
  244 
  245         /* XXX Hack to tell atmelarm about the AIC */
  246         at91sc->sc_aic_sh = sc->sc_aic_sh;
  247         at91sc->sc_irq_system = AT91SAM9260_IRQ_SYSTEM;
  248 
  249         for (i = 0; i < 32; i++) {
  250                 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SVR + 
  251                     i * 4, i);
  252                 /* Priority. */
  253                 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SMR + i * 4,
  254                     at91_irq_prio[i]);
  255                 if (i < 8)
  256                         bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_EOICR,
  257                             1);
  258         }
  259 
  260         bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SPU, 32);
  261         /* No debug. */
  262         bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_DCR, 0);
  263         /* Disable and clear all interrupts. */
  264         bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_IDCR, 0xffffffff);
  265         bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_ICCR, 0xffffffff);
  266 
  267         /* Disable all interrupts for DBGU */
  268         bus_space_write_4(sc->sc_st, sc->sc_dbg_sh, 0x0c, 0xffffffff);
  269 
  270         if (bus_space_subregion(sc->sc_st, sc->sc_sh,
  271             AT91SAM9260_MATRIX_BASE, AT91SAM9260_MATRIX_SIZE,
  272             &sc->sc_matrix_sh) != 0)
  273                 panic("Enable to map matrix registers");
  274 
  275         /* activate NAND*/
  276         i = bus_space_read_4(sc->sc_st, sc->sc_matrix_sh,
  277             AT91SAM9260_EBICSA);
  278         bus_space_write_4(sc->sc_st, sc->sc_matrix_sh,
  279             AT91SAM9260_EBICSA, 
  280             i | AT91_MATRIX_EBI_CS3A_SMC_SMARTMEDIA);
  281 
  282 
  283         /* Update USB device port clock info */
  284         clk = at91_pmc_clock_ref("udpck");
  285         clk->pmc_mask  = PMC_SCER_UDP_SAM9;
  286         at91_pmc_clock_deref(clk);
  287 
  288         /* Update USB host port clock info */
  289         clk = at91_pmc_clock_ref("uhpck");
  290         clk->pmc_mask  = PMC_SCER_UHP_SAM9;
  291         at91_pmc_clock_deref(clk);
  292 
  293         /* Each SOC has different PLL contraints */
  294         clk = at91_pmc_clock_ref("plla");
  295         clk->pll_min_in    = SAM9260_PLL_A_MIN_IN_FREQ;         /*   1 MHz */
  296         clk->pll_max_in    = SAM9260_PLL_A_MAX_IN_FREQ;         /*  32 MHz */
  297         clk->pll_min_out   = SAM9260_PLL_A_MIN_OUT_FREQ;        /*  80 MHz */
  298         clk->pll_max_out   = SAM9260_PLL_A_MAX_OUT_FREQ;        /* 240 MHz */
  299         clk->pll_mul_shift = SAM9260_PLL_A_MUL_SHIFT;
  300         clk->pll_mul_mask  = SAM9260_PLL_A_MUL_MASK;
  301         clk->pll_div_shift = SAM9260_PLL_A_DIV_SHIFT;
  302         clk->pll_div_mask  = SAM9260_PLL_A_DIV_MASK;
  303         clk->set_outb      = at91_pll_outa;
  304         at91_pmc_clock_deref(clk);
  305 
  306         /*
  307          * Fudge MAX pll in frequence down below 3.0 Mhz to ensure 
  308          * PMC alogrithm choose the divisor that causes the input clock 
  309          * to be near the optimal 2 Mhz per datasheet. We know
  310          * we are going to be using this for the USB clock at 96 Mhz.
  311          * Causes no extra frequency deviation for all recomended crystal values.
  312          */
  313         clk = at91_pmc_clock_ref("pllb");
  314         clk->pll_min_in    = SAM9260_PLL_B_MIN_IN_FREQ;         /*   1 MHz */
  315         clk->pll_max_in    = SAM9260_PLL_B_MAX_IN_FREQ;         /*   5 MHz */
  316         clk->pll_max_in    = 2999999;                           /*  ~3 MHz */
  317         clk->pll_min_out   = SAM9260_PLL_B_MIN_OUT_FREQ;        /*  70 MHz */
  318         clk->pll_max_out   = SAM9260_PLL_B_MAX_OUT_FREQ;        /* 130 MHz */
  319         clk->pll_mul_shift = SAM9260_PLL_B_MUL_SHIFT;
  320         clk->pll_mul_mask  = SAM9260_PLL_B_MUL_MASK;
  321         clk->pll_div_shift = SAM9260_PLL_B_DIV_SHIFT;
  322         clk->pll_div_mask  = SAM9260_PLL_B_DIV_MASK;
  323         clk->set_outb      = at91_pll_outb;
  324         at91_pmc_clock_deref(clk);
  325         return (0);
  326 }
  327 
  328 static device_method_t at91sam9260_methods[] = {
  329         DEVMETHOD(device_probe, at91_probe),
  330         DEVMETHOD(device_attach, at91_attach),
  331         DEVMETHOD(device_identify, at91_identify),
  332         {0, 0},
  333 };
  334 
  335 static driver_t at91sam9260_driver = {
  336         "at91sam9260",
  337         at91sam9260_methods,
  338         sizeof(struct at91sam9_softc),
  339 };
  340 
  341 static devclass_t at91sam9260_devclass;
  342 
  343 DRIVER_MODULE(at91sam9260, atmelarm, at91sam9260_driver, at91sam9260_devclass, 0, 0);

Cache object: fbc02d33657d079c7ee62911ca857ed3


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