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