Path: blob/master/arch/arm/mach-omap2/clockdomains3xxx_data.c
26292 views
// SPDX-License-Identifier: GPL-2.01/*2* OMAP3xxx clockdomains3*4* Copyright (C) 2008-2011 Texas Instruments, Inc.5* Copyright (C) 2008-2010 Nokia Corporation6*7* Paul Walmsley, Jouni Högander8*9* This file contains clockdomains and clockdomain wakeup/sleep10* dependencies for the OMAP3xxx chips. Some notes:11*12* A useful validation rule for struct clockdomain: Any clockdomain13* referenced by a wkdep_srcs or sleepdep_srcs array must have a14* dep_bit assigned. So wkdep_srcs/sleepdep_srcs are really just15* software-controllable dependencies. Non-software-controllable16* dependencies do exist, but they are not encoded below (yet).17*18* The overly-specific dep_bit names are due to a bit name collision19* with CM_FCLKEN_{DSP,IVA2}. The DSP/IVA2 PM_WKDEP and CM_SLEEPDEP shift20* value are the same for all powerdomains: 221*22* XXX should dep_bit be a mask, so we can test to see if it is 0 as a23* sanity check?24* XXX encode hardware fixed wakeup dependencies -- esp. for 3430 CORE25*/2627/*28* To-Do List29* -> Port the Sleep/Wakeup dependencies for the domains30* from the Power domain framework31*/3233#include <linux/kernel.h>34#include <linux/io.h>3536#include "soc.h"37#include "clockdomain.h"38#include "prm2xxx_3xxx.h"39#include "cm2xxx_3xxx.h"40#include "cm-regbits-34xx.h"41#include "prm-regbits-34xx.h"4243/*44* Clockdomain dependencies for wkdeps/sleepdeps45*46* XXX Hardware dependencies (e.g., dependencies that cannot be47* changed in software) are not included here yet, but should be.48*/4950/* OMAP3-specific possible dependencies */5152/*53* 3430ES1 PM_WKDEP_GFX: adds IVA2, removes CORE54* 3430ES2 PM_WKDEP_SGX: adds IVA2, removes CORE55*/56static struct clkdm_dep gfx_sgx_3xxx_wkdeps[] = {57{ .clkdm_name = "iva2_clkdm" },58{ .clkdm_name = "mpu_clkdm" },59{ .clkdm_name = "wkup_clkdm" },60{ NULL },61};6263static struct clkdm_dep gfx_sgx_am35x_wkdeps[] = {64{ .clkdm_name = "mpu_clkdm" },65{ .clkdm_name = "wkup_clkdm" },66{ NULL },67};6869/* 3430: PM_WKDEP_PER: CORE, IVA2, MPU, WKUP */70static struct clkdm_dep per_wkdeps[] = {71{ .clkdm_name = "core_l3_clkdm" },72{ .clkdm_name = "core_l4_clkdm" },73{ .clkdm_name = "iva2_clkdm" },74{ .clkdm_name = "mpu_clkdm" },75{ .clkdm_name = "wkup_clkdm" },76{ NULL },77};7879static struct clkdm_dep per_am35x_wkdeps[] = {80{ .clkdm_name = "core_l3_clkdm" },81{ .clkdm_name = "core_l4_clkdm" },82{ .clkdm_name = "mpu_clkdm" },83{ .clkdm_name = "wkup_clkdm" },84{ NULL },85};8687/* 3430ES2: PM_WKDEP_USBHOST: CORE, IVA2, MPU, WKUP */88static struct clkdm_dep usbhost_wkdeps[] = {89{ .clkdm_name = "core_l3_clkdm" },90{ .clkdm_name = "core_l4_clkdm" },91{ .clkdm_name = "iva2_clkdm" },92{ .clkdm_name = "mpu_clkdm" },93{ .clkdm_name = "wkup_clkdm" },94{ NULL },95};9697static struct clkdm_dep usbhost_am35x_wkdeps[] = {98{ .clkdm_name = "core_l3_clkdm" },99{ .clkdm_name = "core_l4_clkdm" },100{ .clkdm_name = "mpu_clkdm" },101{ .clkdm_name = "wkup_clkdm" },102{ NULL },103};104105/* 3430 PM_WKDEP_MPU: CORE, IVA2, DSS, PER */106static struct clkdm_dep mpu_3xxx_wkdeps[] = {107{ .clkdm_name = "core_l3_clkdm" },108{ .clkdm_name = "core_l4_clkdm" },109{ .clkdm_name = "iva2_clkdm" },110{ .clkdm_name = "dss_clkdm" },111{ .clkdm_name = "per_clkdm" },112{ NULL },113};114115static struct clkdm_dep mpu_am35x_wkdeps[] = {116{ .clkdm_name = "core_l3_clkdm" },117{ .clkdm_name = "core_l4_clkdm" },118{ .clkdm_name = "dss_clkdm" },119{ .clkdm_name = "per_clkdm" },120{ NULL },121};122123/* 3430 PM_WKDEP_IVA2: CORE, MPU, WKUP, DSS, PER */124static struct clkdm_dep iva2_wkdeps[] = {125{ .clkdm_name = "core_l3_clkdm" },126{ .clkdm_name = "core_l4_clkdm" },127{ .clkdm_name = "mpu_clkdm" },128{ .clkdm_name = "wkup_clkdm" },129{ .clkdm_name = "dss_clkdm" },130{ .clkdm_name = "per_clkdm" },131{ NULL },132};133134/* 3430 PM_WKDEP_CAM: IVA2, MPU, WKUP */135static struct clkdm_dep cam_wkdeps[] = {136{ .clkdm_name = "iva2_clkdm" },137{ .clkdm_name = "mpu_clkdm" },138{ .clkdm_name = "wkup_clkdm" },139{ NULL },140};141142/* 3430 PM_WKDEP_DSS: IVA2, MPU, WKUP */143static struct clkdm_dep dss_wkdeps[] = {144{ .clkdm_name = "iva2_clkdm" },145{ .clkdm_name = "mpu_clkdm" },146{ .clkdm_name = "wkup_clkdm" },147{ NULL },148};149150static struct clkdm_dep dss_am35x_wkdeps[] = {151{ .clkdm_name = "mpu_clkdm" },152{ .clkdm_name = "wkup_clkdm" },153{ NULL },154};155156/* 3430: PM_WKDEP_NEON: MPU */157static struct clkdm_dep neon_wkdeps[] = {158{ .clkdm_name = "mpu_clkdm" },159{ NULL },160};161162/* Sleep dependency source arrays for OMAP3-specific clkdms */163164/* 3430: CM_SLEEPDEP_DSS: MPU, IVA */165static struct clkdm_dep dss_sleepdeps[] = {166{ .clkdm_name = "mpu_clkdm" },167{ .clkdm_name = "iva2_clkdm" },168{ NULL },169};170171static struct clkdm_dep dss_am35x_sleepdeps[] = {172{ .clkdm_name = "mpu_clkdm" },173{ NULL },174};175176/* 3430: CM_SLEEPDEP_PER: MPU, IVA */177static struct clkdm_dep per_sleepdeps[] = {178{ .clkdm_name = "mpu_clkdm" },179{ .clkdm_name = "iva2_clkdm" },180{ NULL },181};182183static struct clkdm_dep per_am35x_sleepdeps[] = {184{ .clkdm_name = "mpu_clkdm" },185{ NULL },186};187188/* 3430ES2: CM_SLEEPDEP_USBHOST: MPU, IVA */189static struct clkdm_dep usbhost_sleepdeps[] = {190{ .clkdm_name = "mpu_clkdm" },191{ .clkdm_name = "iva2_clkdm" },192{ NULL },193};194195static struct clkdm_dep usbhost_am35x_sleepdeps[] = {196{ .clkdm_name = "mpu_clkdm" },197{ NULL },198};199200/* 3430: CM_SLEEPDEP_CAM: MPU */201static struct clkdm_dep cam_sleepdeps[] = {202{ .clkdm_name = "mpu_clkdm" },203{ NULL },204};205206/*207* 3430ES1: CM_SLEEPDEP_GFX: MPU208* 3430ES2: CM_SLEEPDEP_SGX: MPU209* These can share data since they will never be present simultaneously210* on the same device.211*/212static struct clkdm_dep gfx_sgx_sleepdeps[] = {213{ .clkdm_name = "mpu_clkdm" },214{ NULL },215};216217/*218* OMAP3 clockdomains219*/220221static struct clockdomain mpu_3xxx_clkdm = {222.name = "mpu_clkdm",223.pwrdm = { .name = "mpu_pwrdm" },224.flags = CLKDM_CAN_HWSUP | CLKDM_CAN_FORCE_WAKEUP,225.dep_bit = OMAP3430_EN_MPU_SHIFT,226.wkdep_srcs = mpu_3xxx_wkdeps,227.clktrctrl_mask = OMAP3430_CLKTRCTRL_MPU_MASK,228};229230static struct clockdomain mpu_am35x_clkdm = {231.name = "mpu_clkdm",232.pwrdm = { .name = "mpu_pwrdm" },233.flags = CLKDM_CAN_HWSUP | CLKDM_CAN_FORCE_WAKEUP,234.dep_bit = OMAP3430_EN_MPU_SHIFT,235.wkdep_srcs = mpu_am35x_wkdeps,236.clktrctrl_mask = OMAP3430_CLKTRCTRL_MPU_MASK,237};238239static struct clockdomain neon_clkdm = {240.name = "neon_clkdm",241.pwrdm = { .name = "neon_pwrdm" },242.flags = CLKDM_CAN_HWSUP_SWSUP,243.wkdep_srcs = neon_wkdeps,244.clktrctrl_mask = OMAP3430_CLKTRCTRL_NEON_MASK,245};246247static struct clockdomain iva2_clkdm = {248.name = "iva2_clkdm",249.pwrdm = { .name = "iva2_pwrdm" },250.flags = CLKDM_CAN_SWSUP,251.dep_bit = OMAP3430_PM_WKDEP_MPU_EN_IVA2_SHIFT,252.wkdep_srcs = iva2_wkdeps,253.clktrctrl_mask = OMAP3430_CLKTRCTRL_IVA2_MASK,254};255256static struct clockdomain gfx_3430es1_clkdm = {257.name = "gfx_clkdm",258.pwrdm = { .name = "gfx_pwrdm" },259.flags = CLKDM_CAN_HWSUP_SWSUP,260.wkdep_srcs = gfx_sgx_3xxx_wkdeps,261.sleepdep_srcs = gfx_sgx_sleepdeps,262.clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_GFX_MASK,263};264265static struct clockdomain sgx_clkdm = {266.name = "sgx_clkdm",267.pwrdm = { .name = "sgx_pwrdm" },268.flags = CLKDM_CAN_HWSUP_SWSUP,269.wkdep_srcs = gfx_sgx_3xxx_wkdeps,270.sleepdep_srcs = gfx_sgx_sleepdeps,271.clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_SGX_MASK,272};273274static struct clockdomain sgx_am35x_clkdm = {275.name = "sgx_clkdm",276.pwrdm = { .name = "sgx_pwrdm" },277.flags = CLKDM_CAN_HWSUP_SWSUP,278.wkdep_srcs = gfx_sgx_am35x_wkdeps,279.sleepdep_srcs = gfx_sgx_sleepdeps,280.clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_SGX_MASK,281};282283/*284* The die-to-die clockdomain was documented in the 34xx ES1 TRM, but285* then that information was removed from the 34xx ES2+ TRM. It is286* unclear whether the core is still there, but the clockdomain logic287* is there, and must be programmed to an appropriate state if the288* CORE clockdomain is to become inactive.289*/290static struct clockdomain d2d_clkdm = {291.name = "d2d_clkdm",292.pwrdm = { .name = "core_pwrdm" },293.flags = CLKDM_CAN_HWSUP_SWSUP,294.clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_D2D_MASK,295};296297/*298* XXX add usecounting for clkdm dependencies, otherwise the presence299* of a single dep bit for core_l3_3xxx_clkdm and core_l4_3xxx_clkdm300* could cause trouble301*/302static struct clockdomain core_l3_3xxx_clkdm = {303.name = "core_l3_clkdm",304.pwrdm = { .name = "core_pwrdm" },305.flags = CLKDM_CAN_HWSUP,306.dep_bit = OMAP3430_EN_CORE_SHIFT,307.clktrctrl_mask = OMAP3430_CLKTRCTRL_L3_MASK,308};309310/*311* XXX add usecounting for clkdm dependencies, otherwise the presence312* of a single dep bit for core_l3_3xxx_clkdm and core_l4_3xxx_clkdm313* could cause trouble314*/315static struct clockdomain core_l4_3xxx_clkdm = {316.name = "core_l4_clkdm",317.pwrdm = { .name = "core_pwrdm" },318.flags = CLKDM_CAN_HWSUP,319.dep_bit = OMAP3430_EN_CORE_SHIFT,320.clktrctrl_mask = OMAP3430_CLKTRCTRL_L4_MASK,321};322323/* Another case of bit name collisions between several registers: EN_DSS */324static struct clockdomain dss_3xxx_clkdm = {325.name = "dss_clkdm",326.pwrdm = { .name = "dss_pwrdm" },327.flags = CLKDM_CAN_HWSUP_SWSUP,328.dep_bit = OMAP3430_PM_WKDEP_MPU_EN_DSS_SHIFT,329.wkdep_srcs = dss_wkdeps,330.sleepdep_srcs = dss_sleepdeps,331.clktrctrl_mask = OMAP3430_CLKTRCTRL_DSS_MASK,332};333334static struct clockdomain dss_am35x_clkdm = {335.name = "dss_clkdm",336.pwrdm = { .name = "dss_pwrdm" },337.flags = CLKDM_CAN_HWSUP_SWSUP,338.dep_bit = OMAP3430_PM_WKDEP_MPU_EN_DSS_SHIFT,339.wkdep_srcs = dss_am35x_wkdeps,340.sleepdep_srcs = dss_am35x_sleepdeps,341.clktrctrl_mask = OMAP3430_CLKTRCTRL_DSS_MASK,342};343344static struct clockdomain cam_clkdm = {345.name = "cam_clkdm",346.pwrdm = { .name = "cam_pwrdm" },347.flags = CLKDM_CAN_HWSUP_SWSUP,348.wkdep_srcs = cam_wkdeps,349.sleepdep_srcs = cam_sleepdeps,350.clktrctrl_mask = OMAP3430_CLKTRCTRL_CAM_MASK,351};352353static struct clockdomain usbhost_clkdm = {354.name = "usbhost_clkdm",355.pwrdm = { .name = "usbhost_pwrdm" },356.flags = CLKDM_CAN_HWSUP_SWSUP,357.wkdep_srcs = usbhost_wkdeps,358.sleepdep_srcs = usbhost_sleepdeps,359.clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_USBHOST_MASK,360};361362static struct clockdomain usbhost_am35x_clkdm = {363.name = "usbhost_clkdm",364.pwrdm = { .name = "core_pwrdm" },365.flags = CLKDM_CAN_HWSUP_SWSUP,366.wkdep_srcs = usbhost_am35x_wkdeps,367.sleepdep_srcs = usbhost_am35x_sleepdeps,368.clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_USBHOST_MASK,369};370371static struct clockdomain per_clkdm = {372.name = "per_clkdm",373.pwrdm = { .name = "per_pwrdm" },374.flags = CLKDM_CAN_HWSUP_SWSUP,375.dep_bit = OMAP3430_EN_PER_SHIFT,376.wkdep_srcs = per_wkdeps,377.sleepdep_srcs = per_sleepdeps,378.clktrctrl_mask = OMAP3430_CLKTRCTRL_PER_MASK,379};380381static struct clockdomain per_am35x_clkdm = {382.name = "per_clkdm",383.pwrdm = { .name = "per_pwrdm" },384.flags = CLKDM_CAN_HWSUP_SWSUP,385.dep_bit = OMAP3430_EN_PER_SHIFT,386.wkdep_srcs = per_am35x_wkdeps,387.sleepdep_srcs = per_am35x_sleepdeps,388.clktrctrl_mask = OMAP3430_CLKTRCTRL_PER_MASK,389};390391static struct clockdomain emu_clkdm = {392.name = "emu_clkdm",393.pwrdm = { .name = "emu_pwrdm" },394.flags = (CLKDM_CAN_ENABLE_AUTO | CLKDM_CAN_SWSUP |395CLKDM_MISSING_IDLE_REPORTING),396.clktrctrl_mask = OMAP3430_CLKTRCTRL_EMU_MASK,397};398399static struct clockdomain dpll1_clkdm = {400.name = "dpll1_clkdm",401.pwrdm = { .name = "dpll1_pwrdm" },402};403404static struct clockdomain dpll2_clkdm = {405.name = "dpll2_clkdm",406.pwrdm = { .name = "dpll2_pwrdm" },407};408409static struct clockdomain dpll3_clkdm = {410.name = "dpll3_clkdm",411.pwrdm = { .name = "dpll3_pwrdm" },412};413414static struct clockdomain dpll4_clkdm = {415.name = "dpll4_clkdm",416.pwrdm = { .name = "dpll4_pwrdm" },417};418419static struct clockdomain dpll5_clkdm = {420.name = "dpll5_clkdm",421.pwrdm = { .name = "dpll5_pwrdm" },422};423424/*425* Clockdomain hwsup dependencies426*/427428static struct clkdm_autodep clkdm_autodeps[] = {429{430.clkdm = { .name = "mpu_clkdm" },431},432{433.clkdm = { .name = "iva2_clkdm" },434},435{436.clkdm = { .name = NULL },437}438};439440static struct clkdm_autodep clkdm_am35x_autodeps[] = {441{442.clkdm = { .name = "mpu_clkdm" },443},444{445.clkdm = { .name = NULL },446}447};448449/*450*451*/452453static struct clockdomain *clockdomains_common[] __initdata = {454&wkup_common_clkdm,455&neon_clkdm,456&core_l3_3xxx_clkdm,457&core_l4_3xxx_clkdm,458&emu_clkdm,459&dpll1_clkdm,460&dpll3_clkdm,461&dpll4_clkdm,462NULL463};464465static struct clockdomain *clockdomains_omap3430[] __initdata = {466&mpu_3xxx_clkdm,467&iva2_clkdm,468&d2d_clkdm,469&dss_3xxx_clkdm,470&cam_clkdm,471&per_clkdm,472&dpll2_clkdm,473NULL474};475476static struct clockdomain *clockdomains_omap3430es1[] __initdata = {477&gfx_3430es1_clkdm,478NULL,479};480481static struct clockdomain *clockdomains_omap3430es2plus[] __initdata = {482&sgx_clkdm,483&dpll5_clkdm,484&usbhost_clkdm,485NULL,486};487488static struct clockdomain *clockdomains_am35x[] __initdata = {489&mpu_am35x_clkdm,490&sgx_am35x_clkdm,491&dss_am35x_clkdm,492&per_am35x_clkdm,493&usbhost_am35x_clkdm,494&dpll5_clkdm,495NULL496};497498void __init omap3xxx_clockdomains_init(void)499{500struct clockdomain **sc;501unsigned int rev;502503if (!cpu_is_omap34xx())504return;505506clkdm_register_platform_funcs(&omap3_clkdm_operations);507clkdm_register_clkdms(clockdomains_common);508509rev = omap_rev();510511if (rev == AM35XX_REV_ES1_0 || rev == AM35XX_REV_ES1_1) {512clkdm_register_clkdms(clockdomains_am35x);513clkdm_register_autodeps(clkdm_am35x_autodeps);514} else {515clkdm_register_clkdms(clockdomains_omap3430);516517sc = (rev == OMAP3430_REV_ES1_0) ?518clockdomains_omap3430es1 : clockdomains_omap3430es2plus;519520clkdm_register_clkdms(sc);521clkdm_register_autodeps(clkdm_autodeps);522}523524clkdm_complete_init();525}526527528