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/at91_pmc.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) 2006 M. Warner Losh.  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 "opt_platform.h"
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD$");
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/kernel.h>
   35 #include <sys/malloc.h>
   36 #include <sys/module.h>
   37 #include <sys/time.h>
   38 #include <sys/bus.h>
   39 #include <sys/resource.h>
   40 #include <sys/rman.h>
   41 #include <sys/timetc.h>
   42 
   43 #include <machine/bus.h>
   44 #include <machine/cpu.h>
   45 #include <machine/cpufunc.h>
   46 #include <machine/resource.h>
   47 #include <machine/intr.h>
   48 #include <arm/at91/at91reg.h>
   49 #include <arm/at91/at91var.h>
   50 
   51 #include <arm/at91/at91_pmcreg.h>
   52 #include <arm/at91/at91_pmcvar.h>
   53 
   54 #ifdef FDT
   55 #include <dev/fdt/fdt_common.h>
   56 #include <dev/ofw/ofw_bus.h>
   57 #include <dev/ofw/ofw_bus_subr.h>
   58 #endif
   59 
   60 static struct at91_pmc_softc {
   61         bus_space_tag_t         sc_st;
   62         bus_space_handle_t      sc_sh;
   63         struct resource *mem_res;       /* Memory resource */
   64         device_t                dev;
   65 } *pmc_softc;
   66 
   67 static uint32_t pllb_init;
   68 
   69 MALLOC_DECLARE(M_PMC);
   70 MALLOC_DEFINE(M_PMC, "at91_pmc_clocks", "AT91 PMC Clock descriptors");
   71 
   72 #define AT91_PMC_BASE 0xffffc00
   73 
   74 static void at91_pmc_set_pllb_mode(struct at91_pmc_clock *, int);
   75 static void at91_pmc_set_upll_mode(struct at91_pmc_clock *, int);
   76 static void at91_pmc_set_sys_mode(struct at91_pmc_clock *, int);
   77 static void at91_pmc_set_periph_mode(struct at91_pmc_clock *, int);
   78 static void at91_pmc_clock_alias(const char *name, const char *alias);
   79 
   80 static struct at91_pmc_clock slck = {
   81         .name = "slck",         /* 32,768 Hz slow clock */
   82         .hz = 32768,
   83         .refcnt = 1,
   84         .id = 0,
   85         .primary = 1,
   86 };
   87 
   88 /*
   89  * NOTE: Clocks for "ordinary peripheral" devices e.g. spi0, udp0, uhp0 etc.
   90  * are now created automatically. Only "system" clocks need be defined here.
   91  */
   92 static struct at91_pmc_clock main_ck = {
   93         .name = "main",         /* Main clock */
   94         .refcnt = 0,
   95         .id = 1,
   96         .primary = 1,
   97         .pmc_mask = PMC_IER_MOSCS,
   98 };
   99 
  100 static struct at91_pmc_clock plla = {
  101         .name = "plla",         /* PLLA Clock, used for CPU clocking */
  102         .parent = &main_ck,
  103         .refcnt = 1,
  104         .id = 0,
  105         .primary = 1,
  106         .pll = 1,
  107         .pmc_mask = PMC_IER_LOCKA,
  108 };
  109 
  110 static struct at91_pmc_clock pllb = {
  111         .name = "pllb",         /* PLLB Clock, used for USB functions */
  112         .parent = &main_ck,
  113         .refcnt = 0,
  114         .id = 0,
  115         .primary = 1,
  116         .pll = 1,
  117         .pmc_mask = PMC_IER_LOCKB,
  118         .set_mode = &at91_pmc_set_pllb_mode,
  119 };
  120 
  121 /* Used by USB on at91sam9g45 */
  122 static struct at91_pmc_clock upll = {
  123         .name = "upll",         /* UTMI PLL, used for USB functions on 9G45 family */
  124         .parent = &main_ck,
  125         .refcnt = 0,
  126         .id = 0,
  127         .primary = 1,
  128         .pll = 1,
  129         .pmc_mask = (1 << 6),
  130         .set_mode = &at91_pmc_set_upll_mode,
  131 };
  132 
  133 static struct at91_pmc_clock udpck = {
  134         .name = "udpck",
  135         .parent = &pllb,
  136         .pmc_mask = PMC_SCER_UDP,
  137         .set_mode = at91_pmc_set_sys_mode
  138 };
  139 
  140 static struct at91_pmc_clock uhpck = {
  141         .name = "uhpck",
  142         .parent = &pllb,
  143         .pmc_mask = PMC_SCER_UHP,
  144         .set_mode = at91_pmc_set_sys_mode
  145 };
  146 
  147 static struct at91_pmc_clock mck = {
  148         .name = "mck",          /* Master (Peripheral) Clock */
  149         .pmc_mask = PMC_IER_MCKRDY,
  150         .refcnt = 0,
  151 };
  152 
  153 static struct at91_pmc_clock cpu = {
  154         .name = "cpu",          /* CPU Clock */
  155         .parent = &plla,
  156         .pmc_mask = PMC_SCER_PCK,
  157         .refcnt = 0,
  158 };
  159 
  160 /* "+32" or the automatic peripheral clocks */
  161 static struct at91_pmc_clock *clock_list[16+32] = {
  162         &slck,
  163         &main_ck,
  164         &plla,
  165         &pllb,
  166         &upll,
  167         &udpck,
  168         &uhpck,
  169         &mck,
  170         &cpu
  171 };
  172 
  173 static inline uint32_t
  174 RD4(struct at91_pmc_softc *sc, bus_size_t off)
  175 {
  176 
  177         if (sc == NULL) {
  178                 uint32_t *p = (uint32_t *)(AT91_BASE + AT91_PMC_BASE + off);
  179 
  180                 return *p;
  181         }
  182         return (bus_read_4(sc->mem_res, off));
  183 }
  184 
  185 static inline void
  186 WR4(struct at91_pmc_softc *sc, bus_size_t off, uint32_t val)
  187 {
  188 
  189         if (sc == NULL) {
  190                 uint32_t *p = (uint32_t *)(AT91_BASE + AT91_PMC_BASE + off);
  191 
  192                 *p = val;
  193         } else
  194                 bus_write_4(sc->mem_res, off, val);
  195 }
  196 
  197 /*
  198  * The following is unused currently since we don't ever set the PLLA
  199  * frequency of the device.  If we did, we'd have to also pay attention
  200  * to the ICPLLA bit in the PMC_PLLICPR register for frequencies lower
  201  * than ~600MHz, which the PMC code doesn't do right now.
  202  */
  203 uint32_t
  204 at91_pmc_800mhz_plla_outb(int freq)
  205 {
  206         uint32_t outa;
  207 
  208         /*
  209          * Set OUTA, per the data sheet.  See Table 46-16 titled
  210          * PLLA Frequency Regarding ICPLLA and OUTA in the SAM9X25 doc,
  211          * Table 46-17 in the SAM9G20 doc, or Table 46-16 in the SAM9G45 doc.
  212          * Note: the frequencies overlap by 5MHz, so we add 3 here to
  213          * center shoot the transition.
  214          */
  215 
  216         freq /= 1000000;                /* MHz */
  217         if (freq >= 800)
  218                 freq = 800;
  219         freq += 3;                      /* Allow for overlap. */
  220         outa = 3 - ((freq / 50) & 3);   /* 750 / 50 = 7, see table */
  221         return (1 << 29)| (outa << 14);
  222 }
  223 
  224 uint32_t
  225 at91_pmc_800mhz_pllb_outb(int freq)
  226 {
  227 
  228         return (0);
  229 }
  230 
  231 void
  232 at91_pmc_set_pllb_mode(struct at91_pmc_clock *clk, int on)
  233 {
  234         struct at91_pmc_softc *sc = pmc_softc;
  235         uint32_t value;
  236 
  237         value = on ? pllb_init : 0;
  238 
  239         /*
  240          * Only write to the register if the value is changing.  Besides being
  241          * good common sense, this works around RM9200 Errata #26 (CKGR_PLL[AB]R
  242          * must not be written with the same value currently in the register).
  243          */
  244         if (RD4(sc, CKGR_PLLBR) != value) {
  245                 WR4(sc, CKGR_PLLBR, value);
  246                 while (on && (RD4(sc, PMC_SR) & PMC_IER_LOCKB) != PMC_IER_LOCKB)
  247                         continue;
  248         }
  249 }
  250 
  251 static void
  252 at91_pmc_set_upll_mode(struct at91_pmc_clock *clk, int on)
  253 {
  254         struct at91_pmc_softc *sc = pmc_softc;
  255         uint32_t value;
  256 
  257         if (on) {
  258                 on = PMC_IER_LOCKU;
  259                 value = CKGR_UCKR_UPLLEN | CKGR_UCKR_BIASEN;
  260         } else
  261                 value = 0;
  262 
  263         WR4(sc, CKGR_UCKR, RD4(sc, CKGR_UCKR) | value);
  264         while ((RD4(sc, PMC_SR) & PMC_IER_LOCKU) != on)
  265                 continue;
  266 
  267         WR4(sc, PMC_USB, PMC_USB_USBDIV(9) | PMC_USB_USBS);
  268         WR4(sc, PMC_SCER, PMC_SCER_UHP_SAM9);
  269 }
  270 
  271 static void
  272 at91_pmc_set_sys_mode(struct at91_pmc_clock *clk, int on)
  273 {
  274         struct at91_pmc_softc *sc = pmc_softc;
  275 
  276         WR4(sc, on ? PMC_SCER : PMC_SCDR, clk->pmc_mask);
  277         if (on)
  278                 while ((RD4(sc, PMC_SCSR) & clk->pmc_mask) != clk->pmc_mask)
  279                         continue;
  280         else
  281                 while ((RD4(sc, PMC_SCSR) & clk->pmc_mask) == clk->pmc_mask)
  282                         continue;
  283 }
  284 
  285 static void
  286 at91_pmc_set_periph_mode(struct at91_pmc_clock *clk, int on)
  287 {
  288         struct at91_pmc_softc *sc = pmc_softc;
  289 
  290         WR4(sc, on ? PMC_PCER : PMC_PCDR, clk->pmc_mask);
  291         if (on)
  292                 while ((RD4(sc, PMC_PCSR) & clk->pmc_mask) != clk->pmc_mask)
  293                         continue;
  294         else
  295                 while ((RD4(sc, PMC_PCSR) & clk->pmc_mask) == clk->pmc_mask)
  296                         continue;
  297 }
  298 
  299 struct at91_pmc_clock *
  300 at91_pmc_clock_add(const char *name, uint32_t irq,
  301     struct at91_pmc_clock *parent)
  302 {
  303         struct at91_pmc_clock *clk;
  304         int i, buflen;
  305 
  306         clk = malloc(sizeof(*clk), M_PMC, M_NOWAIT | M_ZERO);
  307         if (clk == NULL)
  308                 goto err;
  309 
  310         buflen = strlen(name) + 1;
  311         clk->name = malloc(buflen, M_PMC, M_NOWAIT);
  312         if (clk->name == NULL)
  313                 goto err;
  314 
  315         strlcpy(clk->name, name, buflen);
  316         clk->pmc_mask = 1 << irq;
  317         clk->set_mode = &at91_pmc_set_periph_mode;
  318         if (parent == NULL)
  319                 clk->parent = &mck;
  320         else
  321                 clk->parent = parent;
  322 
  323         for (i = 0; i < sizeof(clock_list) / sizeof(clock_list[0]); i++) {
  324                 if (clock_list[i] == NULL) {
  325                         clock_list[i] = clk;
  326                         return (clk);
  327                 }
  328         }
  329 err:
  330         if (clk != NULL) {
  331                 if (clk->name != NULL)
  332                         free(clk->name, M_PMC);
  333                 free(clk, M_PMC);
  334         }
  335 
  336         panic("could not allocate pmc clock '%s'", name);
  337         return (NULL);
  338 }
  339 
  340 static void
  341 at91_pmc_clock_alias(const char *name, const char *alias)
  342 {
  343         struct at91_pmc_clock *clk, *alias_clk;
  344 
  345         clk = at91_pmc_clock_ref(name);
  346         if (clk)
  347                 alias_clk = at91_pmc_clock_add(alias, 0, clk->parent);
  348 
  349         if (clk && alias_clk) {
  350                 alias_clk->hz = clk->hz;
  351                 alias_clk->pmc_mask = clk->pmc_mask;
  352                 alias_clk->set_mode = clk->set_mode;
  353         }
  354 }
  355 
  356 struct at91_pmc_clock *
  357 at91_pmc_clock_ref(const char *name)
  358 {
  359         int i;
  360 
  361         for (i = 0; i < sizeof(clock_list) / sizeof(clock_list[0]); i++) {
  362                 if (clock_list[i] == NULL)
  363                     break;
  364                 if (strcmp(name, clock_list[i]->name) == 0)
  365                         return (clock_list[i]);
  366         }
  367 
  368         return (NULL);
  369 }
  370 
  371 void
  372 at91_pmc_clock_deref(struct at91_pmc_clock *clk)
  373 {
  374         if (clk == NULL)
  375                 return;
  376 }
  377 
  378 void
  379 at91_pmc_clock_enable(struct at91_pmc_clock *clk)
  380 {
  381         if (clk == NULL)
  382                 return;
  383 
  384         /* XXX LOCKING? XXX */
  385         if (clk->parent)
  386                 at91_pmc_clock_enable(clk->parent);
  387         if (clk->refcnt++ == 0 && clk->set_mode)
  388                 clk->set_mode(clk, 1);
  389 }
  390 
  391 void
  392 at91_pmc_clock_disable(struct at91_pmc_clock *clk)
  393 {
  394         if (clk == NULL)
  395                 return;
  396 
  397         /* XXX LOCKING? XXX */
  398         if (--clk->refcnt == 0 && clk->set_mode)
  399                 clk->set_mode(clk, 0);
  400         if (clk->parent)
  401                 at91_pmc_clock_disable(clk->parent);
  402 }
  403 
  404 static int
  405 at91_pmc_pll_rate(struct at91_pmc_clock *clk, uint32_t reg)
  406 {
  407         uint32_t mul, div, freq;
  408 
  409         freq = clk->parent->hz;
  410         div = (reg >> clk->pll_div_shift) & clk->pll_div_mask;
  411         mul = (reg >> clk->pll_mul_shift) & clk->pll_mul_mask;
  412 
  413 #if 0
  414         printf("pll = (%d /  %d) * %d = %d\n",
  415             freq, div, mul + 1, (freq/div) * (mul+1));
  416 #endif
  417 
  418         if (div != 0 && mul != 0) {
  419                 freq /= div;
  420                 freq *= mul + 1;
  421         } else
  422                 freq = 0;
  423         clk->hz = freq;
  424 
  425         return (freq);
  426 }
  427 
  428 static uint32_t
  429 at91_pmc_pll_calc(struct at91_pmc_clock *clk, uint32_t out_freq)
  430 {
  431         uint32_t i, div = 0, mul = 0, diff = 1 << 30;
  432 
  433         unsigned ret = 0x3e00;
  434 
  435         if (out_freq > clk->pll_max_out)
  436                 goto fail;
  437 
  438         for (i = 1; i < 256; i++) {
  439                 int32_t diff1;
  440                 uint32_t input, mul1;
  441 
  442                 input = clk->parent->hz / i;
  443                 if (input < clk->pll_min_in)
  444                         break;
  445                 if (input > clk->pll_max_in)
  446                         continue;
  447 
  448                 mul1 = out_freq / input;
  449                 if (mul1 > (clk->pll_mul_mask + 1))
  450                         continue;
  451                 if (mul1 == 0)
  452                         break;
  453 
  454                 diff1 = out_freq - input * mul1;
  455                 if (diff1 < 0)
  456                         diff1 = -diff1;
  457                 if (diff > diff1) {
  458                         diff = diff1;
  459                         div = i;
  460                         mul = mul1;
  461                         if (diff == 0)
  462                                 break;
  463                 }
  464         }
  465         if (diff > (out_freq >> PMC_PLL_SHIFT_TOL))
  466                 goto fail;
  467 
  468         if (clk->set_outb != NULL)
  469                 ret |= clk->set_outb(out_freq);
  470 
  471         return (ret |
  472                 ((mul - 1) << clk->pll_mul_shift) |
  473                 (div << clk->pll_div_shift));
  474 fail:
  475         return (0);
  476 }
  477 
  478 #if !defined(AT91C_MAIN_CLOCK)
  479 static const unsigned int at91_main_clock_tbl[] = {
  480         3000000, 3276800, 3686400, 3840000, 4000000,
  481         4433619, 4915200, 5000000, 5242880, 6000000,
  482         6144000, 6400000, 6553600, 7159090, 7372800,
  483         7864320, 8000000, 9830400, 10000000, 11059200,
  484         12000000, 12288000, 13560000, 14318180, 14745600,
  485         16000000, 17344700, 18432000, 20000000
  486 };
  487 #define MAIN_CLOCK_TBL_LEN      (sizeof(at91_main_clock_tbl) / sizeof(*at91_main_clock_tbl))
  488 #endif
  489 
  490 static unsigned int
  491 at91_pmc_sense_main_clock(void)
  492 {
  493 #if !defined(AT91C_MAIN_CLOCK)
  494         unsigned int ckgr_val;
  495         unsigned int diff, matchdiff, freq;
  496         int i;
  497 
  498         ckgr_val = (RD4(NULL, CKGR_MCFR) & CKGR_MCFR_MAINF_MASK) << 11;
  499 
  500         /*
  501          * Clocks up to 50MHz can be connected to some models.  If
  502          * the frequency is >= 21MHz, assume that the slow clock can
  503          * measure it correctly, and that any error can be adequately
  504          * compensated for by roudning to the nearest 500Hz.  Users
  505          * with fast, or odd-ball clocks will need to set
  506          * AT91C_MAIN_CLOCK in the kernel config file.
  507          */
  508         if (ckgr_val >= 21000000)
  509                 return ((ckgr_val + 250) / 500 * 500);
  510 
  511         /*
  512          * Try to find the standard frequency that match best.
  513          */
  514         freq = at91_main_clock_tbl[0];
  515         matchdiff = abs(ckgr_val - at91_main_clock_tbl[0]);
  516         for (i = 1; i < MAIN_CLOCK_TBL_LEN; i++) {
  517                 diff = abs(ckgr_val - at91_main_clock_tbl[i]);
  518                 if (diff < matchdiff) {
  519                         freq = at91_main_clock_tbl[i];
  520                         matchdiff = diff;
  521                 }
  522         }
  523         return (freq);
  524 #else
  525         return (AT91C_MAIN_CLOCK);
  526 #endif
  527 }
  528 
  529 void
  530 at91_pmc_init_clock(void)
  531 {
  532         struct at91_pmc_softc *sc = NULL;
  533         unsigned int main_clock;
  534         uint32_t mckr;
  535         uint32_t mdiv;
  536 
  537         soc_info.soc_data->soc_clock_init();
  538 
  539         main_clock = at91_pmc_sense_main_clock();
  540 
  541         if (at91_is_sam9() || at91_is_sam9xe()) {
  542                 uhpck.pmc_mask = PMC_SCER_UHP_SAM9;
  543                 udpck.pmc_mask = PMC_SCER_UDP_SAM9;
  544         }
  545 
  546         /* There is no pllb on AT91SAM9G45 */
  547         if (at91_cpu_is(AT91_T_SAM9G45)) {
  548                 uhpck.parent = &upll;
  549                 uhpck.pmc_mask = PMC_SCER_UHP_SAM9;
  550         }
  551 
  552         mckr = RD4(sc, PMC_MCKR);
  553         main_ck.hz = main_clock;
  554 
  555         /*
  556          * Note: this means outa calc code for plla never used since
  557          * we never change it.  If we did, we'd also have to mind
  558          * ICPLLA to get the charge pump current right.
  559          */
  560         at91_pmc_pll_rate(&plla, RD4(sc, CKGR_PLLAR));
  561 
  562         if (at91_cpu_is(AT91_T_SAM9G45) && (mckr & PMC_MCKR_PLLADIV2))
  563                 plla.hz /= 2;
  564 
  565         /*
  566          * Initialize the usb clock.  This sets up pllb, but disables the
  567          * actual clock. XXX except for the if 0 :(
  568          */
  569         if (!at91_cpu_is(AT91_T_SAM9G45)) {
  570                 pllb_init = at91_pmc_pll_calc(&pllb, 48000000 * 2) | 0x10000000;
  571                 at91_pmc_pll_rate(&pllb, pllb_init);
  572 #if 0
  573                 /* Turn off USB clocks */
  574                 at91_pmc_set_periph_mode(&ohci_clk, 0);
  575                 at91_pmc_set_periph_mode(&udc_clk, 0);
  576 #endif
  577         }
  578 
  579         if (at91_is_rm92()) {
  580                 WR4(sc, PMC_SCDR, PMC_SCER_UHP | PMC_SCER_UDP);
  581                 WR4(sc, PMC_SCER, PMC_SCER_MCKUDP);
  582         } else
  583                 WR4(sc, PMC_SCDR, PMC_SCER_UHP_SAM9 | PMC_SCER_UDP_SAM9);
  584 
  585         /*
  586          * MCK and PCU derive from one of the primary clocks.  Initialize
  587          * this relationship.
  588          */
  589         mck.parent = clock_list[mckr & 0x3];
  590         mck.parent->refcnt++;
  591 
  592         cpu.hz = mck.hz = mck.parent->hz /
  593             (1 << ((mckr & PMC_MCKR_PRES_MASK) >> 2));
  594 
  595         mdiv = (mckr & PMC_MCKR_MDIV_MASK) >> 8;
  596         if (at91_is_sam9() || at91_is_sam9xe()) {
  597                 /*
  598                  * On AT91SAM9G45 when mdiv == 3 we need to divide
  599                  * MCK by 3 but not, for example, on 9g20.
  600                  */
  601                 if (!at91_cpu_is(AT91_T_SAM9G45) || mdiv <= 2)
  602                         mdiv *= 2;
  603                 if (mdiv > 0)
  604                         mck.hz /= mdiv;
  605         } else
  606                 mck.hz /= (1 + mdiv);
  607 
  608         /* Only found on SAM9G20 */
  609         if (at91_cpu_is(AT91_T_SAM9G20))
  610                 cpu.hz /= (mckr & PMC_MCKR_PDIV) ?  2 : 1;
  611 
  612         at91_master_clock = mck.hz;
  613 
  614         /* These clocks refrenced by "special" names */
  615         at91_pmc_clock_alias("ohci0", "ohci_clk");
  616         at91_pmc_clock_alias("udp0",  "udp_clk");
  617 
  618         /* Turn off "Progamable" clocks */
  619         WR4(sc, PMC_SCDR, PMC_SCER_PCK0 | PMC_SCER_PCK1 | PMC_SCER_PCK2 |
  620             PMC_SCER_PCK3);
  621 
  622         /* XXX kludge, turn on all peripherals */
  623         WR4(sc, PMC_PCER, 0xffffffff);
  624 
  625         /* Disable all interrupts for PMC */
  626         WR4(sc, PMC_IDR, 0xffffffff);
  627 }
  628 
  629 static void
  630 at91_pmc_deactivate(device_t dev)
  631 {
  632         struct at91_pmc_softc *sc;
  633 
  634         sc = device_get_softc(dev);
  635         bus_generic_detach(sc->dev);
  636         if (sc->mem_res)
  637                 bus_release_resource(dev, SYS_RES_IOPORT,
  638                     rman_get_rid(sc->mem_res), sc->mem_res);
  639         sc->mem_res = 0;
  640 }
  641 
  642 static int
  643 at91_pmc_activate(device_t dev)
  644 {
  645         struct at91_pmc_softc *sc;
  646         int rid;
  647 
  648         sc = device_get_softc(dev);
  649         rid = 0;
  650         sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
  651             RF_ACTIVE);
  652         if (sc->mem_res == NULL)
  653                 goto errout;
  654         return (0);
  655 errout:
  656         at91_pmc_deactivate(dev);
  657         return (ENOMEM);
  658 }
  659 
  660 static int
  661 at91_pmc_probe(device_t dev)
  662 {
  663 #ifdef FDT
  664         if (!ofw_bus_is_compatible(dev, "atmel,at91rm9200-pmc"))
  665                 return (ENXIO);
  666 #endif
  667         device_set_desc(dev, "PMC");
  668         return (0);
  669 }
  670 
  671 static int
  672 at91_pmc_attach(device_t dev)
  673 {
  674         int err;
  675 
  676         pmc_softc = device_get_softc(dev);
  677         pmc_softc->dev = dev;
  678         if ((err = at91_pmc_activate(dev)) != 0)
  679                 return (err);
  680 
  681         /*
  682          * Configure main clock frequency.
  683          */
  684         at91_pmc_init_clock();
  685 
  686         /*
  687          * Display info about clocks previously computed
  688          */
  689         device_printf(dev,
  690             "Primary: %d Hz PLLA: %d MHz CPU: %d MHz MCK: %d MHz\n",
  691             main_ck.hz,
  692             plla.hz / 1000000,
  693             cpu.hz / 1000000, mck.hz / 1000000);
  694 
  695         return (0);
  696 }
  697 
  698 static device_method_t at91_pmc_methods[] = {
  699         DEVMETHOD(device_probe, at91_pmc_probe),
  700         DEVMETHOD(device_attach, at91_pmc_attach),
  701         DEVMETHOD_END
  702 };
  703 
  704 static driver_t at91_pmc_driver = {
  705         "at91_pmc",
  706         at91_pmc_methods,
  707         sizeof(struct at91_pmc_softc),
  708 };
  709 static devclass_t at91_pmc_devclass;
  710 
  711 #ifdef FDT
  712 DRIVER_MODULE(at91_pmc, simplebus, at91_pmc_driver, at91_pmc_devclass, NULL,
  713     NULL);
  714 #else
  715 DRIVER_MODULE(at91_pmc, atmelarm, at91_pmc_driver, at91_pmc_devclass, NULL,
  716     NULL);
  717 #endif

Cache object: b8833a21a61e58a32b166b557f191a8c


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