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/ti/omap4/omap4_prcm_clks.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  * SPDX-License-Identifier: BSD-3-Clause
    3  *
    4  * Copyright (c) 2011
    5  *      Ben Gray <ben.r.gray@gmail.com>.
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. The name of the company nor the name of the author may be used to
   17  *    endorse or promote products derived from this software without specific
   18  *    prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``AS IS'' AND ANY EXPRESS OR
   21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   23  * IN NO EVENT SHALL BEN GRAY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
   26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __FBSDID("$FreeBSD$");
   34 
   35 #include <sys/param.h>
   36 #include <sys/systm.h>
   37 #include <sys/kernel.h>
   38 #include <sys/module.h>
   39 #include <sys/bus.h>
   40 #include <sys/resource.h>
   41 #include <sys/rman.h>
   42 #include <sys/lock.h>
   43 #include <sys/malloc.h>
   44 
   45 #include <machine/bus.h>
   46 #include <machine/resource.h>
   47 #include <machine/intr.h>
   48 
   49 #include <arm/arm/mpcore_timervar.h>
   50 #include <arm/ti/tivar.h>
   51 #include <arm/ti/ti_prcm.h>
   52 #include <arm/ti/omap4/omap4_reg.h>
   53 
   54 #include <dev/ofw/openfirm.h>
   55 #include <dev/ofw/ofw_bus.h>
   56 #include <dev/ofw/ofw_bus_subr.h>
   57 
   58 /*
   59  *      This file defines the clock configuration for the OMAP4xxx series of
   60  *      devices.
   61  *
   62  *      How This is Suppose to Work
   63  *      ===========================
   64  *      - There is a top level omap_prcm module that defines all OMAP SoC drivers
   65  *      should use to enable/disable the system clocks regardless of the version
   66  *      of OMAP device they are running on.  This top level PRCM module is just
   67  *      a thin shim to chip specific functions that perform the donkey work of
   68  *      configuring the clock - this file is the 'donkey' for OMAP44xx devices.
   69  *
   70  *      - The key bit in this file is the omap_clk_devmap array, it's
   71  *      used by the omap_prcm driver to determine what clocks are valid and which
   72  *      functions to call to manipulate them.
   73  *
   74  *      - In essence you just need to define some callbacks for each of the
   75  *      clocks and then you're done.
   76  *
   77  *      - The other thing that is worth noting is that when the omap_prcm device
   78  *      is registered you typically pass in some memory ranges which are the
   79  *      SYS_MEMORY resources.  These resources are in turn allocated using 
   80  *      bus_allocate_resources(...) and the resource handles are passed to all
   81  *      individual clock callback handlers. 
   82  *
   83  *
   84  *
   85  *      OMAP4 devices are different from the previous OMAP3 devices in that there
   86  *      is no longer a separate functional and interface clock for each module,
   87  *      instead there is typically an interface clock that spans many modules.
   88  */
   89 
   90 #define FREQ_96MHZ    96000000
   91 #define FREQ_64MHZ    64000000
   92 #define FREQ_48MHZ    48000000
   93 #define FREQ_32KHZ    32000
   94 
   95 #define PRM_INSTANCE    1
   96 #define CM1_INSTANCE    2
   97 #define CM2_INSTANCE    3
   98 
   99 /**
  100  *      Address offsets from the PRM memory region to the top level clock control
  101  *      registers.
  102  */
  103 #define CKGEN_PRM_OFFSET               0x00000100UL
  104 #define MPU_PRM_OFFSET                 0x00000300UL
  105 #define DSP_PRM_OFFSET                 0x00000400UL
  106 #define ABE_PRM_OFFSET                 0x00000500UL
  107 #define ALWAYS_ON_PRM_OFFSET           0x00000600UL
  108 #define CORE_PRM_OFFSET                0x00000700UL
  109 #define IVAHD_PRM_OFFSET               0x00000F00UL
  110 #define CAM_PRM_OFFSET                 0x00001000UL
  111 #define DSS_PRM_OFFSET                 0x00001100UL
  112 #define SGX_PRM_OFFSET                 0x00001200UL
  113 #define L3INIT_PRM_OFFSET              0x00001300UL
  114 #define L4PER_PRM_OFFSET               0x00001400UL
  115 #define WKUP_PRM_OFFSET                0x00001700UL
  116 #define WKUP_CM_OFFSET                 0x00001800UL
  117 #define EMU_PRM_OFFSET                 0x00001900UL
  118 #define EMU_CM_OFFSET                  0x00001A00UL
  119 #define DEVICE_PRM_OFFSET              0x00001B00UL
  120 #define INSTR_PRM_OFFSET               0x00001F00UL
  121 
  122 #define CM_ABE_DSS_SYS_CLKSEL_OFFSET   (CKGEN_PRM_OFFSET + 0x0000UL)
  123 #define CM_L4_WKUP_CLKSELL_OFFSET      (CKGEN_PRM_OFFSET + 0x0008UL)
  124 #define CM_ABE_PLL_REF_CLKSEL_OFFSET   (CKGEN_PRM_OFFSET + 0x000CUL)
  125 #define CM_SYS_CLKSEL_OFFSET           (CKGEN_PRM_OFFSET + 0x0010UL)
  126 
  127 /**
  128  *      Address offsets from the CM1 memory region to the top level clock control
  129  *      registers.
  130  */
  131 #define CKGEN_CM1_OFFSET               0x00000100UL
  132 #define MPU_CM1_OFFSET                 0x00000300UL
  133 #define DSP_CM1_OFFSET                 0x00000400UL
  134 #define ABE_CM1_OFFSET                 0x00000500UL
  135 #define RESTORE_CM1_OFFSET             0x00000E00UL
  136 #define INSTR_CM1_OFFSET               0x00000F00UL
  137 
  138 #define CM_CLKSEL_DPLL_MPU             (CKGEN_CM1_OFFSET + 0x006CUL)
  139 
  140 /**
  141  *      Address offsets from the CM2 memory region to the top level clock control
  142  *      registers.
  143  */
  144 #define INTRCONN_SOCKET_CM2_OFFSET     0x00000000UL
  145 #define CKGEN_CM2_OFFSET               0x00000100UL
  146 #define ALWAYS_ON_CM2_OFFSET           0x00000600UL
  147 #define CORE_CM2_OFFSET                0x00000700UL
  148 #define IVAHD_CM2_OFFSET               0x00000F00UL
  149 #define CAM_CM2_OFFSET                 0x00001000UL
  150 #define DSS_CM2_OFFSET                 0x00001100UL
  151 #define SGX_CM2_OFFSET                 0x00001200UL
  152 #define L3INIT_CM2_OFFSET              0x00001300UL
  153 #define L4PER_CM2_OFFSET               0x00001400UL
  154 #define RESTORE_CM2_OFFSET             0x00001E00UL
  155 #define INSTR_CM2_OFFSET               0x00001F00UL
  156 
  157 #define CLKCTRL_MODULEMODE_MASK       0x00000003UL
  158 #define CLKCTRL_MODULEMODE_DISABLE    0x00000000UL
  159 #define CLKCTRL_MODULEMODE_AUTO       0x00000001UL
  160 #define CLKCTRL_MODULEMODE_ENABLE     0x00000001UL
  161 
  162 #define CLKCTRL_IDLEST_MASK           0x00030000UL
  163 #define CLKCTRL_IDLEST_ENABLED        0x00000000UL
  164 #define CLKCTRL_IDLEST_WAKING         0x00010000UL
  165 #define CLKCTRL_IDLEST_IDLE           0x00020000UL
  166 #define CLKCTRL_IDLEST_DISABLED       0x00030000UL
  167 
  168 static struct ofw_compat_data compat_data[] = {
  169         {"ti,omap4-cm1",        (uintptr_t)CM1_INSTANCE},
  170         {"ti,omap4-cm2",        (uintptr_t)CM2_INSTANCE},
  171         {"ti,omap4-prm",        (uintptr_t)PRM_INSTANCE},
  172         {NULL,                  (uintptr_t)0},
  173 };
  174 
  175 struct omap4_prcm_softc {
  176         struct resource *sc_res;
  177         int             sc_rid;
  178         int             sc_instance;
  179         int             attach_done;
  180 };
  181 
  182 static int omap4_clk_generic_activate(struct ti_clock_dev *clkdev);
  183 static int omap4_clk_generic_deactivate(struct ti_clock_dev *clkdev);
  184 static int omap4_clk_generic_accessible(struct ti_clock_dev *clkdev);
  185 static int omap4_clk_generic_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc);
  186 static int omap4_clk_generic_get_source_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
  187 
  188 static int omap4_clk_gptimer_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc);
  189 static int omap4_clk_gptimer_get_source_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
  190 
  191 static int omap4_clk_hsmmc_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc);
  192 static int omap4_clk_hsmmc_get_source_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
  193 
  194 static int omap4_clk_hsusbhost_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc);
  195 static int omap4_clk_hsusbhost_activate(struct ti_clock_dev *clkdev);
  196 static int omap4_clk_hsusbhost_deactivate(struct ti_clock_dev *clkdev);
  197 static int omap4_clk_hsusbhost_accessible(struct ti_clock_dev *clkdev);
  198 
  199 static int omap4_clk_get_sysclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
  200 static int omap4_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
  201 
  202 /**
  203  *      omap_clk_devmap - Array of clock devices available on OMAP4xxx devices
  204  *
  205  *      This map only defines which clocks are valid and the callback functions
  206  *      for clock activate, deactivate, etc.  It is used by the top level omap_prcm
  207  *      driver.
  208  *
  209  *      The actual details of the clocks (config registers, bit fields, sources,
  210  *      etc) are in the private g_omap3_clk_details array below.
  211  *
  212  */
  213 
  214 #define OMAP4_GENERIC_CLOCK_DEV(i) \
  215         {       .id = (i), \
  216                 .clk_activate = omap4_clk_generic_activate, \
  217                 .clk_deactivate = omap4_clk_generic_deactivate, \
  218                 .clk_set_source = omap4_clk_generic_set_source, \
  219                 .clk_accessible = omap4_clk_generic_accessible, \
  220                 .clk_get_source_freq = omap4_clk_generic_get_source_freq, \
  221                 .clk_set_source_freq = NULL \
  222         }
  223 
  224 #define OMAP4_GPTIMER_CLOCK_DEV(i) \
  225         {       .id = (i), \
  226                 .clk_activate = omap4_clk_generic_activate, \
  227                 .clk_deactivate = omap4_clk_generic_deactivate, \
  228                 .clk_set_source = omap4_clk_gptimer_set_source, \
  229                 .clk_accessible = omap4_clk_generic_accessible, \
  230                 .clk_get_source_freq = omap4_clk_gptimer_get_source_freq, \
  231                 .clk_set_source_freq = NULL \
  232         }
  233 
  234 #define OMAP4_HSMMC_CLOCK_DEV(i) \
  235         {       .id = (i), \
  236                 .clk_activate = omap4_clk_generic_activate, \
  237                 .clk_deactivate = omap4_clk_generic_deactivate, \
  238                 .clk_set_source = omap4_clk_hsmmc_set_source, \
  239                 .clk_accessible = omap4_clk_generic_accessible, \
  240                 .clk_get_source_freq = omap4_clk_hsmmc_get_source_freq, \
  241                 .clk_set_source_freq = NULL \
  242         }
  243 
  244 #define OMAP4_HSUSBHOST_CLOCK_DEV(i) \
  245         {       .id = (i), \
  246                 .clk_activate = omap4_clk_hsusbhost_activate, \
  247                 .clk_deactivate = omap4_clk_hsusbhost_deactivate, \
  248                 .clk_set_source = omap4_clk_hsusbhost_set_source, \
  249                 .clk_accessible = omap4_clk_hsusbhost_accessible, \
  250                 .clk_get_source_freq = NULL, \
  251                 .clk_set_source_freq = NULL \
  252         }
  253 
  254 struct ti_clock_dev ti_omap4_clk_devmap[] = {
  255         /* System clocks */
  256         {       .id                  = SYS_CLK,
  257                 .clk_activate        = NULL,
  258                 .clk_deactivate      = NULL,
  259                 .clk_set_source      = NULL,
  260                 .clk_accessible      = NULL,
  261                 .clk_get_source_freq = omap4_clk_get_sysclk_freq,
  262                 .clk_set_source_freq = NULL,
  263         },
  264         /* MPU (ARM) core clocks */
  265         {       .id                  = MPU_CLK,
  266                 .clk_activate        = NULL,
  267                 .clk_deactivate      = NULL,
  268                 .clk_set_source      = NULL,
  269                 .clk_accessible      = NULL,
  270                 .clk_get_source_freq = omap4_clk_get_arm_fclk_freq,
  271                 .clk_set_source_freq = NULL,
  272         },
  273 
  274         /* UART device clocks */
  275         OMAP4_GENERIC_CLOCK_DEV(UART1_CLK),
  276         OMAP4_GENERIC_CLOCK_DEV(UART2_CLK),
  277         OMAP4_GENERIC_CLOCK_DEV(UART3_CLK),
  278         OMAP4_GENERIC_CLOCK_DEV(UART4_CLK),
  279 
  280         /* Timer device source clocks */
  281         OMAP4_GPTIMER_CLOCK_DEV(TIMER1_CLK),
  282         OMAP4_GPTIMER_CLOCK_DEV(TIMER2_CLK),
  283         OMAP4_GPTIMER_CLOCK_DEV(TIMER3_CLK),
  284         OMAP4_GPTIMER_CLOCK_DEV(TIMER4_CLK),
  285         OMAP4_GPTIMER_CLOCK_DEV(TIMER5_CLK),
  286         OMAP4_GPTIMER_CLOCK_DEV(TIMER6_CLK),
  287         OMAP4_GPTIMER_CLOCK_DEV(TIMER7_CLK),
  288         OMAP4_GPTIMER_CLOCK_DEV(TIMER8_CLK),
  289         OMAP4_GPTIMER_CLOCK_DEV(TIMER9_CLK),
  290         OMAP4_GPTIMER_CLOCK_DEV(TIMER10_CLK),
  291         OMAP4_GPTIMER_CLOCK_DEV(TIMER11_CLK),
  292 
  293         /* MMC device clocks (MMC1 and MMC2 can have different input clocks) */
  294         OMAP4_HSMMC_CLOCK_DEV(MMC1_CLK),
  295         OMAP4_HSMMC_CLOCK_DEV(MMC2_CLK),
  296         OMAP4_GENERIC_CLOCK_DEV(MMC3_CLK),
  297         OMAP4_GENERIC_CLOCK_DEV(MMC4_CLK),
  298         OMAP4_GENERIC_CLOCK_DEV(MMC5_CLK),
  299 
  300         /* USB HS (high speed TLL, EHCI and OHCI) */
  301         OMAP4_HSUSBHOST_CLOCK_DEV(USBTLL_CLK),
  302         OMAP4_HSUSBHOST_CLOCK_DEV(USBHSHOST_CLK),
  303         OMAP4_HSUSBHOST_CLOCK_DEV(USBFSHOST_CLK),
  304         OMAP4_HSUSBHOST_CLOCK_DEV(USBP1_PHY_CLK),
  305         OMAP4_HSUSBHOST_CLOCK_DEV(USBP2_PHY_CLK),
  306         OMAP4_HSUSBHOST_CLOCK_DEV(USBP1_UTMI_CLK),
  307         OMAP4_HSUSBHOST_CLOCK_DEV(USBP2_UTMI_CLK),
  308         OMAP4_HSUSBHOST_CLOCK_DEV(USBP1_HSIC_CLK),
  309         OMAP4_HSUSBHOST_CLOCK_DEV(USBP2_HSIC_CLK),
  310 
  311         /* GPIO */
  312         OMAP4_GENERIC_CLOCK_DEV(GPIO1_CLK),
  313         OMAP4_GENERIC_CLOCK_DEV(GPIO2_CLK),
  314         OMAP4_GENERIC_CLOCK_DEV(GPIO3_CLK),
  315         OMAP4_GENERIC_CLOCK_DEV(GPIO4_CLK),
  316         OMAP4_GENERIC_CLOCK_DEV(GPIO5_CLK),
  317         OMAP4_GENERIC_CLOCK_DEV(GPIO6_CLK),
  318 
  319         /* sDMA */
  320         OMAP4_GENERIC_CLOCK_DEV(SDMA_CLK),      
  321 
  322         /* I2C */
  323         OMAP4_GENERIC_CLOCK_DEV(I2C1_CLK),
  324         OMAP4_GENERIC_CLOCK_DEV(I2C2_CLK),
  325         OMAP4_GENERIC_CLOCK_DEV(I2C3_CLK),
  326         OMAP4_GENERIC_CLOCK_DEV(I2C4_CLK),
  327         {  INVALID_CLK_IDENT, NULL, NULL, NULL, NULL }
  328 };
  329 
  330 /**
  331  *      omap4_clk_details - Stores details for all the different clocks supported
  332  *
  333  *      Whenever an operation on a clock is being performed (activated, deactivated,
  334  *      etc) this array is looked up to find the correct register and bit(s) we
  335  *      should be modifying.
  336  *
  337  */
  338 struct omap4_clk_details {
  339         clk_ident_t id;
  340 
  341         uint32_t    instance;
  342         uint32_t    clksel_reg;
  343 
  344         int32_t     src_freq;
  345 
  346         uint32_t    enable_mode;
  347 };
  348 
  349 #define OMAP4_GENERIC_CLOCK_DETAILS(i, f, di, r, e) \
  350         {       .id = (i), \
  351                 .instance = (di), \
  352                 .clksel_reg = (r), \
  353                 .src_freq = (f), \
  354                 .enable_mode = (e), \
  355         }
  356 
  357 static struct omap4_clk_details g_omap4_clk_details[] = {
  358         /* UART */
  359         OMAP4_GENERIC_CLOCK_DETAILS(UART1_CLK, FREQ_48MHZ, CM2_INSTANCE,
  360                 (L4PER_CM2_OFFSET + 0x0140), CLKCTRL_MODULEMODE_ENABLE),
  361         OMAP4_GENERIC_CLOCK_DETAILS(UART2_CLK, FREQ_48MHZ, CM2_INSTANCE,
  362                 (L4PER_CM2_OFFSET + 0x0148), CLKCTRL_MODULEMODE_ENABLE),
  363         OMAP4_GENERIC_CLOCK_DETAILS(UART3_CLK, FREQ_48MHZ, CM2_INSTANCE,
  364                 (L4PER_CM2_OFFSET + 0x0150), CLKCTRL_MODULEMODE_ENABLE),
  365         OMAP4_GENERIC_CLOCK_DETAILS(UART4_CLK, FREQ_48MHZ, CM2_INSTANCE,
  366                 (L4PER_CM2_OFFSET + 0x0158), CLKCTRL_MODULEMODE_ENABLE),
  367 
  368         /* General purpose timers */
  369         OMAP4_GENERIC_CLOCK_DETAILS(TIMER1_CLK,  -1, PRM_INSTANCE,
  370                 (WKUP_CM_OFFSET + 0x040), CLKCTRL_MODULEMODE_ENABLE),
  371         OMAP4_GENERIC_CLOCK_DETAILS(TIMER2_CLK,  -1, CM2_INSTANCE,
  372                 (L4PER_CM2_OFFSET + 0x038), CLKCTRL_MODULEMODE_ENABLE),
  373         OMAP4_GENERIC_CLOCK_DETAILS(TIMER3_CLK,  -1, CM2_INSTANCE,
  374                 (L4PER_CM2_OFFSET + 0x040), CLKCTRL_MODULEMODE_ENABLE),
  375         OMAP4_GENERIC_CLOCK_DETAILS(TIMER4_CLK,  -1, CM2_INSTANCE,
  376                 (L4PER_CM2_OFFSET + 0x048), CLKCTRL_MODULEMODE_ENABLE),
  377         OMAP4_GENERIC_CLOCK_DETAILS(TIMER5_CLK,  -1, CM1_INSTANCE,
  378                 (ABE_CM1_OFFSET + 0x068), CLKCTRL_MODULEMODE_ENABLE),
  379         OMAP4_GENERIC_CLOCK_DETAILS(TIMER6_CLK,  -1, CM1_INSTANCE,
  380                 (ABE_CM1_OFFSET + 0x070), CLKCTRL_MODULEMODE_ENABLE),
  381         OMAP4_GENERIC_CLOCK_DETAILS(TIMER7_CLK,  -1, CM1_INSTANCE,
  382                 (ABE_CM1_OFFSET + 0x078), CLKCTRL_MODULEMODE_ENABLE),
  383         OMAP4_GENERIC_CLOCK_DETAILS(TIMER8_CLK,  -1, CM1_INSTANCE,
  384                 (ABE_CM1_OFFSET + 0x080), CLKCTRL_MODULEMODE_ENABLE),
  385         OMAP4_GENERIC_CLOCK_DETAILS(TIMER9_CLK,  -1, CM2_INSTANCE,
  386                 (L4PER_CM2_OFFSET + 0x050), CLKCTRL_MODULEMODE_ENABLE),
  387         OMAP4_GENERIC_CLOCK_DETAILS(TIMER10_CLK, -1, CM2_INSTANCE,
  388                 (L4PER_CM2_OFFSET + 0x028), CLKCTRL_MODULEMODE_ENABLE),
  389         OMAP4_GENERIC_CLOCK_DETAILS(TIMER11_CLK, -1, CM2_INSTANCE,
  390                 (L4PER_CM2_OFFSET + 0x030), CLKCTRL_MODULEMODE_ENABLE),
  391 
  392         /* HSMMC (MMC1 and MMC2 can have different input clocks) */
  393         OMAP4_GENERIC_CLOCK_DETAILS(MMC1_CLK, -1, CM2_INSTANCE,
  394                 (L3INIT_CM2_OFFSET + 0x028), /*CLKCTRL_MODULEMODE_ENABLE*/2),
  395         OMAP4_GENERIC_CLOCK_DETAILS(MMC2_CLK, -1, CM2_INSTANCE,
  396                 (L3INIT_CM2_OFFSET + 0x030), /*CLKCTRL_MODULEMODE_ENABLE*/2),
  397         OMAP4_GENERIC_CLOCK_DETAILS(MMC3_CLK, FREQ_48MHZ, CM2_INSTANCE,
  398                 (L4PER_CM2_OFFSET + 0x120), /*CLKCTRL_MODULEMODE_ENABLE*/2),
  399         OMAP4_GENERIC_CLOCK_DETAILS(MMC4_CLK, FREQ_48MHZ, CM2_INSTANCE,
  400                 (L4PER_CM2_OFFSET + 0x128), /*CLKCTRL_MODULEMODE_ENABLE*/2),
  401         OMAP4_GENERIC_CLOCK_DETAILS(MMC5_CLK, FREQ_48MHZ, CM2_INSTANCE,
  402                (L4PER_CM2_OFFSET + 0x160), /*CLKCTRL_MODULEMODE_ENABLE*/1),
  403 
  404         /* GPIO modules */
  405         OMAP4_GENERIC_CLOCK_DETAILS(GPIO1_CLK, -1, PRM_INSTANCE,
  406                 (WKUP_CM_OFFSET + 0x038), CLKCTRL_MODULEMODE_AUTO),
  407         OMAP4_GENERIC_CLOCK_DETAILS(GPIO2_CLK, -1, CM2_INSTANCE,
  408                 (L4PER_CM2_OFFSET + 0x060), CLKCTRL_MODULEMODE_AUTO),
  409         OMAP4_GENERIC_CLOCK_DETAILS(GPIO3_CLK, -1, CM2_INSTANCE,
  410                 (L4PER_CM2_OFFSET + 0x068), CLKCTRL_MODULEMODE_AUTO),
  411         OMAP4_GENERIC_CLOCK_DETAILS(GPIO4_CLK, -1, CM2_INSTANCE,
  412                 (L4PER_CM2_OFFSET + 0x070), CLKCTRL_MODULEMODE_AUTO),
  413         OMAP4_GENERIC_CLOCK_DETAILS(GPIO5_CLK, -1, CM2_INSTANCE,
  414                 (L4PER_CM2_OFFSET + 0x078), CLKCTRL_MODULEMODE_AUTO),
  415         OMAP4_GENERIC_CLOCK_DETAILS(GPIO6_CLK, -1, CM2_INSTANCE,
  416                 (L4PER_CM2_OFFSET + 0x080), CLKCTRL_MODULEMODE_AUTO),
  417                 
  418         /* sDMA block */
  419         OMAP4_GENERIC_CLOCK_DETAILS(SDMA_CLK, -1, CM2_INSTANCE,
  420                 (CORE_CM2_OFFSET + 0x300), CLKCTRL_MODULEMODE_AUTO),
  421 
  422         /* I2C modules */
  423         OMAP4_GENERIC_CLOCK_DETAILS(I2C1_CLK, -1, CM2_INSTANCE,
  424                 (L4PER_CM2_OFFSET + 0x0A0), CLKCTRL_MODULEMODE_ENABLE),
  425         OMAP4_GENERIC_CLOCK_DETAILS(I2C2_CLK, -1, CM2_INSTANCE,
  426                 (L4PER_CM2_OFFSET + 0x0A8), CLKCTRL_MODULEMODE_ENABLE),
  427         OMAP4_GENERIC_CLOCK_DETAILS(I2C3_CLK, -1, CM2_INSTANCE,
  428                 (L4PER_CM2_OFFSET + 0x0B0), CLKCTRL_MODULEMODE_ENABLE),
  429         OMAP4_GENERIC_CLOCK_DETAILS(I2C4_CLK, -1, CM2_INSTANCE,
  430                 (L4PER_CM2_OFFSET + 0x0B8), CLKCTRL_MODULEMODE_ENABLE),
  431 
  432         { INVALID_CLK_IDENT, 0, 0, 0, 0 },
  433 };
  434 
  435 /**
  436  *      MAX_MODULE_ENABLE_WAIT - the number of loops to wait for the module to come
  437  *      alive.
  438  *
  439  */
  440 #define MAX_MODULE_ENABLE_WAIT    100
  441 
  442 /**
  443  *      ARRAY_SIZE - Macro to return the number of elements in a static const array.
  444  *
  445  */
  446 #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
  447 
  448 /**
  449  *      omap4_clk_details - writes a 32-bit value to one of the timer registers
  450  *      @timer: Timer device context
  451  *      @off: The offset of a register from the timer register address range
  452  *      @val: The value to write into the register
  453  *
  454  *
  455  *      RETURNS:
  456  *      nothing
  457  */
  458 static struct omap4_clk_details*
  459 omap4_clk_details(clk_ident_t id)
  460 {
  461         struct omap4_clk_details *walker;
  462 
  463         for (walker = g_omap4_clk_details; walker->id != INVALID_CLK_IDENT; walker++) {
  464                 if (id == walker->id)
  465                         return (walker);
  466         }
  467 
  468         return NULL;
  469 }
  470 
  471 static struct omap4_prcm_softc *
  472 omap4_prcm_get_instance_softc(int module_instance)
  473 {
  474         int i, maxunit;
  475         devclass_t prcm_devclass;
  476         device_t dev;
  477         struct omap4_prcm_softc *sc;
  478 
  479         prcm_devclass = devclass_find("omap4_prcm");
  480         maxunit = devclass_get_maxunit(prcm_devclass);
  481 
  482         for (i = 0; i < maxunit; i++) {
  483                 dev = devclass_get_device(prcm_devclass, i);
  484                 sc = device_get_softc(dev);
  485                 if (sc->sc_instance == module_instance)
  486                         return (sc);
  487         }
  488 
  489         return (NULL);
  490 }
  491 
  492 /**
  493  *      omap4_clk_generic_activate - checks if a module is accessible
  494  *      @module: identifier for the module to check, see omap3_prcm.h for a list
  495  *               of possible modules.
  496  *               Example: OMAP3_MODULE_MMC1
  497  *      
  498  *      
  499  *
  500  *      LOCKING:
  501  *      Inherits the locks from the omap_prcm driver, no internal locking.
  502  *
  503  *      RETURNS:
  504  *      Returns 0 on success or a positive error code on failure.
  505  */
  506 static int
  507 omap4_clk_generic_activate(struct ti_clock_dev *clkdev)
  508 {
  509         struct omap4_prcm_softc *sc;
  510         struct omap4_clk_details* clk_details;
  511         struct resource* clk_mem_res;
  512         uint32_t clksel;
  513         unsigned int i;
  514         clk_details = omap4_clk_details(clkdev->id);
  515 
  516         if (clk_details == NULL)
  517                 return (ENXIO);
  518 
  519         sc = omap4_prcm_get_instance_softc(clk_details->instance);
  520         if (sc == NULL)
  521                 return ENXIO;
  522 
  523         clk_mem_res = sc->sc_res;
  524 
  525         if (clk_mem_res == NULL)
  526                 return (EINVAL);
  527 
  528         /* All the 'generic' clocks have a CLKCTRL register which is more or less
  529          * generic - the have at least two fielda called MODULEMODE and IDLEST.
  530          */
  531         clksel = bus_read_4(clk_mem_res, clk_details->clksel_reg);
  532         clksel &= ~CLKCTRL_MODULEMODE_MASK;
  533         clksel |=  clk_details->enable_mode;
  534         bus_write_4(clk_mem_res, clk_details->clksel_reg, clksel);
  535 
  536         /* Now poll on the IDLEST register to tell us if the module has come up.
  537          * TODO: We need to take into account the parent clocks.
  538          */
  539 
  540         /* Try MAX_MODULE_ENABLE_WAIT number of times to check if enabled */
  541         for (i = 0; i < MAX_MODULE_ENABLE_WAIT; i++) {
  542                 clksel = bus_read_4(clk_mem_res, clk_details->clksel_reg);
  543                 if ((clksel & CLKCTRL_IDLEST_MASK) == CLKCTRL_IDLEST_ENABLED)
  544                         break;
  545                 DELAY(10);
  546         }
  547                 
  548         /* Check the enabled state */
  549         if ((clksel & CLKCTRL_IDLEST_MASK) != CLKCTRL_IDLEST_ENABLED) {
  550                 printf("Error: failed to enable module with clock %d\n", clkdev->id);
  551                 printf("Error: 0x%08x => 0x%08x\n", clk_details->clksel_reg, clksel);
  552                 return (ETIMEDOUT);
  553         }
  554 
  555         return (0);
  556 }
  557 
  558 /**
  559  *      omap4_clk_generic_deactivate - checks if a module is accessible
  560  *      @module: identifier for the module to check, see omap3_prcm.h for a list
  561  *               of possible modules.
  562  *               Example: OMAP3_MODULE_MMC1
  563  *      
  564  *      
  565  *
  566  *      LOCKING:
  567  *      Inherits the locks from the omap_prcm driver, no internal locking.
  568  *
  569  *      RETURNS:
  570  *      Returns 0 on success or a positive error code on failure.
  571  */
  572 static int
  573 omap4_clk_generic_deactivate(struct ti_clock_dev *clkdev)
  574 {
  575         struct omap4_prcm_softc *sc;
  576         struct omap4_clk_details* clk_details;
  577         struct resource* clk_mem_res;
  578         uint32_t clksel;
  579 
  580         clk_details = omap4_clk_details(clkdev->id);
  581 
  582         if (clk_details == NULL)
  583                 return (ENXIO);
  584 
  585         sc = omap4_prcm_get_instance_softc(clk_details->instance);
  586         if (sc == NULL)
  587                 return ENXIO;
  588 
  589         clk_mem_res = sc->sc_res;
  590 
  591         if (clk_mem_res == NULL)
  592                 return (EINVAL);
  593 
  594         /* All the 'generic' clocks have a CLKCTRL register which is more or less
  595          * generic - the have at least two fielda called MODULEMODE and IDLEST.
  596          */
  597         clksel = bus_read_4(clk_mem_res, clk_details->clksel_reg);
  598         clksel &= ~CLKCTRL_MODULEMODE_MASK;
  599         clksel |=  CLKCTRL_MODULEMODE_DISABLE;
  600         bus_write_4(clk_mem_res, clk_details->clksel_reg, clksel);
  601 
  602         return (0);
  603 }
  604 
  605 /**
  606  *      omap4_clk_generic_set_source - checks if a module is accessible
  607  *      @module: identifier for the module to check, see omap3_prcm.h for a list
  608  *               of possible modules.
  609  *               Example: OMAP3_MODULE_MMC1
  610  *      
  611  *      
  612  *
  613  *      LOCKING:
  614  *      Inherits the locks from the omap_prcm driver, no internal locking.
  615  *
  616  *      RETURNS:
  617  *      Returns 0 on success or a positive error code on failure.
  618  */
  619 static int
  620 omap4_clk_generic_set_source(struct ti_clock_dev *clkdev,
  621                              clk_src_t clksrc)
  622 {
  623 
  624         return (0);
  625 }
  626 
  627 /**
  628  *      omap4_clk_generic_accessible - checks if a module is accessible
  629  *      @module: identifier for the module to check, see omap3_prcm.h for a list
  630  *               of possible modules.
  631  *               Example: OMAP3_MODULE_MMC1
  632  *      
  633  *      
  634  *
  635  *      LOCKING:
  636  *      Inherits the locks from the omap_prcm driver, no internal locking.
  637  *
  638  *      RETURNS:
  639  *      Returns 0 on success or a negative error code on failure.
  640  */
  641 static int
  642 omap4_clk_generic_accessible(struct ti_clock_dev *clkdev)
  643 {
  644         struct omap4_prcm_softc *sc;
  645         struct omap4_clk_details* clk_details;
  646         struct resource* clk_mem_res;
  647         uint32_t clksel;
  648 
  649         clk_details = omap4_clk_details(clkdev->id);
  650 
  651         if (clk_details == NULL)
  652                 return (ENXIO);
  653 
  654         sc = omap4_prcm_get_instance_softc(clk_details->instance);
  655         if (sc == NULL)
  656                 return ENXIO;
  657 
  658         clk_mem_res = sc->sc_res;
  659 
  660         if (clk_mem_res == NULL)
  661                 return (EINVAL);
  662 
  663         clksel = bus_read_4(clk_mem_res, clk_details->clksel_reg);
  664                 
  665         /* Check the enabled state */
  666         if ((clksel & CLKCTRL_IDLEST_MASK) != CLKCTRL_IDLEST_ENABLED)
  667                 return (0);
  668 
  669         return (1);
  670 }
  671 
  672 /**
  673  *      omap4_clk_generic_get_source_freq - checks if a module is accessible
  674  *      @module: identifier for the module to check, see omap3_prcm.h for a list
  675  *               of possible modules.
  676  *               Example: OMAP3_MODULE_MMC1
  677  *      
  678  *      
  679  *
  680  *      LOCKING:
  681  *      Inherits the locks from the omap_prcm driver, no internal locking.
  682  *
  683  *      RETURNS:
  684  *      Returns 0 on success or a negative error code on failure.
  685  */
  686 static int
  687 omap4_clk_generic_get_source_freq(struct ti_clock_dev *clkdev,
  688                                   unsigned int *freq
  689                                   )
  690 {
  691         struct omap4_clk_details* clk_details = omap4_clk_details(clkdev->id);
  692 
  693         if (clk_details == NULL)
  694                 return (ENXIO);
  695 
  696         /* Simply return the stored frequency */
  697         if (freq)
  698                 *freq = (unsigned int)clk_details->src_freq;
  699 
  700         return (0);
  701 }
  702 
  703 /**
  704  *      omap4_clk_gptimer_set_source - checks if a module is accessible
  705  *      @module: identifier for the module to check, see omap3_prcm.h for a list
  706  *               of possible modules.
  707  *               Example: OMAP3_MODULE_MMC1
  708  *      
  709  *      
  710  *
  711  *      LOCKING:
  712  *      Inherits the locks from the omap_prcm driver, no internal locking.
  713  *
  714  *      RETURNS:
  715  *      Returns 0 on success or a negative error code on failure.
  716  */
  717 static int
  718 omap4_clk_gptimer_set_source(struct ti_clock_dev *clkdev,
  719                              clk_src_t clksrc)
  720 {
  721         struct omap4_prcm_softc *sc;
  722         struct omap4_clk_details* clk_details;
  723         struct resource* clk_mem_res;
  724 
  725         clk_details = omap4_clk_details(clkdev->id);
  726 
  727         if (clk_details == NULL)
  728                 return (ENXIO);
  729 
  730         sc = omap4_prcm_get_instance_softc(clk_details->instance);
  731         if (sc == NULL)
  732                 return ENXIO;
  733 
  734         clk_mem_res = sc->sc_res;
  735 
  736         if (clk_mem_res == NULL)
  737                 return (EINVAL);
  738 
  739         /* TODO: Implement */
  740 
  741         return (0);
  742 }
  743 
  744 /**
  745  *      omap4_clk_gptimer_get_source_freq - checks if a module is accessible
  746  *      @module: identifier for the module to check, see omap3_prcm.h for a list
  747  *               of possible modules.
  748  *               Example: OMAP3_MODULE_MMC1
  749  *      
  750  *      
  751  *
  752  *      LOCKING:
  753  *      Inherits the locks from the omap_prcm driver, no internal locking.
  754  *
  755  *      RETURNS:
  756  *      Returns 0 on success or a negative error code on failure.
  757  */
  758 static int
  759 omap4_clk_gptimer_get_source_freq(struct ti_clock_dev *clkdev,
  760                                   unsigned int *freq
  761                                   )
  762 {
  763         struct omap4_prcm_softc *sc;
  764         struct omap4_clk_details* clk_details;
  765         struct resource* clk_mem_res;
  766         uint32_t clksel;
  767         unsigned int src_freq;
  768 
  769         clk_details = omap4_clk_details(clkdev->id);
  770 
  771         if (clk_details == NULL)
  772                 return (ENXIO);
  773 
  774         sc = omap4_prcm_get_instance_softc(clk_details->instance);
  775         if (sc == NULL)
  776                 return ENXIO;
  777 
  778         clk_mem_res = sc->sc_res;
  779 
  780         if (clk_mem_res == NULL)
  781                 return (EINVAL);
  782 
  783         /* Need to read the CLKSEL field to determine the clock source */
  784         clksel = bus_read_4(clk_mem_res, clk_details->clksel_reg);
  785         if (clksel & (0x1UL << 24))
  786                 src_freq = FREQ_32KHZ;
  787         else
  788                 omap4_clk_get_sysclk_freq(NULL, &src_freq);
  789 
  790         /* Return the frequency */
  791         if (freq)
  792                 *freq = src_freq;
  793 
  794         return (0);
  795 }
  796 
  797 /**
  798  *      omap4_clk_hsmmc_set_source - sets the source clock (freq)
  799  *      @clkdev: pointer to the clockdev structure (id field will contain clock id)
  800  *      
  801  *      The MMC 1 and 2 clocks can be source from either a 64MHz or 96MHz clock.
  802  *
  803  *      LOCKING:
  804  *      Inherits the locks from the omap_prcm driver, no internal locking.
  805  *
  806  *      RETURNS:
  807  *      Returns 0 on success or a negative error code on failure.
  808  */
  809 static int
  810 omap4_clk_hsmmc_set_source(struct ti_clock_dev *clkdev,
  811                            clk_src_t clksrc)
  812 {
  813         struct omap4_prcm_softc *sc;
  814         struct omap4_clk_details* clk_details;
  815         struct resource* clk_mem_res;
  816         uint32_t clksel;
  817 
  818         clk_details = omap4_clk_details(clkdev->id);
  819 
  820         if (clk_details == NULL)
  821                 return (ENXIO);
  822 
  823         sc = omap4_prcm_get_instance_softc(clk_details->instance);
  824         if (sc == NULL)
  825                 return ENXIO;
  826 
  827         clk_mem_res = sc->sc_res;
  828 
  829         if (clk_mem_res == NULL)
  830                 return (EINVAL);
  831                 
  832         /* For MMC modules 3, 4 & 5 you can't change the freq, it's always 48MHz */
  833         if ((clkdev->id == MMC3_CLK) || (clkdev->id == MMC4_CLK) ||
  834             (clkdev->id == MMC5_CLK)) {
  835                 if (clksrc != F48MHZ_CLK)
  836                         return (EINVAL);
  837                 return 0;
  838         }
  839 
  840         clksel = bus_read_4(clk_mem_res, clk_details->clksel_reg);
  841 
  842         /* Bit 24 is set if 96MHz clock or cleared for 64MHz clock */
  843         if (clksrc == F64MHZ_CLK)
  844                 clksel &= ~(0x1UL << 24);
  845         else if (clksrc == F96MHZ_CLK)
  846                 clksel |= (0x1UL << 24);
  847         else
  848                 return (EINVAL);
  849                 
  850         bus_write_4(clk_mem_res, clk_details->clksel_reg, clksel);
  851 
  852         return (0);
  853 }
  854 
  855 /**
  856  *      omap4_clk_hsmmc_get_source_freq - checks if a module is accessible
  857  *      @clkdev: pointer to the clockdev structure (id field will contain clock id)
  858  *      
  859  *      
  860  *
  861  *      LOCKING:
  862  *      Inherits the locks from the omap_prcm driver, no internal locking.
  863  *
  864  *      RETURNS:
  865  *      Returns 0 on success or a negative error code on failure.
  866  */
  867 static int
  868 omap4_clk_hsmmc_get_source_freq(struct ti_clock_dev *clkdev,
  869                                 unsigned int *freq
  870                                 )
  871 {
  872         struct omap4_prcm_softc *sc;
  873         struct omap4_clk_details* clk_details;
  874         struct resource* clk_mem_res;
  875         uint32_t clksel;
  876         unsigned int src_freq;
  877 
  878         clk_details = omap4_clk_details(clkdev->id);
  879 
  880         if (clk_details == NULL)
  881                 return (ENXIO);
  882 
  883         sc = omap4_prcm_get_instance_softc(clk_details->instance);
  884         if (sc == NULL)
  885                 return ENXIO;
  886 
  887         clk_mem_res = sc->sc_res;
  888 
  889         if (clk_mem_res == NULL)
  890                 return (EINVAL);
  891 
  892         switch (clkdev->id) {
  893         case MMC1_CLK:
  894         case MMC2_CLK:
  895                 /* Need to read the CLKSEL field to determine the clock source */
  896                 clksel = bus_read_4(clk_mem_res, clk_details->clksel_reg);
  897                 if (clksel & (0x1UL << 24))
  898                         src_freq = FREQ_96MHZ;
  899                 else
  900                         src_freq = FREQ_64MHZ;
  901                 break;
  902         case MMC3_CLK:
  903         case MMC4_CLK:
  904         case MMC5_CLK:
  905                 src_freq = FREQ_48MHZ;
  906                 break;
  907         default:
  908                 return (EINVAL);
  909         }
  910                 
  911         /* Return the frequency */
  912         if (freq)
  913                 *freq = src_freq;
  914 
  915         return (0);
  916 }
  917 
  918 /**
  919  *      omap4_clk_get_sysclk_freq - gets the sysclk frequency
  920  *      @sc: pointer to the clk module/device context
  921  *
  922  *      Read the clocking information from the power-control/boot-strap registers,
  923  *  and stored in two global variables.
  924  *
  925  *      RETURNS:
  926  *      nothing, values are saved in global variables
  927  */
  928 static int
  929 omap4_clk_get_sysclk_freq(struct ti_clock_dev *clkdev,
  930                           unsigned int *freq)
  931 {
  932         uint32_t clksel;
  933         uint32_t sysclk;
  934         struct omap4_prcm_softc *sc;
  935 
  936         sc = omap4_prcm_get_instance_softc(PRM_INSTANCE);
  937         if (sc == NULL)
  938                 return ENXIO;
  939 
  940         /* Read the input clock freq from the configuration register (CM_SYS_CLKSEL) */
  941         clksel = bus_read_4(sc->sc_res, CM_SYS_CLKSEL_OFFSET);
  942         switch (clksel & 0x7) {
  943         case 0x1:
  944                 /* 12Mhz */
  945                 sysclk = 12000000;
  946                 break;
  947         case 0x3:
  948                 /* 16.8Mhz */
  949                 sysclk = 16800000;
  950                 break;
  951         case 0x4:
  952                 /* 19.2Mhz */
  953                 sysclk = 19200000;
  954                 break;
  955         case 0x5:
  956                 /* 26Mhz */
  957                 sysclk = 26000000;
  958                 break;
  959         case 0x7:
  960                 /* 38.4Mhz */
  961                 sysclk = 38400000;
  962                 break;
  963         default:
  964                 panic("%s: Invalid clock freq", __func__);
  965         }
  966 
  967         /* Return the value */
  968         if (freq)
  969                 *freq = sysclk;
  970                 
  971         return (0);
  972 }
  973 
  974 /**
  975  *      omap4_clk_get_arm_fclk_freq - gets the MPU clock frequency
  976  *      @clkdev: ignored
  977  *      @freq: pointer which upon return will contain the freq in hz
  978  *      @mem_res: array of allocated memory resources
  979  *
  980  *      Reads the frequency setting information registers and returns the value
  981  *      in the freq variable.
  982  *
  983  *      RETURNS:
  984  *      returns 0 on success, a positive error code on failure.
  985  */
  986 static int
  987 omap4_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev,
  988                             unsigned int *freq)
  989 {
  990         uint32_t clksel;
  991         uint32_t pll_mult, pll_div;
  992         uint32_t mpuclk, sysclk;
  993         struct omap4_prcm_softc *sc;
  994 
  995         sc = omap4_prcm_get_instance_softc(CM1_INSTANCE);
  996         if (sc == NULL)
  997                 return ENXIO;
  998 
  999         /* Read the clksel register which contains the DPLL multiple and divide
 1000          * values.  These are applied to the sysclk.
 1001          */
 1002         clksel = bus_read_4(sc->sc_res, CM_CLKSEL_DPLL_MPU);
 1003 
 1004         pll_mult = ((clksel >> 8) & 0x7ff);
 1005         pll_div = (clksel & 0x7f) + 1;
 1006 
 1007         /* Get the system clock freq */
 1008         omap4_clk_get_sysclk_freq(NULL, &sysclk);
 1009 
 1010         /* Calculate the MPU freq */
 1011         mpuclk = ((uint64_t)sysclk * pll_mult) / pll_div;
 1012 
 1013         /* Return the value */
 1014         if (freq)
 1015                 *freq = mpuclk;
 1016                 
 1017         return (0);
 1018 }
 1019 
 1020 /**
 1021  *      omap4_clk_hsusbhost_activate - activates the USB clocks for the given module
 1022  *      @clkdev: pointer to the clock device structure.
 1023  *      @mem_res: array of memory resources allocated by the top level PRCM driver.
 1024  *      
 1025  *      The USB clocking setup seems to be a bit more tricky than the other modules,
 1026  *      to start with the clocking diagram for the HS host module shows 13 different
 1027  *      clocks.  So to try and make it easier to follow the clocking activation
 1028  *      and deactivation is handled in its own set of callbacks.
 1029  *
 1030  *      LOCKING:
 1031  *      Inherits the locks from the omap_prcm driver, no internal locking.
 1032  *
 1033  *      RETURNS:
 1034  *      Returns 0 on success or a positive error code on failure.
 1035  */
 1036 
 1037 struct dpll_param {
 1038         unsigned int m;
 1039         unsigned int n;
 1040         unsigned int m2;
 1041         unsigned int m3;
 1042         unsigned int m4;
 1043         unsigned int m5;
 1044         unsigned int m6;
 1045         unsigned int m7;
 1046 };
 1047 /* USB parameters */
 1048 struct dpll_param usb_dpll_param[7] = {
 1049         /* 12M values */
 1050         {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
 1051         /* 13M values */
 1052         {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
 1053         /* 16.8M values */
 1054         {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
 1055         /* 19.2M values */
 1056         {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
 1057         /* 26M values */
 1058         {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
 1059         /* 27M values */
 1060         {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
 1061         /* 38.4M values */
 1062 #ifdef CONFIG_OMAP4_SDC
 1063         {0x32, 0x1, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0},
 1064 #else
 1065         {0x32, 0x1, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0},
 1066 #endif
 1067 };
 1068 static int
 1069 omap4_clk_hsusbhost_activate(struct ti_clock_dev *clkdev)
 1070 {
 1071         struct omap4_prcm_softc *sc;
 1072         struct resource* clk_mem_res;
 1073         uint32_t clksel_reg_off;
 1074         uint32_t clksel;
 1075         unsigned int i;
 1076 
 1077         sc = omap4_prcm_get_instance_softc(CM2_INSTANCE);
 1078         if (sc == NULL)
 1079                 return ENXIO;
 1080 
 1081         switch (clkdev->id) {
 1082         case USBTLL_CLK:
 1083                 /* For the USBTLL module we need to enable the following clocks:
 1084                  *  - INIT_L4_ICLK  (will be enabled by bootloader)
 1085                  *  - TLL_CH0_FCLK
 1086                  *  - TLL_CH1_FCLK
 1087                  */
 1088 
 1089                 /* We need the CM_L3INIT_HSUSBTLL_CLKCTRL register in CM2 register set */
 1090                 clk_mem_res = sc->sc_res;
 1091                 clksel_reg_off = L3INIT_CM2_OFFSET + 0x68;
 1092 
 1093                 /* Enable the module and also enable the optional func clocks for
 1094                  * channels 0 & 1 (is this needed ?)
 1095                  */
 1096                 clksel = bus_read_4(clk_mem_res, clksel_reg_off);
 1097                 clksel &= ~CLKCTRL_MODULEMODE_MASK;
 1098                 clksel |=  CLKCTRL_MODULEMODE_ENABLE;
 1099                 
 1100                 clksel |= (0x1 << 8); /* USB-HOST optional clock: USB_CH0_CLK */
 1101                 clksel |= (0x1 << 9); /* USB-HOST optional clock: USB_CH1_CLK */
 1102                 break;
 1103 
 1104         case USBHSHOST_CLK:
 1105         case USBP1_PHY_CLK:
 1106         case USBP2_PHY_CLK:
 1107         case USBP1_UTMI_CLK:
 1108         case USBP2_UTMI_CLK:
 1109         case USBP1_HSIC_CLK:
 1110         case USBP2_HSIC_CLK:
 1111                 /* For the USB HS HOST module we need to enable the following clocks:
 1112                  *  - INIT_L4_ICLK     (will be enabled by bootloader)
 1113                  *  - INIT_L3_ICLK     (will be enabled by bootloader)
 1114                  *  - INIT_48MC_FCLK
 1115                  *  - UTMI_ROOT_GFCLK  (UTMI only, create a new clock for that ?)
 1116                  *  - UTMI_P1_FCLK     (UTMI only, create a new clock for that ?)
 1117                  *  - UTMI_P2_FCLK     (UTMI only, create a new clock for that ?)
 1118                  *  - HSIC_P1_60       (HSIC only, create a new clock for that ?)
 1119                  *  - HSIC_P1_480      (HSIC only, create a new clock for that ?)
 1120                  *  - HSIC_P2_60       (HSIC only, create a new clock for that ?)
 1121                  *  - HSIC_P2_480      (HSIC only, create a new clock for that ?)
 1122                  */
 1123 
 1124                 /* We need the CM_L3INIT_HSUSBHOST_CLKCTRL register in CM2 register set */
 1125                 clk_mem_res = sc->sc_res;
 1126                 clksel_reg_off = L3INIT_CM2_OFFSET + 0x58;
 1127                 clksel = bus_read_4(clk_mem_res, clksel_reg_off);       
 1128                 /* Enable the module and also enable the optional func clocks */
 1129                 if (clkdev->id == USBHSHOST_CLK) {
 1130                         clksel &= ~CLKCTRL_MODULEMODE_MASK;
 1131                         clksel |=  /*CLKCTRL_MODULEMODE_ENABLE*/2;
 1132 
 1133                         clksel |= (0x1 << 15); /* USB-HOST clock control: FUNC48MCLK */
 1134                 }
 1135                 
 1136                 else if (clkdev->id == USBP1_UTMI_CLK)
 1137                         clksel |= (0x1 << 8);  /* UTMI_P1_CLK */
 1138                 else if (clkdev->id == USBP2_UTMI_CLK)
 1139                         clksel |= (0x1 << 9);  /* UTMI_P2_CLK */
 1140 
 1141                 else if (clkdev->id == USBP1_HSIC_CLK)
 1142                         clksel |= (0x5 << 11);  /* HSIC60M_P1_CLK + HSIC480M_P1_CLK */
 1143                 else if (clkdev->id == USBP2_HSIC_CLK)
 1144                         clksel |= (0x5 << 12);  /* HSIC60M_P2_CLK + HSIC480M_P2_CLK */
 1145                 
 1146                 break;
 1147 
 1148         default:
 1149                 return (EINVAL);
 1150         }
 1151 
 1152         bus_write_4(clk_mem_res, clksel_reg_off, clksel);
 1153 
 1154         /* Try MAX_MODULE_ENABLE_WAIT number of times to check if enabled */
 1155         for (i = 0; i < MAX_MODULE_ENABLE_WAIT; i++) {
 1156                 clksel = bus_read_4(clk_mem_res, clksel_reg_off);
 1157                 if ((clksel & CLKCTRL_IDLEST_MASK) == CLKCTRL_IDLEST_ENABLED)
 1158                         break;
 1159         }
 1160                 
 1161         /* Check the enabled state */
 1162         if ((clksel & CLKCTRL_IDLEST_MASK) != CLKCTRL_IDLEST_ENABLED) {
 1163                 printf("Error: HERE failed to enable module with clock %d\n", clkdev->id);
 1164                 printf("Error: 0x%08x => 0x%08x\n", clksel_reg_off, clksel);
 1165                 return (ETIMEDOUT);
 1166         }
 1167 
 1168         return (0);
 1169 }
 1170 
 1171 /**
 1172  *      omap4_clk_generic_deactivate - checks if a module is accessible
 1173  *      @clkdev: pointer to the clock device structure.
 1174  *      @mem_res: array of memory resources allocated by the top level PRCM driver.
 1175  *      
 1176  *      
 1177  *
 1178  *      LOCKING:
 1179  *      Inherits the locks from the omap_prcm driver, no internal locking.
 1180  *
 1181  *      RETURNS:
 1182  *      Returns 0 on success or a positive error code on failure.
 1183  */
 1184 static int
 1185 omap4_clk_hsusbhost_deactivate(struct ti_clock_dev *clkdev)
 1186 {
 1187         struct omap4_prcm_softc *sc;
 1188         struct resource* clk_mem_res;
 1189         uint32_t clksel_reg_off;
 1190         uint32_t clksel;
 1191 
 1192         sc = omap4_prcm_get_instance_softc(CM2_INSTANCE);
 1193         if (sc == NULL)
 1194                 return ENXIO;
 1195 
 1196         switch (clkdev->id) {
 1197         case USBTLL_CLK:
 1198                 /* We need the CM_L3INIT_HSUSBTLL_CLKCTRL register in CM2 register set */
 1199                 clk_mem_res = sc->sc_res;
 1200                 clksel_reg_off = L3INIT_CM2_OFFSET + 0x68;
 1201 
 1202                 clksel = bus_read_4(clk_mem_res, clksel_reg_off);
 1203                 clksel &= ~CLKCTRL_MODULEMODE_MASK;
 1204                 clksel |=  CLKCTRL_MODULEMODE_DISABLE;
 1205                 break;
 1206 
 1207         case USBHSHOST_CLK:
 1208         case USBP1_PHY_CLK:
 1209         case USBP2_PHY_CLK:
 1210         case USBP1_UTMI_CLK:
 1211         case USBP2_UTMI_CLK:
 1212         case USBP1_HSIC_CLK:
 1213         case USBP2_HSIC_CLK:
 1214                 /* For the USB HS HOST module we need to enable the following clocks:
 1215                  *  - INIT_L4_ICLK     (will be enabled by bootloader)
 1216                  *  - INIT_L3_ICLK     (will be enabled by bootloader)
 1217                  *  - INIT_48MC_FCLK
 1218                  *  - UTMI_ROOT_GFCLK  (UTMI only, create a new clock for that ?)
 1219                  *  - UTMI_P1_FCLK     (UTMI only, create a new clock for that ?)
 1220                  *  - UTMI_P2_FCLK     (UTMI only, create a new clock for that ?)
 1221                  *  - HSIC_P1_60       (HSIC only, create a new clock for that ?)
 1222                  *  - HSIC_P1_480      (HSIC only, create a new clock for that ?)
 1223                  *  - HSIC_P2_60       (HSIC only, create a new clock for that ?)
 1224                  *  - HSIC_P2_480      (HSIC only, create a new clock for that ?)
 1225                  */
 1226 
 1227                 /* We need the CM_L3INIT_HSUSBHOST_CLKCTRL register in CM2 register set */
 1228                 clk_mem_res = sc->sc_res;
 1229                 clksel_reg_off = L3INIT_CM2_OFFSET + 0x58;
 1230                 clksel = bus_read_4(clk_mem_res, clksel_reg_off);
 1231 
 1232                 /* Enable the module and also enable the optional func clocks */
 1233                 if (clkdev->id == USBHSHOST_CLK) {
 1234                         clksel &= ~CLKCTRL_MODULEMODE_MASK;
 1235                         clksel |=  CLKCTRL_MODULEMODE_DISABLE;
 1236 
 1237                         clksel &= ~(0x1 << 15); /* USB-HOST clock control: FUNC48MCLK */
 1238                 }
 1239                 
 1240                 else if (clkdev->id == USBP1_UTMI_CLK)
 1241                         clksel &= ~(0x1 << 8);  /* UTMI_P1_CLK */
 1242                 else if (clkdev->id == USBP2_UTMI_CLK)
 1243                         clksel &= ~(0x1 << 9);  /* UTMI_P2_CLK */
 1244 
 1245                 else if (clkdev->id == USBP1_HSIC_CLK)
 1246                         clksel &= ~(0x5 << 11);  /* HSIC60M_P1_CLK + HSIC480M_P1_CLK */
 1247                 else if (clkdev->id == USBP2_HSIC_CLK)
 1248                         clksel &= ~(0x5 << 12);  /* HSIC60M_P2_CLK + HSIC480M_P2_CLK */
 1249                 
 1250                 break;
 1251 
 1252         default:
 1253                 return (EINVAL);
 1254         }
 1255 
 1256         bus_write_4(clk_mem_res, clksel_reg_off, clksel);
 1257 
 1258         return (0);
 1259 }
 1260 
 1261 /**
 1262  *      omap4_clk_hsusbhost_accessible - checks if a module is accessible
 1263  *      @clkdev: pointer to the clock device structure.
 1264  *      @mem_res: array of memory resources allocated by the top level PRCM driver.
 1265  *      
 1266  *      
 1267  *
 1268  *      LOCKING:
 1269  *      Inherits the locks from the omap_prcm driver, no internal locking.
 1270  *
 1271  *      RETURNS:
 1272  *      Returns 0 if module is not enable, 1 if module is enabled or a negative
 1273  *      error code on failure.
 1274  */
 1275 static int
 1276 omap4_clk_hsusbhost_accessible(struct ti_clock_dev *clkdev)
 1277 {
 1278         struct omap4_prcm_softc *sc;
 1279         struct resource* clk_mem_res;
 1280         uint32_t clksel_reg_off;
 1281         uint32_t clksel;
 1282 
 1283         sc = omap4_prcm_get_instance_softc(CM2_INSTANCE);
 1284         if (sc == NULL)
 1285                 return ENXIO;
 1286 
 1287         if (clkdev->id == USBTLL_CLK) {
 1288                 /* We need the CM_L3INIT_HSUSBTLL_CLKCTRL register in CM2 register set */
 1289                 clk_mem_res = sc->sc_res;
 1290                 clksel_reg_off = L3INIT_CM2_OFFSET + 0x68;
 1291         }
 1292         else if (clkdev->id == USBHSHOST_CLK) {
 1293                 /* We need the CM_L3INIT_HSUSBHOST_CLKCTRL register in CM2 register set */
 1294                 clk_mem_res = sc->sc_res;
 1295                 clksel_reg_off = L3INIT_CM2_OFFSET + 0x58;
 1296         }
 1297         else {
 1298                 return (EINVAL);
 1299         }
 1300 
 1301         clksel = bus_read_4(clk_mem_res, clksel_reg_off);
 1302                 
 1303         /* Check the enabled state */
 1304         if ((clksel & CLKCTRL_IDLEST_MASK) != CLKCTRL_IDLEST_ENABLED)
 1305                 return (0);
 1306 
 1307         return (1);
 1308 }
 1309 
 1310 /**
 1311  *      omap4_clk_hsusbhost_set_source - sets the source clocks
 1312  *      @clkdev: pointer to the clock device structure.
 1313  *      @clksrc: the clock source ID for the given clock.
 1314  *      @mem_res: array of memory resources allocated by the top level PRCM driver.
 1315  *      
 1316  *      
 1317  *
 1318  *      LOCKING:
 1319  *      Inherits the locks from the omap_prcm driver, no internal locking.
 1320  *
 1321  *      RETURNS:
 1322  *      Returns 0 if successful otherwise a negative error code on failure.
 1323  */
 1324 static int
 1325 omap4_clk_hsusbhost_set_source(struct ti_clock_dev *clkdev,
 1326                                clk_src_t clksrc)
 1327 {
 1328         struct omap4_prcm_softc *sc;
 1329         struct resource* clk_mem_res;
 1330         uint32_t clksel_reg_off;
 1331         uint32_t clksel;
 1332         unsigned int bit;
 1333 
 1334         sc = omap4_prcm_get_instance_softc(CM2_INSTANCE);
 1335         if (sc == NULL)
 1336                 return ENXIO;
 1337 
 1338         if (clkdev->id == USBP1_PHY_CLK)
 1339                 bit = 24;
 1340         else if (clkdev->id != USBP2_PHY_CLK)
 1341                 bit = 25;
 1342         else
 1343                 return (EINVAL);
 1344 
 1345         /* We need the CM_L3INIT_HSUSBHOST_CLKCTRL register in CM2 register set */
 1346         clk_mem_res = sc->sc_res;
 1347         clksel_reg_off = L3INIT_CM2_OFFSET + 0x58;
 1348         clksel = bus_read_4(clk_mem_res, clksel_reg_off);
 1349 
 1350         /* Set the clock source to either external or internal */
 1351         if (clksrc == EXT_CLK)
 1352                 clksel |= (0x1 << bit);
 1353         else
 1354                 clksel &= ~(0x1 << bit);
 1355 
 1356         bus_write_4(clk_mem_res, clksel_reg_off, clksel);
 1357 
 1358         return (0);
 1359 }
 1360 
 1361 #define PRM_RSTCTRL             0x1b00
 1362 #define PRM_RSTCTRL_RESET       0x2
 1363 
 1364 static void
 1365 omap4_prcm_reset(void)
 1366 {
 1367         struct omap4_prcm_softc *sc;
 1368 
 1369         sc = omap4_prcm_get_instance_softc(PRM_INSTANCE);
 1370         if (sc == NULL)
 1371                 return;
 1372 
 1373         bus_write_4(sc->sc_res, PRM_RSTCTRL,
 1374             bus_read_4(sc->sc_res, PRM_RSTCTRL) | PRM_RSTCTRL_RESET);
 1375         bus_read_4(sc->sc_res, PRM_RSTCTRL);
 1376 }
 1377 
 1378 /**
 1379  *      omap4_prcm_probe - probe function for the driver
 1380  *      @dev: prcm device handle
 1381  *
 1382  *      Simply sets the name of the driver module.
 1383  *
 1384  *      LOCKING:
 1385  *      None
 1386  *
 1387  *      RETURNS:
 1388  *      Always returns 0
 1389  */
 1390 static int
 1391 omap4_prcm_probe(device_t dev)
 1392 {
 1393         const struct ofw_compat_data *ocd;
 1394 
 1395         if (!ofw_bus_status_okay(dev))
 1396                 return (ENXIO);
 1397 
 1398         ocd = ofw_bus_search_compatible(dev, compat_data);
 1399         if ((int)ocd->ocd_data == 0)
 1400                 return (ENXIO);
 1401 
 1402         switch ((int)ocd->ocd_data) {
 1403                 case PRM_INSTANCE:
 1404                         device_set_desc(dev, "TI OMAP Power, Reset and Clock Management (PRM)");
 1405                         break;
 1406                 case CM1_INSTANCE:
 1407                         device_set_desc(dev, "TI OMAP Power, Reset and Clock Management (C1)");
 1408                         break;
 1409                 case CM2_INSTANCE:
 1410                         device_set_desc(dev, "TI OMAP Power, Reset and Clock Management (C2)");
 1411                         break;
 1412                 default:
 1413                         device_printf(dev, "unknown instance type: %d\n", (int)ocd->ocd_data);
 1414                         return (ENXIO);
 1415         }
 1416 
 1417         return (BUS_PROBE_DEFAULT);
 1418 }
 1419 
 1420 /**
 1421  *      omap_prcm_attach - attach function for the driver
 1422  *      @dev: prcm device handle
 1423  *
 1424  *      Allocates and sets up the driver context, this simply entails creating a
 1425  *      bus mappings for the PRCM register set.
 1426  *
 1427  *      LOCKING:
 1428  *      None
 1429  *
 1430  *      RETURNS:
 1431  *      Always returns 0
 1432  */
 1433 
 1434 extern uint32_t platform_arm_tmr_freq;
 1435 
 1436 static int
 1437 omap4_prcm_attach(device_t dev)
 1438 {
 1439         struct omap4_prcm_softc *sc;
 1440         const struct ofw_compat_data *ocd;
 1441 
 1442         sc = device_get_softc(dev);
 1443         ocd = ofw_bus_search_compatible(dev, compat_data);
 1444         sc->sc_instance = (int)ocd->ocd_data;
 1445 
 1446         sc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rid,
 1447             RF_ACTIVE);
 1448         if (sc->sc_res == NULL) {
 1449                 device_printf(dev, "could not allocate resources\n");
 1450                 return (ENXIO);
 1451         }
 1452 
 1453         ti_cpu_reset = omap4_prcm_reset;
 1454 
 1455         return (0);
 1456 }
 1457 
 1458 static void
 1459 omap4_prcm_new_pass(device_t dev)
 1460 {
 1461         struct omap4_prcm_softc *sc = device_get_softc(dev);
 1462         unsigned int freq;
 1463 
 1464         if (sc->attach_done ||
 1465           bus_current_pass < (BUS_PASS_TIMER + BUS_PASS_ORDER_EARLY)) {
 1466                 bus_generic_new_pass(dev);
 1467                 return;
 1468         }
 1469         sc->attach_done = 1;
 1470 
 1471         /*
 1472          * In order to determine ARM frequency we need both RPM and CM1 
 1473          * instances up and running. So wait until all CRM devices are
 1474          * initialized. Should be replaced with proper clock framework
 1475          */
 1476         if (device_get_unit(dev) == 2) {
 1477                 omap4_clk_get_arm_fclk_freq(NULL, &freq);
 1478                 arm_tmr_change_frequency(freq / 2);
 1479         }
 1480 
 1481         return;
 1482 }
 1483 
 1484 static device_method_t omap4_prcm_methods[] = {
 1485         DEVMETHOD(device_probe, omap4_prcm_probe),
 1486         DEVMETHOD(device_attach, omap4_prcm_attach),
 1487 
 1488         /* Bus interface */
 1489         DEVMETHOD(bus_new_pass, omap4_prcm_new_pass),
 1490 
 1491         {0, 0},
 1492 };
 1493 
 1494 static driver_t omap4_prcm_driver = {
 1495         "omap4_prcm",
 1496         omap4_prcm_methods,
 1497         sizeof(struct omap4_prcm_softc),
 1498 };
 1499 
 1500 EARLY_DRIVER_MODULE(omap4_prcm, simplebus, omap4_prcm_driver, 0, 0,
 1501     BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
 1502 MODULE_VERSION(omap4_prcm, 1);

Cache object: 17ec5481689a5038930d14bcc8f93f13


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