1239281Sgonzo/*- 2239281Sgonzo * Copyright (c) 2011 3239281Sgonzo * Ben Gray <ben.r.gray@gmail.com>. 4239281Sgonzo * All rights reserved. 5239281Sgonzo * 6239281Sgonzo * Redistribution and use in source and binary forms, with or without 7239281Sgonzo * modification, are permitted provided that the following conditions 8239281Sgonzo * are met: 9239281Sgonzo * 1. Redistributions of source code must retain the above copyright 10239281Sgonzo * notice, this list of conditions and the following disclaimer. 11239281Sgonzo * 2. Redistributions in binary form must reproduce the above copyright 12239281Sgonzo * notice, this list of conditions and the following disclaimer in the 13239281Sgonzo * documentation and/or other materials provided with the distribution. 14239281Sgonzo * 3. The name of the company nor the name of the author may be used to 15239281Sgonzo * endorse or promote products derived from this software without specific 16239281Sgonzo * prior written permission. 17239281Sgonzo * 18239281Sgonzo * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``AS IS'' AND ANY EXPRESS OR 19239281Sgonzo * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20239281Sgonzo * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21239281Sgonzo * IN NO EVENT SHALL BEN GRAY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22239281Sgonzo * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23239281Sgonzo * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 24239281Sgonzo * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25239281Sgonzo * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26239281Sgonzo * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 27239281Sgonzo * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28239281Sgonzo */ 29239281Sgonzo 30239281Sgonzo#include <sys/cdefs.h> 31239281Sgonzo__FBSDID("$FreeBSD$"); 32239281Sgonzo 33239281Sgonzo#include <sys/param.h> 34239281Sgonzo#include <sys/systm.h> 35239281Sgonzo#include <sys/kernel.h> 36239281Sgonzo#include <sys/module.h> 37239281Sgonzo#include <sys/bus.h> 38239281Sgonzo#include <sys/resource.h> 39239281Sgonzo#include <sys/rman.h> 40239281Sgonzo#include <sys/lock.h> 41239281Sgonzo#include <sys/malloc.h> 42239281Sgonzo 43239281Sgonzo#include <machine/bus.h> 44239281Sgonzo#include <machine/cpu.h> 45239281Sgonzo#include <machine/cpufunc.h> 46239281Sgonzo#include <machine/resource.h> 47239281Sgonzo#include <machine/intr.h> 48239281Sgonzo 49266347Sian#include <arm/arm/mpcore_timervar.h> 50239281Sgonzo#include <arm/ti/tivar.h> 51239281Sgonzo#include <arm/ti/ti_prcm.h> 52239281Sgonzo#include <arm/ti/omap4/omap4_reg.h> 53239281Sgonzo 54239281Sgonzo#include <dev/fdt/fdt_common.h> 55239281Sgonzo#include <dev/ofw/openfirm.h> 56239281Sgonzo#include <dev/ofw/ofw_bus.h> 57239281Sgonzo#include <dev/ofw/ofw_bus_subr.h> 58239281Sgonzo 59239281Sgonzo/* 60239281Sgonzo * This file defines the clock configuration for the OMAP4xxx series of 61239281Sgonzo * devices. 62239281Sgonzo * 63239281Sgonzo * How This is Suppose to Work 64239281Sgonzo * =========================== 65239281Sgonzo * - There is a top level omap_prcm module that defines all OMAP SoC drivers 66239281Sgonzo * should use to enable/disable the system clocks regardless of the version 67239281Sgonzo * of OMAP device they are running on. This top level PRCM module is just 68239281Sgonzo * a thin shim to chip specific functions that perform the donkey work of 69239281Sgonzo * configuring the clock - this file is the 'donkey' for OMAP44xx devices. 70239281Sgonzo * 71239281Sgonzo * - The key bit in this file is the omap_clk_devmap array, it's 72239281Sgonzo * used by the omap_prcm driver to determine what clocks are valid and which 73239281Sgonzo * functions to call to manipulate them. 74239281Sgonzo * 75239281Sgonzo * - In essence you just need to define some callbacks for each of the 76239281Sgonzo * clocks and then you're done. 77239281Sgonzo * 78239281Sgonzo * - The other thing that is worth noting is that when the omap_prcm device 79239281Sgonzo * is registered you typically pass in some memory ranges which are the 80239281Sgonzo * SYS_MEMORY resources. These resources are in turn allocated using 81239281Sgonzo * bus_allocate_resources(...) and the resource handles are passed to all 82239281Sgonzo * individual clock callback handlers. 83239281Sgonzo * 84239281Sgonzo * 85239281Sgonzo * 86239281Sgonzo * OMAP4 devices are different from the previous OMAP3 devices in that there 87239281Sgonzo * is no longer a separate functional and interface clock for each module, 88239281Sgonzo * instead there is typically an interface clock that spans many modules. 89239281Sgonzo */ 90239281Sgonzo 91239281Sgonzo#define FREQ_96MHZ 96000000 92239281Sgonzo#define FREQ_64MHZ 64000000 93239281Sgonzo#define FREQ_48MHZ 48000000 94239281Sgonzo#define FREQ_32KHZ 32000 95239281Sgonzo 96239281Sgonzo/** 97239281Sgonzo * We need three memory regions to cover all the clock configuration registers. 98239281Sgonzo * 99239281Sgonzo * PRM Instance - 0x4A30 6000 : 0x4A30 8000 100239281Sgonzo * CM1 Instance - 0x4A00 4000 : 0x4A00 5000 101239281Sgonzo * CM2 Instance - 0x4A00 8000 : 0x4A00 A000 102239281Sgonzo * 103239281Sgonzo */ 104239281Sgonzo#define PRM_INSTANCE_MEM_REGION 0 105239281Sgonzo#define CM1_INSTANCE_MEM_REGION 1 106239281Sgonzo#define CM2_INSTANCE_MEM_REGION 2 107239281Sgonzo 108239281Sgonzo/** 109239281Sgonzo * Address offsets from the PRM memory region to the top level clock control 110239281Sgonzo * registers. 111239281Sgonzo */ 112239281Sgonzo#define CKGEN_PRM_OFFSET 0x00000100UL 113239281Sgonzo#define MPU_PRM_OFFSET 0x00000300UL 114239281Sgonzo#define DSP_PRM_OFFSET 0x00000400UL 115239281Sgonzo#define ABE_PRM_OFFSET 0x00000500UL 116239281Sgonzo#define ALWAYS_ON_PRM_OFFSET 0x00000600UL 117239281Sgonzo#define CORE_PRM_OFFSET 0x00000700UL 118239281Sgonzo#define IVAHD_PRM_OFFSET 0x00000F00UL 119239281Sgonzo#define CAM_PRM_OFFSET 0x00001000UL 120239281Sgonzo#define DSS_PRM_OFFSET 0x00001100UL 121239281Sgonzo#define SGX_PRM_OFFSET 0x00001200UL 122239281Sgonzo#define L3INIT_PRM_OFFSET 0x00001300UL 123239281Sgonzo#define L4PER_PRM_OFFSET 0x00001400UL 124239281Sgonzo#define WKUP_PRM_OFFSET 0x00001700UL 125239281Sgonzo#define WKUP_CM_OFFSET 0x00001800UL 126239281Sgonzo#define EMU_PRM_OFFSET 0x00001900UL 127239281Sgonzo#define EMU_CM_OFFSET 0x00001A00UL 128239281Sgonzo#define DEVICE_PRM_OFFSET 0x00001B00UL 129239281Sgonzo#define INSTR_PRM_OFFSET 0x00001F00UL 130239281Sgonzo 131239281Sgonzo#define CM_ABE_DSS_SYS_CLKSEL_OFFSET (CKGEN_PRM_OFFSET + 0x0000UL) 132239281Sgonzo#define CM_L4_WKUP_CLKSELL_OFFSET (CKGEN_PRM_OFFSET + 0x0008UL) 133239281Sgonzo#define CM_ABE_PLL_REF_CLKSEL_OFFSET (CKGEN_PRM_OFFSET + 0x000CUL) 134239281Sgonzo#define CM_SYS_CLKSEL_OFFSET (CKGEN_PRM_OFFSET + 0x0010UL) 135239281Sgonzo 136239281Sgonzo/** 137239281Sgonzo * Address offsets from the CM1 memory region to the top level clock control 138239281Sgonzo * registers. 139239281Sgonzo */ 140239281Sgonzo#define CKGEN_CM1_OFFSET 0x00000100UL 141239281Sgonzo#define MPU_CM1_OFFSET 0x00000300UL 142239281Sgonzo#define DSP_CM1_OFFSET 0x00000400UL 143239281Sgonzo#define ABE_CM1_OFFSET 0x00000500UL 144239281Sgonzo#define RESTORE_CM1_OFFSET 0x00000E00UL 145239281Sgonzo#define INSTR_CM1_OFFSET 0x00000F00UL 146239281Sgonzo 147239281Sgonzo#define CM_CLKSEL_DPLL_MPU (CKGEN_CM1_OFFSET + 0x006CUL) 148239281Sgonzo 149239281Sgonzo/** 150239281Sgonzo * Address offsets from the CM2 memory region to the top level clock control 151239281Sgonzo * registers. 152239281Sgonzo */ 153239281Sgonzo#define INTRCONN_SOCKET_CM2_OFFSET 0x00000000UL 154239281Sgonzo#define CKGEN_CM2_OFFSET 0x00000100UL 155239281Sgonzo#define ALWAYS_ON_CM2_OFFSET 0x00000600UL 156239281Sgonzo#define CORE_CM2_OFFSET 0x00000700UL 157239281Sgonzo#define IVAHD_CM2_OFFSET 0x00000F00UL 158239281Sgonzo#define CAM_CM2_OFFSET 0x00001000UL 159239281Sgonzo#define DSS_CM2_OFFSET 0x00001100UL 160239281Sgonzo#define SGX_CM2_OFFSET 0x00001200UL 161239281Sgonzo#define L3INIT_CM2_OFFSET 0x00001300UL 162239281Sgonzo#define L4PER_CM2_OFFSET 0x00001400UL 163239281Sgonzo#define RESTORE_CM2_OFFSET 0x00001E00UL 164239281Sgonzo#define INSTR_CM2_OFFSET 0x00001F00UL 165239281Sgonzo 166239281Sgonzo#define CLKCTRL_MODULEMODE_MASK 0x00000003UL 167239281Sgonzo#define CLKCTRL_MODULEMODE_DISABLE 0x00000000UL 168239281Sgonzo#define CLKCTRL_MODULEMODE_AUTO 0x00000001UL 169239281Sgonzo#define CLKCTRL_MODULEMODE_ENABLE 0x00000001UL 170239281Sgonzo 171239281Sgonzo#define CLKCTRL_IDLEST_MASK 0x00030000UL 172239281Sgonzo#define CLKCTRL_IDLEST_ENABLED 0x00000000UL 173239281Sgonzo#define CLKCTRL_IDLEST_WAKING 0x00010000UL 174239281Sgonzo#define CLKCTRL_IDLEST_IDLE 0x00020000UL 175239281Sgonzo#define CLKCTRL_IDLEST_DISABLED 0x00030000UL 176239281Sgonzo 177239281Sgonzostatic struct resource_spec omap4_scm_res_spec[] = { 178239281Sgonzo { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* Control memory window */ 179239281Sgonzo { SYS_RES_MEMORY, 1, RF_ACTIVE }, /* Control memory window */ 180239281Sgonzo { SYS_RES_MEMORY, 2, RF_ACTIVE }, /* Control memory window */ 181239281Sgonzo { -1, 0 } 182239281Sgonzo}; 183239281Sgonzo 184239281Sgonzostruct omap4_prcm_softc { 185239281Sgonzo struct resource *sc_res[3]; 186239281Sgonzo}; 187239281Sgonzo 188239281Sgonzostatic struct omap4_prcm_softc *omap4_prcm_sc; 189239281Sgonzo 190239281Sgonzostatic int omap4_clk_generic_activate(struct ti_clock_dev *clkdev); 191239281Sgonzostatic int omap4_clk_generic_deactivate(struct ti_clock_dev *clkdev); 192239281Sgonzostatic int omap4_clk_generic_accessible(struct ti_clock_dev *clkdev); 193239281Sgonzostatic int omap4_clk_generic_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc); 194239281Sgonzostatic int omap4_clk_generic_get_source_freq(struct ti_clock_dev *clkdev, unsigned int *freq); 195239281Sgonzo 196239281Sgonzostatic int omap4_clk_gptimer_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc); 197239281Sgonzostatic int omap4_clk_gptimer_get_source_freq(struct ti_clock_dev *clkdev, unsigned int *freq); 198239281Sgonzo 199239281Sgonzostatic int omap4_clk_hsmmc_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc); 200239281Sgonzostatic int omap4_clk_hsmmc_get_source_freq(struct ti_clock_dev *clkdev, unsigned int *freq); 201239281Sgonzo 202239281Sgonzostatic int omap4_clk_hsusbhost_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc); 203239281Sgonzostatic int omap4_clk_hsusbhost_activate(struct ti_clock_dev *clkdev); 204239281Sgonzostatic int omap4_clk_hsusbhost_deactivate(struct ti_clock_dev *clkdev); 205239281Sgonzostatic int omap4_clk_hsusbhost_accessible(struct ti_clock_dev *clkdev); 206239281Sgonzo 207239281Sgonzostatic int omap4_clk_get_sysclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq); 208239281Sgonzostatic int omap4_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq); 209239281Sgonzo 210239281Sgonzo/** 211239281Sgonzo * omap_clk_devmap - Array of clock devices available on OMAP4xxx devices 212239281Sgonzo * 213239281Sgonzo * This map only defines which clocks are valid and the callback functions 214239281Sgonzo * for clock activate, deactivate, etc. It is used by the top level omap_prcm 215239281Sgonzo * driver. 216239281Sgonzo * 217239281Sgonzo * The actual details of the clocks (config registers, bit fields, sources, 218239281Sgonzo * etc) are in the private g_omap3_clk_details array below. 219239281Sgonzo * 220239281Sgonzo */ 221239281Sgonzo 222239281Sgonzo#define OMAP4_GENERIC_CLOCK_DEV(i) \ 223239281Sgonzo { .id = (i), \ 224239281Sgonzo .clk_activate = omap4_clk_generic_activate, \ 225239281Sgonzo .clk_deactivate = omap4_clk_generic_deactivate, \ 226239281Sgonzo .clk_set_source = omap4_clk_generic_set_source, \ 227239281Sgonzo .clk_accessible = omap4_clk_generic_accessible, \ 228239281Sgonzo .clk_get_source_freq = omap4_clk_generic_get_source_freq \ 229239281Sgonzo } 230239281Sgonzo 231239281Sgonzo#define OMAP4_GPTIMER_CLOCK_DEV(i) \ 232239281Sgonzo { .id = (i), \ 233239281Sgonzo .clk_activate = omap4_clk_generic_activate, \ 234239281Sgonzo .clk_deactivate = omap4_clk_generic_deactivate, \ 235239281Sgonzo .clk_set_source = omap4_clk_gptimer_set_source, \ 236239281Sgonzo .clk_accessible = omap4_clk_generic_accessible, \ 237239281Sgonzo .clk_get_source_freq = omap4_clk_gptimer_get_source_freq \ 238239281Sgonzo } 239239281Sgonzo 240239281Sgonzo#define OMAP4_HSMMC_CLOCK_DEV(i) \ 241239281Sgonzo { .id = (i), \ 242239281Sgonzo .clk_activate = omap4_clk_generic_activate, \ 243239281Sgonzo .clk_deactivate = omap4_clk_generic_deactivate, \ 244239281Sgonzo .clk_set_source = omap4_clk_hsmmc_set_source, \ 245239281Sgonzo .clk_accessible = omap4_clk_generic_accessible, \ 246239281Sgonzo .clk_get_source_freq = omap4_clk_hsmmc_get_source_freq \ 247239281Sgonzo } 248239281Sgonzo 249239281Sgonzo#define OMAP4_HSUSBHOST_CLOCK_DEV(i) \ 250239281Sgonzo { .id = (i), \ 251239281Sgonzo .clk_activate = omap4_clk_hsusbhost_activate, \ 252239281Sgonzo .clk_deactivate = omap4_clk_hsusbhost_deactivate, \ 253239281Sgonzo .clk_set_source = omap4_clk_hsusbhost_set_source, \ 254239281Sgonzo .clk_accessible = omap4_clk_hsusbhost_accessible, \ 255239281Sgonzo .clk_get_source_freq = NULL \ 256239281Sgonzo } 257239281Sgonzo 258239281Sgonzo 259239281Sgonzostruct ti_clock_dev ti_clk_devmap[] = { 260239281Sgonzo 261239281Sgonzo /* System clocks */ 262239281Sgonzo { .id = SYS_CLK, 263239281Sgonzo .clk_activate = NULL, 264239281Sgonzo .clk_deactivate = NULL, 265239281Sgonzo .clk_set_source = NULL, 266239281Sgonzo .clk_accessible = NULL, 267239281Sgonzo .clk_get_source_freq = omap4_clk_get_sysclk_freq, 268239281Sgonzo }, 269239281Sgonzo /* MPU (ARM) core clocks */ 270239281Sgonzo { .id = MPU_CLK, 271239281Sgonzo .clk_activate = NULL, 272239281Sgonzo .clk_deactivate = NULL, 273239281Sgonzo .clk_set_source = NULL, 274239281Sgonzo .clk_accessible = NULL, 275239281Sgonzo .clk_get_source_freq = omap4_clk_get_arm_fclk_freq, 276239281Sgonzo }, 277239281Sgonzo 278239281Sgonzo 279239281Sgonzo /* UART device clocks */ 280239281Sgonzo OMAP4_GENERIC_CLOCK_DEV(UART1_CLK), 281239281Sgonzo OMAP4_GENERIC_CLOCK_DEV(UART2_CLK), 282239281Sgonzo OMAP4_GENERIC_CLOCK_DEV(UART3_CLK), 283239281Sgonzo OMAP4_GENERIC_CLOCK_DEV(UART4_CLK), 284239281Sgonzo 285239281Sgonzo /* Timer device source clocks */ 286239281Sgonzo OMAP4_GPTIMER_CLOCK_DEV(GPTIMER1_CLK), 287239281Sgonzo OMAP4_GPTIMER_CLOCK_DEV(GPTIMER2_CLK), 288239281Sgonzo OMAP4_GPTIMER_CLOCK_DEV(GPTIMER3_CLK), 289239281Sgonzo OMAP4_GPTIMER_CLOCK_DEV(GPTIMER4_CLK), 290239281Sgonzo OMAP4_GPTIMER_CLOCK_DEV(GPTIMER5_CLK), 291239281Sgonzo OMAP4_GPTIMER_CLOCK_DEV(GPTIMER6_CLK), 292239281Sgonzo OMAP4_GPTIMER_CLOCK_DEV(GPTIMER7_CLK), 293239281Sgonzo OMAP4_GPTIMER_CLOCK_DEV(GPTIMER8_CLK), 294239281Sgonzo OMAP4_GPTIMER_CLOCK_DEV(GPTIMER9_CLK), 295239281Sgonzo OMAP4_GPTIMER_CLOCK_DEV(GPTIMER10_CLK), 296239281Sgonzo OMAP4_GPTIMER_CLOCK_DEV(GPTIMER11_CLK), 297239281Sgonzo 298239281Sgonzo /* MMC device clocks (MMC1 and MMC2 can have different input clocks) */ 299239281Sgonzo OMAP4_HSMMC_CLOCK_DEV(MMC1_CLK), 300239281Sgonzo OMAP4_HSMMC_CLOCK_DEV(MMC2_CLK), 301239281Sgonzo OMAP4_GENERIC_CLOCK_DEV(MMC3_CLK), 302239281Sgonzo OMAP4_GENERIC_CLOCK_DEV(MMC4_CLK), 303239281Sgonzo OMAP4_GENERIC_CLOCK_DEV(MMC5_CLK), 304239281Sgonzo 305239281Sgonzo /* USB HS (high speed TLL, EHCI and OHCI) */ 306239281Sgonzo OMAP4_HSUSBHOST_CLOCK_DEV(USBTLL_CLK), 307239281Sgonzo OMAP4_HSUSBHOST_CLOCK_DEV(USBHSHOST_CLK), 308239281Sgonzo OMAP4_HSUSBHOST_CLOCK_DEV(USBFSHOST_CLK), 309239281Sgonzo OMAP4_HSUSBHOST_CLOCK_DEV(USBP1_PHY_CLK), 310239281Sgonzo OMAP4_HSUSBHOST_CLOCK_DEV(USBP2_PHY_CLK), 311239281Sgonzo OMAP4_HSUSBHOST_CLOCK_DEV(USBP1_UTMI_CLK), 312239281Sgonzo OMAP4_HSUSBHOST_CLOCK_DEV(USBP2_UTMI_CLK), 313239281Sgonzo OMAP4_HSUSBHOST_CLOCK_DEV(USBP1_HSIC_CLK), 314239281Sgonzo OMAP4_HSUSBHOST_CLOCK_DEV(USBP2_HSIC_CLK), 315239281Sgonzo 316239281Sgonzo /* GPIO */ 317239281Sgonzo OMAP4_GENERIC_CLOCK_DEV(GPIO1_CLK), 318239281Sgonzo OMAP4_GENERIC_CLOCK_DEV(GPIO2_CLK), 319239281Sgonzo OMAP4_GENERIC_CLOCK_DEV(GPIO3_CLK), 320239281Sgonzo OMAP4_GENERIC_CLOCK_DEV(GPIO4_CLK), 321239281Sgonzo OMAP4_GENERIC_CLOCK_DEV(GPIO5_CLK), 322239281Sgonzo OMAP4_GENERIC_CLOCK_DEV(GPIO6_CLK), 323239281Sgonzo 324239281Sgonzo /* sDMA */ 325239281Sgonzo OMAP4_GENERIC_CLOCK_DEV(SDMA_CLK), 326239281Sgonzo 327239281Sgonzo /* I2C */ 328239281Sgonzo OMAP4_GENERIC_CLOCK_DEV(I2C1_CLK), 329239281Sgonzo OMAP4_GENERIC_CLOCK_DEV(I2C2_CLK), 330239281Sgonzo OMAP4_GENERIC_CLOCK_DEV(I2C3_CLK), 331239281Sgonzo OMAP4_GENERIC_CLOCK_DEV(I2C4_CLK), 332239281Sgonzo 333239281Sgonzo { INVALID_CLK_IDENT, NULL, NULL, NULL, NULL } 334239281Sgonzo}; 335239281Sgonzo 336239281Sgonzo/** 337239281Sgonzo * omap4_clk_details - Stores details for all the different clocks supported 338239281Sgonzo * 339239281Sgonzo * Whenever an operation on a clock is being performed (activated, deactivated, 340239281Sgonzo * etc) this array is looked up to find the correct register and bit(s) we 341239281Sgonzo * should be modifying. 342239281Sgonzo * 343239281Sgonzo */ 344239281Sgonzostruct omap4_clk_details { 345239281Sgonzo clk_ident_t id; 346239281Sgonzo 347239281Sgonzo uint32_t mem_region; 348239281Sgonzo uint32_t clksel_reg; 349239281Sgonzo 350239281Sgonzo int32_t src_freq; 351239281Sgonzo 352239281Sgonzo uint32_t enable_mode; 353239281Sgonzo}; 354239281Sgonzo 355239281Sgonzo#define OMAP4_GENERIC_CLOCK_DETAILS(i, f, m, r, e) \ 356239281Sgonzo { .id = (i), \ 357239281Sgonzo .mem_region = (m), \ 358239281Sgonzo .clksel_reg = (r), \ 359239281Sgonzo .src_freq = (f), \ 360239281Sgonzo .enable_mode = (e), \ 361239281Sgonzo } 362239281Sgonzo 363239281Sgonzostatic struct omap4_clk_details g_omap4_clk_details[] = { 364239281Sgonzo 365239281Sgonzo /* UART */ 366239281Sgonzo OMAP4_GENERIC_CLOCK_DETAILS(UART1_CLK, FREQ_48MHZ, CM2_INSTANCE_MEM_REGION, 367239281Sgonzo (L4PER_CM2_OFFSET + 0x0140), CLKCTRL_MODULEMODE_ENABLE), 368239281Sgonzo OMAP4_GENERIC_CLOCK_DETAILS(UART2_CLK, FREQ_48MHZ, CM2_INSTANCE_MEM_REGION, 369239281Sgonzo (L4PER_CM2_OFFSET + 0x0148), CLKCTRL_MODULEMODE_ENABLE), 370239281Sgonzo OMAP4_GENERIC_CLOCK_DETAILS(UART3_CLK, FREQ_48MHZ, CM2_INSTANCE_MEM_REGION, 371239281Sgonzo (L4PER_CM2_OFFSET + 0x0140), CLKCTRL_MODULEMODE_ENABLE), 372239281Sgonzo OMAP4_GENERIC_CLOCK_DETAILS(UART4_CLK, FREQ_48MHZ, CM2_INSTANCE_MEM_REGION, 373239281Sgonzo (L4PER_CM2_OFFSET + 0x0148), CLKCTRL_MODULEMODE_ENABLE), 374239281Sgonzo 375239281Sgonzo /* General purpose timers */ 376239281Sgonzo OMAP4_GENERIC_CLOCK_DETAILS(GPTIMER1_CLK, -1, PRM_INSTANCE_MEM_REGION, 377239281Sgonzo (WKUP_CM_OFFSET + 0x040), CLKCTRL_MODULEMODE_ENABLE), 378239281Sgonzo OMAP4_GENERIC_CLOCK_DETAILS(GPTIMER2_CLK, -1, CM2_INSTANCE_MEM_REGION, 379239281Sgonzo (L4PER_CM2_OFFSET + 0x038), CLKCTRL_MODULEMODE_ENABLE), 380239281Sgonzo OMAP4_GENERIC_CLOCK_DETAILS(GPTIMER3_CLK, -1, CM2_INSTANCE_MEM_REGION, 381239281Sgonzo (L4PER_CM2_OFFSET + 0x040), CLKCTRL_MODULEMODE_ENABLE), 382239281Sgonzo OMAP4_GENERIC_CLOCK_DETAILS(GPTIMER4_CLK, -1, CM2_INSTANCE_MEM_REGION, 383239281Sgonzo (L4PER_CM2_OFFSET + 0x048), CLKCTRL_MODULEMODE_ENABLE), 384239281Sgonzo OMAP4_GENERIC_CLOCK_DETAILS(GPTIMER5_CLK, -1, CM1_INSTANCE_MEM_REGION, 385239281Sgonzo (ABE_CM1_OFFSET + 0x068), CLKCTRL_MODULEMODE_ENABLE), 386239281Sgonzo OMAP4_GENERIC_CLOCK_DETAILS(GPTIMER6_CLK, -1, CM1_INSTANCE_MEM_REGION, 387239281Sgonzo (ABE_CM1_OFFSET + 0x070), CLKCTRL_MODULEMODE_ENABLE), 388239281Sgonzo OMAP4_GENERIC_CLOCK_DETAILS(GPTIMER7_CLK, -1, CM1_INSTANCE_MEM_REGION, 389239281Sgonzo (ABE_CM1_OFFSET + 0x078), CLKCTRL_MODULEMODE_ENABLE), 390239281Sgonzo OMAP4_GENERIC_CLOCK_DETAILS(GPTIMER8_CLK, -1, CM1_INSTANCE_MEM_REGION, 391239281Sgonzo (ABE_CM1_OFFSET + 0x080), CLKCTRL_MODULEMODE_ENABLE), 392239281Sgonzo OMAP4_GENERIC_CLOCK_DETAILS(GPTIMER9_CLK, -1, CM2_INSTANCE_MEM_REGION, 393239281Sgonzo (L4PER_CM2_OFFSET + 0x050), CLKCTRL_MODULEMODE_ENABLE), 394239281Sgonzo OMAP4_GENERIC_CLOCK_DETAILS(GPTIMER10_CLK, -1, CM2_INSTANCE_MEM_REGION, 395239281Sgonzo (L4PER_CM2_OFFSET + 0x028), CLKCTRL_MODULEMODE_ENABLE), 396239281Sgonzo OMAP4_GENERIC_CLOCK_DETAILS(GPTIMER11_CLK, -1, CM2_INSTANCE_MEM_REGION, 397239281Sgonzo (L4PER_CM2_OFFSET + 0x030), CLKCTRL_MODULEMODE_ENABLE), 398239281Sgonzo 399239281Sgonzo /* HSMMC (MMC1 and MMC2 can have different input clocks) */ 400239281Sgonzo OMAP4_GENERIC_CLOCK_DETAILS(MMC1_CLK, -1, CM2_INSTANCE_MEM_REGION, 401239281Sgonzo (L3INIT_CM2_OFFSET + 0x028), /*CLKCTRL_MODULEMODE_ENABLE*/2), 402239281Sgonzo OMAP4_GENERIC_CLOCK_DETAILS(MMC2_CLK, -1, CM2_INSTANCE_MEM_REGION, 403239281Sgonzo (L3INIT_CM2_OFFSET + 0x030), /*CLKCTRL_MODULEMODE_ENABLE*/2), 404239281Sgonzo OMAP4_GENERIC_CLOCK_DETAILS(MMC3_CLK, FREQ_48MHZ, CM2_INSTANCE_MEM_REGION, 405239281Sgonzo (L4PER_CM2_OFFSET + 0x120), /*CLKCTRL_MODULEMODE_ENABLE*/2), 406239281Sgonzo OMAP4_GENERIC_CLOCK_DETAILS(MMC4_CLK, FREQ_48MHZ, CM2_INSTANCE_MEM_REGION, 407239281Sgonzo (L4PER_CM2_OFFSET + 0x128), /*CLKCTRL_MODULEMODE_ENABLE*/2), 408239281Sgonzo OMAP4_GENERIC_CLOCK_DETAILS(MMC5_CLK, FREQ_48MHZ, CM2_INSTANCE_MEM_REGION, 409239281Sgonzo (L4PER_CM2_OFFSET + 0x160), /*CLKCTRL_MODULEMODE_ENABLE*/1), 410239281Sgonzo 411239281Sgonzo /* GPIO modules */ 412239281Sgonzo OMAP4_GENERIC_CLOCK_DETAILS(GPIO1_CLK, -1, PRM_INSTANCE_MEM_REGION, 413239281Sgonzo (WKUP_CM_OFFSET + 0x038), CLKCTRL_MODULEMODE_AUTO), 414239281Sgonzo OMAP4_GENERIC_CLOCK_DETAILS(GPIO2_CLK, -1, CM2_INSTANCE_MEM_REGION, 415239281Sgonzo (L4PER_CM2_OFFSET + 0x060), CLKCTRL_MODULEMODE_AUTO), 416239281Sgonzo OMAP4_GENERIC_CLOCK_DETAILS(GPIO3_CLK, -1, CM2_INSTANCE_MEM_REGION, 417239281Sgonzo (L4PER_CM2_OFFSET + 0x068), CLKCTRL_MODULEMODE_AUTO), 418239281Sgonzo OMAP4_GENERIC_CLOCK_DETAILS(GPIO4_CLK, -1, CM2_INSTANCE_MEM_REGION, 419239281Sgonzo (L4PER_CM2_OFFSET + 0x070), CLKCTRL_MODULEMODE_AUTO), 420239281Sgonzo OMAP4_GENERIC_CLOCK_DETAILS(GPIO5_CLK, -1, CM2_INSTANCE_MEM_REGION, 421239281Sgonzo (L4PER_CM2_OFFSET + 0x078), CLKCTRL_MODULEMODE_AUTO), 422239281Sgonzo OMAP4_GENERIC_CLOCK_DETAILS(GPIO6_CLK, -1, CM2_INSTANCE_MEM_REGION, 423239281Sgonzo (L4PER_CM2_OFFSET + 0x080), CLKCTRL_MODULEMODE_AUTO), 424239281Sgonzo 425239281Sgonzo /* sDMA block */ 426239281Sgonzo OMAP4_GENERIC_CLOCK_DETAILS(SDMA_CLK, -1, CM2_INSTANCE_MEM_REGION, 427239281Sgonzo (CORE_CM2_OFFSET + 0x300), CLKCTRL_MODULEMODE_AUTO), 428239281Sgonzo 429239281Sgonzo /* I2C modules */ 430239281Sgonzo OMAP4_GENERIC_CLOCK_DETAILS(I2C1_CLK, -1, CM2_INSTANCE_MEM_REGION, 431239281Sgonzo (L4PER_CM2_OFFSET + 0x0A0), CLKCTRL_MODULEMODE_ENABLE), 432239281Sgonzo OMAP4_GENERIC_CLOCK_DETAILS(I2C2_CLK, -1, CM2_INSTANCE_MEM_REGION, 433239281Sgonzo (L4PER_CM2_OFFSET + 0x0A8), CLKCTRL_MODULEMODE_ENABLE), 434239281Sgonzo OMAP4_GENERIC_CLOCK_DETAILS(I2C3_CLK, -1, CM2_INSTANCE_MEM_REGION, 435239281Sgonzo (L4PER_CM2_OFFSET + 0x0B0), CLKCTRL_MODULEMODE_ENABLE), 436239281Sgonzo OMAP4_GENERIC_CLOCK_DETAILS(I2C4_CLK, -1, CM2_INSTANCE_MEM_REGION, 437239281Sgonzo (L4PER_CM2_OFFSET + 0x0B8), CLKCTRL_MODULEMODE_ENABLE), 438239281Sgonzo 439239281Sgonzo { INVALID_CLK_IDENT, 0, 0, 0, 0 }, 440239281Sgonzo}; 441239281Sgonzo 442239281Sgonzo/** 443239281Sgonzo * MAX_MODULE_ENABLE_WAIT - the number of loops to wait for the module to come 444239281Sgonzo * alive. 445239281Sgonzo * 446239281Sgonzo */ 447239281Sgonzo#define MAX_MODULE_ENABLE_WAIT 100 448239281Sgonzo 449239281Sgonzo/** 450239281Sgonzo * ARRAY_SIZE - Macro to return the number of elements in a static const array. 451239281Sgonzo * 452239281Sgonzo */ 453239281Sgonzo#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) 454239281Sgonzo 455239281Sgonzo/** 456239281Sgonzo * omap4_clk_details - writes a 32-bit value to one of the timer registers 457239281Sgonzo * @timer: Timer device context 458239281Sgonzo * @off: The offset of a register from the timer register address range 459239281Sgonzo * @val: The value to write into the register 460239281Sgonzo * 461239281Sgonzo * 462239281Sgonzo * RETURNS: 463239281Sgonzo * nothing 464239281Sgonzo */ 465239281Sgonzostatic struct omap4_clk_details* 466239281Sgonzoomap4_clk_details(clk_ident_t id) 467239281Sgonzo{ 468239281Sgonzo struct omap4_clk_details *walker; 469239281Sgonzo 470239281Sgonzo for (walker = g_omap4_clk_details; walker->id != INVALID_CLK_IDENT; walker++) { 471239281Sgonzo if (id == walker->id) 472239281Sgonzo return (walker); 473239281Sgonzo } 474239281Sgonzo 475239281Sgonzo return NULL; 476239281Sgonzo} 477239281Sgonzo 478239281Sgonzo/** 479239281Sgonzo * omap4_clk_generic_activate - checks if a module is accessible 480239281Sgonzo * @module: identifier for the module to check, see omap3_prcm.h for a list 481239281Sgonzo * of possible modules. 482239281Sgonzo * Example: OMAP3_MODULE_MMC1 483239281Sgonzo * 484239281Sgonzo * 485239281Sgonzo * 486239281Sgonzo * LOCKING: 487239281Sgonzo * Inherits the locks from the omap_prcm driver, no internal locking. 488239281Sgonzo * 489239281Sgonzo * RETURNS: 490239281Sgonzo * Returns 0 on success or a positive error code on failure. 491239281Sgonzo */ 492239281Sgonzostatic int 493239281Sgonzoomap4_clk_generic_activate(struct ti_clock_dev *clkdev) 494239281Sgonzo{ 495239281Sgonzo struct omap4_prcm_softc *sc = omap4_prcm_sc; 496239281Sgonzo struct omap4_clk_details* clk_details; 497239281Sgonzo struct resource* clk_mem_res; 498239281Sgonzo uint32_t clksel; 499239281Sgonzo unsigned int i; 500239281Sgonzo 501239281Sgonzo if (sc == NULL) 502239281Sgonzo return ENXIO; 503239281Sgonzo 504239281Sgonzo clk_details = omap4_clk_details(clkdev->id); 505239281Sgonzo 506239281Sgonzo if (clk_details == NULL) 507239281Sgonzo return (ENXIO); 508239281Sgonzo 509239281Sgonzo clk_mem_res = sc->sc_res[clk_details->mem_region]; 510239281Sgonzo 511239281Sgonzo if (clk_mem_res == NULL) 512239281Sgonzo return (EINVAL); 513239281Sgonzo 514239281Sgonzo /* All the 'generic' clocks have a CLKCTRL register which is more or less 515239281Sgonzo * generic - the have at least two fielda called MODULEMODE and IDLEST. 516239281Sgonzo */ 517239281Sgonzo clksel = bus_read_4(clk_mem_res, clk_details->clksel_reg); 518239281Sgonzo clksel &= ~CLKCTRL_MODULEMODE_MASK; 519239281Sgonzo clksel |= clk_details->enable_mode; 520239281Sgonzo bus_write_4(clk_mem_res, clk_details->clksel_reg, clksel); 521239281Sgonzo 522239281Sgonzo /* Now poll on the IDLEST register to tell us if the module has come up. 523239281Sgonzo * TODO: We need to take into account the parent clocks. 524239281Sgonzo */ 525239281Sgonzo 526239281Sgonzo /* Try MAX_MODULE_ENABLE_WAIT number of times to check if enabled */ 527239281Sgonzo for (i = 0; i < MAX_MODULE_ENABLE_WAIT; i++) { 528239281Sgonzo clksel = bus_read_4(clk_mem_res, clk_details->clksel_reg); 529239281Sgonzo if ((clksel & CLKCTRL_IDLEST_MASK) == CLKCTRL_IDLEST_ENABLED) 530239281Sgonzo break; 531239281Sgonzo DELAY(10); 532239281Sgonzo } 533239281Sgonzo 534239281Sgonzo /* Check the enabled state */ 535239281Sgonzo if ((clksel & CLKCTRL_IDLEST_MASK) != CLKCTRL_IDLEST_ENABLED) { 536239281Sgonzo printf("Error: failed to enable module with clock %d\n", clkdev->id); 537239281Sgonzo printf("Error: 0x%08x => 0x%08x\n", clk_details->clksel_reg, clksel); 538239281Sgonzo return (ETIMEDOUT); 539239281Sgonzo } 540239281Sgonzo 541239281Sgonzo return (0); 542239281Sgonzo} 543239281Sgonzo 544239281Sgonzo/** 545239281Sgonzo * omap4_clk_generic_deactivate - checks if a module is accessible 546239281Sgonzo * @module: identifier for the module to check, see omap3_prcm.h for a list 547239281Sgonzo * of possible modules. 548239281Sgonzo * Example: OMAP3_MODULE_MMC1 549239281Sgonzo * 550239281Sgonzo * 551239281Sgonzo * 552239281Sgonzo * LOCKING: 553239281Sgonzo * Inherits the locks from the omap_prcm driver, no internal locking. 554239281Sgonzo * 555239281Sgonzo * RETURNS: 556239281Sgonzo * Returns 0 on success or a positive error code on failure. 557239281Sgonzo */ 558239281Sgonzostatic int 559239281Sgonzoomap4_clk_generic_deactivate(struct ti_clock_dev *clkdev) 560239281Sgonzo{ 561239281Sgonzo struct omap4_prcm_softc *sc = omap4_prcm_sc; 562239281Sgonzo struct omap4_clk_details* clk_details; 563239281Sgonzo struct resource* clk_mem_res; 564239281Sgonzo uint32_t clksel; 565239281Sgonzo 566239281Sgonzo if (sc == NULL) 567239281Sgonzo return ENXIO; 568239281Sgonzo 569239281Sgonzo clk_details = omap4_clk_details(clkdev->id); 570239281Sgonzo 571239281Sgonzo if (clk_details == NULL) 572239281Sgonzo return (ENXIO); 573239281Sgonzo 574239281Sgonzo clk_mem_res = sc->sc_res[clk_details->mem_region]; 575239281Sgonzo 576239281Sgonzo if (clk_mem_res == NULL) 577239281Sgonzo return (EINVAL); 578239281Sgonzo 579239281Sgonzo /* All the 'generic' clocks have a CLKCTRL register which is more or less 580239281Sgonzo * generic - the have at least two fielda called MODULEMODE and IDLEST. 581239281Sgonzo */ 582239281Sgonzo clksel = bus_read_4(clk_mem_res, clk_details->clksel_reg); 583239281Sgonzo clksel &= ~CLKCTRL_MODULEMODE_MASK; 584239281Sgonzo clksel |= CLKCTRL_MODULEMODE_DISABLE; 585239281Sgonzo bus_write_4(clk_mem_res, clk_details->clksel_reg, clksel); 586239281Sgonzo 587239281Sgonzo return (0); 588239281Sgonzo} 589239281Sgonzo 590239281Sgonzo/** 591239281Sgonzo * omap4_clk_generic_set_source - checks if a module is accessible 592239281Sgonzo * @module: identifier for the module to check, see omap3_prcm.h for a list 593239281Sgonzo * of possible modules. 594239281Sgonzo * Example: OMAP3_MODULE_MMC1 595239281Sgonzo * 596239281Sgonzo * 597239281Sgonzo * 598239281Sgonzo * LOCKING: 599239281Sgonzo * Inherits the locks from the omap_prcm driver, no internal locking. 600239281Sgonzo * 601239281Sgonzo * RETURNS: 602239281Sgonzo * Returns 0 on success or a positive error code on failure. 603239281Sgonzo */ 604239281Sgonzostatic int 605239281Sgonzoomap4_clk_generic_set_source(struct ti_clock_dev *clkdev, 606239281Sgonzo clk_src_t clksrc) 607239281Sgonzo{ 608239281Sgonzo 609239281Sgonzo return (0); 610239281Sgonzo} 611239281Sgonzo 612239281Sgonzo/** 613239281Sgonzo * omap4_clk_generic_accessible - checks if a module is accessible 614239281Sgonzo * @module: identifier for the module to check, see omap3_prcm.h for a list 615239281Sgonzo * of possible modules. 616239281Sgonzo * Example: OMAP3_MODULE_MMC1 617239281Sgonzo * 618239281Sgonzo * 619239281Sgonzo * 620239281Sgonzo * LOCKING: 621239281Sgonzo * Inherits the locks from the omap_prcm driver, no internal locking. 622239281Sgonzo * 623239281Sgonzo * RETURNS: 624239281Sgonzo * Returns 0 on success or a negative error code on failure. 625239281Sgonzo */ 626239281Sgonzostatic int 627239281Sgonzoomap4_clk_generic_accessible(struct ti_clock_dev *clkdev) 628239281Sgonzo{ 629239281Sgonzo struct omap4_prcm_softc *sc = omap4_prcm_sc; 630239281Sgonzo struct omap4_clk_details* clk_details; 631239281Sgonzo struct resource* clk_mem_res; 632239281Sgonzo uint32_t clksel; 633239281Sgonzo 634239281Sgonzo if (sc == NULL) 635239281Sgonzo return ENXIO; 636239281Sgonzo 637239281Sgonzo clk_details = omap4_clk_details(clkdev->id); 638239281Sgonzo 639239281Sgonzo if (clk_details == NULL) 640239281Sgonzo return (ENXIO); 641239281Sgonzo 642239281Sgonzo clk_mem_res = sc->sc_res[clk_details->mem_region]; 643239281Sgonzo 644239281Sgonzo if (clk_mem_res == NULL) 645239281Sgonzo return (EINVAL); 646239281Sgonzo 647239281Sgonzo clksel = bus_read_4(clk_mem_res, clk_details->clksel_reg); 648239281Sgonzo 649239281Sgonzo /* Check the enabled state */ 650239281Sgonzo if ((clksel & CLKCTRL_IDLEST_MASK) != CLKCTRL_IDLEST_ENABLED) 651239281Sgonzo return (0); 652239281Sgonzo 653239281Sgonzo return (1); 654239281Sgonzo} 655239281Sgonzo 656239281Sgonzo/** 657239281Sgonzo * omap4_clk_generic_get_source_freq - checks if a module is accessible 658239281Sgonzo * @module: identifier for the module to check, see omap3_prcm.h for a list 659239281Sgonzo * of possible modules. 660239281Sgonzo * Example: OMAP3_MODULE_MMC1 661239281Sgonzo * 662239281Sgonzo * 663239281Sgonzo * 664239281Sgonzo * LOCKING: 665239281Sgonzo * Inherits the locks from the omap_prcm driver, no internal locking. 666239281Sgonzo * 667239281Sgonzo * RETURNS: 668239281Sgonzo * Returns 0 on success or a negative error code on failure. 669239281Sgonzo */ 670239281Sgonzostatic int 671239281Sgonzoomap4_clk_generic_get_source_freq(struct ti_clock_dev *clkdev, 672239281Sgonzo unsigned int *freq 673239281Sgonzo ) 674239281Sgonzo{ 675239281Sgonzo struct omap4_clk_details* clk_details = omap4_clk_details(clkdev->id); 676239281Sgonzo 677239281Sgonzo if (clk_details == NULL) 678239281Sgonzo return (ENXIO); 679239281Sgonzo 680239281Sgonzo /* Simply return the stored frequency */ 681239281Sgonzo if (freq) 682239281Sgonzo *freq = (unsigned int)clk_details->src_freq; 683239281Sgonzo 684239281Sgonzo return (0); 685239281Sgonzo} 686239281Sgonzo 687239281Sgonzo 688239281Sgonzo/** 689239281Sgonzo * omap4_clk_gptimer_set_source - checks if a module is accessible 690239281Sgonzo * @module: identifier for the module to check, see omap3_prcm.h for a list 691239281Sgonzo * of possible modules. 692239281Sgonzo * Example: OMAP3_MODULE_MMC1 693239281Sgonzo * 694239281Sgonzo * 695239281Sgonzo * 696239281Sgonzo * LOCKING: 697239281Sgonzo * Inherits the locks from the omap_prcm driver, no internal locking. 698239281Sgonzo * 699239281Sgonzo * RETURNS: 700239281Sgonzo * Returns 0 on success or a negative error code on failure. 701239281Sgonzo */ 702239281Sgonzostatic int 703239281Sgonzoomap4_clk_gptimer_set_source(struct ti_clock_dev *clkdev, 704239281Sgonzo clk_src_t clksrc) 705239281Sgonzo{ 706239281Sgonzo struct omap4_prcm_softc *sc = omap4_prcm_sc; 707239281Sgonzo struct omap4_clk_details* clk_details; 708239281Sgonzo struct resource* clk_mem_res; 709239281Sgonzo 710239281Sgonzo if (sc == NULL) 711239281Sgonzo return ENXIO; 712239281Sgonzo 713239281Sgonzo clk_details = omap4_clk_details(clkdev->id); 714239281Sgonzo 715239281Sgonzo if (clk_details == NULL) 716239281Sgonzo return (ENXIO); 717239281Sgonzo 718239281Sgonzo clk_mem_res = sc->sc_res[clk_details->mem_region]; 719239281Sgonzo 720239281Sgonzo if (clk_mem_res == NULL) 721239281Sgonzo return (EINVAL); 722239281Sgonzo 723239281Sgonzo /* TODO: Implement */ 724239281Sgonzo 725239281Sgonzo return (0); 726239281Sgonzo} 727239281Sgonzo 728239281Sgonzo/** 729239281Sgonzo * omap4_clk_gptimer_get_source_freq - checks if a module is accessible 730239281Sgonzo * @module: identifier for the module to check, see omap3_prcm.h for a list 731239281Sgonzo * of possible modules. 732239281Sgonzo * Example: OMAP3_MODULE_MMC1 733239281Sgonzo * 734239281Sgonzo * 735239281Sgonzo * 736239281Sgonzo * LOCKING: 737239281Sgonzo * Inherits the locks from the omap_prcm driver, no internal locking. 738239281Sgonzo * 739239281Sgonzo * RETURNS: 740239281Sgonzo * Returns 0 on success or a negative error code on failure. 741239281Sgonzo */ 742239281Sgonzostatic int 743239281Sgonzoomap4_clk_gptimer_get_source_freq(struct ti_clock_dev *clkdev, 744239281Sgonzo unsigned int *freq 745239281Sgonzo ) 746239281Sgonzo{ 747239281Sgonzo struct omap4_prcm_softc *sc = omap4_prcm_sc; 748239281Sgonzo struct omap4_clk_details* clk_details; 749239281Sgonzo struct resource* clk_mem_res; 750239281Sgonzo uint32_t clksel; 751239281Sgonzo unsigned int src_freq; 752239281Sgonzo 753239281Sgonzo if (sc == NULL) 754239281Sgonzo return ENXIO; 755239281Sgonzo 756239281Sgonzo clk_details = omap4_clk_details(clkdev->id); 757239281Sgonzo 758239281Sgonzo if (clk_details == NULL) 759239281Sgonzo return (ENXIO); 760239281Sgonzo 761239281Sgonzo clk_mem_res = sc->sc_res[clk_details->mem_region]; 762239281Sgonzo 763239281Sgonzo if (clk_mem_res == NULL) 764239281Sgonzo return (EINVAL); 765239281Sgonzo 766239281Sgonzo /* Need to read the CLKSEL field to determine the clock source */ 767239281Sgonzo clksel = bus_read_4(clk_mem_res, clk_details->clksel_reg); 768239281Sgonzo if (clksel & (0x1UL << 24)) 769239281Sgonzo src_freq = FREQ_32KHZ; 770239281Sgonzo else 771239281Sgonzo omap4_clk_get_sysclk_freq(NULL, &src_freq); 772239281Sgonzo 773239281Sgonzo /* Return the frequency */ 774239281Sgonzo if (freq) 775239281Sgonzo *freq = src_freq; 776239281Sgonzo 777239281Sgonzo return (0); 778239281Sgonzo} 779239281Sgonzo 780239281Sgonzo/** 781239281Sgonzo * omap4_clk_hsmmc_set_source - sets the source clock (freq) 782239281Sgonzo * @clkdev: pointer to the clockdev structure (id field will contain clock id) 783239281Sgonzo * 784239281Sgonzo * The MMC 1 and 2 clocks can be source from either a 64MHz or 96MHz clock. 785239281Sgonzo * 786239281Sgonzo * LOCKING: 787239281Sgonzo * Inherits the locks from the omap_prcm driver, no internal locking. 788239281Sgonzo * 789239281Sgonzo * RETURNS: 790239281Sgonzo * Returns 0 on success or a negative error code on failure. 791239281Sgonzo */ 792239281Sgonzostatic int 793239281Sgonzoomap4_clk_hsmmc_set_source(struct ti_clock_dev *clkdev, 794239281Sgonzo clk_src_t clksrc) 795239281Sgonzo{ 796239281Sgonzo struct omap4_prcm_softc *sc = omap4_prcm_sc; 797239281Sgonzo struct omap4_clk_details* clk_details; 798239281Sgonzo struct resource* clk_mem_res; 799239281Sgonzo uint32_t clksel; 800239281Sgonzo 801239281Sgonzo if (sc == NULL) 802239281Sgonzo return ENXIO; 803239281Sgonzo 804239281Sgonzo clk_details = omap4_clk_details(clkdev->id); 805239281Sgonzo 806239281Sgonzo if (clk_details == NULL) 807239281Sgonzo return (ENXIO); 808239281Sgonzo 809239281Sgonzo clk_mem_res = sc->sc_res[clk_details->mem_region]; 810239281Sgonzo 811239281Sgonzo if (clk_mem_res == NULL) 812239281Sgonzo return (EINVAL); 813239281Sgonzo 814239281Sgonzo /* For MMC modules 3, 4 & 5 you can't change the freq, it's always 48MHz */ 815239281Sgonzo if ((clkdev->id == MMC3_CLK) || (clkdev->id == MMC4_CLK) || 816239281Sgonzo (clkdev->id == MMC5_CLK)) { 817239281Sgonzo if (clksrc != F48MHZ_CLK) 818239281Sgonzo return (EINVAL); 819239281Sgonzo return 0; 820239281Sgonzo } 821239281Sgonzo 822239281Sgonzo 823239281Sgonzo clksel = bus_read_4(clk_mem_res, clk_details->clksel_reg); 824239281Sgonzo 825239281Sgonzo /* Bit 24 is set if 96MHz clock or cleared for 64MHz clock */ 826239281Sgonzo if (clksrc == F64MHZ_CLK) 827239281Sgonzo clksel &= ~(0x1UL << 24); 828239281Sgonzo else if (clksrc == F96MHZ_CLK) 829239281Sgonzo clksel |= (0x1UL << 24); 830239281Sgonzo else 831239281Sgonzo return (EINVAL); 832239281Sgonzo 833239281Sgonzo bus_write_4(clk_mem_res, clk_details->clksel_reg, clksel); 834239281Sgonzo 835239281Sgonzo return (0); 836239281Sgonzo} 837239281Sgonzo 838239281Sgonzo/** 839239281Sgonzo * omap4_clk_hsmmc_get_source_freq - checks if a module is accessible 840239281Sgonzo * @clkdev: pointer to the clockdev structure (id field will contain clock id) 841239281Sgonzo * 842239281Sgonzo * 843239281Sgonzo * 844239281Sgonzo * LOCKING: 845239281Sgonzo * Inherits the locks from the omap_prcm driver, no internal locking. 846239281Sgonzo * 847239281Sgonzo * RETURNS: 848239281Sgonzo * Returns 0 on success or a negative error code on failure. 849239281Sgonzo */ 850239281Sgonzostatic int 851239281Sgonzoomap4_clk_hsmmc_get_source_freq(struct ti_clock_dev *clkdev, 852239281Sgonzo unsigned int *freq 853239281Sgonzo ) 854239281Sgonzo{ 855239281Sgonzo struct omap4_prcm_softc *sc = omap4_prcm_sc; 856239281Sgonzo struct omap4_clk_details* clk_details; 857239281Sgonzo struct resource* clk_mem_res; 858239281Sgonzo uint32_t clksel; 859239281Sgonzo unsigned int src_freq; 860239281Sgonzo 861239281Sgonzo if (sc == NULL) 862239281Sgonzo return ENXIO; 863239281Sgonzo 864239281Sgonzo clk_details = omap4_clk_details(clkdev->id); 865239281Sgonzo 866239281Sgonzo if (clk_details == NULL) 867239281Sgonzo return (ENXIO); 868239281Sgonzo 869239281Sgonzo clk_mem_res = sc->sc_res[clk_details->mem_region]; 870239281Sgonzo 871239281Sgonzo if (clk_mem_res == NULL) 872239281Sgonzo return (EINVAL); 873239281Sgonzo 874239281Sgonzo switch (clkdev->id) { 875239281Sgonzo case MMC1_CLK: 876239281Sgonzo case MMC2_CLK: 877239281Sgonzo /* Need to read the CLKSEL field to determine the clock source */ 878239281Sgonzo clksel = bus_read_4(clk_mem_res, clk_details->clksel_reg); 879239281Sgonzo if (clksel & (0x1UL << 24)) 880239281Sgonzo src_freq = FREQ_96MHZ; 881239281Sgonzo else 882239281Sgonzo src_freq = FREQ_64MHZ; 883239281Sgonzo break; 884239281Sgonzo case MMC3_CLK: 885239281Sgonzo case MMC4_CLK: 886239281Sgonzo case MMC5_CLK: 887239281Sgonzo src_freq = FREQ_48MHZ; 888239281Sgonzo break; 889239281Sgonzo default: 890239281Sgonzo return (EINVAL); 891239281Sgonzo } 892239281Sgonzo 893239281Sgonzo /* Return the frequency */ 894239281Sgonzo if (freq) 895239281Sgonzo *freq = src_freq; 896239281Sgonzo 897239281Sgonzo return (0); 898239281Sgonzo} 899239281Sgonzo 900239281Sgonzo/** 901239281Sgonzo * omap4_clk_get_sysclk_freq - gets the sysclk frequency 902239281Sgonzo * @sc: pointer to the clk module/device context 903239281Sgonzo * 904239281Sgonzo * Read the clocking information from the power-control/boot-strap registers, 905239281Sgonzo * and stored in two global variables. 906239281Sgonzo * 907239281Sgonzo * RETURNS: 908239281Sgonzo * nothing, values are saved in global variables 909239281Sgonzo */ 910239281Sgonzostatic int 911239281Sgonzoomap4_clk_get_sysclk_freq(struct ti_clock_dev *clkdev, 912239281Sgonzo unsigned int *freq) 913239281Sgonzo{ 914239281Sgonzo uint32_t clksel; 915239281Sgonzo uint32_t sysclk; 916239281Sgonzo struct omap4_prcm_softc *sc = omap4_prcm_sc; 917239281Sgonzo 918239281Sgonzo if (sc == NULL) 919239281Sgonzo return ENXIO; 920239281Sgonzo 921239281Sgonzo /* Read the input clock freq from the configuration register (CM_SYS_CLKSEL) */ 922239281Sgonzo clksel = bus_read_4(sc->sc_res[PRM_INSTANCE_MEM_REGION], CM_SYS_CLKSEL_OFFSET); 923239281Sgonzo switch (clksel & 0x7) { 924239281Sgonzo case 0x1: 925239281Sgonzo /* 12Mhz */ 926239281Sgonzo sysclk = 12000000; 927239281Sgonzo break; 928239281Sgonzo case 0x3: 929239281Sgonzo /* 16.8Mhz */ 930239281Sgonzo sysclk = 16800000; 931239281Sgonzo break; 932239281Sgonzo case 0x4: 933239281Sgonzo /* 19.2Mhz */ 934239281Sgonzo sysclk = 19200000; 935239281Sgonzo break; 936239281Sgonzo case 0x5: 937239281Sgonzo /* 26Mhz */ 938239281Sgonzo sysclk = 26000000; 939239281Sgonzo break; 940239281Sgonzo case 0x7: 941239281Sgonzo /* 38.4Mhz */ 942239281Sgonzo sysclk = 38400000; 943239281Sgonzo break; 944239281Sgonzo default: 945239281Sgonzo panic("%s: Invalid clock freq", __func__); 946239281Sgonzo } 947239281Sgonzo 948239281Sgonzo /* Return the value */ 949239281Sgonzo if (freq) 950239281Sgonzo *freq = sysclk; 951239281Sgonzo 952239281Sgonzo return (0); 953239281Sgonzo} 954239281Sgonzo 955239281Sgonzo/** 956239281Sgonzo * omap4_clk_get_arm_fclk_freq - gets the MPU clock frequency 957239281Sgonzo * @clkdev: ignored 958239281Sgonzo * @freq: pointer which upon return will contain the freq in hz 959239281Sgonzo * @mem_res: array of allocated memory resources 960239281Sgonzo * 961239281Sgonzo * Reads the frequency setting information registers and returns the value 962239281Sgonzo * in the freq variable. 963239281Sgonzo * 964239281Sgonzo * RETURNS: 965239281Sgonzo * returns 0 on success, a positive error code on failure. 966239281Sgonzo */ 967239281Sgonzostatic int 968239281Sgonzoomap4_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, 969239281Sgonzo unsigned int *freq) 970239281Sgonzo{ 971239281Sgonzo uint32_t clksel; 972239281Sgonzo uint32_t pll_mult, pll_div; 973239281Sgonzo uint32_t mpuclk, sysclk; 974239281Sgonzo struct omap4_prcm_softc *sc = omap4_prcm_sc; 975239281Sgonzo 976239281Sgonzo if (sc == NULL) 977239281Sgonzo return ENXIO; 978239281Sgonzo 979239281Sgonzo /* Read the clksel register which contains the DPLL multiple and divide 980239281Sgonzo * values. These are applied to the sysclk. 981239281Sgonzo */ 982239281Sgonzo clksel = bus_read_4(sc->sc_res[CM1_INSTANCE_MEM_REGION], CM_CLKSEL_DPLL_MPU); 983239281Sgonzo 984239281Sgonzo pll_mult = ((clksel >> 8) & 0x7ff); 985239281Sgonzo pll_div = (clksel & 0x7f) + 1; 986239281Sgonzo 987239281Sgonzo 988239281Sgonzo /* Get the system clock freq */ 989239281Sgonzo omap4_clk_get_sysclk_freq(NULL, &sysclk); 990239281Sgonzo 991239281Sgonzo 992239281Sgonzo /* Calculate the MPU freq */ 993266274Sian mpuclk = ((uint64_t)sysclk * pll_mult) / pll_div; 994239281Sgonzo 995239281Sgonzo /* Return the value */ 996239281Sgonzo if (freq) 997239281Sgonzo *freq = mpuclk; 998239281Sgonzo 999239281Sgonzo return (0); 1000239281Sgonzo} 1001239281Sgonzo 1002239281Sgonzo/** 1003239281Sgonzo * omap4_clk_hsusbhost_activate - activates the USB clocks for the given module 1004239281Sgonzo * @clkdev: pointer to the clock device structure. 1005249586Sgabor * @mem_res: array of memory resources allocated by the top level PRCM driver. 1006239281Sgonzo * 1007239281Sgonzo * The USB clocking setup seems to be a bit more tricky than the other modules, 1008239281Sgonzo * to start with the clocking diagram for the HS host module shows 13 different 1009239281Sgonzo * clocks. So to try and make it easier to follow the clocking activation 1010239281Sgonzo * and deactivation is handled in it's own set of callbacks. 1011239281Sgonzo * 1012239281Sgonzo * LOCKING: 1013239281Sgonzo * Inherits the locks from the omap_prcm driver, no internal locking. 1014239281Sgonzo * 1015239281Sgonzo * RETURNS: 1016239281Sgonzo * Returns 0 on success or a positive error code on failure. 1017239281Sgonzo */ 1018239281Sgonzo 1019239281Sgonzostruct dpll_param { 1020239281Sgonzo unsigned int m; 1021239281Sgonzo unsigned int n; 1022239281Sgonzo unsigned int m2; 1023239281Sgonzo unsigned int m3; 1024239281Sgonzo unsigned int m4; 1025239281Sgonzo unsigned int m5; 1026239281Sgonzo unsigned int m6; 1027239281Sgonzo unsigned int m7; 1028239281Sgonzo}; 1029239281Sgonzo/* USB parameters */ 1030239281Sgonzostruct dpll_param usb_dpll_param[7] = { 1031239281Sgonzo /* 12M values */ 1032239281Sgonzo {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, 1033239281Sgonzo /* 13M values */ 1034239281Sgonzo {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, 1035239281Sgonzo /* 16.8M values */ 1036239281Sgonzo {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, 1037239281Sgonzo /* 19.2M values */ 1038239281Sgonzo {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, 1039239281Sgonzo /* 26M values */ 1040239281Sgonzo {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, 1041239281Sgonzo /* 27M values */ 1042239281Sgonzo {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, 1043239281Sgonzo /* 38.4M values */ 1044239281Sgonzo#ifdef CONFIG_OMAP4_SDC 1045239281Sgonzo {0x32, 0x1, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0}, 1046239281Sgonzo#else 1047239281Sgonzo {0x32, 0x1, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0}, 1048239281Sgonzo#endif 1049239281Sgonzo}; 1050239281Sgonzostatic int 1051239281Sgonzoomap4_clk_hsusbhost_activate(struct ti_clock_dev *clkdev) 1052239281Sgonzo{ 1053239281Sgonzo struct omap4_prcm_softc *sc = omap4_prcm_sc; 1054239281Sgonzo struct resource* clk_mem_res; 1055239281Sgonzo uint32_t clksel_reg_off; 1056239281Sgonzo uint32_t clksel; 1057239281Sgonzo unsigned int i; 1058239281Sgonzo 1059239281Sgonzo if (sc == NULL) 1060239281Sgonzo return ENXIO; 1061239281Sgonzo 1062239281Sgonzo switch (clkdev->id) { 1063239281Sgonzo case USBTLL_CLK: 1064239281Sgonzo /* For the USBTLL module we need to enable the following clocks: 1065239281Sgonzo * - INIT_L4_ICLK (will be enabled by bootloader) 1066239281Sgonzo * - TLL_CH0_FCLK 1067239281Sgonzo * - TLL_CH1_FCLK 1068239281Sgonzo */ 1069239281Sgonzo 1070239281Sgonzo /* We need the CM_L3INIT_HSUSBTLL_CLKCTRL register in CM2 register set */ 1071239281Sgonzo clk_mem_res = sc->sc_res[CM2_INSTANCE_MEM_REGION]; 1072239281Sgonzo clksel_reg_off = L3INIT_CM2_OFFSET + 0x68; 1073239281Sgonzo 1074239281Sgonzo /* Enable the module and also enable the optional func clocks for 1075239281Sgonzo * channels 0 & 1 (is this needed ?) 1076239281Sgonzo */ 1077239281Sgonzo clksel = bus_read_4(clk_mem_res, clksel_reg_off); 1078239281Sgonzo clksel &= ~CLKCTRL_MODULEMODE_MASK; 1079239281Sgonzo clksel |= CLKCTRL_MODULEMODE_ENABLE; 1080239281Sgonzo 1081239281Sgonzo clksel |= (0x1 << 8); /* USB-HOST optional clock: USB_CH0_CLK */ 1082239281Sgonzo clksel |= (0x1 << 9); /* USB-HOST optional clock: USB_CH1_CLK */ 1083239281Sgonzo break; 1084239281Sgonzo 1085239281Sgonzo case USBHSHOST_CLK: 1086239281Sgonzo case USBP1_PHY_CLK: 1087239281Sgonzo case USBP2_PHY_CLK: 1088239281Sgonzo case USBP1_UTMI_CLK: 1089239281Sgonzo case USBP2_UTMI_CLK: 1090239281Sgonzo case USBP1_HSIC_CLK: 1091239281Sgonzo case USBP2_HSIC_CLK: 1092239281Sgonzo /* For the USB HS HOST module we need to enable the following clocks: 1093239281Sgonzo * - INIT_L4_ICLK (will be enabled by bootloader) 1094239281Sgonzo * - INIT_L3_ICLK (will be enabled by bootloader) 1095239281Sgonzo * - INIT_48MC_FCLK 1096239281Sgonzo * - UTMI_ROOT_GFCLK (UTMI only, create a new clock for that ?) 1097239281Sgonzo * - UTMI_P1_FCLK (UTMI only, create a new clock for that ?) 1098239281Sgonzo * - UTMI_P2_FCLK (UTMI only, create a new clock for that ?) 1099239281Sgonzo * - HSIC_P1_60 (HSIC only, create a new clock for that ?) 1100239281Sgonzo * - HSIC_P1_480 (HSIC only, create a new clock for that ?) 1101239281Sgonzo * - HSIC_P2_60 (HSIC only, create a new clock for that ?) 1102239281Sgonzo * - HSIC_P2_480 (HSIC only, create a new clock for that ?) 1103239281Sgonzo */ 1104239281Sgonzo 1105239281Sgonzo /* We need the CM_L3INIT_HSUSBHOST_CLKCTRL register in CM2 register set */ 1106239281Sgonzo clk_mem_res = sc->sc_res[CM2_INSTANCE_MEM_REGION]; 1107239281Sgonzo clksel_reg_off = L3INIT_CM2_OFFSET + 0x58; 1108239281Sgonzo clksel = bus_read_4(clk_mem_res, clksel_reg_off); 1109239281Sgonzo /* Enable the module and also enable the optional func clocks */ 1110239281Sgonzo if (clkdev->id == USBHSHOST_CLK) { 1111239281Sgonzo clksel &= ~CLKCTRL_MODULEMODE_MASK; 1112239281Sgonzo clksel |= /*CLKCTRL_MODULEMODE_ENABLE*/2; 1113239281Sgonzo 1114239281Sgonzo clksel |= (0x1 << 15); /* USB-HOST clock control: FUNC48MCLK */ 1115239281Sgonzo } 1116239281Sgonzo 1117239281Sgonzo else if (clkdev->id == USBP1_UTMI_CLK) 1118239281Sgonzo clksel |= (0x1 << 8); /* UTMI_P1_CLK */ 1119239281Sgonzo else if (clkdev->id == USBP2_UTMI_CLK) 1120239281Sgonzo clksel |= (0x1 << 9); /* UTMI_P2_CLK */ 1121239281Sgonzo 1122239281Sgonzo else if (clkdev->id == USBP1_HSIC_CLK) 1123239281Sgonzo clksel |= (0x5 << 11); /* HSIC60M_P1_CLK + HSIC480M_P1_CLK */ 1124239281Sgonzo else if (clkdev->id == USBP2_HSIC_CLK) 1125239281Sgonzo clksel |= (0x5 << 12); /* HSIC60M_P2_CLK + HSIC480M_P2_CLK */ 1126239281Sgonzo 1127239281Sgonzo break; 1128239281Sgonzo 1129239281Sgonzo default: 1130239281Sgonzo return (EINVAL); 1131239281Sgonzo } 1132239281Sgonzo 1133239281Sgonzo bus_write_4(clk_mem_res, clksel_reg_off, clksel); 1134239281Sgonzo 1135239281Sgonzo /* Try MAX_MODULE_ENABLE_WAIT number of times to check if enabled */ 1136239281Sgonzo for (i = 0; i < MAX_MODULE_ENABLE_WAIT; i++) { 1137239281Sgonzo clksel = bus_read_4(clk_mem_res, clksel_reg_off); 1138239281Sgonzo if ((clksel & CLKCTRL_IDLEST_MASK) == CLKCTRL_IDLEST_ENABLED) 1139239281Sgonzo break; 1140239281Sgonzo } 1141239281Sgonzo 1142239281Sgonzo /* Check the enabled state */ 1143239281Sgonzo if ((clksel & CLKCTRL_IDLEST_MASK) != CLKCTRL_IDLEST_ENABLED) { 1144239281Sgonzo printf("Error: HERE failed to enable module with clock %d\n", clkdev->id); 1145239281Sgonzo printf("Error: 0x%08x => 0x%08x\n", clksel_reg_off, clksel); 1146239281Sgonzo return (ETIMEDOUT); 1147239281Sgonzo } 1148239281Sgonzo 1149239281Sgonzo return (0); 1150239281Sgonzo} 1151239281Sgonzo 1152239281Sgonzo/** 1153239281Sgonzo * omap4_clk_generic_deactivate - checks if a module is accessible 1154239281Sgonzo * @clkdev: pointer to the clock device structure. 1155249586Sgabor * @mem_res: array of memory resources allocated by the top level PRCM driver. 1156239281Sgonzo * 1157239281Sgonzo * 1158239281Sgonzo * 1159239281Sgonzo * LOCKING: 1160239281Sgonzo * Inherits the locks from the omap_prcm driver, no internal locking. 1161239281Sgonzo * 1162239281Sgonzo * RETURNS: 1163239281Sgonzo * Returns 0 on success or a positive error code on failure. 1164239281Sgonzo */ 1165239281Sgonzostatic int 1166239281Sgonzoomap4_clk_hsusbhost_deactivate(struct ti_clock_dev *clkdev) 1167239281Sgonzo{ 1168239281Sgonzo struct omap4_prcm_softc *sc = omap4_prcm_sc; 1169239281Sgonzo struct resource* clk_mem_res; 1170239281Sgonzo uint32_t clksel_reg_off; 1171239281Sgonzo uint32_t clksel; 1172239281Sgonzo 1173239281Sgonzo if (sc == NULL) 1174239281Sgonzo return ENXIO; 1175239281Sgonzo 1176239281Sgonzo switch (clkdev->id) { 1177239281Sgonzo case USBTLL_CLK: 1178239281Sgonzo /* We need the CM_L3INIT_HSUSBTLL_CLKCTRL register in CM2 register set */ 1179239281Sgonzo clk_mem_res = sc->sc_res[CM2_INSTANCE_MEM_REGION]; 1180239281Sgonzo clksel_reg_off = L3INIT_CM2_OFFSET + 0x68; 1181239281Sgonzo 1182239281Sgonzo clksel = bus_read_4(clk_mem_res, clksel_reg_off); 1183239281Sgonzo clksel &= ~CLKCTRL_MODULEMODE_MASK; 1184239281Sgonzo clksel |= CLKCTRL_MODULEMODE_DISABLE; 1185239281Sgonzo break; 1186239281Sgonzo 1187239281Sgonzo case USBHSHOST_CLK: 1188239281Sgonzo case USBP1_PHY_CLK: 1189239281Sgonzo case USBP2_PHY_CLK: 1190239281Sgonzo case USBP1_UTMI_CLK: 1191239281Sgonzo case USBP2_UTMI_CLK: 1192239281Sgonzo case USBP1_HSIC_CLK: 1193239281Sgonzo case USBP2_HSIC_CLK: 1194239281Sgonzo /* For the USB HS HOST module we need to enable the following clocks: 1195239281Sgonzo * - INIT_L4_ICLK (will be enabled by bootloader) 1196239281Sgonzo * - INIT_L3_ICLK (will be enabled by bootloader) 1197239281Sgonzo * - INIT_48MC_FCLK 1198239281Sgonzo * - UTMI_ROOT_GFCLK (UTMI only, create a new clock for that ?) 1199239281Sgonzo * - UTMI_P1_FCLK (UTMI only, create a new clock for that ?) 1200239281Sgonzo * - UTMI_P2_FCLK (UTMI only, create a new clock for that ?) 1201239281Sgonzo * - HSIC_P1_60 (HSIC only, create a new clock for that ?) 1202239281Sgonzo * - HSIC_P1_480 (HSIC only, create a new clock for that ?) 1203239281Sgonzo * - HSIC_P2_60 (HSIC only, create a new clock for that ?) 1204239281Sgonzo * - HSIC_P2_480 (HSIC only, create a new clock for that ?) 1205239281Sgonzo */ 1206239281Sgonzo 1207239281Sgonzo /* We need the CM_L3INIT_HSUSBHOST_CLKCTRL register in CM2 register set */ 1208239281Sgonzo clk_mem_res = sc->sc_res[CM2_INSTANCE_MEM_REGION]; 1209239281Sgonzo clksel_reg_off = L3INIT_CM2_OFFSET + 0x58; 1210239281Sgonzo clksel = bus_read_4(clk_mem_res, clksel_reg_off); 1211239281Sgonzo 1212239281Sgonzo /* Enable the module and also enable the optional func clocks */ 1213239281Sgonzo if (clkdev->id == USBHSHOST_CLK) { 1214239281Sgonzo clksel &= ~CLKCTRL_MODULEMODE_MASK; 1215239281Sgonzo clksel |= CLKCTRL_MODULEMODE_DISABLE; 1216239281Sgonzo 1217239281Sgonzo clksel &= ~(0x1 << 15); /* USB-HOST clock control: FUNC48MCLK */ 1218239281Sgonzo } 1219239281Sgonzo 1220239281Sgonzo else if (clkdev->id == USBP1_UTMI_CLK) 1221239281Sgonzo clksel &= ~(0x1 << 8); /* UTMI_P1_CLK */ 1222239281Sgonzo else if (clkdev->id == USBP2_UTMI_CLK) 1223239281Sgonzo clksel &= ~(0x1 << 9); /* UTMI_P2_CLK */ 1224239281Sgonzo 1225239281Sgonzo else if (clkdev->id == USBP1_HSIC_CLK) 1226239281Sgonzo clksel &= ~(0x5 << 11); /* HSIC60M_P1_CLK + HSIC480M_P1_CLK */ 1227239281Sgonzo else if (clkdev->id == USBP2_HSIC_CLK) 1228239281Sgonzo clksel &= ~(0x5 << 12); /* HSIC60M_P2_CLK + HSIC480M_P2_CLK */ 1229239281Sgonzo 1230239281Sgonzo break; 1231239281Sgonzo 1232239281Sgonzo default: 1233239281Sgonzo return (EINVAL); 1234239281Sgonzo } 1235239281Sgonzo 1236239281Sgonzo bus_write_4(clk_mem_res, clksel_reg_off, clksel); 1237239281Sgonzo 1238239281Sgonzo return (0); 1239239281Sgonzo} 1240239281Sgonzo 1241239281Sgonzo/** 1242239281Sgonzo * omap4_clk_hsusbhost_accessible - checks if a module is accessible 1243239281Sgonzo * @clkdev: pointer to the clock device structure. 1244249586Sgabor * @mem_res: array of memory resources allocated by the top level PRCM driver. 1245239281Sgonzo * 1246239281Sgonzo * 1247239281Sgonzo * 1248239281Sgonzo * LOCKING: 1249239281Sgonzo * Inherits the locks from the omap_prcm driver, no internal locking. 1250239281Sgonzo * 1251239281Sgonzo * RETURNS: 1252239281Sgonzo * Returns 0 if module is not enable, 1 if module is enabled or a negative 1253239281Sgonzo * error code on failure. 1254239281Sgonzo */ 1255239281Sgonzostatic int 1256239281Sgonzoomap4_clk_hsusbhost_accessible(struct ti_clock_dev *clkdev) 1257239281Sgonzo{ 1258239281Sgonzo struct omap4_prcm_softc *sc = omap4_prcm_sc; 1259239281Sgonzo struct resource* clk_mem_res; 1260239281Sgonzo uint32_t clksel_reg_off; 1261239281Sgonzo uint32_t clksel; 1262239281Sgonzo 1263239281Sgonzo if (sc == NULL) 1264239281Sgonzo return ENXIO; 1265239281Sgonzo 1266239281Sgonzo if (clkdev->id == USBTLL_CLK) { 1267239281Sgonzo /* We need the CM_L3INIT_HSUSBTLL_CLKCTRL register in CM2 register set */ 1268239281Sgonzo clk_mem_res = sc->sc_res[CM2_INSTANCE_MEM_REGION]; 1269239281Sgonzo clksel_reg_off = L3INIT_CM2_OFFSET + 0x68; 1270239281Sgonzo } 1271239281Sgonzo else if (clkdev->id == USBHSHOST_CLK) { 1272239281Sgonzo /* We need the CM_L3INIT_HSUSBHOST_CLKCTRL register in CM2 register set */ 1273239281Sgonzo clk_mem_res = sc->sc_res[CM2_INSTANCE_MEM_REGION]; 1274239281Sgonzo clksel_reg_off = L3INIT_CM2_OFFSET + 0x58; 1275239281Sgonzo } 1276239281Sgonzo else { 1277239281Sgonzo return (EINVAL); 1278239281Sgonzo } 1279239281Sgonzo 1280239281Sgonzo clksel = bus_read_4(clk_mem_res, clksel_reg_off); 1281239281Sgonzo 1282239281Sgonzo /* Check the enabled state */ 1283239281Sgonzo if ((clksel & CLKCTRL_IDLEST_MASK) != CLKCTRL_IDLEST_ENABLED) 1284239281Sgonzo return (0); 1285239281Sgonzo 1286239281Sgonzo return (1); 1287239281Sgonzo} 1288239281Sgonzo 1289239281Sgonzo/** 1290239281Sgonzo * omap4_clk_hsusbhost_set_source - sets the source clocks 1291239281Sgonzo * @clkdev: pointer to the clock device structure. 1292239281Sgonzo * @clksrc: the clock source ID for the given clock. 1293249586Sgabor * @mem_res: array of memory resources allocated by the top level PRCM driver. 1294239281Sgonzo * 1295239281Sgonzo * 1296239281Sgonzo * 1297239281Sgonzo * LOCKING: 1298239281Sgonzo * Inherits the locks from the omap_prcm driver, no internal locking. 1299239281Sgonzo * 1300239281Sgonzo * RETURNS: 1301239281Sgonzo * Returns 0 if sucessful otherwise a negative error code on failure. 1302239281Sgonzo */ 1303239281Sgonzostatic int 1304239281Sgonzoomap4_clk_hsusbhost_set_source(struct ti_clock_dev *clkdev, 1305239281Sgonzo clk_src_t clksrc) 1306239281Sgonzo{ 1307239281Sgonzo struct omap4_prcm_softc *sc = omap4_prcm_sc; 1308239281Sgonzo struct resource* clk_mem_res; 1309239281Sgonzo uint32_t clksel_reg_off; 1310239281Sgonzo uint32_t clksel; 1311239281Sgonzo unsigned int bit; 1312239281Sgonzo 1313239281Sgonzo if (sc == NULL) 1314239281Sgonzo return ENXIO; 1315239281Sgonzo 1316239281Sgonzo if (clkdev->id == USBP1_PHY_CLK) 1317239281Sgonzo bit = 24; 1318239281Sgonzo else if (clkdev->id != USBP2_PHY_CLK) 1319239281Sgonzo bit = 25; 1320239281Sgonzo else 1321239281Sgonzo return (EINVAL); 1322239281Sgonzo 1323239281Sgonzo /* We need the CM_L3INIT_HSUSBHOST_CLKCTRL register in CM2 register set */ 1324239281Sgonzo clk_mem_res = sc->sc_res[CM2_INSTANCE_MEM_REGION]; 1325239281Sgonzo clksel_reg_off = L3INIT_CM2_OFFSET + 0x58; 1326239281Sgonzo clksel = bus_read_4(clk_mem_res, clksel_reg_off); 1327239281Sgonzo 1328239281Sgonzo /* Set the clock source to either external or internal */ 1329239281Sgonzo if (clksrc == EXT_CLK) 1330239281Sgonzo clksel |= (0x1 << bit); 1331239281Sgonzo else 1332239281Sgonzo clksel &= ~(0x1 << bit); 1333239281Sgonzo 1334239281Sgonzo bus_write_4(clk_mem_res, clksel_reg_off, clksel); 1335239281Sgonzo 1336239281Sgonzo return (0); 1337239281Sgonzo} 1338239281Sgonzo 1339239281Sgonzo#define PRM_RSTCTRL 0x1b00 1340239281Sgonzo#define PRM_RSTCTRL_RESET 0x2 1341239281Sgonzo 1342239281Sgonzostatic void 1343239281Sgonzoomap4_prcm_reset(void) 1344239281Sgonzo{ 1345239281Sgonzo struct omap4_prcm_softc *sc = omap4_prcm_sc; 1346239281Sgonzo bus_write_4(sc->sc_res[0], PRM_RSTCTRL, 1347239281Sgonzo bus_read_4(sc->sc_res[0], PRM_RSTCTRL) | PRM_RSTCTRL_RESET); 1348239281Sgonzo bus_read_4(sc->sc_res[0], PRM_RSTCTRL); 1349239281Sgonzo} 1350239281Sgonzo 1351239281Sgonzo/** 1352239281Sgonzo * omap4_prcm_probe - probe function for the driver 1353239281Sgonzo * @dev: prcm device handle 1354239281Sgonzo * 1355239281Sgonzo * Simply sets the name of the driver module. 1356239281Sgonzo * 1357239281Sgonzo * LOCKING: 1358239281Sgonzo * None 1359239281Sgonzo * 1360239281Sgonzo * RETURNS: 1361239281Sgonzo * Always returns 0 1362239281Sgonzo */ 1363239281Sgonzostatic int 1364239281Sgonzoomap4_prcm_probe(device_t dev) 1365239281Sgonzo{ 1366266152Sian 1367266152Sian if (!ofw_bus_status_okay(dev)) 1368266152Sian return (ENXIO); 1369266152Sian 1370239281Sgonzo if (!ofw_bus_is_compatible(dev, "ti,omap4_prcm")) 1371239281Sgonzo return (ENXIO); 1372239281Sgonzo 1373239281Sgonzo device_set_desc(dev, "TI OMAP Power, Reset and Clock Management"); 1374239281Sgonzo return (0); 1375239281Sgonzo} 1376239281Sgonzo 1377239281Sgonzo/** 1378239281Sgonzo * omap_prcm_attach - attach function for the driver 1379239281Sgonzo * @dev: prcm device handle 1380239281Sgonzo * 1381239281Sgonzo * Allocates and sets up the driver context, this simply entails creating a 1382239281Sgonzo * bus mappings for the PRCM register set. 1383239281Sgonzo * 1384239281Sgonzo * LOCKING: 1385239281Sgonzo * None 1386239281Sgonzo * 1387239281Sgonzo * RETURNS: 1388239281Sgonzo * Always returns 0 1389239281Sgonzo */ 1390253971Scognet 1391253971Scognetextern uint32_t platform_arm_tmr_freq; 1392253971Scognet 1393239281Sgonzostatic int 1394239281Sgonzoomap4_prcm_attach(device_t dev) 1395239281Sgonzo{ 1396239281Sgonzo struct omap4_prcm_softc *sc = device_get_softc(dev); 1397253971Scognet unsigned int freq; 1398239281Sgonzo 1399239281Sgonzo if (bus_alloc_resources(dev, omap4_scm_res_spec, sc->sc_res)) { 1400239281Sgonzo device_printf(dev, "could not allocate resources\n"); 1401239281Sgonzo return (ENXIO); 1402239281Sgonzo } 1403239281Sgonzo 1404239281Sgonzo omap4_prcm_sc = sc; 1405239281Sgonzo ti_cpu_reset = omap4_prcm_reset; 1406253971Scognet omap4_clk_get_arm_fclk_freq(NULL, &freq); 1407266347Sian arm_tmr_change_frequency(freq / 2); 1408239281Sgonzo 1409239281Sgonzo return (0); 1410239281Sgonzo} 1411239281Sgonzo 1412239281Sgonzostatic device_method_t omap4_prcm_methods[] = { 1413239281Sgonzo DEVMETHOD(device_probe, omap4_prcm_probe), 1414239281Sgonzo DEVMETHOD(device_attach, omap4_prcm_attach), 1415239281Sgonzo {0, 0}, 1416239281Sgonzo}; 1417239281Sgonzo 1418239281Sgonzostatic driver_t omap4_prcm_driver = { 1419239281Sgonzo "omap4_prcm", 1420239281Sgonzo omap4_prcm_methods, 1421239281Sgonzo sizeof(struct omap4_prcm_softc), 1422239281Sgonzo}; 1423239281Sgonzo 1424239281Sgonzostatic devclass_t omap4_prcm_devclass; 1425239281Sgonzo 1426283338SianEARLY_DRIVER_MODULE(omap4_prcm, simplebus, omap4_prcm_driver, 1427283338Sian omap4_prcm_devclass, 0, 0, BUS_PASS_TIMER + BUS_PASS_ORDER_EARLY); 1428239281SgonzoMODULE_VERSION(omap4_prcm, 1); 1429