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