ARM: arm-soc: power management and clock changes
This branch contains a largeish set of updates of power management and clock setup. The bulk of it is for OMAP/AM33xx platforms, but also a few around hotplug/suspend/resume on Exynos. It includes a split-up of some of the OMAP clock data into separate files which adds to the diffstat, but gross delta is fairly reasonable. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJQySrdAAoJEIwa5zzehBx3XBMQAJCgrE/I1vbuiENiVMLpQkN7 0Y5t89SwoALnme5jsM8vW/H0o6b163FfH+249UNs6dyk6MdCqqSv8cQVvSfCKRKn m4JTXS6njSnYgU025klNU9W3FyMuFcgH8b63+c5+sCcqfvdkxrjpNoKqAYNxQlgJ 6DHgHCKZP3JB1e2EFqViw0GJgZIjTNxlWvx8XLcAShSapQ+Ovq/iAcKo41o7ZadB 4zV//VkBMv0TLNTs6SoR0EO8qM+2nIUKE8fgPrRxvvb98tuasKPvlSq9VUeIjnYk kWjNTQYbD1IkrAMPYrwcpLU3xkEr14wrKDBtPK6GdCDcXzdyKq3fzROOXNsqrLmn Y8PkY+J39B59F0DKjyrCjasZyi0tQQV6ps5Xm2X2CB003GWEbo1yu+BodShYEyaL 7OvkLiVpOtq+LOYcsScHtOGdO9le2O3yZevNRvlrCDCvJUYbXNjaM9ZrWcQuTlJc oseYNSRPaIP5PMv2c+Xup9qh/dyAjj8g6gSi9BlDvwVOu/+Cf3laaCAXaFph22jT /m8fW2paiP5UJ0gSt1MLAGFxKi0YI/Qxck8G11LJxUwMZd3SIfOPUAY27tnNC4yL GRynOi3BFRMUAe/Leu2qgwEyoME5nHn+OmAKb36WTYH/HL+PGzHq84e+Wfdan8ha YcSKc1A52LSoYTi4XTUX =h2Qo -----END PGP SIGNATURE----- Merge tag 'pm-merge' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc Pull ARM SoC power management and clock changes from Olof Johansson: "This branch contains a largeish set of updates of power management and clock setup. The bulk of it is for OMAP/AM33xx platforms, but also a few around hotplug/suspend/resume on Exynos. It includes a split-up of some of the OMAP clock data into separate files which adds to the diffstat, but gross delta is fairly reasonable." * tag 'pm-merge' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (60 commits) ARM: OMAP: Move plat-omap/dma-omap.h to include/linux/omap-dma.h ASoC: OMAP: mcbsp fixes for enabling ARM multiplatform support watchdog: OMAP: fixup for ARM multiplatform support ARM: EXYNOS: Add flush_cache_all in suspend finisher ARM: EXYNOS: Remove scu_enable from cpuidle ARM: EXYNOS: Fix soft reboot hang after suspend/resume ARM: EXYNOS: Add support for rtc wakeup ARM: EXYNOS: fix the hotplug for Cortex-A15 ARM: OMAP2+: omap_device: Correct resource handling for DT boot ARM: OMAP2+: hwmod: Add possibility to count hwmod resources based on type ARM: OMAP2+: hwmod: Add support for per hwmod/module context lost count ARM: OMAP2+: PRM: initialize some PRM functions early ARM: OMAP2+: voltage: fixup oscillator handling when CONFIG_PM=n ARM: OMAP4: USB: power down MUSB PHY during boot ARM: OMAP2+: clock: Cleanup !CONFIG_COMMON_CLK parts ARM: OMAP2xxx: clock: drop obsolete clock data ARM: OMAP2: clock: Cleanup !CONFIG_COMMON_CLK parts ARM: OMAP3+: DPLL: drop !CONFIG_COMMON_CLK sections ARM: AM33xx: clock: drop obsolete clock data ARM: OMAP3xxx: clk: drop obsolete clock data ...
This commit is contained in:
commit
a11da7df65
|
@ -680,6 +680,8 @@ void __init exynos5_init_irq(void)
|
|||
* uses GIC instead of VIC.
|
||||
*/
|
||||
s5p_init_irq(NULL, 0);
|
||||
|
||||
gic_arch_extn.irq_set_wake = s3c_irq_wake;
|
||||
}
|
||||
|
||||
struct bus_type exynos_subsys = {
|
||||
|
|
|
@ -116,7 +116,8 @@ static int exynos4_enter_core0_aftr(struct cpuidle_device *dev,
|
|||
cpu_suspend(0, idle_finisher);
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
scu_enable(S5P_VA_SCU);
|
||||
if (!soc_is_exynos5250())
|
||||
scu_enable(S5P_VA_SCU);
|
||||
#endif
|
||||
cpu_pm_exit();
|
||||
|
||||
|
|
|
@ -20,10 +20,11 @@
|
|||
#include <asm/smp_plat.h>
|
||||
|
||||
#include <mach/regs-pmu.h>
|
||||
#include <plat/cpu.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
static inline void cpu_enter_lowpower(void)
|
||||
static inline void cpu_enter_lowpower_a9(void)
|
||||
{
|
||||
unsigned int v;
|
||||
|
||||
|
@ -45,6 +46,35 @@ static inline void cpu_enter_lowpower(void)
|
|||
: "cc");
|
||||
}
|
||||
|
||||
static inline void cpu_enter_lowpower_a15(void)
|
||||
{
|
||||
unsigned int v;
|
||||
|
||||
asm volatile(
|
||||
" mrc p15, 0, %0, c1, c0, 0\n"
|
||||
" bic %0, %0, %1\n"
|
||||
" mcr p15, 0, %0, c1, c0, 0\n"
|
||||
: "=&r" (v)
|
||||
: "Ir" (CR_C)
|
||||
: "cc");
|
||||
|
||||
flush_cache_louis();
|
||||
|
||||
asm volatile(
|
||||
/*
|
||||
* Turn off coherency
|
||||
*/
|
||||
" mrc p15, 0, %0, c1, c0, 1\n"
|
||||
" bic %0, %0, %1\n"
|
||||
" mcr p15, 0, %0, c1, c0, 1\n"
|
||||
: "=&r" (v)
|
||||
: "Ir" (0x40)
|
||||
: "cc");
|
||||
|
||||
isb();
|
||||
dsb();
|
||||
}
|
||||
|
||||
static inline void cpu_leave_lowpower(void)
|
||||
{
|
||||
unsigned int v;
|
||||
|
@ -103,11 +133,20 @@ static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
|
|||
void __ref exynos_cpu_die(unsigned int cpu)
|
||||
{
|
||||
int spurious = 0;
|
||||
int primary_part = 0;
|
||||
|
||||
/*
|
||||
* we're ready for shutdown now, so do it
|
||||
* we're ready for shutdown now, so do it.
|
||||
* Exynos4 is A9 based while Exynos5 is A15; check the CPU part
|
||||
* number by reading the Main ID register and then perform the
|
||||
* appropriate sequence for entering low power.
|
||||
*/
|
||||
cpu_enter_lowpower();
|
||||
asm("mrc p15, 0, %0, c0, c0, 0" : "=r"(primary_part) : : "cc");
|
||||
if ((primary_part & 0xfff0) == 0xc0f0)
|
||||
cpu_enter_lowpower_a15();
|
||||
else
|
||||
cpu_enter_lowpower_a9();
|
||||
|
||||
platform_do_lowpower(cpu, &spurious);
|
||||
|
||||
/*
|
||||
|
|
|
@ -81,6 +81,9 @@ static int exynos_cpu_suspend(unsigned long arg)
|
|||
outer_flush_all();
|
||||
#endif
|
||||
|
||||
if (soc_is_exynos5250())
|
||||
flush_cache_all();
|
||||
|
||||
/* issue the standby signal into the pm unit. */
|
||||
cpu_do_idle();
|
||||
|
||||
|
@ -312,6 +315,10 @@ static void exynos_pm_resume(void)
|
|||
}
|
||||
|
||||
early_wakeup:
|
||||
|
||||
/* Clear SLEEP mode set in INFORM1 */
|
||||
__raw_writel(0x0, S5P_INFORM1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
#include <asm/mach/map.h>
|
||||
|
||||
#include <mach/mux.h>
|
||||
#include <plat-omap/dma-omap.h>
|
||||
#include <linux/omap-dma.h>
|
||||
#include <mach/tc.h>
|
||||
#include <mach/irda.h>
|
||||
#include <linux/platform_data/keypad-omap.h>
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
#include <mach/mux.h>
|
||||
#include <mach/tc.h>
|
||||
#include <linux/platform_data/keypad-omap.h>
|
||||
#include <plat-omap/dma-omap.h>
|
||||
#include <linux/omap-dma.h>
|
||||
#include <mach/flash.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
#include <mach/flash.h>
|
||||
#include <mach/mux.h>
|
||||
#include <mach/tc.h>
|
||||
#include <plat-omap/dma-omap.h>
|
||||
#include <linux/omap-dma.h>
|
||||
#include <mach/irda.h>
|
||||
#include <linux/platform_data/keypad-omap.h>
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
#include <mach/flash.h>
|
||||
#include <mach/mux.h>
|
||||
#include <plat-omap/dma-omap.h>
|
||||
#include <linux/omap-dma.h>
|
||||
#include <mach/tc.h>
|
||||
#include <mach/irda.h>
|
||||
#include <linux/platform_data/keypad-omap.h>
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
|
||||
#include <mach/flash.h>
|
||||
#include <mach/mux.h>
|
||||
#include <plat-omap/dma-omap.h>
|
||||
#include <linux/omap-dma.h>
|
||||
#include <mach/tc.h>
|
||||
#include <mach/irda.h>
|
||||
#include <linux/platform_data/keypad-omap.h>
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
#include <mach/flash.h>
|
||||
#include <mach/mux.h>
|
||||
#include <plat-omap/dma-omap.h>
|
||||
#include <linux/omap-dma.h>
|
||||
#include <mach/irda.h>
|
||||
#include <mach/tc.h>
|
||||
#include <mach/board-sx1.h>
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include <linux/device.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <plat-omap/dma-omap.h>
|
||||
#include <linux/omap-dma.h>
|
||||
#include <mach/tc.h>
|
||||
|
||||
#include <mach/irqs.h>
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
#include <mach/mux.h>
|
||||
#include <mach/tc.h>
|
||||
#include <plat-omap/dma-omap.h>
|
||||
#include <linux/omap-dma.h>
|
||||
|
||||
#include "iomap.h"
|
||||
#include "common.h"
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <plat-omap/dma-omap.h>
|
||||
#include <linux/omap-dma.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/lcdc.h>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <plat-omap/dma-omap.h>
|
||||
#include <linux/omap-dma.h>
|
||||
#include <mach/mux.h>
|
||||
#include "soc.h"
|
||||
#include <linux/platform_data/asoc-ti-mcbsp.h>
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
|
||||
#include <mach/tc.h>
|
||||
#include <mach/mux.h>
|
||||
#include <plat-omap/dma-omap.h>
|
||||
#include <linux/omap-dma.h>
|
||||
#include <plat/dmtimer.h>
|
||||
|
||||
#include <mach/irqs.h>
|
||||
|
|
|
@ -34,6 +34,7 @@ config ARCH_OMAP2
|
|||
select CPU_V6
|
||||
select MULTI_IRQ_HANDLER
|
||||
select SOC_HAS_OMAP2_SDRC
|
||||
select COMMON_CLK
|
||||
|
||||
config ARCH_OMAP3
|
||||
bool "TI OMAP3"
|
||||
|
@ -47,6 +48,7 @@ config ARCH_OMAP3
|
|||
select PM_OPP if PM
|
||||
select PM_RUNTIME if CPU_IDLE
|
||||
select SOC_HAS_OMAP2_SDRC
|
||||
select COMMON_CLK
|
||||
select USB_ARCH_HAS_EHCI if USB_SUPPORT
|
||||
|
||||
config ARCH_OMAP4
|
||||
|
@ -68,6 +70,7 @@ config ARCH_OMAP4
|
|||
select PM_OPP if PM
|
||||
select PM_RUNTIME if CPU_IDLE
|
||||
select USB_ARCH_HAS_EHCI if USB_SUPPORT
|
||||
select COMMON_CLK
|
||||
|
||||
config SOC_OMAP5
|
||||
bool "TI OMAP5"
|
||||
|
@ -77,6 +80,7 @@ config SOC_OMAP5
|
|||
select CPU_V7
|
||||
select HAVE_SMP
|
||||
select SOC_HAS_REALTIME_COUNTER
|
||||
select COMMON_CLK
|
||||
|
||||
comment "OMAP Core Type"
|
||||
depends on ARCH_OMAP2
|
||||
|
@ -111,6 +115,7 @@ config SOC_AM33XX
|
|||
select ARM_CPU_SUSPEND if PM
|
||||
select CPU_V7
|
||||
select MULTI_IRQ_HANDLER
|
||||
select COMMON_CLK
|
||||
|
||||
config OMAP_PACKAGE_ZAF
|
||||
bool
|
||||
|
|
|
@ -160,17 +160,17 @@ obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_dpllcore.o
|
|||
obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_virt_prcm_set.o
|
||||
obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_apll.o clkt2xxx_osc.o
|
||||
obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_dpll.o clkt_iclk.o
|
||||
obj-$(CONFIG_SOC_OMAP2420) += clock2420_data.o
|
||||
obj-$(CONFIG_SOC_OMAP2430) += clock2430.o clock2430_data.o
|
||||
obj-$(CONFIG_SOC_OMAP2420) += cclock2420_data.o
|
||||
obj-$(CONFIG_SOC_OMAP2430) += clock2430.o cclock2430_data.o
|
||||
obj-$(CONFIG_ARCH_OMAP3) += $(clock-common) clock3xxx.o
|
||||
obj-$(CONFIG_ARCH_OMAP3) += clock34xx.o clkt34xx_dpll3m2.o
|
||||
obj-$(CONFIG_ARCH_OMAP3) += clock3517.o clock36xx.o
|
||||
obj-$(CONFIG_ARCH_OMAP3) += dpll3xxx.o clock3xxx_data.o
|
||||
obj-$(CONFIG_ARCH_OMAP3) += dpll3xxx.o cclock3xxx_data.o
|
||||
obj-$(CONFIG_ARCH_OMAP3) += clkt_iclk.o
|
||||
obj-$(CONFIG_ARCH_OMAP4) += $(clock-common) clock44xx_data.o
|
||||
obj-$(CONFIG_ARCH_OMAP4) += $(clock-common) cclock44xx_data.o
|
||||
obj-$(CONFIG_ARCH_OMAP4) += dpll3xxx.o dpll44xx.o
|
||||
obj-$(CONFIG_SOC_AM33XX) += $(clock-common) dpll3xxx.o
|
||||
obj-$(CONFIG_SOC_AM33XX) += clock33xx_data.o
|
||||
obj-$(CONFIG_SOC_AM33XX) += cclock33xx_data.o
|
||||
obj-$(CONFIG_SOC_OMAP5) += $(clock-common)
|
||||
obj-$(CONFIG_SOC_OMAP5) += dpll3xxx.o dpll44xx.o
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
#include <asm/mach/map.h>
|
||||
|
||||
#include "common.h"
|
||||
#include <plat-omap/dma-omap.h>
|
||||
#include <linux/omap-dma.h>
|
||||
#include <video/omapdss.h>
|
||||
#include <video/omap-panel-tfp410.h>
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
|
||||
#include <plat-omap/dma-omap.h>
|
||||
#include <linux/omap-dma.h>
|
||||
#include <plat/debug-devices.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
#include <asm/system_info.h>
|
||||
|
||||
#include "common.h"
|
||||
#include <plat-omap/dma-omap.h>
|
||||
#include <linux/omap-dma.h>
|
||||
#include "gpmc-smc91x.h"
|
||||
|
||||
#include "board-rx51.h"
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
|
||||
#include <plat-omap/dma-omap.h>
|
||||
#include <linux/omap-dma.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "mux.h"
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,961 @@
|
|||
/*
|
||||
* AM33XX Clock data
|
||||
*
|
||||
* Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* Vaibhav Hiremath <hvaibhav@ti.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation version 2.
|
||||
*
|
||||
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
|
||||
* kind, whether express or implied; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/clk-private.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include "am33xx.h"
|
||||
#include "soc.h"
|
||||
#include "iomap.h"
|
||||
#include "clock.h"
|
||||
#include "control.h"
|
||||
#include "cm.h"
|
||||
#include "cm33xx.h"
|
||||
#include "cm-regbits-33xx.h"
|
||||
#include "prm.h"
|
||||
|
||||
/* Modulemode control */
|
||||
#define AM33XX_MODULEMODE_HWCTRL_SHIFT 0
|
||||
#define AM33XX_MODULEMODE_SWCTRL_SHIFT 1
|
||||
|
||||
/*LIST_HEAD(clocks);*/
|
||||
|
||||
/* Root clocks */
|
||||
|
||||
/* RTC 32k */
|
||||
DEFINE_CLK_FIXED_RATE(clk_32768_ck, CLK_IS_ROOT, 32768, 0x0);
|
||||
|
||||
/* On-Chip 32KHz RC OSC */
|
||||
DEFINE_CLK_FIXED_RATE(clk_rc32k_ck, CLK_IS_ROOT, 32000, 0x0);
|
||||
|
||||
/* Crystal input clks */
|
||||
DEFINE_CLK_FIXED_RATE(virt_19200000_ck, CLK_IS_ROOT, 19200000, 0x0);
|
||||
|
||||
DEFINE_CLK_FIXED_RATE(virt_24000000_ck, CLK_IS_ROOT, 24000000, 0x0);
|
||||
|
||||
DEFINE_CLK_FIXED_RATE(virt_25000000_ck, CLK_IS_ROOT, 25000000, 0x0);
|
||||
|
||||
DEFINE_CLK_FIXED_RATE(virt_26000000_ck, CLK_IS_ROOT, 26000000, 0x0);
|
||||
|
||||
/* Oscillator clock */
|
||||
/* 19.2, 24, 25 or 26 MHz */
|
||||
static const char *sys_clkin_ck_parents[] = {
|
||||
"virt_19200000_ck", "virt_24000000_ck", "virt_25000000_ck",
|
||||
"virt_26000000_ck",
|
||||
};
|
||||
|
||||
/*
|
||||
* sys_clk in: input to the dpll and also used as funtional clock for,
|
||||
* adc_tsc, smartreflex0-1, timer1-7, mcasp0-1, dcan0-1, cefuse
|
||||
*
|
||||
*/
|
||||
DEFINE_CLK_MUX(sys_clkin_ck, sys_clkin_ck_parents, NULL, 0x0,
|
||||
AM33XX_CTRL_REGADDR(AM33XX_CONTROL_STATUS),
|
||||
AM33XX_CONTROL_STATUS_SYSBOOT1_SHIFT,
|
||||
AM33XX_CONTROL_STATUS_SYSBOOT1_WIDTH,
|
||||
0, NULL);
|
||||
|
||||
/* External clock - 12 MHz */
|
||||
DEFINE_CLK_FIXED_RATE(tclkin_ck, CLK_IS_ROOT, 12000000, 0x0);
|
||||
|
||||
/* Module clocks and DPLL outputs */
|
||||
|
||||
/* DPLL_CORE */
|
||||
static struct dpll_data dpll_core_dd = {
|
||||
.mult_div1_reg = AM33XX_CM_CLKSEL_DPLL_CORE,
|
||||
.clk_bypass = &sys_clkin_ck,
|
||||
.clk_ref = &sys_clkin_ck,
|
||||
.control_reg = AM33XX_CM_CLKMODE_DPLL_CORE,
|
||||
.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
|
||||
.idlest_reg = AM33XX_CM_IDLEST_DPLL_CORE,
|
||||
.mult_mask = AM33XX_DPLL_MULT_MASK,
|
||||
.div1_mask = AM33XX_DPLL_DIV_MASK,
|
||||
.enable_mask = AM33XX_DPLL_EN_MASK,
|
||||
.idlest_mask = AM33XX_ST_DPLL_CLK_MASK,
|
||||
.max_multiplier = 2047,
|
||||
.max_divider = 128,
|
||||
.min_divider = 1,
|
||||
};
|
||||
|
||||
/* CLKDCOLDO output */
|
||||
static const char *dpll_core_ck_parents[] = {
|
||||
"sys_clkin_ck",
|
||||
};
|
||||
|
||||
static struct clk dpll_core_ck;
|
||||
|
||||
static const struct clk_ops dpll_core_ck_ops = {
|
||||
.recalc_rate = &omap3_dpll_recalc,
|
||||
.get_parent = &omap2_init_dpll_parent,
|
||||
};
|
||||
|
||||
static struct clk_hw_omap dpll_core_ck_hw = {
|
||||
.hw = {
|
||||
.clk = &dpll_core_ck,
|
||||
},
|
||||
.dpll_data = &dpll_core_dd,
|
||||
.ops = &clkhwops_omap3_dpll,
|
||||
};
|
||||
|
||||
DEFINE_STRUCT_CLK(dpll_core_ck, dpll_core_ck_parents, dpll_core_ck_ops);
|
||||
|
||||
static const char *dpll_core_x2_ck_parents[] = {
|
||||
"dpll_core_ck",
|
||||
};
|
||||
|
||||
static struct clk dpll_core_x2_ck;
|
||||
|
||||
static const struct clk_ops dpll_x2_ck_ops = {
|
||||
.recalc_rate = &omap3_clkoutx2_recalc,
|
||||
};
|
||||
|
||||
static struct clk_hw_omap dpll_core_x2_ck_hw = {
|
||||
.hw = {
|
||||
.clk = &dpll_core_x2_ck,
|
||||
},
|
||||
.flags = CLOCK_CLKOUTX2,
|
||||
};
|
||||
|
||||
DEFINE_STRUCT_CLK(dpll_core_x2_ck, dpll_core_x2_ck_parents, dpll_x2_ck_ops);
|
||||
|
||||
DEFINE_CLK_DIVIDER(dpll_core_m4_ck, "dpll_core_x2_ck", &dpll_core_x2_ck,
|
||||
0x0, AM33XX_CM_DIV_M4_DPLL_CORE,
|
||||
AM33XX_HSDIVIDER_CLKOUT1_DIV_SHIFT,
|
||||
AM33XX_HSDIVIDER_CLKOUT1_DIV_WIDTH, CLK_DIVIDER_ONE_BASED,
|
||||
NULL);
|
||||
|
||||
DEFINE_CLK_DIVIDER(dpll_core_m5_ck, "dpll_core_x2_ck", &dpll_core_x2_ck,
|
||||
0x0, AM33XX_CM_DIV_M5_DPLL_CORE,
|
||||
AM33XX_HSDIVIDER_CLKOUT2_DIV_SHIFT,
|
||||
AM33XX_HSDIVIDER_CLKOUT2_DIV_WIDTH,
|
||||
CLK_DIVIDER_ONE_BASED, NULL);
|
||||
|
||||
DEFINE_CLK_DIVIDER(dpll_core_m6_ck, "dpll_core_x2_ck", &dpll_core_x2_ck,
|
||||
0x0, AM33XX_CM_DIV_M6_DPLL_CORE,
|
||||
AM33XX_HSDIVIDER_CLKOUT3_DIV_SHIFT,
|
||||
AM33XX_HSDIVIDER_CLKOUT3_DIV_WIDTH,
|
||||
CLK_DIVIDER_ONE_BASED, NULL);
|
||||
|
||||
|
||||
/* DPLL_MPU */
|
||||
static struct dpll_data dpll_mpu_dd = {
|
||||
.mult_div1_reg = AM33XX_CM_CLKSEL_DPLL_MPU,
|
||||
.clk_bypass = &sys_clkin_ck,
|
||||
.clk_ref = &sys_clkin_ck,
|
||||
.control_reg = AM33XX_CM_CLKMODE_DPLL_MPU,
|
||||
.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
|
||||
.idlest_reg = AM33XX_CM_IDLEST_DPLL_MPU,
|
||||
.mult_mask = AM33XX_DPLL_MULT_MASK,
|
||||
.div1_mask = AM33XX_DPLL_DIV_MASK,
|
||||
.enable_mask = AM33XX_DPLL_EN_MASK,
|
||||
.idlest_mask = AM33XX_ST_DPLL_CLK_MASK,
|
||||
.max_multiplier = 2047,
|
||||
.max_divider = 128,
|
||||
.min_divider = 1,
|
||||
};
|
||||
|
||||
/* CLKOUT: fdpll/M2 */
|
||||
static struct clk dpll_mpu_ck;
|
||||
|
||||
static const struct clk_ops dpll_mpu_ck_ops = {
|
||||
.enable = &omap3_noncore_dpll_enable,
|
||||
.disable = &omap3_noncore_dpll_disable,
|
||||
.recalc_rate = &omap3_dpll_recalc,
|
||||
.round_rate = &omap2_dpll_round_rate,
|
||||
.set_rate = &omap3_noncore_dpll_set_rate,
|
||||
.get_parent = &omap2_init_dpll_parent,
|
||||
};
|
||||
|
||||
static struct clk_hw_omap dpll_mpu_ck_hw = {
|
||||
.hw = {
|
||||
.clk = &dpll_mpu_ck,
|
||||
},
|
||||
.dpll_data = &dpll_mpu_dd,
|
||||
.ops = &clkhwops_omap3_dpll,
|
||||
};
|
||||
|
||||
DEFINE_STRUCT_CLK(dpll_mpu_ck, dpll_core_ck_parents, dpll_mpu_ck_ops);
|
||||
|
||||
/*
|
||||
* TODO: Add clksel here (sys_clkin, CORE_CLKOUTM6, PER_CLKOUTM2
|
||||
* and ALT_CLK1/2)
|
||||
*/
|
||||
DEFINE_CLK_DIVIDER(dpll_mpu_m2_ck, "dpll_mpu_ck", &dpll_mpu_ck,
|
||||
0x0, AM33XX_CM_DIV_M2_DPLL_MPU, AM33XX_DPLL_CLKOUT_DIV_SHIFT,
|
||||
AM33XX_DPLL_CLKOUT_DIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL);
|
||||
|
||||
/* DPLL_DDR */
|
||||
static struct dpll_data dpll_ddr_dd = {
|
||||
.mult_div1_reg = AM33XX_CM_CLKSEL_DPLL_DDR,
|
||||
.clk_bypass = &sys_clkin_ck,
|
||||
.clk_ref = &sys_clkin_ck,
|
||||
.control_reg = AM33XX_CM_CLKMODE_DPLL_DDR,
|
||||
.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
|
||||
.idlest_reg = AM33XX_CM_IDLEST_DPLL_DDR,
|
||||
.mult_mask = AM33XX_DPLL_MULT_MASK,
|
||||
.div1_mask = AM33XX_DPLL_DIV_MASK,
|
||||
.enable_mask = AM33XX_DPLL_EN_MASK,
|
||||
.idlest_mask = AM33XX_ST_DPLL_CLK_MASK,
|
||||
.max_multiplier = 2047,
|
||||
.max_divider = 128,
|
||||
.min_divider = 1,
|
||||
};
|
||||
|
||||
/* CLKOUT: fdpll/M2 */
|
||||
static struct clk dpll_ddr_ck;
|
||||
|
||||
static const struct clk_ops dpll_ddr_ck_ops = {
|
||||
.recalc_rate = &omap3_dpll_recalc,
|
||||
.get_parent = &omap2_init_dpll_parent,
|
||||
.round_rate = &omap2_dpll_round_rate,
|
||||
.set_rate = &omap3_noncore_dpll_set_rate,
|
||||
};
|
||||
|
||||
static struct clk_hw_omap dpll_ddr_ck_hw = {
|
||||
.hw = {
|
||||
.clk = &dpll_ddr_ck,
|
||||
},
|
||||
.dpll_data = &dpll_ddr_dd,
|
||||
.ops = &clkhwops_omap3_dpll,
|
||||
};
|
||||
|
||||
DEFINE_STRUCT_CLK(dpll_ddr_ck, dpll_core_ck_parents, dpll_ddr_ck_ops);
|
||||
|
||||
/*
|
||||
* TODO: Add clksel here (sys_clkin, CORE_CLKOUTM6, PER_CLKOUTM2
|
||||
* and ALT_CLK1/2)
|
||||
*/
|
||||
DEFINE_CLK_DIVIDER(dpll_ddr_m2_ck, "dpll_ddr_ck", &dpll_ddr_ck,
|
||||
0x0, AM33XX_CM_DIV_M2_DPLL_DDR,
|
||||
AM33XX_DPLL_CLKOUT_DIV_SHIFT, AM33XX_DPLL_CLKOUT_DIV_WIDTH,
|
||||
CLK_DIVIDER_ONE_BASED, NULL);
|
||||
|
||||
/* emif_fck functional clock */
|
||||
DEFINE_CLK_FIXED_FACTOR(dpll_ddr_m2_div2_ck, "dpll_ddr_m2_ck", &dpll_ddr_m2_ck,
|
||||
0x0, 1, 2);
|
||||
|
||||
/* DPLL_DISP */
|
||||
static struct dpll_data dpll_disp_dd = {
|
||||
.mult_div1_reg = AM33XX_CM_CLKSEL_DPLL_DISP,
|
||||
.clk_bypass = &sys_clkin_ck,
|
||||
.clk_ref = &sys_clkin_ck,
|
||||
.control_reg = AM33XX_CM_CLKMODE_DPLL_DISP,
|
||||
.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
|
||||
.idlest_reg = AM33XX_CM_IDLEST_DPLL_DISP,
|
||||
.mult_mask = AM33XX_DPLL_MULT_MASK,
|
||||
.div1_mask = AM33XX_DPLL_DIV_MASK,
|
||||
.enable_mask = AM33XX_DPLL_EN_MASK,
|
||||
.idlest_mask = AM33XX_ST_DPLL_CLK_MASK,
|
||||
.max_multiplier = 2047,
|
||||
.max_divider = 128,
|
||||
.min_divider = 1,
|
||||
};
|
||||
|
||||
/* CLKOUT: fdpll/M2 */
|
||||
static struct clk dpll_disp_ck;
|
||||
|
||||
static struct clk_hw_omap dpll_disp_ck_hw = {
|
||||
.hw = {
|
||||
.clk = &dpll_disp_ck,
|
||||
},
|
||||
.dpll_data = &dpll_disp_dd,
|
||||
.ops = &clkhwops_omap3_dpll,
|
||||
};
|
||||
|
||||
DEFINE_STRUCT_CLK(dpll_disp_ck, dpll_core_ck_parents, dpll_ddr_ck_ops);
|
||||
|
||||
/*
|
||||
* TODO: Add clksel here (sys_clkin, CORE_CLKOUTM6, PER_CLKOUTM2
|
||||
* and ALT_CLK1/2)
|
||||
*/
|
||||
DEFINE_CLK_DIVIDER(dpll_disp_m2_ck, "dpll_disp_ck", &dpll_disp_ck, 0x0,
|
||||
AM33XX_CM_DIV_M2_DPLL_DISP, AM33XX_DPLL_CLKOUT_DIV_SHIFT,
|
||||
AM33XX_DPLL_CLKOUT_DIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL);
|
||||
|
||||
/* DPLL_PER */
|
||||
static struct dpll_data dpll_per_dd = {
|
||||
.mult_div1_reg = AM33XX_CM_CLKSEL_DPLL_PERIPH,
|
||||
.clk_bypass = &sys_clkin_ck,
|
||||
.clk_ref = &sys_clkin_ck,
|
||||
.control_reg = AM33XX_CM_CLKMODE_DPLL_PER,
|
||||
.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
|
||||
.idlest_reg = AM33XX_CM_IDLEST_DPLL_PER,
|
||||
.mult_mask = AM33XX_DPLL_MULT_PERIPH_MASK,
|
||||
.div1_mask = AM33XX_DPLL_PER_DIV_MASK,
|
||||
.enable_mask = AM33XX_DPLL_EN_MASK,
|
||||
.idlest_mask = AM33XX_ST_DPLL_CLK_MASK,
|
||||
.max_multiplier = 2047,
|
||||
.max_divider = 128,
|
||||
.min_divider = 1,
|
||||
.flags = DPLL_J_TYPE,
|
||||
};
|
||||
|
||||
/* CLKDCOLDO */
|
||||
static struct clk dpll_per_ck;
|
||||
|
||||
static struct clk_hw_omap dpll_per_ck_hw = {
|
||||
.hw = {
|
||||
.clk = &dpll_per_ck,
|
||||
},
|
||||
.dpll_data = &dpll_per_dd,
|
||||
.ops = &clkhwops_omap3_dpll,
|
||||
};
|
||||
|
||||
DEFINE_STRUCT_CLK(dpll_per_ck, dpll_core_ck_parents, dpll_ddr_ck_ops);
|
||||
|
||||
/* CLKOUT: fdpll/M2 */
|
||||
DEFINE_CLK_DIVIDER(dpll_per_m2_ck, "dpll_per_ck", &dpll_per_ck, 0x0,
|
||||
AM33XX_CM_DIV_M2_DPLL_PER, AM33XX_DPLL_CLKOUT_DIV_SHIFT,
|
||||
AM33XX_DPLL_CLKOUT_DIV_WIDTH, CLK_DIVIDER_ONE_BASED,
|
||||
NULL);
|
||||
|
||||
DEFINE_CLK_FIXED_FACTOR(dpll_per_m2_div4_wkupdm_ck, "dpll_per_m2_ck",
|
||||
&dpll_per_m2_ck, 0x0, 1, 4);
|
||||
|
||||
DEFINE_CLK_FIXED_FACTOR(dpll_per_m2_div4_ck, "dpll_per_m2_ck",
|
||||
&dpll_per_m2_ck, 0x0, 1, 4);
|
||||
|
||||
DEFINE_CLK_FIXED_FACTOR(dpll_core_m4_div2_ck, "dpll_core_m4_ck",
|
||||
&dpll_core_m4_ck, 0x0, 1, 2);
|
||||
|
||||
DEFINE_CLK_FIXED_FACTOR(l4_rtc_gclk, "dpll_core_m4_ck", &dpll_core_m4_ck, 0x0,
|
||||
1, 2);
|
||||
|
||||
DEFINE_CLK_FIXED_FACTOR(clk_24mhz, "dpll_per_m2_ck", &dpll_per_m2_ck, 0x0, 1,
|
||||
8);
|
||||
|
||||
/*
|
||||
* Below clock nodes describes clockdomains derived out
|
||||
* of core clock.
|
||||
*/
|
||||
static const struct clk_ops clk_ops_null = {
|
||||
};
|
||||
|
||||
static const char *l3_gclk_parents[] = {
|
||||
"dpll_core_m4_ck"
|
||||
};
|
||||
|
||||
static struct clk l3_gclk;
|
||||
DEFINE_STRUCT_CLK_HW_OMAP(l3_gclk, NULL);
|
||||
DEFINE_STRUCT_CLK(l3_gclk, l3_gclk_parents, clk_ops_null);
|
||||
|
||||
static struct clk l4hs_gclk;
|
||||
DEFINE_STRUCT_CLK_HW_OMAP(l4hs_gclk, NULL);
|
||||
DEFINE_STRUCT_CLK(l4hs_gclk, l3_gclk_parents, clk_ops_null);
|
||||
|
||||
static const char *l3s_gclk_parents[] = {
|
||||
"dpll_core_m4_div2_ck"
|
||||
};
|
||||
|
||||
static struct clk l3s_gclk;
|
||||
DEFINE_STRUCT_CLK_HW_OMAP(l3s_gclk, NULL);
|
||||
DEFINE_STRUCT_CLK(l3s_gclk, l3s_gclk_parents, clk_ops_null);
|
||||
|
||||
static struct clk l4fw_gclk;
|
||||
DEFINE_STRUCT_CLK_HW_OMAP(l4fw_gclk, NULL);
|
||||
DEFINE_STRUCT_CLK(l4fw_gclk, l3s_gclk_parents, clk_ops_null);
|
||||
|
||||
static struct clk l4ls_gclk;
|
||||
DEFINE_STRUCT_CLK_HW_OMAP(l4ls_gclk, NULL);
|
||||
DEFINE_STRUCT_CLK(l4ls_gclk, l3s_gclk_parents, clk_ops_null);
|
||||
|
||||
static struct clk sysclk_div_ck;
|
||||
DEFINE_STRUCT_CLK_HW_OMAP(sysclk_div_ck, NULL);
|
||||
DEFINE_STRUCT_CLK(sysclk_div_ck, l3_gclk_parents, clk_ops_null);
|
||||
|
||||
/*
|
||||
* In order to match the clock domain with hwmod clockdomain entry,
|
||||
* separate clock nodes is required for the modules which are
|
||||
* directly getting their funtioncal clock from sys_clkin.
|
||||
*/
|
||||
static struct clk adc_tsc_fck;
|
||||
DEFINE_STRUCT_CLK_HW_OMAP(adc_tsc_fck, NULL);
|
||||
DEFINE_STRUCT_CLK(adc_tsc_fck, dpll_core_ck_parents, clk_ops_null);
|
||||
|
||||
static struct clk dcan0_fck;
|
||||
DEFINE_STRUCT_CLK_HW_OMAP(dcan0_fck, NULL);
|
||||
DEFINE_STRUCT_CLK(dcan0_fck, dpll_core_ck_parents, clk_ops_null);
|
||||
|
||||
static struct clk dcan1_fck;
|
||||
DEFINE_STRUCT_CLK_HW_OMAP(dcan1_fck, NULL);
|
||||
DEFINE_STRUCT_CLK(dcan1_fck, dpll_core_ck_parents, clk_ops_null);
|
||||
|
||||
static struct clk mcasp0_fck;
|
||||
DEFINE_STRUCT_CLK_HW_OMAP(mcasp0_fck, NULL);
|
||||
DEFINE_STRUCT_CLK(mcasp0_fck, dpll_core_ck_parents, clk_ops_null);
|
||||
|
||||
static struct clk mcasp1_fck;
|
||||
DEFINE_STRUCT_CLK_HW_OMAP(mcasp1_fck, NULL);
|
||||
DEFINE_STRUCT_CLK(mcasp1_fck, dpll_core_ck_parents, clk_ops_null);
|
||||
|
||||
static struct clk smartreflex0_fck;
|
||||
DEFINE_STRUCT_CLK_HW_OMAP(smartreflex0_fck, NULL);
|
||||
DEFINE_STRUCT_CLK(smartreflex0_fck, dpll_core_ck_parents, clk_ops_null);
|
||||
|
||||
static struct clk smartreflex1_fck;
|
||||
DEFINE_STRUCT_CLK_HW_OMAP(smartreflex1_fck, NULL);
|
||||
DEFINE_STRUCT_CLK(smartreflex1_fck, dpll_core_ck_parents, clk_ops_null);
|
||||
|
||||
/*
|
||||
* Modules clock nodes
|
||||
*
|
||||
* The following clock leaf nodes are added for the moment because:
|
||||
*
|
||||
* - hwmod data is not present for these modules, either hwmod
|
||||
* control is not required or its not populated.
|
||||
* - Driver code is not yet migrated to use hwmod/runtime pm
|
||||
* - Modules outside kernel access (to disable them by default)
|
||||
*
|
||||
* - debugss
|
||||
* - mmu (gfx domain)
|
||||
* - cefuse
|
||||
* - usbotg_fck (its additional clock and not really a modulemode)
|
||||
* - ieee5000
|
||||
*/
|
||||
DEFINE_CLK_GATE(debugss_ick, "dpll_core_m4_ck", &dpll_core_m4_ck, 0x0,
|
||||
AM33XX_CM_WKUP_DEBUGSS_CLKCTRL, AM33XX_MODULEMODE_SWCTRL_SHIFT,
|
||||
0x0, NULL);
|
||||
|
||||
DEFINE_CLK_GATE(mmu_fck, "dpll_core_m4_ck", &dpll_core_m4_ck, 0x0,
|
||||
AM33XX_CM_GFX_MMUDATA_CLKCTRL, AM33XX_MODULEMODE_SWCTRL_SHIFT,
|
||||
0x0, NULL);
|
||||
|
||||
DEFINE_CLK_GATE(cefuse_fck, "sys_clkin_ck", &sys_clkin_ck, 0x0,
|
||||
AM33XX_CM_CEFUSE_CEFUSE_CLKCTRL, AM33XX_MODULEMODE_SWCTRL_SHIFT,
|
||||
0x0, NULL);
|
||||
|
||||
/*
|
||||
* clkdiv32 is generated from fixed division of 732.4219
|
||||
*/
|
||||
DEFINE_CLK_FIXED_FACTOR(clkdiv32k_ck, "clk_24mhz", &clk_24mhz, 0x0, 1, 732);
|
||||
|
||||
DEFINE_CLK_GATE(clkdiv32k_ick, "clkdiv32k_ck", &clkdiv32k_ck, 0x0,
|
||||
AM33XX_CM_PER_CLKDIV32K_CLKCTRL, AM33XX_MODULEMODE_SWCTRL_SHIFT,
|
||||
0x0, NULL);
|
||||
|
||||
/* "usbotg_fck" is an additional clock and not really a modulemode */
|
||||
DEFINE_CLK_GATE(usbotg_fck, "dpll_per_ck", &dpll_per_ck, 0x0,
|
||||
AM33XX_CM_CLKDCOLDO_DPLL_PER, AM33XX_ST_DPLL_CLKDCOLDO_SHIFT,
|
||||
0x0, NULL);
|
||||
|
||||
DEFINE_CLK_GATE(ieee5000_fck, "dpll_core_m4_div2_ck", &dpll_core_m4_div2_ck,
|
||||
0x0, AM33XX_CM_PER_IEEE5000_CLKCTRL,
|
||||
AM33XX_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
|
||||
|
||||
/* Timers */
|
||||
static const struct clksel timer1_clkmux_sel[] = {
|
||||
{ .parent = &sys_clkin_ck, .rates = div_1_0_rates },
|
||||
{ .parent = &clkdiv32k_ick, .rates = div_1_1_rates },
|
||||
{ .parent = &tclkin_ck, .rates = div_1_2_rates },
|
||||
{ .parent = &clk_rc32k_ck, .rates = div_1_3_rates },
|
||||
{ .parent = &clk_32768_ck, .rates = div_1_4_rates },
|
||||
{ .parent = NULL },
|
||||
};
|
||||
|
||||
static const char *timer1_ck_parents[] = {
|
||||
"sys_clkin_ck", "clkdiv32k_ick", "tclkin_ck", "clk_rc32k_ck",
|
||||
"clk_32768_ck",
|
||||
};
|
||||
|
||||
static struct clk timer1_fck;
|
||||
|
||||
static const struct clk_ops timer1_fck_ops = {
|
||||
.recalc_rate = &omap2_clksel_recalc,
|
||||
.get_parent = &omap2_clksel_find_parent_index,
|
||||
.set_parent = &omap2_clksel_set_parent,
|
||||
.init = &omap2_init_clk_clkdm,
|
||||
};
|
||||
|
||||
static struct clk_hw_omap timer1_fck_hw = {
|
||||
.hw = {
|
||||
.clk = &timer1_fck,
|
||||
},
|
||||
.clkdm_name = "l4ls_clkdm",
|
||||
.clksel = timer1_clkmux_sel,
|
||||
.clksel_reg = AM33XX_CLKSEL_TIMER1MS_CLK,
|
||||
.clksel_mask = AM33XX_CLKSEL_0_2_MASK,
|
||||
};
|
||||
|
||||
DEFINE_STRUCT_CLK(timer1_fck, timer1_ck_parents, timer1_fck_ops);
|
||||
|
||||
static const struct clksel timer2_to_7_clk_sel[] = {
|
||||
{ .parent = &tclkin_ck, .rates = div_1_0_rates },
|
||||
{ .parent = &sys_clkin_ck, .rates = div_1_1_rates },
|
||||
{ .parent = &clkdiv32k_ick, .rates = div_1_2_rates },
|
||||
{ .parent = NULL },
|
||||
};
|
||||
|
||||
static const char *timer2_to_7_ck_parents[] = {
|
||||
"tclkin_ck", "sys_clkin_ck", "clkdiv32k_ick",
|
||||
};
|
||||
|
||||
static struct clk timer2_fck;
|
||||
|
||||
static struct clk_hw_omap timer2_fck_hw = {
|
||||
.hw = {
|
||||
.clk = &timer2_fck,
|
||||
},
|
||||
.clkdm_name = "l4ls_clkdm",
|
||||
.clksel = timer2_to_7_clk_sel,
|
||||
.clksel_reg = AM33XX_CLKSEL_TIMER2_CLK,
|
||||
.clksel_mask = AM33XX_CLKSEL_0_1_MASK,
|
||||
};
|
||||
|
||||
DEFINE_STRUCT_CLK(timer2_fck, timer2_to_7_ck_parents, timer1_fck_ops);
|
||||
|
||||
static struct clk timer3_fck;
|
||||
|
||||
static struct clk_hw_omap timer3_fck_hw = {
|
||||
.hw = {
|
||||
.clk = &timer3_fck,
|
||||
},
|
||||
.clkdm_name = "l4ls_clkdm",
|
||||
.clksel = timer2_to_7_clk_sel,
|
||||
.clksel_reg = AM33XX_CLKSEL_TIMER3_CLK,
|
||||
.clksel_mask = AM33XX_CLKSEL_0_1_MASK,
|
||||
};
|
||||
|
||||
DEFINE_STRUCT_CLK(timer3_fck, timer2_to_7_ck_parents, timer1_fck_ops);
|
||||
|
||||
static struct clk timer4_fck;
|
||||
|
||||
static struct clk_hw_omap timer4_fck_hw = {
|
||||
.hw = {
|
||||
.clk = &timer4_fck,
|
||||
},
|
||||
.clkdm_name = "l4ls_clkdm",
|
||||
.clksel = timer2_to_7_clk_sel,
|
||||
.clksel_reg = AM33XX_CLKSEL_TIMER4_CLK,
|
||||
.clksel_mask = AM33XX_CLKSEL_0_1_MASK,
|
||||
};
|
||||
|
||||
DEFINE_STRUCT_CLK(timer4_fck, timer2_to_7_ck_parents, timer1_fck_ops);
|
||||
|
||||
static struct clk timer5_fck;
|
||||
|
||||
static struct clk_hw_omap timer5_fck_hw = {
|
||||
.hw = {
|
||||
.clk = &timer5_fck,
|
||||
},
|
||||
.clkdm_name = "l4ls_clkdm",
|
||||
.clksel = timer2_to_7_clk_sel,
|
||||
.clksel_reg = AM33XX_CLKSEL_TIMER5_CLK,
|
||||
.clksel_mask = AM33XX_CLKSEL_0_1_MASK,
|
||||
};
|
||||
|
||||
DEFINE_STRUCT_CLK(timer5_fck, timer2_to_7_ck_parents, timer1_fck_ops);
|
||||
|
||||
static struct clk timer6_fck;
|
||||
|
||||
static struct clk_hw_omap timer6_fck_hw = {
|
||||
.hw = {
|
||||
.clk = &timer6_fck,
|
||||
},
|
||||
.clkdm_name = "l4ls_clkdm",
|
||||
.clksel = timer2_to_7_clk_sel,
|
||||
.clksel_reg = AM33XX_CLKSEL_TIMER6_CLK,
|
||||
.clksel_mask = AM33XX_CLKSEL_0_1_MASK,
|
||||
};
|
||||
|
||||
DEFINE_STRUCT_CLK(timer6_fck, timer2_to_7_ck_parents, timer1_fck_ops);
|
||||
|
||||
static struct clk timer7_fck;
|
||||
|
||||
static struct clk_hw_omap timer7_fck_hw = {
|
||||
.hw = {
|
||||
.clk = &timer7_fck,
|
||||
},
|
||||
.clkdm_name = "l4ls_clkdm",
|
||||
.clksel = timer2_to_7_clk_sel,
|
||||
.clksel_reg = AM33XX_CLKSEL_TIMER7_CLK,
|
||||
.clksel_mask = AM33XX_CLKSEL_0_1_MASK,
|
||||
};
|
||||
|
||||
DEFINE_STRUCT_CLK(timer7_fck, timer2_to_7_ck_parents, timer1_fck_ops);
|
||||
|
||||
DEFINE_CLK_FIXED_FACTOR(cpsw_125mhz_gclk,
|
||||
"dpll_core_m5_ck",
|
||||
&dpll_core_m5_ck,
|
||||
0x0,
|
||||
1, 2);
|
||||
|
||||
static const struct clk_ops cpsw_fck_ops = {
|
||||
.recalc_rate = &omap2_clksel_recalc,
|
||||
.get_parent = &omap2_clksel_find_parent_index,
|
||||
.set_parent = &omap2_clksel_set_parent,
|
||||
};
|
||||
|
||||
static const struct clksel cpsw_cpts_rft_clkmux_sel[] = {
|
||||
{ .parent = &dpll_core_m5_ck, .rates = div_1_0_rates },
|
||||
{ .parent = &dpll_core_m4_ck, .rates = div_1_1_rates },
|
||||
{ .parent = NULL },
|
||||
};
|
||||
|
||||
static const char *cpsw_cpts_rft_ck_parents[] = {
|
||||
"dpll_core_m5_ck", "dpll_core_m4_ck",
|
||||
};
|
||||
|
||||
static struct clk cpsw_cpts_rft_clk;
|
||||
|
||||
static struct clk_hw_omap cpsw_cpts_rft_clk_hw = {
|
||||
.hw = {
|
||||
.clk = &cpsw_cpts_rft_clk,
|
||||
},
|
||||
.clkdm_name = "cpsw_125mhz_clkdm",
|
||||
.clksel = cpsw_cpts_rft_clkmux_sel,
|
||||
.clksel_reg = AM33XX_CM_CPTS_RFT_CLKSEL,
|
||||
.clksel_mask = AM33XX_CLKSEL_0_0_MASK,
|
||||
};
|
||||
|
||||
DEFINE_STRUCT_CLK(cpsw_cpts_rft_clk, cpsw_cpts_rft_ck_parents, cpsw_fck_ops);
|
||||
|
||||
|
||||
/* gpio */
|
||||
static const char *gpio0_ck_parents[] = {
|
||||
"clk_rc32k_ck", "clk_32768_ck", "clkdiv32k_ick",
|
||||
};
|
||||
|
||||
static const struct clksel gpio0_dbclk_mux_sel[] = {
|
||||
{ .parent = &clk_rc32k_ck, .rates = div_1_0_rates },
|
||||
{ .parent = &clk_32768_ck, .rates = div_1_1_rates },
|
||||
{ .parent = &clkdiv32k_ick, .rates = div_1_2_rates },
|
||||
{ .parent = NULL },
|
||||
};
|
||||
|
||||
static const struct clk_ops gpio_fck_ops = {
|
||||
.recalc_rate = &omap2_clksel_recalc,
|
||||
.get_parent = &omap2_clksel_find_parent_index,
|
||||
.set_parent = &omap2_clksel_set_parent,
|
||||
.init = &omap2_init_clk_clkdm,
|
||||
};
|
||||
|
||||
static struct clk gpio0_dbclk_mux_ck;
|
||||
|
||||
static struct clk_hw_omap gpio0_dbclk_mux_ck_hw = {
|
||||
.hw = {
|
||||
.clk = &gpio0_dbclk_mux_ck,
|
||||
},
|
||||
.clkdm_name = "l4_wkup_clkdm",
|
||||
.clksel = gpio0_dbclk_mux_sel,
|
||||
.clksel_reg = AM33XX_CLKSEL_GPIO0_DBCLK,
|
||||
.clksel_mask = AM33XX_CLKSEL_0_1_MASK,
|
||||
};
|
||||
|
||||
DEFINE_STRUCT_CLK(gpio0_dbclk_mux_ck, gpio0_ck_parents, gpio_fck_ops);
|
||||
|
||||
DEFINE_CLK_GATE(gpio0_dbclk, "gpio0_dbclk_mux_ck", &gpio0_dbclk_mux_ck, 0x0,
|
||||
AM33XX_CM_WKUP_GPIO0_CLKCTRL,
|
||||
AM33XX_OPTFCLKEN_GPIO0_GDBCLK_SHIFT, 0x0, NULL);
|
||||
|
||||
DEFINE_CLK_GATE(gpio1_dbclk, "clkdiv32k_ick", &clkdiv32k_ick, 0x0,
|
||||
AM33XX_CM_PER_GPIO1_CLKCTRL,
|
||||
AM33XX_OPTFCLKEN_GPIO_1_GDBCLK_SHIFT, 0x0, NULL);
|
||||
|
||||
DEFINE_CLK_GATE(gpio2_dbclk, "clkdiv32k_ick", &clkdiv32k_ick, 0x0,
|
||||
AM33XX_CM_PER_GPIO2_CLKCTRL,
|
||||
AM33XX_OPTFCLKEN_GPIO_2_GDBCLK_SHIFT, 0x0, NULL);
|
||||
|
||||
DEFINE_CLK_GATE(gpio3_dbclk, "clkdiv32k_ick", &clkdiv32k_ick, 0x0,
|
||||
AM33XX_CM_PER_GPIO3_CLKCTRL,
|
||||
AM33XX_OPTFCLKEN_GPIO_3_GDBCLK_SHIFT, 0x0, NULL);
|
||||
|
||||
|
||||
static const char *pruss_ck_parents[] = {
|
||||
"l3_gclk", "dpll_disp_m2_ck",
|
||||
};
|
||||
|
||||
static const struct clksel pruss_ocp_clk_mux_sel[] = {
|
||||
{ .parent = &l3_gclk, .rates = div_1_0_rates },
|
||||
{ .parent = &dpll_disp_m2_ck, .rates = div_1_1_rates },
|
||||
{ .parent = NULL },
|
||||
};
|
||||
|
||||
static struct clk pruss_ocp_gclk;
|
||||
|
||||
static struct clk_hw_omap pruss_ocp_gclk_hw = {
|
||||
.hw = {
|
||||
.clk = &pruss_ocp_gclk,
|
||||
},
|
||||
.clkdm_name = "pruss_ocp_clkdm",
|
||||
.clksel = pruss_ocp_clk_mux_sel,
|
||||
.clksel_reg = AM33XX_CLKSEL_PRUSS_OCP_CLK,
|
||||
.clksel_mask = AM33XX_CLKSEL_0_0_MASK,
|
||||
};
|
||||
|
||||
DEFINE_STRUCT_CLK(pruss_ocp_gclk, pruss_ck_parents, gpio_fck_ops);
|
||||
|
||||
static const char *lcd_ck_parents[] = {
|
||||
"dpll_disp_m2_ck", "dpll_core_m5_ck", "dpll_per_m2_ck",
|
||||
};
|
||||
|
||||
static const struct clksel lcd_clk_mux_sel[] = {
|
||||
{ .parent = &dpll_disp_m2_ck, .rates = div_1_0_rates },
|
||||
{ .parent = &dpll_core_m5_ck, .rates = div_1_1_rates },
|
||||
{ .parent = &dpll_per_m2_ck, .rates = div_1_2_rates },
|
||||
{ .parent = NULL },
|
||||
};
|
||||
|
||||
static struct clk lcd_gclk;
|
||||
|
||||
static struct clk_hw_omap lcd_gclk_hw = {
|
||||
.hw = {
|
||||
.clk = &lcd_gclk,
|
||||
},
|
||||
.clkdm_name = "lcdc_clkdm",
|
||||
.clksel = lcd_clk_mux_sel,
|
||||
.clksel_reg = AM33XX_CLKSEL_LCDC_PIXEL_CLK,
|
||||
.clksel_mask = AM33XX_CLKSEL_0_1_MASK,
|
||||
};
|
||||
|
||||
DEFINE_STRUCT_CLK(lcd_gclk, lcd_ck_parents, gpio_fck_ops);
|
||||
|
||||
DEFINE_CLK_FIXED_FACTOR(mmc_clk, "dpll_per_m2_ck", &dpll_per_m2_ck, 0x0, 1, 2);
|
||||
|
||||
static const char *gfx_ck_parents[] = {
|
||||
"dpll_core_m4_ck", "dpll_per_m2_ck",
|
||||
};
|
||||
|
||||
static const struct clksel gfx_clksel_sel[] = {
|
||||
{ .parent = &dpll_core_m4_ck, .rates = div_1_0_rates },
|
||||
{ .parent = &dpll_per_m2_ck, .rates = div_1_1_rates },
|
||||
{ .parent = NULL },
|
||||
};
|
||||
|
||||
static struct clk gfx_fclk_clksel_ck;
|
||||
|
||||
static struct clk_hw_omap gfx_fclk_clksel_ck_hw = {
|
||||
.hw = {
|
||||
.clk = &gfx_fclk_clksel_ck,
|
||||
},
|
||||
.clksel = gfx_clksel_sel,
|
||||
.clksel_reg = AM33XX_CLKSEL_GFX_FCLK,
|
||||
.clksel_mask = AM33XX_CLKSEL_GFX_FCLK_MASK,
|
||||
};
|
||||
|
||||
DEFINE_STRUCT_CLK(gfx_fclk_clksel_ck, gfx_ck_parents, gpio_fck_ops);
|
||||
|
||||
static const struct clk_div_table div_1_0_2_1_rates[] = {
|
||||
{ .div = 1, .val = 0, },
|
||||
{ .div = 2, .val = 1, },
|
||||
{ .div = 0 },
|
||||
};
|
||||
|
||||
DEFINE_CLK_DIVIDER_TABLE(gfx_fck_div_ck, "gfx_fclk_clksel_ck",
|
||||
&gfx_fclk_clksel_ck, 0x0, AM33XX_CLKSEL_GFX_FCLK,
|
||||
AM33XX_CLKSEL_0_0_SHIFT, AM33XX_CLKSEL_0_0_WIDTH,
|
||||
0x0, div_1_0_2_1_rates, NULL);
|
||||
|
||||
static const char *sysclkout_ck_parents[] = {
|
||||
"clk_32768_ck", "l3_gclk", "dpll_ddr_m2_ck", "dpll_per_m2_ck",
|
||||
"lcd_gclk",
|
||||
};
|
||||
|
||||
static const struct clksel sysclkout_pre_sel[] = {
|
||||
{ .parent = &clk_32768_ck, .rates = div_1_0_rates },
|
||||
{ .parent = &l3_gclk, .rates = div_1_1_rates },
|
||||
{ .parent = &dpll_ddr_m2_ck, .rates = div_1_2_rates },
|
||||
{ .parent = &dpll_per_m2_ck, .rates = div_1_3_rates },
|
||||
{ .parent = &lcd_gclk, .rates = div_1_4_rates },
|
||||
{ .parent = NULL },
|
||||
};
|
||||
|
||||
static struct clk sysclkout_pre_ck;
|
||||
|
||||
static struct clk_hw_omap sysclkout_pre_ck_hw = {
|
||||
.hw = {
|
||||
.clk = &sysclkout_pre_ck,
|
||||
},
|
||||
.clksel = sysclkout_pre_sel,
|
||||
.clksel_reg = AM33XX_CM_CLKOUT_CTRL,
|
||||
.clksel_mask = AM33XX_CLKOUT2SOURCE_MASK,
|
||||
};
|
||||
|
||||
DEFINE_STRUCT_CLK(sysclkout_pre_ck, sysclkout_ck_parents, gpio_fck_ops);
|
||||
|
||||
/* Divide by 8 clock rates with default clock is 1/1*/
|
||||
static const struct clk_div_table div8_rates[] = {
|
||||
{ .div = 1, .val = 0, },
|
||||
{ .div = 2, .val = 1, },
|
||||
{ .div = 3, .val = 2, },
|
||||
{ .div = 4, .val = 3, },
|
||||
{ .div = 5, .val = 4, },
|
||||
{ .div = 6, .val = 5, },
|
||||
{ .div = 7, .val = 6, },
|
||||
{ .div = 8, .val = 7, },
|
||||
{ .div = 0 },
|
||||
};
|
||||
|
||||
DEFINE_CLK_DIVIDER_TABLE(clkout2_div_ck, "sysclkout_pre_ck", &sysclkout_pre_ck,
|
||||
0x0, AM33XX_CM_CLKOUT_CTRL, AM33XX_CLKOUT2DIV_SHIFT,
|
||||
AM33XX_CLKOUT2DIV_WIDTH, 0x0, div8_rates, NULL);
|
||||
|
||||
DEFINE_CLK_GATE(clkout2_ck, "clkout2_div_ck", &clkout2_div_ck, 0x0,
|
||||
AM33XX_CM_CLKOUT_CTRL, AM33XX_CLKOUT2EN_SHIFT, 0x0, NULL);
|
||||
|
||||
static const char *wdt_ck_parents[] = {
|
||||
"clk_rc32k_ck", "clkdiv32k_ick",
|
||||
};
|
||||
|
||||
static const struct clksel wdt_clkmux_sel[] = {
|
||||
{ .parent = &clk_rc32k_ck, .rates = div_1_0_rates },
|
||||
{ .parent = &clkdiv32k_ick, .rates = div_1_1_rates },
|
||||
{ .parent = NULL },
|
||||
};
|
||||
|
||||
static struct clk wdt1_fck;
|
||||
|
||||
static struct clk_hw_omap wdt1_fck_hw = {
|
||||
.hw = {
|
||||
.clk = &wdt1_fck,
|
||||
},
|
||||
.clkdm_name = "l4_wkup_clkdm",
|
||||
.clksel = wdt_clkmux_sel,
|
||||
.clksel_reg = AM33XX_CLKSEL_WDT1_CLK,
|
||||
.clksel_mask = AM33XX_CLKSEL_0_1_MASK,
|
||||
};
|
||||
|
||||
DEFINE_STRUCT_CLK(wdt1_fck, wdt_ck_parents, gpio_fck_ops);
|
||||
|
||||
/*
|
||||
* clkdev
|
||||
*/
|
||||
static struct omap_clk am33xx_clks[] = {
|
||||
CLK(NULL, "clk_32768_ck", &clk_32768_ck, CK_AM33XX),
|
||||
CLK(NULL, "clk_rc32k_ck", &clk_rc32k_ck, CK_AM33XX),
|
||||
CLK(NULL, "virt_19200000_ck", &virt_19200000_ck, CK_AM33XX),
|
||||
CLK(NULL, "virt_24000000_ck", &virt_24000000_ck, CK_AM33XX),
|
||||
CLK(NULL, "virt_25000000_ck", &virt_25000000_ck, CK_AM33XX),
|
||||
CLK(NULL, "virt_26000000_ck", &virt_26000000_ck, CK_AM33XX),
|
||||
CLK(NULL, "sys_clkin_ck", &sys_clkin_ck, CK_AM33XX),
|
||||
CLK(NULL, "tclkin_ck", &tclkin_ck, CK_AM33XX),
|
||||
CLK(NULL, "dpll_core_ck", &dpll_core_ck, CK_AM33XX),
|
||||
CLK(NULL, "dpll_core_x2_ck", &dpll_core_x2_ck, CK_AM33XX),
|
||||
CLK(NULL, "dpll_core_m4_ck", &dpll_core_m4_ck, CK_AM33XX),
|
||||
CLK(NULL, "dpll_core_m5_ck", &dpll_core_m5_ck, CK_AM33XX),
|
||||
CLK(NULL, "dpll_core_m6_ck", &dpll_core_m6_ck, CK_AM33XX),
|
||||
CLK(NULL, "dpll_mpu_ck", &dpll_mpu_ck, CK_AM33XX),
|
||||
CLK("cpu0", NULL, &dpll_mpu_ck, CK_AM33XX),
|
||||
CLK(NULL, "dpll_mpu_m2_ck", &dpll_mpu_m2_ck, CK_AM33XX),
|
||||
CLK(NULL, "dpll_ddr_ck", &dpll_ddr_ck, CK_AM33XX),
|
||||
CLK(NULL, "dpll_ddr_m2_ck", &dpll_ddr_m2_ck, CK_AM33XX),
|
||||
CLK(NULL, "dpll_ddr_m2_div2_ck", &dpll_ddr_m2_div2_ck, CK_AM33XX),
|
||||
CLK(NULL, "dpll_disp_ck", &dpll_disp_ck, CK_AM33XX),
|
||||
CLK(NULL, "dpll_disp_m2_ck", &dpll_disp_m2_ck, CK_AM33XX),
|
||||
CLK(NULL, "dpll_per_ck", &dpll_per_ck, CK_AM33XX),
|
||||
CLK(NULL, "dpll_per_m2_ck", &dpll_per_m2_ck, CK_AM33XX),
|
||||
CLK(NULL, "dpll_per_m2_div4_wkupdm_ck", &dpll_per_m2_div4_wkupdm_ck, CK_AM33XX),
|
||||
CLK(NULL, "dpll_per_m2_div4_ck", &dpll_per_m2_div4_ck, CK_AM33XX),
|
||||
CLK(NULL, "adc_tsc_fck", &adc_tsc_fck, CK_AM33XX),
|
||||
CLK(NULL, "cefuse_fck", &cefuse_fck, CK_AM33XX),
|
||||
CLK(NULL, "clkdiv32k_ck", &clkdiv32k_ck, CK_AM33XX),
|
||||
CLK(NULL, "clkdiv32k_ick", &clkdiv32k_ick, CK_AM33XX),
|
||||
CLK(NULL, "dcan0_fck", &dcan0_fck, CK_AM33XX),
|
||||
CLK("481cc000.d_can", NULL, &dcan0_fck, CK_AM33XX),
|
||||
CLK(NULL, "dcan1_fck", &dcan1_fck, CK_AM33XX),
|
||||
CLK("481d0000.d_can", NULL, &dcan1_fck, CK_AM33XX),
|
||||
CLK(NULL, "debugss_ick", &debugss_ick, CK_AM33XX),
|
||||
CLK(NULL, "pruss_ocp_gclk", &pruss_ocp_gclk, CK_AM33XX),
|
||||
CLK(NULL, "mcasp0_fck", &mcasp0_fck, CK_AM33XX),
|
||||
CLK(NULL, "mcasp1_fck", &mcasp1_fck, CK_AM33XX),
|
||||
CLK(NULL, "mmu_fck", &mmu_fck, CK_AM33XX),
|
||||
CLK(NULL, "smartreflex0_fck", &smartreflex0_fck, CK_AM33XX),
|
||||
CLK(NULL, "smartreflex1_fck", &smartreflex1_fck, CK_AM33XX),
|
||||
CLK(NULL, "timer1_fck", &timer1_fck, CK_AM33XX),
|
||||
CLK(NULL, "timer2_fck", &timer2_fck, CK_AM33XX),
|
||||
CLK(NULL, "timer3_fck", &timer3_fck, CK_AM33XX),
|
||||
CLK(NULL, "timer4_fck", &timer4_fck, CK_AM33XX),
|
||||
CLK(NULL, "timer5_fck", &timer5_fck, CK_AM33XX),
|
||||
CLK(NULL, "timer6_fck", &timer6_fck, CK_AM33XX),
|
||||
CLK(NULL, "timer7_fck", &timer7_fck, CK_AM33XX),
|
||||
CLK(NULL, "usbotg_fck", &usbotg_fck, CK_AM33XX),
|
||||
CLK(NULL, "ieee5000_fck", &ieee5000_fck, CK_AM33XX),
|
||||
CLK(NULL, "wdt1_fck", &wdt1_fck, CK_AM33XX),
|
||||
CLK(NULL, "l4_rtc_gclk", &l4_rtc_gclk, CK_AM33XX),
|
||||
CLK(NULL, "l3_gclk", &l3_gclk, CK_AM33XX),
|
||||
CLK(NULL, "dpll_core_m4_div2_ck", &dpll_core_m4_div2_ck, CK_AM33XX),
|
||||
CLK(NULL, "l4hs_gclk", &l4hs_gclk, CK_AM33XX),
|
||||
CLK(NULL, "l3s_gclk", &l3s_gclk, CK_AM33XX),
|
||||
CLK(NULL, "l4fw_gclk", &l4fw_gclk, CK_AM33XX),
|
||||
CLK(NULL, "l4ls_gclk", &l4ls_gclk, CK_AM33XX),
|
||||
CLK(NULL, "clk_24mhz", &clk_24mhz, CK_AM33XX),
|
||||
CLK(NULL, "sysclk_div_ck", &sysclk_div_ck, CK_AM33XX),
|
||||
CLK(NULL, "cpsw_125mhz_gclk", &cpsw_125mhz_gclk, CK_AM33XX),
|
||||
CLK(NULL, "cpsw_cpts_rft_clk", &cpsw_cpts_rft_clk, CK_AM33XX),
|
||||
CLK(NULL, "gpio0_dbclk_mux_ck", &gpio0_dbclk_mux_ck, CK_AM33XX),
|
||||
CLK(NULL, "gpio0_dbclk", &gpio0_dbclk, CK_AM33XX),
|
||||
CLK(NULL, "gpio1_dbclk", &gpio1_dbclk, CK_AM33XX),
|
||||
CLK(NULL, "gpio2_dbclk", &gpio2_dbclk, CK_AM33XX),
|
||||
CLK(NULL, "gpio3_dbclk", &gpio3_dbclk, CK_AM33XX),
|
||||
CLK(NULL, "lcd_gclk", &lcd_gclk, CK_AM33XX),
|
||||
CLK(NULL, "mmc_clk", &mmc_clk, CK_AM33XX),
|
||||
CLK(NULL, "gfx_fclk_clksel_ck", &gfx_fclk_clksel_ck, CK_AM33XX),
|
||||
CLK(NULL, "gfx_fck_div_ck", &gfx_fck_div_ck, CK_AM33XX),
|
||||
CLK(NULL, "sysclkout_pre_ck", &sysclkout_pre_ck, CK_AM33XX),
|
||||
CLK(NULL, "clkout2_div_ck", &clkout2_div_ck, CK_AM33XX),
|
||||
CLK(NULL, "timer_32k_ck", &clkdiv32k_ick, CK_AM33XX),
|
||||
CLK(NULL, "timer_sys_ck", &sys_clkin_ck, CK_AM33XX),
|
||||
};
|
||||
|
||||
|
||||
static const char *enable_init_clks[] = {
|
||||
"dpll_ddr_m2_ck",
|
||||
"dpll_mpu_m2_ck",
|
||||
"l3_gclk",
|
||||
"l4hs_gclk",
|
||||
"l4fw_gclk",
|
||||
"l4ls_gclk",
|
||||
};
|
||||
|
||||
int __init am33xx_clk_init(void)
|
||||
{
|
||||
struct omap_clk *c;
|
||||
u32 cpu_clkflg;
|
||||
|
||||
if (soc_is_am33xx()) {
|
||||
cpu_mask = RATE_IN_AM33XX;
|
||||
cpu_clkflg = CK_AM33XX;
|
||||
}
|
||||
|
||||
for (c = am33xx_clks; c < am33xx_clks + ARRAY_SIZE(am33xx_clks); c++) {
|
||||
if (c->cpu & cpu_clkflg) {
|
||||
clkdev_add(&c->lk);
|
||||
if (!__clk_init(NULL, c->lk.clk))
|
||||
omap2_init_clk_hw_omap_clocks(c->lk.clk);
|
||||
}
|
||||
}
|
||||
|
||||
omap2_clk_disable_autoidle_all();
|
||||
|
||||
omap2_clk_enable_init_clocks(enable_init_clks,
|
||||
ARRAY_SIZE(enable_init_clks));
|
||||
|
||||
/* TRM ERRATA: Timer 3 & 6 default parent (TCLKIN) may not be always
|
||||
* physically present, in such a case HWMOD enabling of
|
||||
* clock would be failure with default parent. And timer
|
||||
* probe thinks clock is already enabled, this leads to
|
||||
* crash upon accessing timer 3 & 6 registers in probe.
|
||||
* Fix by setting parent of both these timers to master
|
||||
* oscillator clock.
|
||||
*/
|
||||
|
||||
clk_set_parent(&timer3_fck, &sys_clkin_ck);
|
||||
clk_set_parent(&timer6_fck, &sys_clkin_ck);
|
||||
|
||||
return 0;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -38,62 +38,88 @@
|
|||
|
||||
/* Private functions */
|
||||
|
||||
static int _apll96_enable(struct clk *clk)
|
||||
/**
|
||||
* omap2xxx_clk_apll_locked - is the APLL locked?
|
||||
* @hw: struct clk_hw * of the APLL to check
|
||||
*
|
||||
* If the APLL IP block referred to by @hw indicates that it's locked,
|
||||
* return true; otherwise, return false.
|
||||
*/
|
||||
static bool omap2xxx_clk_apll_locked(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
|
||||
u32 r, apll_mask;
|
||||
|
||||
apll_mask = EN_APLL_LOCKED << clk->enable_bit;
|
||||
|
||||
r = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKEN);
|
||||
|
||||
return ((r & apll_mask) == apll_mask) ? true : false;
|
||||
}
|
||||
|
||||
int omap2_clk_apll96_enable(struct clk_hw *hw)
|
||||
{
|
||||
return omap2xxx_cm_apll96_enable();
|
||||
}
|
||||
|
||||
static int _apll54_enable(struct clk *clk)
|
||||
int omap2_clk_apll54_enable(struct clk_hw *hw)
|
||||
{
|
||||
return omap2xxx_cm_apll54_enable();
|
||||
}
|
||||
|
||||
static void _apll96_allow_idle(struct clk *clk)
|
||||
static void _apll96_allow_idle(struct clk_hw_omap *clk)
|
||||
{
|
||||
omap2xxx_cm_set_apll96_auto_low_power_stop();
|
||||
}
|
||||
|
||||
static void _apll96_deny_idle(struct clk *clk)
|
||||
static void _apll96_deny_idle(struct clk_hw_omap *clk)
|
||||
{
|
||||
omap2xxx_cm_set_apll96_disable_autoidle();
|
||||
}
|
||||
|
||||
static void _apll54_allow_idle(struct clk *clk)
|
||||
static void _apll54_allow_idle(struct clk_hw_omap *clk)
|
||||
{
|
||||
omap2xxx_cm_set_apll54_auto_low_power_stop();
|
||||
}
|
||||
|
||||
static void _apll54_deny_idle(struct clk *clk)
|
||||
static void _apll54_deny_idle(struct clk_hw_omap *clk)
|
||||
{
|
||||
omap2xxx_cm_set_apll54_disable_autoidle();
|
||||
}
|
||||
|
||||
static void _apll96_disable(struct clk *clk)
|
||||
void omap2_clk_apll96_disable(struct clk_hw *hw)
|
||||
{
|
||||
omap2xxx_cm_apll96_disable();
|
||||
}
|
||||
|
||||
static void _apll54_disable(struct clk *clk)
|
||||
void omap2_clk_apll54_disable(struct clk_hw *hw)
|
||||
{
|
||||
omap2xxx_cm_apll54_disable();
|
||||
}
|
||||
|
||||
unsigned long omap2_clk_apll54_recalc(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
return (omap2xxx_clk_apll_locked(hw)) ? 54000000 : 0;
|
||||
}
|
||||
|
||||
unsigned long omap2_clk_apll96_recalc(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
return (omap2xxx_clk_apll_locked(hw)) ? 96000000 : 0;
|
||||
}
|
||||
|
||||
/* Public data */
|
||||
|
||||
const struct clkops clkops_apll96 = {
|
||||
.enable = _apll96_enable,
|
||||
.disable = _apll96_disable,
|
||||
.allow_idle = _apll96_allow_idle,
|
||||
.deny_idle = _apll96_deny_idle,
|
||||
};
|
||||
|
||||
const struct clkops clkops_apll54 = {
|
||||
.enable = _apll54_enable,
|
||||
.disable = _apll54_disable,
|
||||
const struct clk_hw_omap_ops clkhwops_apll54 = {
|
||||
.allow_idle = _apll54_allow_idle,
|
||||
.deny_idle = _apll54_deny_idle,
|
||||
};
|
||||
|
||||
const struct clk_hw_omap_ops clkhwops_apll96 = {
|
||||
.allow_idle = _apll96_allow_idle,
|
||||
.deny_idle = _apll96_deny_idle,
|
||||
};
|
||||
|
||||
/* Public functions */
|
||||
|
||||
u32 omap2xxx_get_apll_clkin(void)
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
* REVISIT: DPLL can optionally enter low-power bypass by writing 0x1
|
||||
* instead. Add some mechanism to optionally enter this mode.
|
||||
*/
|
||||
static void _allow_idle(struct clk *clk)
|
||||
static void _allow_idle(struct clk_hw_omap *clk)
|
||||
{
|
||||
if (!clk || !clk->dpll_data)
|
||||
return;
|
||||
|
@ -43,7 +43,7 @@ static void _allow_idle(struct clk *clk)
|
|||
*
|
||||
* Disable DPLL automatic idle control. No return value.
|
||||
*/
|
||||
static void _deny_idle(struct clk *clk)
|
||||
static void _deny_idle(struct clk_hw_omap *clk)
|
||||
{
|
||||
if (!clk || !clk->dpll_data)
|
||||
return;
|
||||
|
@ -53,9 +53,7 @@ static void _deny_idle(struct clk *clk)
|
|||
|
||||
|
||||
/* Public data */
|
||||
|
||||
const struct clkops clkops_omap2xxx_dpll_ops = {
|
||||
const struct clk_hw_omap_ops clkhwops_omap2xxx_dpll = {
|
||||
.allow_idle = _allow_idle,
|
||||
.deny_idle = _deny_idle,
|
||||
};
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
* (currently defined as "dpll_ck" in the OMAP2xxx clock tree). Set
|
||||
* during dpll_ck init and used later by omap2xxx_clk_get_core_rate().
|
||||
*/
|
||||
static struct clk *dpll_core_ck;
|
||||
static struct clk_hw_omap *dpll_core_ck;
|
||||
|
||||
/**
|
||||
* omap2xxx_clk_get_core_rate - return the CORE_CLK rate
|
||||
|
@ -104,13 +104,16 @@ static long omap2_dpllcore_round_rate(unsigned long target_rate)
|
|||
|
||||
}
|
||||
|
||||
unsigned long omap2_dpllcore_recalc(struct clk *clk)
|
||||
unsigned long omap2_dpllcore_recalc(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
return omap2xxx_clk_get_core_rate();
|
||||
}
|
||||
|
||||
int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate)
|
||||
int omap2_reprogram_dpllcore(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
|
||||
u32 cur_rate, low, mult, div, valid_rate, done_rate;
|
||||
u32 bypass = 0;
|
||||
struct prcm_config tmpset;
|
||||
|
@ -188,8 +191,8 @@ int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate)
|
|||
* statically defined, this code may need to change to increment some
|
||||
* kind of use count on dpll_ck.
|
||||
*/
|
||||
void omap2xxx_clkt_dpllcore_init(struct clk *clk)
|
||||
void omap2xxx_clkt_dpllcore_init(struct clk_hw *hw)
|
||||
{
|
||||
WARN(dpll_core_ck, "dpll_core_ck already set - should never happen");
|
||||
dpll_core_ck = clk;
|
||||
dpll_core_ck = to_clk_hw_omap(hw);
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
* clk_enable/clk_disable()-based usecounting for osc_ck should be
|
||||
* replaced with autoidle-based usecounting.
|
||||
*/
|
||||
static int omap2_enable_osc_ck(struct clk *clk)
|
||||
int omap2_enable_osc_ck(struct clk_hw *clk)
|
||||
{
|
||||
u32 pcc;
|
||||
|
||||
|
@ -53,7 +53,7 @@ static int omap2_enable_osc_ck(struct clk *clk)
|
|||
* clk_enable/clk_disable()-based usecounting for osc_ck should be
|
||||
* replaced with autoidle-based usecounting.
|
||||
*/
|
||||
static void omap2_disable_osc_ck(struct clk *clk)
|
||||
void omap2_disable_osc_ck(struct clk_hw *clk)
|
||||
{
|
||||
u32 pcc;
|
||||
|
||||
|
@ -62,13 +62,8 @@ static void omap2_disable_osc_ck(struct clk *clk)
|
|||
__raw_writel(pcc | OMAP_AUTOEXTCLKMODE_MASK, prcm_clksrc_ctrl);
|
||||
}
|
||||
|
||||
const struct clkops clkops_oscck = {
|
||||
.enable = omap2_enable_osc_ck,
|
||||
.disable = omap2_disable_osc_ck,
|
||||
};
|
||||
|
||||
unsigned long omap2_osc_clk_recalc(struct clk *clk)
|
||||
unsigned long omap2_osc_clk_recalc(struct clk_hw *clk,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
return omap2xxx_get_apll_clkin() * omap2xxx_get_sysclkdiv();
|
||||
}
|
||||
|
||||
|
|
|
@ -40,9 +40,8 @@ u32 omap2xxx_get_sysclkdiv(void)
|
|||
return div;
|
||||
}
|
||||
|
||||
unsigned long omap2xxx_sys_clk_recalc(struct clk *clk)
|
||||
unsigned long omap2xxx_sys_clk_recalc(struct clk_hw *clk,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
return clk->parent->rate / omap2xxx_get_sysclkdiv();
|
||||
return parent_rate / omap2xxx_get_sysclkdiv();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -58,7 +58,8 @@ static unsigned long sys_ck_rate;
|
|||
*
|
||||
* Set virt_prcm_set's rate to the mpu_speed field of the current PRCM set.
|
||||
*/
|
||||
unsigned long omap2_table_mpu_recalc(struct clk *clk)
|
||||
unsigned long omap2_table_mpu_recalc(struct clk_hw *clk,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
return curr_prcm_set->mpu_speed;
|
||||
}
|
||||
|
@ -70,7 +71,8 @@ unsigned long omap2_table_mpu_recalc(struct clk *clk)
|
|||
* Some might argue L3-DDR, others ARM, others IVA. This code is simple and
|
||||
* just uses the ARM rates.
|
||||
*/
|
||||
long omap2_round_to_table_rate(struct clk *clk, unsigned long rate)
|
||||
long omap2_round_to_table_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long *parent_rate)
|
||||
{
|
||||
const struct prcm_config *ptr;
|
||||
long highest_rate;
|
||||
|
@ -93,7 +95,8 @@ long omap2_round_to_table_rate(struct clk *clk, unsigned long rate)
|
|||
}
|
||||
|
||||
/* Sets basic clocks based on the specified rate */
|
||||
int omap2_select_table_rate(struct clk *clk, unsigned long rate)
|
||||
int omap2_select_table_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
u32 cur_rate, done_rate, bypass = 0, tmp;
|
||||
const struct prcm_config *prcm;
|
||||
|
|
|
@ -44,8 +44,10 @@
|
|||
* Program the DPLL M2 divider with the rounded target rate. Returns
|
||||
* -EINVAL upon error, or 0 upon success.
|
||||
*/
|
||||
int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
|
||||
int omap3_core_dpll_m2_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
|
||||
u32 new_div = 0;
|
||||
u32 unlock_dll = 0;
|
||||
u32 c;
|
||||
|
@ -63,7 +65,7 @@ int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
|
|||
return -EINVAL;
|
||||
|
||||
sdrcrate = __clk_get_rate(sdrc_ick_p);
|
||||
clkrate = __clk_get_rate(clk);
|
||||
clkrate = __clk_get_rate(hw->clk);
|
||||
if (rate > clkrate)
|
||||
sdrcrate <<= ((rate / clkrate) >> 1);
|
||||
else
|
||||
|
@ -112,8 +114,6 @@ int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
|
|||
sdrc_cs0->rfr_ctrl, sdrc_cs0->actim_ctrla,
|
||||
sdrc_cs0->actim_ctrlb, sdrc_cs0->mr,
|
||||
0, 0, 0, 0);
|
||||
clk->rate = rate;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/bug.h>
|
||||
|
||||
|
@ -58,11 +58,14 @@
|
|||
* the element associated with the supplied parent clock address.
|
||||
* Returns a pointer to the struct clksel on success or NULL on error.
|
||||
*/
|
||||
static const struct clksel *_get_clksel_by_parent(struct clk *clk,
|
||||
static const struct clksel *_get_clksel_by_parent(struct clk_hw_omap *clk,
|
||||
struct clk *src_clk)
|
||||
{
|
||||
const struct clksel *clks;
|
||||
|
||||
if (!src_clk)
|
||||
return NULL;
|
||||
|
||||
for (clks = clk->clksel; clks->parent; clks++)
|
||||
if (clks->parent == src_clk)
|
||||
break; /* Found the requested parent */
|
||||
|
@ -70,71 +73,13 @@ static const struct clksel *_get_clksel_by_parent(struct clk *clk,
|
|||
if (!clks->parent) {
|
||||
/* This indicates a data problem */
|
||||
WARN(1, "clock: %s: could not find parent clock %s in clksel array\n",
|
||||
__clk_get_name(clk), __clk_get_name(src_clk));
|
||||
__clk_get_name(clk->hw.clk), __clk_get_name(src_clk));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return clks;
|
||||
}
|
||||
|
||||
/**
|
||||
* _get_div_and_fieldval() - find the new clksel divisor and field value to use
|
||||
* @src_clk: planned new parent struct clk *
|
||||
* @clk: struct clk * that is being reparented
|
||||
* @field_val: pointer to a u32 to contain the register data for the divisor
|
||||
*
|
||||
* Given an intended new parent struct clk * @src_clk, and the struct
|
||||
* clk * @clk to the clock that is being reparented, find the
|
||||
* appropriate rate divisor for the new clock (returned as the return
|
||||
* value), and the corresponding register bitfield data to program to
|
||||
* reach that divisor (returned in the u32 pointed to by @field_val).
|
||||
* Returns 0 on error, or returns the newly-selected divisor upon
|
||||
* success (in this latter case, the corresponding register bitfield
|
||||
* value is passed back in the variable pointed to by @field_val)
|
||||
*/
|
||||
static u8 _get_div_and_fieldval(struct clk *src_clk, struct clk *clk,
|
||||
u32 *field_val)
|
||||
{
|
||||
const struct clksel *clks;
|
||||
const struct clksel_rate *clkr, *max_clkr = NULL;
|
||||
u8 max_div = 0;
|
||||
|
||||
clks = _get_clksel_by_parent(clk, src_clk);
|
||||
if (!clks)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Find the highest divisor (e.g., the one resulting in the
|
||||
* lowest rate) to use as the default. This should avoid
|
||||
* clock rates that are too high for the device. XXX A better
|
||||
* solution here would be to try to determine if there is a
|
||||
* divisor matching the original clock rate before the parent
|
||||
* switch, and if it cannot be found, to fall back to the
|
||||
* highest divisor.
|
||||
*/
|
||||
for (clkr = clks->rates; clkr->div; clkr++) {
|
||||
if (!(clkr->flags & cpu_mask))
|
||||
continue;
|
||||
|
||||
if (clkr->div > max_div) {
|
||||
max_div = clkr->div;
|
||||
max_clkr = clkr;
|
||||
}
|
||||
}
|
||||
|
||||
if (max_div == 0) {
|
||||
/* This indicates an error in the clksel data */
|
||||
WARN(1, "clock: %s: could not find divisor for parent %s\n",
|
||||
__clk_get_name(clk),
|
||||
__clk_get_name(__clk_get_parent(src_clk)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
*field_val = max_clkr->val;
|
||||
|
||||
return max_div;
|
||||
}
|
||||
|
||||
/**
|
||||
* _write_clksel_reg() - program a clock's clksel register in hardware
|
||||
* @clk: struct clk * to program
|
||||
|
@ -148,7 +93,7 @@ static u8 _get_div_and_fieldval(struct clk *src_clk, struct clk *clk,
|
|||
* take into account any time the hardware might take to switch the
|
||||
* clock source.
|
||||
*/
|
||||
static void _write_clksel_reg(struct clk *clk, u32 field_val)
|
||||
static void _write_clksel_reg(struct clk_hw_omap *clk, u32 field_val)
|
||||
{
|
||||
u32 v;
|
||||
|
||||
|
@ -171,13 +116,14 @@ static void _write_clksel_reg(struct clk *clk, u32 field_val)
|
|||
* before calling. Returns 0 on error or returns the actual integer divisor
|
||||
* upon success.
|
||||
*/
|
||||
static u32 _clksel_to_divisor(struct clk *clk, u32 field_val)
|
||||
static u32 _clksel_to_divisor(struct clk_hw_omap *clk, u32 field_val)
|
||||
{
|
||||
const struct clksel *clks;
|
||||
const struct clksel_rate *clkr;
|
||||
struct clk *parent;
|
||||
|
||||
parent = __clk_get_parent(clk);
|
||||
parent = __clk_get_parent(clk->hw.clk);
|
||||
|
||||
clks = _get_clksel_by_parent(clk, parent);
|
||||
if (!clks)
|
||||
return 0;
|
||||
|
@ -193,7 +139,8 @@ static u32 _clksel_to_divisor(struct clk *clk, u32 field_val)
|
|||
if (!clkr->div) {
|
||||
/* This indicates a data error */
|
||||
WARN(1, "clock: %s: could not find fieldval %d for parent %s\n",
|
||||
__clk_get_name(clk), field_val, __clk_get_name(parent));
|
||||
__clk_get_name(clk->hw.clk), field_val,
|
||||
__clk_get_name(parent));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -210,7 +157,7 @@ static u32 _clksel_to_divisor(struct clk *clk, u32 field_val)
|
|||
* register field value _before_ left-shifting (i.e., LSB is at bit
|
||||
* 0); or returns 0xFFFFFFFF (~0) upon error.
|
||||
*/
|
||||
static u32 _divisor_to_clksel(struct clk *clk, u32 div)
|
||||
static u32 _divisor_to_clksel(struct clk_hw_omap *clk, u32 div)
|
||||
{
|
||||
const struct clksel *clks;
|
||||
const struct clksel_rate *clkr;
|
||||
|
@ -219,7 +166,7 @@ static u32 _divisor_to_clksel(struct clk *clk, u32 div)
|
|||
/* should never happen */
|
||||
WARN_ON(div == 0);
|
||||
|
||||
parent = __clk_get_parent(clk);
|
||||
parent = __clk_get_parent(clk->hw.clk);
|
||||
clks = _get_clksel_by_parent(clk, parent);
|
||||
if (!clks)
|
||||
return ~0;
|
||||
|
@ -234,7 +181,8 @@ static u32 _divisor_to_clksel(struct clk *clk, u32 div)
|
|||
|
||||
if (!clkr->div) {
|
||||
pr_err("clock: %s: could not find divisor %d for parent %s\n",
|
||||
__clk_get_name(clk), div, __clk_get_name(parent));
|
||||
__clk_get_name(clk->hw.clk), div,
|
||||
__clk_get_name(parent));
|
||||
return ~0;
|
||||
}
|
||||
|
||||
|
@ -249,7 +197,7 @@ static u32 _divisor_to_clksel(struct clk *clk, u32 div)
|
|||
* into the hardware, convert it into the actual divisor value, and
|
||||
* return it; or return 0 on error.
|
||||
*/
|
||||
static u32 _read_divisor(struct clk *clk)
|
||||
static u32 _read_divisor(struct clk_hw_omap *clk)
|
||||
{
|
||||
u32 v;
|
||||
|
||||
|
@ -277,7 +225,8 @@ static u32 _read_divisor(struct clk *clk)
|
|||
*
|
||||
* Returns the rounded clock rate or returns 0xffffffff on error.
|
||||
*/
|
||||
u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
|
||||
u32 omap2_clksel_round_rate_div(struct clk_hw_omap *clk,
|
||||
unsigned long target_rate,
|
||||
u32 *new_div)
|
||||
{
|
||||
unsigned long test_rate;
|
||||
|
@ -288,9 +237,9 @@ u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
|
|||
unsigned long parent_rate;
|
||||
const char *clk_name;
|
||||
|
||||
parent = __clk_get_parent(clk);
|
||||
parent = __clk_get_parent(clk->hw.clk);
|
||||
clk_name = __clk_get_name(clk->hw.clk);
|
||||
parent_rate = __clk_get_rate(parent);
|
||||
clk_name = __clk_get_name(clk);
|
||||
|
||||
if (!clk->clksel || !clk->clksel_mask)
|
||||
return ~0;
|
||||
|
@ -341,27 +290,35 @@ u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
|
|||
*/
|
||||
|
||||
/**
|
||||
* omap2_init_clksel_parent() - set a clksel clk's parent field from the hdwr
|
||||
* @clk: OMAP clock struct ptr to use
|
||||
* omap2_clksel_find_parent_index() - return the array index of the current
|
||||
* hardware parent of @hw
|
||||
* @hw: struct clk_hw * to find the current hardware parent of
|
||||
*
|
||||
* Given a pointer @clk to a source-selectable struct clk, read the
|
||||
* hardware register and determine what its parent is currently set
|
||||
* to. Update @clk's .parent field with the appropriate clk ptr. No
|
||||
* return value.
|
||||
* Given a struct clk_hw pointer @hw to the 'hw' member of a struct
|
||||
* clk_hw_omap record representing a source-selectable hardware clock,
|
||||
* read the hardware register and determine what its parent is
|
||||
* currently set to. Intended to be called only by the common clock
|
||||
* framework struct clk_hw_ops.get_parent function pointer. Return
|
||||
* the array index of this parent clock upon success -- there is no
|
||||
* way to return an error, so if we encounter an error, just WARN()
|
||||
* and pretend that we know that we're doing.
|
||||
*/
|
||||
void omap2_init_clksel_parent(struct clk *clk)
|
||||
u8 omap2_clksel_find_parent_index(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
|
||||
const struct clksel *clks;
|
||||
const struct clksel_rate *clkr;
|
||||
u32 r, found = 0;
|
||||
struct clk *parent;
|
||||
const char *clk_name;
|
||||
int ret = 0, f = 0;
|
||||
|
||||
if (!clk->clksel || !clk->clksel_mask)
|
||||
return;
|
||||
parent = __clk_get_parent(hw->clk);
|
||||
clk_name = __clk_get_name(hw->clk);
|
||||
|
||||
parent = __clk_get_parent(clk);
|
||||
clk_name = __clk_get_name(clk);
|
||||
/* XXX should be able to return an error */
|
||||
WARN((!clk->clksel || !clk->clksel_mask),
|
||||
"clock: %s: attempt to call on a non-clksel clock", clk_name);
|
||||
|
||||
r = __raw_readl(clk->clksel_reg) & clk->clksel_mask;
|
||||
r >>= __ffs(clk->clksel_mask);
|
||||
|
@ -372,27 +329,21 @@ void omap2_init_clksel_parent(struct clk *clk)
|
|||
continue;
|
||||
|
||||
if (clkr->val == r) {
|
||||
if (parent != clks->parent) {
|
||||
pr_debug("clock: %s: inited parent to %s (was %s)\n",
|
||||
clk_name,
|
||||
__clk_get_name(clks->parent),
|
||||
((parent) ?
|
||||
__clk_get_name(parent) :
|
||||
"NULL"));
|
||||
clk_reparent(clk, clks->parent);
|
||||
}
|
||||
found = 1;
|
||||
ret = f;
|
||||
}
|
||||
}
|
||||
f++;
|
||||
}
|
||||
|
||||
/* This indicates a data error */
|
||||
WARN(!found, "clock: %s: init parent: could not find regval %0x\n",
|
||||
clk_name, r);
|
||||
|
||||
return;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* omap2_clksel_recalc() - function ptr to pass via struct clk .recalc field
|
||||
* @clk: struct clk *
|
||||
|
@ -402,21 +353,23 @@ void omap2_init_clksel_parent(struct clk *clk)
|
|||
* function. Returns the clock's current rate, based on its parent's rate
|
||||
* and its current divisor setting in the hardware.
|
||||
*/
|
||||
unsigned long omap2_clksel_recalc(struct clk *clk)
|
||||
unsigned long omap2_clksel_recalc(struct clk_hw *hw, unsigned long parent_rate)
|
||||
{
|
||||
unsigned long rate;
|
||||
u32 div = 0;
|
||||
struct clk *parent;
|
||||
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
|
||||
|
||||
if (!parent_rate)
|
||||
return 0;
|
||||
|
||||
div = _read_divisor(clk);
|
||||
if (div == 0)
|
||||
return __clk_get_rate(clk);
|
||||
if (!div)
|
||||
rate = parent_rate;
|
||||
else
|
||||
rate = parent_rate / div;
|
||||
|
||||
parent = __clk_get_parent(clk);
|
||||
rate = __clk_get_rate(parent) / div;
|
||||
|
||||
pr_debug("clock: %s: recalc'd rate is %ld (div %d)\n",
|
||||
__clk_get_name(clk), rate, div);
|
||||
pr_debug("%s: recalc'd %s's rate to %lu (div %d)\n", __func__,
|
||||
__clk_get_name(hw->clk), rate, div);
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
@ -432,8 +385,10 @@ unsigned long omap2_clksel_recalc(struct clk *clk)
|
|||
*
|
||||
* Returns the rounded clock rate or returns 0xffffffff on error.
|
||||
*/
|
||||
long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate)
|
||||
long omap2_clksel_round_rate(struct clk_hw *hw, unsigned long target_rate,
|
||||
unsigned long *parent_rate)
|
||||
{
|
||||
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
|
||||
u32 new_div;
|
||||
|
||||
return omap2_clksel_round_rate_div(clk, target_rate, &new_div);
|
||||
|
@ -454,8 +409,10 @@ long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate)
|
|||
* is changed, they will all be affected without any notification.
|
||||
* Returns -EINVAL upon error, or 0 upon success.
|
||||
*/
|
||||
int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
|
||||
int omap2_clksel_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
|
||||
u32 field_val, validrate, new_div = 0;
|
||||
|
||||
if (!clk->clksel || !clk->clksel_mask)
|
||||
|
@ -471,10 +428,8 @@ int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
|
|||
|
||||
_write_clksel_reg(clk, field_val);
|
||||
|
||||
clk->rate = __clk_get_rate(__clk_get_parent(clk)) / new_div;
|
||||
|
||||
pr_debug("clock: %s: set rate to %ld\n", __clk_get_name(clk),
|
||||
__clk_get_rate(clk));
|
||||
pr_debug("clock: %s: set rate to %ld\n", __clk_get_name(hw->clk),
|
||||
__clk_get_rate(hw->clk));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -499,32 +454,13 @@ int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
|
|||
* affected without any notification. Returns -EINVAL upon error, or
|
||||
* 0 upon success.
|
||||
*/
|
||||
int omap2_clksel_set_parent(struct clk *clk, struct clk *new_parent)
|
||||
int omap2_clksel_set_parent(struct clk_hw *hw, u8 field_val)
|
||||
{
|
||||
u32 field_val = 0;
|
||||
u32 parent_div;
|
||||
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
|
||||
|
||||
if (!clk->clksel || !clk->clksel_mask)
|
||||
return -EINVAL;
|
||||
|
||||
parent_div = _get_div_and_fieldval(new_parent, clk, &field_val);
|
||||
if (!parent_div)
|
||||
return -EINVAL;
|
||||
|
||||
_write_clksel_reg(clk, field_val);
|
||||
|
||||
clk_reparent(clk, new_parent);
|
||||
|
||||
/* CLKSEL clocks follow their parents' rates, divided by a divisor */
|
||||
clk->rate = __clk_get_rate(new_parent);
|
||||
|
||||
if (parent_div > 0)
|
||||
__clk_get_rate(clk) /= parent_div;
|
||||
|
||||
pr_debug("clock: %s: set parent to %s (new rate %ld)\n",
|
||||
__clk_get_name(clk),
|
||||
__clk_get_name(__clk_get_parent(clk)),
|
||||
__clk_get_rate(clk));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/div64.h>
|
||||
|
@ -76,7 +76,7 @@
|
|||
* (assuming that it is counting N upwards), or -2 if the enclosing loop
|
||||
* should skip to the next iteration (again assuming N is increasing).
|
||||
*/
|
||||
static int _dpll_test_fint(struct clk *clk, u8 n)
|
||||
static int _dpll_test_fint(struct clk_hw_omap *clk, u8 n)
|
||||
{
|
||||
struct dpll_data *dd;
|
||||
long fint, fint_min, fint_max;
|
||||
|
@ -85,7 +85,7 @@ static int _dpll_test_fint(struct clk *clk, u8 n)
|
|||
dd = clk->dpll_data;
|
||||
|
||||
/* DPLL divider must result in a valid jitter correction val */
|
||||
fint = __clk_get_rate(__clk_get_parent(clk)) / n;
|
||||
fint = __clk_get_rate(__clk_get_parent(clk->hw.clk)) / n;
|
||||
|
||||
if (cpu_is_omap24xx()) {
|
||||
/* Should not be called for OMAP2, so warn if it is called */
|
||||
|
@ -186,15 +186,15 @@ static int _dpll_test_mult(int *m, int n, unsigned long *new_rate,
|
|||
}
|
||||
|
||||
/* Public functions */
|
||||
|
||||
void omap2_init_dpll_parent(struct clk *clk)
|
||||
u8 omap2_init_dpll_parent(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
|
||||
u32 v;
|
||||
struct dpll_data *dd;
|
||||
|
||||
dd = clk->dpll_data;
|
||||
if (!dd)
|
||||
return;
|
||||
return -EINVAL;
|
||||
|
||||
v = __raw_readl(dd->control_reg);
|
||||
v &= dd->enable_mask;
|
||||
|
@ -204,18 +204,18 @@ void omap2_init_dpll_parent(struct clk *clk)
|
|||
if (cpu_is_omap24xx()) {
|
||||
if (v == OMAP2XXX_EN_DPLL_LPBYPASS ||
|
||||
v == OMAP2XXX_EN_DPLL_FRBYPASS)
|
||||
clk_reparent(clk, dd->clk_bypass);
|
||||
return 1;
|
||||
} else if (cpu_is_omap34xx()) {
|
||||
if (v == OMAP3XXX_EN_DPLL_LPBYPASS ||
|
||||
v == OMAP3XXX_EN_DPLL_FRBYPASS)
|
||||
clk_reparent(clk, dd->clk_bypass);
|
||||
return 1;
|
||||
} else if (soc_is_am33xx() || cpu_is_omap44xx()) {
|
||||
if (v == OMAP4XXX_EN_DPLL_LPBYPASS ||
|
||||
v == OMAP4XXX_EN_DPLL_FRBYPASS ||
|
||||
v == OMAP4XXX_EN_DPLL_MNBYPASS)
|
||||
clk_reparent(clk, dd->clk_bypass);
|
||||
return 1;
|
||||
}
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -232,7 +232,7 @@ void omap2_init_dpll_parent(struct clk *clk)
|
|||
* locked, or the appropriate bypass rate if the DPLL is bypassed, or 0
|
||||
* if the clock @clk is not a DPLL.
|
||||
*/
|
||||
u32 omap2_get_dpll_rate(struct clk *clk)
|
||||
unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk)
|
||||
{
|
||||
long long dpll_clk;
|
||||
u32 dpll_mult, dpll_div, v;
|
||||
|
@ -288,8 +288,10 @@ u32 omap2_get_dpll_rate(struct clk *clk)
|
|||
* (expensive) function again. Returns ~0 if the target rate cannot
|
||||
* be rounded, or the rounded rate upon success.
|
||||
*/
|
||||
long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate)
|
||||
long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
|
||||
unsigned long *parent_rate)
|
||||
{
|
||||
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
|
||||
int m, n, r, scaled_max_m;
|
||||
unsigned long scaled_rt_rp;
|
||||
unsigned long new_rate = 0;
|
||||
|
@ -303,7 +305,7 @@ long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate)
|
|||
dd = clk->dpll_data;
|
||||
|
||||
ref_rate = __clk_get_rate(dd->clk_ref);
|
||||
clk_name = __clk_get_name(clk);
|
||||
clk_name = __clk_get_name(hw->clk);
|
||||
pr_debug("clock: %s: starting DPLL round_rate, target rate %ld\n",
|
||||
clk_name, target_rate);
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#undef DEBUG
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
|||
/* Private functions */
|
||||
|
||||
/* XXX */
|
||||
void omap2_clkt_iclk_allow_idle(struct clk *clk)
|
||||
void omap2_clkt_iclk_allow_idle(struct clk_hw_omap *clk)
|
||||
{
|
||||
u32 v, r;
|
||||
|
||||
|
@ -35,7 +35,7 @@ void omap2_clkt_iclk_allow_idle(struct clk *clk)
|
|||
}
|
||||
|
||||
/* XXX */
|
||||
void omap2_clkt_iclk_deny_idle(struct clk *clk)
|
||||
void omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk)
|
||||
{
|
||||
u32 v, r;
|
||||
|
||||
|
@ -48,33 +48,17 @@ void omap2_clkt_iclk_deny_idle(struct clk *clk)
|
|||
|
||||
/* Public data */
|
||||
|
||||
const struct clkops clkops_omap2_iclk_dflt_wait = {
|
||||
.enable = omap2_dflt_clk_enable,
|
||||
.disable = omap2_dflt_clk_disable,
|
||||
.find_companion = omap2_clk_dflt_find_companion,
|
||||
const struct clk_hw_omap_ops clkhwops_iclk = {
|
||||
.allow_idle = omap2_clkt_iclk_allow_idle,
|
||||
.deny_idle = omap2_clkt_iclk_deny_idle,
|
||||
};
|
||||
|
||||
const struct clk_hw_omap_ops clkhwops_iclk_wait = {
|
||||
.allow_idle = omap2_clkt_iclk_allow_idle,
|
||||
.deny_idle = omap2_clkt_iclk_deny_idle,
|
||||
.find_idlest = omap2_clk_dflt_find_idlest,
|
||||
.allow_idle = omap2_clkt_iclk_allow_idle,
|
||||
.deny_idle = omap2_clkt_iclk_deny_idle,
|
||||
};
|
||||
|
||||
const struct clkops clkops_omap2_iclk_dflt = {
|
||||
.enable = omap2_dflt_clk_enable,
|
||||
.disable = omap2_dflt_clk_disable,
|
||||
.allow_idle = omap2_clkt_iclk_allow_idle,
|
||||
.deny_idle = omap2_clkt_iclk_deny_idle,
|
||||
};
|
||||
|
||||
const struct clkops clkops_omap2_iclk_idle_only = {
|
||||
.allow_idle = omap2_clkt_iclk_allow_idle,
|
||||
.deny_idle = omap2_clkt_iclk_deny_idle,
|
||||
};
|
||||
|
||||
const struct clkops clkops_omap2_mdmclk_dflt_wait = {
|
||||
.enable = omap2_dflt_clk_enable,
|
||||
.disable = omap2_dflt_clk_disable,
|
||||
.find_companion = omap2_clk_dflt_find_companion,
|
||||
.find_idlest = omap2_clk_dflt_find_idlest,
|
||||
.allow_idle = omap2_clkt_iclk_allow_idle,
|
||||
.deny_idle = omap2_clkt_iclk_deny_idle,
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -20,6 +20,7 @@
|
|||
#include <linux/list.h>
|
||||
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/clk-provider.h>
|
||||
|
||||
struct omap_clk {
|
||||
u16 cpu;
|
||||
|
@ -52,43 +53,84 @@ struct omap_clk {
|
|||
#define CK_34XX (CK_3430ES1 | CK_3430ES2PLUS)
|
||||
#define CK_3XXX (CK_34XX | CK_AM35XX | CK_36XX)
|
||||
|
||||
struct module;
|
||||
struct clk;
|
||||
struct clockdomain;
|
||||
#define to_clk_hw_omap(_hw) container_of(_hw, struct clk_hw_omap, hw)
|
||||
|
||||
/* Temporary, needed during the common clock framework conversion */
|
||||
#define __clk_get_name(clk) (clk->name)
|
||||
#define __clk_get_parent(clk) (clk->parent)
|
||||
#define __clk_get_rate(clk) (clk->rate)
|
||||
#define DEFINE_STRUCT_CLK(_name, _parent_array_name, _clkops_name) \
|
||||
static struct clk _name = { \
|
||||
.name = #_name, \
|
||||
.hw = &_name##_hw.hw, \
|
||||
.parent_names = _parent_array_name, \
|
||||
.num_parents = ARRAY_SIZE(_parent_array_name), \
|
||||
.ops = &_clkops_name, \
|
||||
};
|
||||
|
||||
/**
|
||||
* struct clkops - some clock function pointers
|
||||
* @enable: fn ptr that enables the current clock in hardware
|
||||
* @disable: fn ptr that enables the current clock in hardware
|
||||
* @find_idlest: function returning the IDLEST register for the clock's IP blk
|
||||
* @find_companion: function returning the "companion" clk reg for the clock
|
||||
* @allow_idle: fn ptr that enables autoidle for the current clock in hardware
|
||||
* @deny_idle: fn ptr that disables autoidle for the current clock in hardware
|
||||
*
|
||||
* A "companion" clk is an accompanying clock to the one being queried
|
||||
* that must be enabled for the IP module connected to the clock to
|
||||
* become accessible by the hardware. Neither @find_idlest nor
|
||||
* @find_companion should be needed; that information is IP
|
||||
* block-specific; the hwmod code has been created to handle this, but
|
||||
* until hwmod data is ready and drivers have been converted to use PM
|
||||
* runtime calls in place of clk_enable()/clk_disable(), @find_idlest and
|
||||
* @find_companion must, unfortunately, remain.
|
||||
*/
|
||||
struct clkops {
|
||||
int (*enable)(struct clk *);
|
||||
void (*disable)(struct clk *);
|
||||
void (*find_idlest)(struct clk *, void __iomem **,
|
||||
u8 *, u8 *);
|
||||
void (*find_companion)(struct clk *, void __iomem **,
|
||||
u8 *);
|
||||
void (*allow_idle)(struct clk *);
|
||||
void (*deny_idle)(struct clk *);
|
||||
};
|
||||
#define DEFINE_STRUCT_CLK_HW_OMAP(_name, _clkdm_name) \
|
||||
static struct clk_hw_omap _name##_hw = { \
|
||||
.hw = { \
|
||||
.clk = &_name, \
|
||||
}, \
|
||||
.clkdm_name = _clkdm_name, \
|
||||
};
|
||||
|
||||
#define DEFINE_CLK_OMAP_MUX(_name, _clkdm_name, _clksel, \
|
||||
_clksel_reg, _clksel_mask, \
|
||||
_parent_names, _ops) \
|
||||
static struct clk _name; \
|
||||
static struct clk_hw_omap _name##_hw = { \
|
||||
.hw = { \
|
||||
.clk = &_name, \
|
||||
}, \
|
||||
.clksel = _clksel, \
|
||||
.clksel_reg = _clksel_reg, \
|
||||
.clksel_mask = _clksel_mask, \
|
||||
.clkdm_name = _clkdm_name, \
|
||||
}; \
|
||||
DEFINE_STRUCT_CLK(_name, _parent_names, _ops);
|
||||
|
||||
#define DEFINE_CLK_OMAP_MUX_GATE(_name, _clkdm_name, _clksel, \
|
||||
_clksel_reg, _clksel_mask, \
|
||||
_enable_reg, _enable_bit, \
|
||||
_hwops, _parent_names, _ops) \
|
||||
static struct clk _name; \
|
||||
static struct clk_hw_omap _name##_hw = { \
|
||||
.hw = { \
|
||||
.clk = &_name, \
|
||||
}, \
|
||||
.ops = _hwops, \
|
||||
.enable_reg = _enable_reg, \
|
||||
.enable_bit = _enable_bit, \
|
||||
.clksel = _clksel, \
|
||||
.clksel_reg = _clksel_reg, \
|
||||
.clksel_mask = _clksel_mask, \
|
||||
.clkdm_name = _clkdm_name, \
|
||||
}; \
|
||||
DEFINE_STRUCT_CLK(_name, _parent_names, _ops);
|
||||
|
||||
#define DEFINE_CLK_OMAP_HSDIVIDER(_name, _parent_name, \
|
||||
_parent_ptr, _flags, \
|
||||
_clksel_reg, _clksel_mask) \
|
||||
static const struct clksel _name##_div[] = { \
|
||||
{ \
|
||||
.parent = _parent_ptr, \
|
||||
.rates = div31_1to31_rates \
|
||||
}, \
|
||||
{ .parent = NULL }, \
|
||||
}; \
|
||||
static struct clk _name; \
|
||||
static const char *_name##_parent_names[] = { \
|
||||
_parent_name, \
|
||||
}; \
|
||||
static struct clk_hw_omap _name##_hw = { \
|
||||
.hw = { \
|
||||
.clk = &_name, \
|
||||
}, \
|
||||
.clksel = _name##_div, \
|
||||
.clksel_reg = _clksel_reg, \
|
||||
.clksel_mask = _clksel_mask, \
|
||||
.ops = &clkhwops_omap4_dpllmx, \
|
||||
}; \
|
||||
DEFINE_STRUCT_CLK(_name, _name##_parent_names, omap_hsdivider_ops);
|
||||
|
||||
/* struct clksel_rate.flags possibilities */
|
||||
#define RATE_IN_242X (1 << 0)
|
||||
|
@ -229,22 +271,10 @@ struct dpll_data {
|
|||
#define CLOCK_CLKOUTX2 (1 << 5)
|
||||
|
||||
/**
|
||||
* struct clk - OMAP struct clk
|
||||
* struct clk_hw_omap - OMAP struct clk
|
||||
* @node: list_head connecting this clock into the full clock list
|
||||
* @ops: struct clkops * for this clock
|
||||
* @name: the name of the clock in the hardware (used in hwmod data and debug)
|
||||
* @parent: pointer to this clock's parent struct clk
|
||||
* @children: list_head connecting to the child clks' @sibling list_heads
|
||||
* @sibling: list_head connecting this clk to its parent clk's @children
|
||||
* @rate: current clock rate
|
||||
* @enable_reg: register to write to enable the clock (see @enable_bit)
|
||||
* @recalc: fn ptr that returns the clock's current rate
|
||||
* @set_rate: fn ptr that can change the clock's current rate
|
||||
* @round_rate: fn ptr that can round the clock's current rate
|
||||
* @init: fn ptr to do clock-specific initialization
|
||||
* @enable_bit: bitshift to write to enable/disable the clock (see @enable_reg)
|
||||
* @usecount: number of users that have requested this clock to be enabled
|
||||
* @fixed_div: when > 0, this clock's rate is its parent's rate / @fixed_div
|
||||
* @flags: see "struct clk.flags possibilities" above
|
||||
* @clksel_reg: for clksel clks, register va containing src/divisor select
|
||||
* @clksel_mask: bitmask in @clksel_reg for the src/divisor selector
|
||||
|
@ -258,39 +288,17 @@ struct dpll_data {
|
|||
* XXX @rate_offset, @src_offset should probably be removed and OMAP1
|
||||
* clock code converted to use clksel.
|
||||
*
|
||||
* XXX @usecount is poorly named. It should be "enable_count" or
|
||||
* something similar. "users" in the description refers to kernel
|
||||
* code (core code or drivers) that have called clk_enable() and not
|
||||
* yet called clk_disable(); the usecount of parent clocks is also
|
||||
* incremented by the clock code when clk_enable() is called on child
|
||||
* clocks and decremented by the clock code when clk_disable() is
|
||||
* called on child clocks.
|
||||
*
|
||||
* XXX @clkdm, @usecount, @children, @sibling should be marked for
|
||||
* internal use only.
|
||||
*
|
||||
* @children and @sibling are used to optimize parent-to-child clock
|
||||
* tree traversals. (child-to-parent traversals use @parent.)
|
||||
*
|
||||
* XXX The notion of the clock's current rate probably needs to be
|
||||
* separated from the clock's target rate.
|
||||
*/
|
||||
struct clk {
|
||||
|
||||
struct clk_hw_omap_ops;
|
||||
|
||||
struct clk_hw_omap {
|
||||
struct clk_hw hw;
|
||||
struct list_head node;
|
||||
const struct clkops *ops;
|
||||
const char *name;
|
||||
struct clk *parent;
|
||||
struct list_head children;
|
||||
struct list_head sibling; /* node for children */
|
||||
unsigned long rate;
|
||||
void __iomem *enable_reg;
|
||||
unsigned long (*recalc)(struct clk *);
|
||||
int (*set_rate)(struct clk *, unsigned long);
|
||||
long (*round_rate)(struct clk *, unsigned long);
|
||||
void (*init)(struct clk *);
|
||||
u8 enable_bit;
|
||||
s8 usecount;
|
||||
unsigned long fixed_rate;
|
||||
u8 fixed_div;
|
||||
void __iomem *enable_reg;
|
||||
u8 enable_bit;
|
||||
u8 flags;
|
||||
void __iomem *clksel_reg;
|
||||
u32 clksel_mask;
|
||||
|
@ -298,42 +306,22 @@ struct clk {
|
|||
struct dpll_data *dpll_data;
|
||||
const char *clkdm_name;
|
||||
struct clockdomain *clkdm;
|
||||
#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
|
||||
struct dentry *dent; /* For visible tree hierarchy */
|
||||
#endif
|
||||
const struct clk_hw_omap_ops *ops;
|
||||
};
|
||||
|
||||
struct clk_functions {
|
||||
int (*clk_enable)(struct clk *clk);
|
||||
void (*clk_disable)(struct clk *clk);
|
||||
long (*clk_round_rate)(struct clk *clk, unsigned long rate);
|
||||
int (*clk_set_rate)(struct clk *clk, unsigned long rate);
|
||||
int (*clk_set_parent)(struct clk *clk, struct clk *parent);
|
||||
void (*clk_allow_idle)(struct clk *clk);
|
||||
void (*clk_deny_idle)(struct clk *clk);
|
||||
void (*clk_disable_unused)(struct clk *clk);
|
||||
struct clk_hw_omap_ops {
|
||||
void (*find_idlest)(struct clk_hw_omap *oclk,
|
||||
void __iomem **idlest_reg,
|
||||
u8 *idlest_bit, u8 *idlest_val);
|
||||
void (*find_companion)(struct clk_hw_omap *oclk,
|
||||
void __iomem **other_reg,
|
||||
u8 *other_bit);
|
||||
void (*allow_idle)(struct clk_hw_omap *oclk);
|
||||
void (*deny_idle)(struct clk_hw_omap *oclk);
|
||||
};
|
||||
|
||||
extern int mpurate;
|
||||
|
||||
extern int clk_init(struct clk_functions *custom_clocks);
|
||||
extern void clk_preinit(struct clk *clk);
|
||||
extern int clk_register(struct clk *clk);
|
||||
extern void clk_reparent(struct clk *child, struct clk *parent);
|
||||
extern void clk_unregister(struct clk *clk);
|
||||
extern void propagate_rate(struct clk *clk);
|
||||
extern void recalculate_root_clocks(void);
|
||||
extern unsigned long followparent_recalc(struct clk *clk);
|
||||
extern void clk_enable_init_clocks(void);
|
||||
unsigned long omap_fixed_divisor_recalc(struct clk *clk);
|
||||
extern struct clk *omap_clk_get_by_name(const char *name);
|
||||
extern int omap_clk_enable_autoidle_all(void);
|
||||
extern int omap_clk_disable_autoidle_all(void);
|
||||
|
||||
extern const struct clkops clkops_null;
|
||||
|
||||
extern struct clk dummy_ck;
|
||||
|
||||
unsigned long omap_fixed_divisor_recalc(struct clk_hw *hw,
|
||||
unsigned long parent_rate);
|
||||
|
||||
/* CM_CLKSEL2_PLL.CORE_CLK_SRC bits (2XXX) */
|
||||
#define CORE_CLK_SRC_32K 0x0
|
||||
|
@ -364,57 +352,62 @@ extern struct clk dummy_ck;
|
|||
/* DPLL Type and DCO Selection Flags */
|
||||
#define DPLL_J_TYPE 0x1
|
||||
|
||||
int omap2_clk_enable(struct clk *clk);
|
||||
void omap2_clk_disable(struct clk *clk);
|
||||
long omap2_clk_round_rate(struct clk *clk, unsigned long rate);
|
||||
int omap2_clk_set_rate(struct clk *clk, unsigned long rate);
|
||||
int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent);
|
||||
long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate);
|
||||
unsigned long omap3_dpll_recalc(struct clk *clk);
|
||||
unsigned long omap3_clkoutx2_recalc(struct clk *clk);
|
||||
void omap3_dpll_allow_idle(struct clk *clk);
|
||||
void omap3_dpll_deny_idle(struct clk *clk);
|
||||
u32 omap3_dpll_autoidle_read(struct clk *clk);
|
||||
int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate);
|
||||
int omap3_noncore_dpll_enable(struct clk *clk);
|
||||
void omap3_noncore_dpll_disable(struct clk *clk);
|
||||
int omap4_dpllmx_gatectrl_read(struct clk *clk);
|
||||
void omap4_dpllmx_allow_gatectrl(struct clk *clk);
|
||||
void omap4_dpllmx_deny_gatectrl(struct clk *clk);
|
||||
long omap4_dpll_regm4xen_round_rate(struct clk *clk, unsigned long target_rate);
|
||||
unsigned long omap4_dpll_regm4xen_recalc(struct clk *clk);
|
||||
long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
|
||||
unsigned long *parent_rate);
|
||||
unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate);
|
||||
int omap3_noncore_dpll_enable(struct clk_hw *hw);
|
||||
void omap3_noncore_dpll_disable(struct clk_hw *hw);
|
||||
int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate);
|
||||
u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk);
|
||||
void omap3_dpll_allow_idle(struct clk_hw_omap *clk);
|
||||
void omap3_dpll_deny_idle(struct clk_hw_omap *clk);
|
||||
unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
|
||||
unsigned long parent_rate);
|
||||
int omap4_dpllmx_gatectrl_read(struct clk_hw_omap *clk);
|
||||
void omap4_dpllmx_allow_gatectrl(struct clk_hw_omap *clk);
|
||||
void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk);
|
||||
unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
|
||||
unsigned long parent_rate);
|
||||
long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
|
||||
unsigned long target_rate,
|
||||
unsigned long *parent_rate);
|
||||
|
||||
#ifdef CONFIG_OMAP_RESET_CLOCKS
|
||||
void omap2_clk_disable_unused(struct clk *clk);
|
||||
#else
|
||||
#define omap2_clk_disable_unused NULL
|
||||
#endif
|
||||
|
||||
void omap2_init_clk_clkdm(struct clk *clk);
|
||||
void omap2_init_clk_clkdm(struct clk_hw *clk);
|
||||
void __init omap2_clk_disable_clkdm_control(void);
|
||||
|
||||
/* clkt_clksel.c public functions */
|
||||
u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
|
||||
u32 omap2_clksel_round_rate_div(struct clk_hw_omap *clk,
|
||||
unsigned long target_rate,
|
||||
u32 *new_div);
|
||||
void omap2_init_clksel_parent(struct clk *clk);
|
||||
unsigned long omap2_clksel_recalc(struct clk *clk);
|
||||
long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate);
|
||||
int omap2_clksel_set_rate(struct clk *clk, unsigned long rate);
|
||||
int omap2_clksel_set_parent(struct clk *clk, struct clk *new_parent);
|
||||
u8 omap2_clksel_find_parent_index(struct clk_hw *hw);
|
||||
unsigned long omap2_clksel_recalc(struct clk_hw *hw, unsigned long parent_rate);
|
||||
long omap2_clksel_round_rate(struct clk_hw *hw, unsigned long target_rate,
|
||||
unsigned long *parent_rate);
|
||||
int omap2_clksel_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate);
|
||||
int omap2_clksel_set_parent(struct clk_hw *hw, u8 field_val);
|
||||
|
||||
/* clkt_iclk.c public functions */
|
||||
extern void omap2_clkt_iclk_allow_idle(struct clk *clk);
|
||||
extern void omap2_clkt_iclk_deny_idle(struct clk *clk);
|
||||
extern void omap2_clkt_iclk_allow_idle(struct clk_hw_omap *clk);
|
||||
extern void omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk);
|
||||
|
||||
u32 omap2_get_dpll_rate(struct clk *clk);
|
||||
void omap2_init_dpll_parent(struct clk *clk);
|
||||
u8 omap2_init_dpll_parent(struct clk_hw *hw);
|
||||
unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk);
|
||||
|
||||
int omap2_dflt_clk_enable(struct clk *clk);
|
||||
void omap2_dflt_clk_disable(struct clk *clk);
|
||||
void omap2_clk_dflt_find_companion(struct clk *clk, void __iomem **other_reg,
|
||||
int omap2_dflt_clk_enable(struct clk_hw *hw);
|
||||
void omap2_dflt_clk_disable(struct clk_hw *hw);
|
||||
int omap2_dflt_clk_is_enabled(struct clk_hw *hw);
|
||||
void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk,
|
||||
void __iomem **other_reg,
|
||||
u8 *other_bit);
|
||||
void omap2_clk_dflt_find_idlest(struct clk *clk, void __iomem **idlest_reg,
|
||||
void omap2_clk_dflt_find_idlest(struct clk_hw_omap *clk,
|
||||
void __iomem **idlest_reg,
|
||||
u8 *idlest_bit, u8 *idlest_val);
|
||||
void omap2_init_clk_hw_omap_clocks(struct clk *clk);
|
||||
int omap2_clk_enable_autoidle_all(void);
|
||||
int omap2_clk_disable_autoidle_all(void);
|
||||
void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks);
|
||||
int omap2_clk_switch_mpurate_at_boot(const char *mpurate_ck_name);
|
||||
void omap2_clk_print_new_rates(const char *hfclkin_ck_name,
|
||||
const char *core_ck_name,
|
||||
|
@ -432,28 +425,38 @@ extern const struct clksel_rate gpt_32k_rates[];
|
|||
extern const struct clksel_rate gpt_sys_rates[];
|
||||
extern const struct clksel_rate gfx_l3_rates[];
|
||||
extern const struct clksel_rate dsp_ick_rates[];
|
||||
extern struct clk dummy_ck;
|
||||
|
||||
extern const struct clkops clkops_omap2_iclk_dflt_wait;
|
||||
extern const struct clkops clkops_omap2_iclk_dflt;
|
||||
extern const struct clkops clkops_omap2_iclk_idle_only;
|
||||
extern const struct clkops clkops_omap2_mdmclk_dflt_wait;
|
||||
extern const struct clkops clkops_omap2xxx_dpll_ops;
|
||||
extern const struct clkops clkops_omap3_noncore_dpll_ops;
|
||||
extern const struct clkops clkops_omap3_core_dpll_ops;
|
||||
extern const struct clkops clkops_omap4_dpllmx_ops;
|
||||
extern const struct clk_hw_omap_ops clkhwops_omap3_dpll;
|
||||
extern const struct clk_hw_omap_ops clkhwops_iclk_wait;
|
||||
extern const struct clk_hw_omap_ops clkhwops_wait;
|
||||
extern const struct clk_hw_omap_ops clkhwops_omap4_dpllmx;
|
||||
extern const struct clk_hw_omap_ops clkhwops_iclk;
|
||||
extern const struct clk_hw_omap_ops clkhwops_omap3430es2_ssi_wait;
|
||||
extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_ssi_wait;
|
||||
extern const struct clk_hw_omap_ops clkhwops_omap3430es2_dss_usbhost_wait;
|
||||
extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_dss_usbhost_wait;
|
||||
extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_hsotgusb_wait;
|
||||
extern const struct clk_hw_omap_ops clkhwops_omap3430es2_hsotgusb_wait;
|
||||
extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait;
|
||||
extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_wait;
|
||||
extern const struct clk_hw_omap_ops clkhwops_apll54;
|
||||
extern const struct clk_hw_omap_ops clkhwops_apll96;
|
||||
extern const struct clk_hw_omap_ops clkhwops_omap2xxx_dpll;
|
||||
extern const struct clk_hw_omap_ops clkhwops_omap2430_i2chs_wait;
|
||||
|
||||
/* clksel_rate blocks shared between OMAP44xx and AM33xx */
|
||||
extern const struct clksel_rate div_1_0_rates[];
|
||||
extern const struct clksel_rate div3_1to4_rates[];
|
||||
extern const struct clksel_rate div_1_1_rates[];
|
||||
extern const struct clksel_rate div_1_2_rates[];
|
||||
extern const struct clksel_rate div_1_3_rates[];
|
||||
extern const struct clksel_rate div_1_4_rates[];
|
||||
extern const struct clksel_rate div31_1to31_rates[];
|
||||
|
||||
/* clocks shared between various OMAP SoCs */
|
||||
extern struct clk virt_19200000_ck;
|
||||
extern struct clk virt_26000000_ck;
|
||||
|
||||
extern int am33xx_clk_init(void);
|
||||
|
||||
extern int omap2_clkops_enable_clkdm(struct clk_hw *hw);
|
||||
extern void omap2_clkops_disable_clkdm(struct clk_hw *hw);
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -40,7 +40,7 @@
|
|||
* passes back the correct CM_IDLEST register address for I2CHS
|
||||
* modules. No return value.
|
||||
*/
|
||||
static void omap2430_clk_i2chs_find_idlest(struct clk *clk,
|
||||
static void omap2430_clk_i2chs_find_idlest(struct clk_hw_omap *clk,
|
||||
void __iomem **idlest_reg,
|
||||
u8 *idlest_bit,
|
||||
u8 *idlest_val)
|
||||
|
@ -51,9 +51,7 @@ static void omap2430_clk_i2chs_find_idlest(struct clk *clk,
|
|||
}
|
||||
|
||||
/* 2430 I2CHS has non-standard IDLEST register */
|
||||
const struct clkops clkops_omap2430_i2chs_wait = {
|
||||
.enable = omap2_dflt_clk_enable,
|
||||
.disable = omap2_dflt_clk_disable,
|
||||
const struct clk_hw_omap_ops clkhwops_omap2430_i2chs_wait = {
|
||||
.find_idlest = omap2430_clk_i2chs_find_idlest,
|
||||
.find_companion = omap2_clk_dflt_find_companion,
|
||||
.find_companion = omap2_clk_dflt_find_companion,
|
||||
};
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -28,6 +28,7 @@
|
|||
#include "cm.h"
|
||||
#include "cm-regbits-24xx.h"
|
||||
|
||||
struct clk_hw *dclk_hw;
|
||||
/*
|
||||
* Omap24xx specific clock functions
|
||||
*/
|
||||
|
|
|
@ -8,18 +8,32 @@
|
|||
#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK2XXX_H
|
||||
#define __ARCH_ARM_MACH_OMAP2_CLOCK2XXX_H
|
||||
|
||||
unsigned long omap2_table_mpu_recalc(struct clk *clk);
|
||||
int omap2_select_table_rate(struct clk *clk, unsigned long rate);
|
||||
long omap2_round_to_table_rate(struct clk *clk, unsigned long rate);
|
||||
unsigned long omap2xxx_sys_clk_recalc(struct clk *clk);
|
||||
unsigned long omap2_osc_clk_recalc(struct clk *clk);
|
||||
unsigned long omap2_dpllcore_recalc(struct clk *clk);
|
||||
int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate);
|
||||
#include <linux/clk-provider.h>
|
||||
#include "clock.h"
|
||||
|
||||
unsigned long omap2_table_mpu_recalc(struct clk_hw *clk,
|
||||
unsigned long parent_rate);
|
||||
int omap2_select_table_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate);
|
||||
long omap2_round_to_table_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long *parent_rate);
|
||||
unsigned long omap2xxx_sys_clk_recalc(struct clk_hw *clk,
|
||||
unsigned long parent_rate);
|
||||
unsigned long omap2_osc_clk_recalc(struct clk_hw *clk,
|
||||
unsigned long parent_rate);
|
||||
unsigned long omap2_dpllcore_recalc(struct clk_hw *hw,
|
||||
unsigned long parent_rate);
|
||||
int omap2_reprogram_dpllcore(struct clk_hw *clk, unsigned long rate,
|
||||
unsigned long parent_rate);
|
||||
void omap2xxx_clkt_dpllcore_init(struct clk_hw *hw);
|
||||
unsigned long omap2_clk_apll54_recalc(struct clk_hw *hw,
|
||||
unsigned long parent_rate);
|
||||
unsigned long omap2_clk_apll96_recalc(struct clk_hw *hw,
|
||||
unsigned long parent_rate);
|
||||
unsigned long omap2xxx_clk_get_core_rate(void);
|
||||
u32 omap2xxx_get_apll_clkin(void);
|
||||
u32 omap2xxx_get_sysclkdiv(void);
|
||||
void omap2xxx_clk_prepare_for_reboot(void);
|
||||
void omap2xxx_clkt_dpllcore_init(struct clk *clk);
|
||||
void omap2xxx_clkt_vps_check_bootloader_rates(void);
|
||||
void omap2xxx_clkt_vps_late_init(void);
|
||||
|
||||
|
@ -37,9 +51,12 @@ int omap2430_clk_init(void);
|
|||
|
||||
extern void __iomem *prcm_clksrc_ctrl;
|
||||
|
||||
extern const struct clkops clkops_omap2430_i2chs_wait;
|
||||
extern const struct clkops clkops_oscck;
|
||||
extern const struct clkops clkops_apll96;
|
||||
extern const struct clkops clkops_apll54;
|
||||
extern struct clk_hw *dclk_hw;
|
||||
int omap2_enable_osc_ck(struct clk_hw *hw);
|
||||
void omap2_disable_osc_ck(struct clk_hw *hw);
|
||||
int omap2_clk_apll96_enable(struct clk_hw *hw);
|
||||
int omap2_clk_apll54_enable(struct clk_hw *hw);
|
||||
void omap2_clk_apll96_disable(struct clk_hw *hw);
|
||||
void omap2_clk_apll54_disable(struct clk_hw *hw);
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -37,7 +37,7 @@
|
|||
* from the CM_{I,F}CLKEN bit. Pass back the correct info via
|
||||
* @idlest_reg and @idlest_bit. No return value.
|
||||
*/
|
||||
static void omap3430es2_clk_ssi_find_idlest(struct clk *clk,
|
||||
static void omap3430es2_clk_ssi_find_idlest(struct clk_hw_omap *clk,
|
||||
void __iomem **idlest_reg,
|
||||
u8 *idlest_bit,
|
||||
u8 *idlest_val)
|
||||
|
@ -49,21 +49,16 @@ static void omap3430es2_clk_ssi_find_idlest(struct clk *clk,
|
|||
*idlest_bit = OMAP3430ES2_ST_SSI_IDLE_SHIFT;
|
||||
*idlest_val = OMAP34XX_CM_IDLEST_VAL;
|
||||
}
|
||||
|
||||
const struct clkops clkops_omap3430es2_ssi_wait = {
|
||||
.enable = omap2_dflt_clk_enable,
|
||||
.disable = omap2_dflt_clk_disable,
|
||||
const struct clk_hw_omap_ops clkhwops_omap3430es2_ssi_wait = {
|
||||
.find_idlest = omap3430es2_clk_ssi_find_idlest,
|
||||
.find_companion = omap2_clk_dflt_find_companion,
|
||||
.find_companion = omap2_clk_dflt_find_companion,
|
||||
};
|
||||
|
||||
const struct clkops clkops_omap3430es2_iclk_ssi_wait = {
|
||||
.enable = omap2_dflt_clk_enable,
|
||||
.disable = omap2_dflt_clk_disable,
|
||||
.find_idlest = omap3430es2_clk_ssi_find_idlest,
|
||||
.find_companion = omap2_clk_dflt_find_companion,
|
||||
const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_ssi_wait = {
|
||||
.allow_idle = omap2_clkt_iclk_allow_idle,
|
||||
.deny_idle = omap2_clkt_iclk_deny_idle,
|
||||
.find_idlest = omap3430es2_clk_ssi_find_idlest,
|
||||
.find_companion = omap2_clk_dflt_find_companion,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -80,7 +75,7 @@ const struct clkops clkops_omap3430es2_iclk_ssi_wait = {
|
|||
* default find_idlest code assumes that they are at the same
|
||||
* position.) No return value.
|
||||
*/
|
||||
static void omap3430es2_clk_dss_usbhost_find_idlest(struct clk *clk,
|
||||
static void omap3430es2_clk_dss_usbhost_find_idlest(struct clk_hw_omap *clk,
|
||||
void __iomem **idlest_reg,
|
||||
u8 *idlest_bit,
|
||||
u8 *idlest_val)
|
||||
|
@ -94,20 +89,16 @@ static void omap3430es2_clk_dss_usbhost_find_idlest(struct clk *clk,
|
|||
*idlest_val = OMAP34XX_CM_IDLEST_VAL;
|
||||
}
|
||||
|
||||
const struct clkops clkops_omap3430es2_dss_usbhost_wait = {
|
||||
.enable = omap2_dflt_clk_enable,
|
||||
.disable = omap2_dflt_clk_disable,
|
||||
const struct clk_hw_omap_ops clkhwops_omap3430es2_dss_usbhost_wait = {
|
||||
.find_idlest = omap3430es2_clk_dss_usbhost_find_idlest,
|
||||
.find_companion = omap2_clk_dflt_find_companion,
|
||||
.find_companion = omap2_clk_dflt_find_companion,
|
||||
};
|
||||
|
||||
const struct clkops clkops_omap3430es2_iclk_dss_usbhost_wait = {
|
||||
.enable = omap2_dflt_clk_enable,
|
||||
.disable = omap2_dflt_clk_disable,
|
||||
.find_idlest = omap3430es2_clk_dss_usbhost_find_idlest,
|
||||
.find_companion = omap2_clk_dflt_find_companion,
|
||||
const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_dss_usbhost_wait = {
|
||||
.allow_idle = omap2_clkt_iclk_allow_idle,
|
||||
.deny_idle = omap2_clkt_iclk_deny_idle,
|
||||
.find_idlest = omap3430es2_clk_dss_usbhost_find_idlest,
|
||||
.find_companion = omap2_clk_dflt_find_companion,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -121,7 +112,7 @@ const struct clkops clkops_omap3430es2_iclk_dss_usbhost_wait = {
|
|||
* shift from the CM_{I,F}CLKEN bit. Pass back the correct info via
|
||||
* @idlest_reg and @idlest_bit. No return value.
|
||||
*/
|
||||
static void omap3430es2_clk_hsotgusb_find_idlest(struct clk *clk,
|
||||
static void omap3430es2_clk_hsotgusb_find_idlest(struct clk_hw_omap *clk,
|
||||
void __iomem **idlest_reg,
|
||||
u8 *idlest_bit,
|
||||
u8 *idlest_val)
|
||||
|
@ -134,18 +125,14 @@ static void omap3430es2_clk_hsotgusb_find_idlest(struct clk *clk,
|
|||
*idlest_val = OMAP34XX_CM_IDLEST_VAL;
|
||||
}
|
||||
|
||||
const struct clkops clkops_omap3430es2_hsotgusb_wait = {
|
||||
.enable = omap2_dflt_clk_enable,
|
||||
.disable = omap2_dflt_clk_disable,
|
||||
.find_idlest = omap3430es2_clk_hsotgusb_find_idlest,
|
||||
.find_companion = omap2_clk_dflt_find_companion,
|
||||
};
|
||||
|
||||
const struct clkops clkops_omap3430es2_iclk_hsotgusb_wait = {
|
||||
.enable = omap2_dflt_clk_enable,
|
||||
.disable = omap2_dflt_clk_disable,
|
||||
.find_idlest = omap3430es2_clk_hsotgusb_find_idlest,
|
||||
.find_companion = omap2_clk_dflt_find_companion,
|
||||
const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_hsotgusb_wait = {
|
||||
.allow_idle = omap2_clkt_iclk_allow_idle,
|
||||
.deny_idle = omap2_clkt_iclk_deny_idle,
|
||||
.find_idlest = omap3430es2_clk_hsotgusb_find_idlest,
|
||||
.find_companion = omap2_clk_dflt_find_companion,
|
||||
};
|
||||
|
||||
const struct clk_hw_omap_ops clkhwops_omap3430es2_hsotgusb_wait = {
|
||||
.find_idlest = omap3430es2_clk_hsotgusb_find_idlest,
|
||||
.find_companion = omap2_clk_dflt_find_companion,
|
||||
};
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
* in the enable register itsel at a bit offset of 4 from the enable
|
||||
* bit. A value of 1 indicates that clock is enabled.
|
||||
*/
|
||||
static void am35xx_clk_find_idlest(struct clk *clk,
|
||||
static void am35xx_clk_find_idlest(struct clk_hw_omap *clk,
|
||||
void __iomem **idlest_reg,
|
||||
u8 *idlest_bit,
|
||||
u8 *idlest_val)
|
||||
|
@ -71,8 +71,9 @@ static void am35xx_clk_find_idlest(struct clk *clk,
|
|||
* associate this type of code with per-module data structures to
|
||||
* avoid this issue, and remove the casts. No return value.
|
||||
*/
|
||||
static void am35xx_clk_find_companion(struct clk *clk, void __iomem **other_reg,
|
||||
u8 *other_bit)
|
||||
static void am35xx_clk_find_companion(struct clk_hw_omap *clk,
|
||||
void __iomem **other_reg,
|
||||
u8 *other_bit)
|
||||
{
|
||||
*other_reg = (__force void __iomem *)(clk->enable_reg);
|
||||
if (clk->enable_bit & AM35XX_IPSS_ICK_MASK)
|
||||
|
@ -80,10 +81,7 @@ static void am35xx_clk_find_companion(struct clk *clk, void __iomem **other_reg,
|
|||
else
|
||||
*other_bit = clk->enable_bit - AM35XX_IPSS_ICK_FCK_OFFSET;
|
||||
}
|
||||
|
||||
const struct clkops clkops_am35xx_ipss_module_wait = {
|
||||
.enable = omap2_dflt_clk_enable,
|
||||
.disable = omap2_dflt_clk_disable,
|
||||
const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait = {
|
||||
.find_idlest = am35xx_clk_find_idlest,
|
||||
.find_companion = am35xx_clk_find_companion,
|
||||
};
|
||||
|
@ -99,7 +97,7 @@ const struct clkops clkops_am35xx_ipss_module_wait = {
|
|||
* CM_{I,F}CLKEN bit. Pass back the correct info via @idlest_reg
|
||||
* and @idlest_bit. No return value.
|
||||
*/
|
||||
static void am35xx_clk_ipss_find_idlest(struct clk *clk,
|
||||
static void am35xx_clk_ipss_find_idlest(struct clk_hw_omap *clk,
|
||||
void __iomem **idlest_reg,
|
||||
u8 *idlest_bit,
|
||||
u8 *idlest_val)
|
||||
|
@ -112,13 +110,9 @@ static void am35xx_clk_ipss_find_idlest(struct clk *clk,
|
|||
*idlest_val = OMAP34XX_CM_IDLEST_VAL;
|
||||
}
|
||||
|
||||
const struct clkops clkops_am35xx_ipss_wait = {
|
||||
.enable = omap2_dflt_clk_enable,
|
||||
.disable = omap2_dflt_clk_disable,
|
||||
.find_idlest = am35xx_clk_ipss_find_idlest,
|
||||
.find_companion = omap2_clk_dflt_find_companion,
|
||||
const struct clk_hw_omap_ops clkhwops_am35xx_ipss_wait = {
|
||||
.allow_idle = omap2_clkt_iclk_allow_idle,
|
||||
.deny_idle = omap2_clkt_iclk_deny_idle,
|
||||
.find_idlest = am35xx_clk_ipss_find_idlest,
|
||||
.find_companion = omap2_clk_dflt_find_companion,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -37,34 +37,32 @@
|
|||
* (Any other value different from the Read value) to the
|
||||
* corresponding CM_CLKSEL register will refresh the dividers.
|
||||
*/
|
||||
static int omap36xx_pwrdn_clk_enable_with_hsdiv_restore(struct clk *clk)
|
||||
int omap36xx_pwrdn_clk_enable_with_hsdiv_restore(struct clk_hw *clk)
|
||||
{
|
||||
struct clk_hw_omap *parent;
|
||||
struct clk_hw *parent_hw;
|
||||
u32 dummy_v, orig_v, clksel_shift;
|
||||
int ret;
|
||||
|
||||
/* Clear PWRDN bit of HSDIVIDER */
|
||||
ret = omap2_dflt_clk_enable(clk);
|
||||
|
||||
parent_hw = __clk_get_hw(__clk_get_parent(clk->clk));
|
||||
parent = to_clk_hw_omap(parent_hw);
|
||||
|
||||
/* Restore the dividers */
|
||||
if (!ret) {
|
||||
clksel_shift = __ffs(clk->parent->clksel_mask);
|
||||
orig_v = __raw_readl(clk->parent->clksel_reg);
|
||||
clksel_shift = __ffs(parent->clksel_mask);
|
||||
orig_v = __raw_readl(parent->clksel_reg);
|
||||
dummy_v = orig_v;
|
||||
|
||||
/* Write any other value different from the Read value */
|
||||
dummy_v ^= (1 << clksel_shift);
|
||||
__raw_writel(dummy_v, clk->parent->clksel_reg);
|
||||
__raw_writel(dummy_v, parent->clksel_reg);
|
||||
|
||||
/* Write the original divider */
|
||||
__raw_writel(orig_v, clk->parent->clksel_reg);
|
||||
__raw_writel(orig_v, parent->clksel_reg);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const struct clkops clkops_omap36xx_pwrdn_with_hsdiv_wait_restore = {
|
||||
.enable = omap36xx_pwrdn_clk_enable_with_hsdiv_restore,
|
||||
.disable = omap2_dflt_clk_disable,
|
||||
.find_companion = omap2_clk_dflt_find_companion,
|
||||
.find_idlest = omap2_clk_dflt_find_idlest,
|
||||
};
|
||||
|
|
|
@ -8,6 +8,6 @@
|
|||
#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK36XX_H
|
||||
#define __ARCH_ARM_MACH_OMAP2_CLOCK36XX_H
|
||||
|
||||
extern const struct clkops clkops_omap36xx_pwrdn_with_hsdiv_wait_restore;
|
||||
extern int omap36xx_pwrdn_clk_enable_with_hsdiv_restore(struct clk_hw *hw);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -38,8 +38,8 @@
|
|||
|
||||
/* needed by omap3_core_dpll_m2_set_rate() */
|
||||
struct clk *sdrc_ick_p, *arm_fck_p;
|
||||
|
||||
int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate)
|
||||
int omap3_dpll4_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
/*
|
||||
* According to the 12-5 CDP code from TI, "Limitation 2.5"
|
||||
|
@ -51,7 +51,7 @@ int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
return omap3_noncore_dpll_set_rate(clk, rate);
|
||||
return omap3_noncore_dpll_set_rate(hw, rate, parent_rate);
|
||||
}
|
||||
|
||||
void __init omap3_clk_lock_dpll5(void)
|
||||
|
|
|
@ -9,8 +9,10 @@
|
|||
#define __ARCH_ARM_MACH_OMAP2_CLOCK3XXX_H
|
||||
|
||||
int omap3xxx_clk_init(void);
|
||||
int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate);
|
||||
int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate);
|
||||
int omap3_dpll4_set_rate(struct clk_hw *clk, unsigned long rate,
|
||||
unsigned long parent_rate);
|
||||
int omap3_core_dpll_m2_set_rate(struct clk_hw *clk, unsigned long rate,
|
||||
unsigned long parent_rate);
|
||||
void omap3_clk_lock_dpll5(void);
|
||||
|
||||
extern struct clk *sdrc_ick_p;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -16,6 +16,7 @@
|
|||
* OMAP3xxx clock definition files.
|
||||
*/
|
||||
|
||||
#include <linux/clk-private.h>
|
||||
#include "clock.h"
|
||||
|
||||
/* clksel_rate data common to 24xx/343x */
|
||||
|
@ -52,6 +53,13 @@ const struct clksel_rate div_1_0_rates[] = {
|
|||
{ .div = 0 },
|
||||
};
|
||||
|
||||
const struct clksel_rate div3_1to4_rates[] = {
|
||||
{ .div = 1, .val = 0, .flags = RATE_IN_4430 },
|
||||
{ .div = 2, .val = 1, .flags = RATE_IN_4430 },
|
||||
{ .div = 4, .val = 2, .flags = RATE_IN_4430 },
|
||||
{ .div = 0 },
|
||||
};
|
||||
|
||||
const struct clksel_rate div_1_1_rates[] = {
|
||||
{ .div = 1, .val = 1, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
|
||||
{ .div = 0 },
|
||||
|
@ -109,14 +117,10 @@ const struct clksel_rate div31_1to31_rates[] = {
|
|||
|
||||
/* Clocks shared between various OMAP SoCs */
|
||||
|
||||
struct clk virt_19200000_ck = {
|
||||
.name = "virt_19200000_ck",
|
||||
.ops = &clkops_null,
|
||||
.rate = 19200000,
|
||||
};
|
||||
static struct clk_ops dummy_ck_ops = {};
|
||||
|
||||
struct clk virt_26000000_ck = {
|
||||
.name = "virt_26000000_ck",
|
||||
.ops = &clkops_null,
|
||||
.rate = 26000000,
|
||||
struct clk dummy_ck = {
|
||||
.name = "dummy_clk",
|
||||
.ops = &dummy_ck_ops,
|
||||
.flags = CLK_IS_BASIC,
|
||||
};
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <linux/clk.h>
|
||||
#include <linux/limits.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/clk-provider.h>
|
||||
|
||||
#include <linux/io.h>
|
||||
|
||||
|
@ -947,35 +948,6 @@ static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int _clkdm_clk_hwmod_disable(struct clockdomain *clkdm)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_disable)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&clkdm->lock, flags);
|
||||
|
||||
if (atomic_read(&clkdm->usecount) == 0) {
|
||||
spin_unlock_irqrestore(&clkdm->lock, flags);
|
||||
WARN_ON(1); /* underflow */
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
if (atomic_dec_return(&clkdm->usecount) > 0) {
|
||||
spin_unlock_irqrestore(&clkdm->lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
arch_clkdm->clkdm_clk_disable(clkdm);
|
||||
pwrdm_state_switch(clkdm->pwrdm.ptr);
|
||||
spin_unlock_irqrestore(&clkdm->lock, flags);
|
||||
|
||||
pr_debug("clockdomain: %s: disabled\n", clkdm->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* clkdm_clk_enable - add an enabled downstream clock to this clkdm
|
||||
* @clkdm: struct clockdomain *
|
||||
|
@ -1018,15 +990,37 @@ int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
|
|||
*/
|
||||
int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
|
||||
{
|
||||
/*
|
||||
* XXX Rewrite this code to maintain a list of enabled
|
||||
* downstream clocks for debugging purposes?
|
||||
*/
|
||||
unsigned long flags;
|
||||
|
||||
if (!clk)
|
||||
if (!clkdm || !clk || !arch_clkdm || !arch_clkdm->clkdm_clk_disable)
|
||||
return -EINVAL;
|
||||
|
||||
return _clkdm_clk_hwmod_disable(clkdm);
|
||||
spin_lock_irqsave(&clkdm->lock, flags);
|
||||
|
||||
/* corner case: disabling unused clocks */
|
||||
if (__clk_get_enable_count(clk) == 0)
|
||||
goto ccd_exit;
|
||||
|
||||
if (atomic_read(&clkdm->usecount) == 0) {
|
||||
spin_unlock_irqrestore(&clkdm->lock, flags);
|
||||
WARN_ON(1); /* underflow */
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
if (atomic_dec_return(&clkdm->usecount) > 0) {
|
||||
spin_unlock_irqrestore(&clkdm->lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
arch_clkdm->clkdm_clk_disable(clkdm);
|
||||
pwrdm_state_switch(clkdm->pwrdm.ptr);
|
||||
|
||||
pr_debug("clockdomain: %s: disabled\n", clkdm->name);
|
||||
|
||||
ccd_exit:
|
||||
spin_unlock_irqrestore(&clkdm->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1077,6 +1071,8 @@ int clkdm_hwmod_enable(struct clockdomain *clkdm, struct omap_hwmod *oh)
|
|||
*/
|
||||
int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
/* The clkdm attribute does not exist yet prior OMAP4 */
|
||||
if (cpu_is_omap24xx() || cpu_is_omap34xx())
|
||||
return 0;
|
||||
|
@ -1086,9 +1082,28 @@ int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh)
|
|||
* downstream hwmods for debugging purposes?
|
||||
*/
|
||||
|
||||
if (!oh)
|
||||
if (!clkdm || !oh || !arch_clkdm || !arch_clkdm->clkdm_clk_disable)
|
||||
return -EINVAL;
|
||||
|
||||
return _clkdm_clk_hwmod_disable(clkdm);
|
||||
spin_lock_irqsave(&clkdm->lock, flags);
|
||||
|
||||
if (atomic_read(&clkdm->usecount) == 0) {
|
||||
spin_unlock_irqrestore(&clkdm->lock, flags);
|
||||
WARN_ON(1); /* underflow */
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
if (atomic_dec_return(&clkdm->usecount) > 0) {
|
||||
spin_unlock_irqrestore(&clkdm->lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
arch_clkdm->clkdm_clk_disable(clkdm);
|
||||
pwrdm_state_switch(clkdm->pwrdm.ptr);
|
||||
spin_unlock_irqrestore(&clkdm->lock, flags);
|
||||
|
||||
pr_debug("clockdomain: %s: disabled\n", clkdm->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
/* CM_CLKSEL_MPU */
|
||||
#define OMAP24XX_CLKSEL_MPU_SHIFT 0
|
||||
#define OMAP24XX_CLKSEL_MPU_MASK (0x1f << 0)
|
||||
#define OMAP24XX_CLKSEL_MPU_WIDTH 5
|
||||
|
||||
/* CM_CLKSTCTRL_MPU */
|
||||
#define OMAP24XX_AUTOSTATE_MPU_SHIFT 0
|
||||
|
@ -237,8 +238,10 @@
|
|||
#define OMAP24XX_CLKSEL_DSS1_MASK (0x1f << 8)
|
||||
#define OMAP24XX_CLKSEL_L4_SHIFT 5
|
||||
#define OMAP24XX_CLKSEL_L4_MASK (0x3 << 5)
|
||||
#define OMAP24XX_CLKSEL_L4_WIDTH 2
|
||||
#define OMAP24XX_CLKSEL_L3_SHIFT 0
|
||||
#define OMAP24XX_CLKSEL_L3_MASK (0x1f << 0)
|
||||
#define OMAP24XX_CLKSEL_L3_WIDTH 5
|
||||
|
||||
/* CM_CLKSEL2_CORE */
|
||||
#define OMAP24XX_CLKSEL_GPT12_SHIFT 22
|
||||
|
@ -363,8 +366,10 @@
|
|||
#define OMAP24XX_DPLL_DIV_MASK (0xf << 8)
|
||||
#define OMAP24XX_54M_SOURCE_SHIFT 5
|
||||
#define OMAP24XX_54M_SOURCE_MASK (1 << 5)
|
||||
#define OMAP24XX_54M_SOURCE_WIDTH 1
|
||||
#define OMAP2430_96M_SOURCE_SHIFT 4
|
||||
#define OMAP2430_96M_SOURCE_MASK (1 << 4)
|
||||
#define OMAP2430_96M_SOURCE_WIDTH 1
|
||||
#define OMAP24XX_48M_SOURCE_SHIFT 3
|
||||
#define OMAP24XX_48M_SOURCE_MASK (1 << 3)
|
||||
#define OMAP2430_ALTCLK_SOURCE_SHIFT 0
|
||||
|
|
|
@ -81,6 +81,7 @@
|
|||
/* CM_CLKSEL1_PLL_IVA2 */
|
||||
#define OMAP3430_IVA2_CLK_SRC_SHIFT 19
|
||||
#define OMAP3430_IVA2_CLK_SRC_MASK (0x7 << 19)
|
||||
#define OMAP3430_IVA2_CLK_SRC_WIDTH 3
|
||||
#define OMAP3430_IVA2_DPLL_MULT_SHIFT 8
|
||||
#define OMAP3430_IVA2_DPLL_MULT_MASK (0x7ff << 8)
|
||||
#define OMAP3430_IVA2_DPLL_DIV_SHIFT 0
|
||||
|
@ -89,6 +90,7 @@
|
|||
/* CM_CLKSEL2_PLL_IVA2 */
|
||||
#define OMAP3430_IVA2_DPLL_CLKOUT_DIV_SHIFT 0
|
||||
#define OMAP3430_IVA2_DPLL_CLKOUT_DIV_MASK (0x1f << 0)
|
||||
#define OMAP3430_IVA2_DPLL_CLKOUT_DIV_WIDTH 5
|
||||
|
||||
/* CM_CLKSTCTRL_IVA2 */
|
||||
#define OMAP3430_CLKTRCTRL_IVA2_SHIFT 0
|
||||
|
@ -118,6 +120,7 @@
|
|||
/* CM_IDLEST_PLL_MPU */
|
||||
#define OMAP3430_ST_MPU_CLK_SHIFT 0
|
||||
#define OMAP3430_ST_MPU_CLK_MASK (1 << 0)
|
||||
#define OMAP3430_ST_MPU_CLK_WIDTH 1
|
||||
|
||||
/* CM_AUTOIDLE_PLL_MPU */
|
||||
#define OMAP3430_AUTO_MPU_DPLL_SHIFT 0
|
||||
|
@ -126,6 +129,7 @@
|
|||
/* CM_CLKSEL1_PLL_MPU */
|
||||
#define OMAP3430_MPU_CLK_SRC_SHIFT 19
|
||||
#define OMAP3430_MPU_CLK_SRC_MASK (0x7 << 19)
|
||||
#define OMAP3430_MPU_CLK_SRC_WIDTH 3
|
||||
#define OMAP3430_MPU_DPLL_MULT_SHIFT 8
|
||||
#define OMAP3430_MPU_DPLL_MULT_MASK (0x7ff << 8)
|
||||
#define OMAP3430_MPU_DPLL_DIV_SHIFT 0
|
||||
|
@ -134,6 +138,7 @@
|
|||
/* CM_CLKSEL2_PLL_MPU */
|
||||
#define OMAP3430_MPU_DPLL_CLKOUT_DIV_SHIFT 0
|
||||
#define OMAP3430_MPU_DPLL_CLKOUT_DIV_MASK (0x1f << 0)
|
||||
#define OMAP3430_MPU_DPLL_CLKOUT_DIV_WIDTH 5
|
||||
|
||||
/* CM_CLKSTCTRL_MPU */
|
||||
#define OMAP3430_CLKTRCTRL_MPU_SHIFT 0
|
||||
|
@ -345,10 +350,13 @@
|
|||
#define OMAP3430ES1_CLKSEL_FSHOSTUSB_MASK (0x3 << 4)
|
||||
#define OMAP3430_CLKSEL_L4_SHIFT 2
|
||||
#define OMAP3430_CLKSEL_L4_MASK (0x3 << 2)
|
||||
#define OMAP3430_CLKSEL_L4_WIDTH 2
|
||||
#define OMAP3430_CLKSEL_L3_SHIFT 0
|
||||
#define OMAP3430_CLKSEL_L3_MASK (0x3 << 0)
|
||||
#define OMAP3430_CLKSEL_L3_WIDTH 2
|
||||
#define OMAP3630_CLKSEL_96M_SHIFT 12
|
||||
#define OMAP3630_CLKSEL_96M_MASK (0x3 << 12)
|
||||
#define OMAP3630_CLKSEL_96M_WIDTH 2
|
||||
|
||||
/* CM_CLKSTCTRL_CORE */
|
||||
#define OMAP3430ES1_CLKTRCTRL_D2D_SHIFT 4
|
||||
|
@ -452,6 +460,7 @@
|
|||
#define OMAP3430ES2_CLKSEL_USIMOCP_MASK (0xf << 3)
|
||||
#define OMAP3430_CLKSEL_RM_SHIFT 1
|
||||
#define OMAP3430_CLKSEL_RM_MASK (0x3 << 1)
|
||||
#define OMAP3430_CLKSEL_RM_WIDTH 2
|
||||
#define OMAP3430_CLKSEL_GPT1_SHIFT 0
|
||||
#define OMAP3430_CLKSEL_GPT1_MASK (1 << 0)
|
||||
|
||||
|
@ -520,14 +529,17 @@
|
|||
/* Note that OMAP3430_CORE_DPLL_CLKOUT_DIV_MASK was (0x3 << 27) on 3430ES1 */
|
||||
#define OMAP3430_CORE_DPLL_CLKOUT_DIV_SHIFT 27
|
||||
#define OMAP3430_CORE_DPLL_CLKOUT_DIV_MASK (0x1f << 27)
|
||||
#define OMAP3430_CORE_DPLL_CLKOUT_DIV_WIDTH 5
|
||||
#define OMAP3430_CORE_DPLL_MULT_SHIFT 16
|
||||
#define OMAP3430_CORE_DPLL_MULT_MASK (0x7ff << 16)
|
||||
#define OMAP3430_CORE_DPLL_DIV_SHIFT 8
|
||||
#define OMAP3430_CORE_DPLL_DIV_MASK (0x7f << 8)
|
||||
#define OMAP3430_SOURCE_96M_SHIFT 6
|
||||
#define OMAP3430_SOURCE_96M_MASK (1 << 6)
|
||||
#define OMAP3430_SOURCE_96M_WIDTH 1
|
||||
#define OMAP3430_SOURCE_54M_SHIFT 5
|
||||
#define OMAP3430_SOURCE_54M_MASK (1 << 5)
|
||||
#define OMAP3430_SOURCE_54M_WIDTH 1
|
||||
#define OMAP3430_SOURCE_48M_SHIFT 3
|
||||
#define OMAP3430_SOURCE_48M_MASK (1 << 3)
|
||||
|
||||
|
@ -545,7 +557,9 @@
|
|||
/* CM_CLKSEL3_PLL */
|
||||
#define OMAP3430_DIV_96M_SHIFT 0
|
||||
#define OMAP3430_DIV_96M_MASK (0x1f << 0)
|
||||
#define OMAP3430_DIV_96M_WIDTH 5
|
||||
#define OMAP3630_DIV_96M_MASK (0x3f << 0)
|
||||
#define OMAP3630_DIV_96M_WIDTH 6
|
||||
|
||||
/* CM_CLKSEL4_PLL */
|
||||
#define OMAP3430ES2_PERIPH2_DPLL_MULT_SHIFT 8
|
||||
|
@ -556,12 +570,14 @@
|
|||
/* CM_CLKSEL5_PLL */
|
||||
#define OMAP3430ES2_DIV_120M_SHIFT 0
|
||||
#define OMAP3430ES2_DIV_120M_MASK (0x1f << 0)
|
||||
#define OMAP3430ES2_DIV_120M_WIDTH 5
|
||||
|
||||
/* CM_CLKOUT_CTRL */
|
||||
#define OMAP3430_CLKOUT2_EN_SHIFT 7
|
||||
#define OMAP3430_CLKOUT2_EN_MASK (1 << 7)
|
||||
#define OMAP3430_CLKOUT2_DIV_SHIFT 3
|
||||
#define OMAP3430_CLKOUT2_DIV_MASK (0x7 << 3)
|
||||
#define OMAP3430_CLKOUT2_DIV_WIDTH 3
|
||||
#define OMAP3430_CLKOUT2SOURCE_SHIFT 0
|
||||
#define OMAP3430_CLKOUT2SOURCE_MASK (0x3 << 0)
|
||||
|
||||
|
@ -592,10 +608,14 @@
|
|||
/* CM_CLKSEL_DSS */
|
||||
#define OMAP3430_CLKSEL_TV_SHIFT 8
|
||||
#define OMAP3430_CLKSEL_TV_MASK (0x1f << 8)
|
||||
#define OMAP3430_CLKSEL_TV_WIDTH 5
|
||||
#define OMAP3630_CLKSEL_TV_MASK (0x3f << 8)
|
||||
#define OMAP3630_CLKSEL_TV_WIDTH 6
|
||||
#define OMAP3430_CLKSEL_DSS1_SHIFT 0
|
||||
#define OMAP3430_CLKSEL_DSS1_MASK (0x1f << 0)
|
||||
#define OMAP3430_CLKSEL_DSS1_WIDTH 5
|
||||
#define OMAP3630_CLKSEL_DSS1_MASK (0x3f << 0)
|
||||
#define OMAP3630_CLKSEL_DSS1_WIDTH 6
|
||||
|
||||
/* CM_SLEEPDEP_DSS specific bits */
|
||||
|
||||
|
@ -623,7 +643,9 @@
|
|||
/* CM_CLKSEL_CAM */
|
||||
#define OMAP3430_CLKSEL_CAM_SHIFT 0
|
||||
#define OMAP3430_CLKSEL_CAM_MASK (0x1f << 0)
|
||||
#define OMAP3430_CLKSEL_CAM_WIDTH 5
|
||||
#define OMAP3630_CLKSEL_CAM_MASK (0x3f << 0)
|
||||
#define OMAP3630_CLKSEL_CAM_WIDTH 6
|
||||
|
||||
/* CM_SLEEPDEP_CAM specific bits */
|
||||
|
||||
|
@ -721,21 +743,30 @@
|
|||
/* CM_CLKSEL1_EMU */
|
||||
#define OMAP3430_DIV_DPLL4_SHIFT 24
|
||||
#define OMAP3430_DIV_DPLL4_MASK (0x1f << 24)
|
||||
#define OMAP3430_DIV_DPLL4_WIDTH 5
|
||||
#define OMAP3630_DIV_DPLL4_MASK (0x3f << 24)
|
||||
#define OMAP3630_DIV_DPLL4_WIDTH 6
|
||||
#define OMAP3430_DIV_DPLL3_SHIFT 16
|
||||
#define OMAP3430_DIV_DPLL3_MASK (0x1f << 16)
|
||||
#define OMAP3430_DIV_DPLL3_WIDTH 5
|
||||
#define OMAP3430_CLKSEL_TRACECLK_SHIFT 11
|
||||
#define OMAP3430_CLKSEL_TRACECLK_MASK (0x7 << 11)
|
||||
#define OMAP3430_CLKSEL_TRACECLK_WIDTH 3
|
||||
#define OMAP3430_CLKSEL_PCLK_SHIFT 8
|
||||
#define OMAP3430_CLKSEL_PCLK_MASK (0x7 << 8)
|
||||
#define OMAP3430_CLKSEL_PCLK_WIDTH 3
|
||||
#define OMAP3430_CLKSEL_PCLKX2_SHIFT 6
|
||||
#define OMAP3430_CLKSEL_PCLKX2_MASK (0x3 << 6)
|
||||
#define OMAP3430_CLKSEL_PCLKX2_WIDTH 2
|
||||
#define OMAP3430_CLKSEL_ATCLK_SHIFT 4
|
||||
#define OMAP3430_CLKSEL_ATCLK_MASK (0x3 << 4)
|
||||
#define OMAP3430_CLKSEL_ATCLK_WIDTH 2
|
||||
#define OMAP3430_TRACE_MUX_CTRL_SHIFT 2
|
||||
#define OMAP3430_TRACE_MUX_CTRL_MASK (0x3 << 2)
|
||||
#define OMAP3430_TRACE_MUX_CTRL_WIDTH 2
|
||||
#define OMAP3430_MUX_CTRL_SHIFT 0
|
||||
#define OMAP3430_MUX_CTRL_MASK (0x3 << 0)
|
||||
#define OMAP3430_MUX_CTRL_WIDTH 2
|
||||
|
||||
/* CM_CLKSTCTRL_EMU */
|
||||
#define OMAP3430_CLKTRCTRL_EMU_SHIFT 0
|
||||
|
|
|
@ -108,6 +108,7 @@ extern void omap2xxx_cm_apll96_disable(void);
|
|||
/* CM_CLKSEL_GFX */
|
||||
#define OMAP_CLKSEL_GFX_SHIFT 0
|
||||
#define OMAP_CLKSEL_GFX_MASK (0x7 << 0)
|
||||
#define OMAP_CLKSEL_GFX_WIDTH 3
|
||||
|
||||
/* CM_ICLKEN_GFX */
|
||||
#define OMAP_EN_GFX_SHIFT 0
|
||||
|
|
|
@ -201,6 +201,7 @@
|
|||
#define OMAP44XX_CONTROL_FUSE_MPU_OPPNITRO 0x249
|
||||
#define OMAP44XX_CONTROL_FUSE_CORE_OPP50 0x254
|
||||
#define OMAP44XX_CONTROL_FUSE_CORE_OPP100 0x257
|
||||
#define OMAP44XX_CONTROL_FUSE_CORE_OPP100OV 0x25A
|
||||
|
||||
/* AM35XX only CONTROL_GENERAL register offsets */
|
||||
#define AM35XX_CONTROL_MSUSPENDMUX_6 (OMAP2_CONTROL_GENERAL + 0x0038)
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include <asm/mach-types.h>
|
||||
#include <asm/mach/map.h>
|
||||
|
||||
#include <plat-omap/dma-omap.h>
|
||||
#include <linux/omap-dma.h>
|
||||
|
||||
#include "iomap.h"
|
||||
#include "omap_hwmod.h"
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
#include <plat-omap/dma-omap.h>
|
||||
#include <linux/omap-dma.h>
|
||||
|
||||
#include "soc.h"
|
||||
#include "omap_hwmod.h"
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <linux/clkdev.h>
|
||||
|
||||
#include "soc.h"
|
||||
#include "clockdomain.h"
|
||||
#include "clock.h"
|
||||
#include "cm2xxx_3xxx.h"
|
||||
#include "cm-regbits-34xx.h"
|
||||
|
@ -42,7 +43,7 @@
|
|||
/* Private functions */
|
||||
|
||||
/* _omap3_dpll_write_clken - write clken_bits arg to a DPLL's enable bits */
|
||||
static void _omap3_dpll_write_clken(struct clk *clk, u8 clken_bits)
|
||||
static void _omap3_dpll_write_clken(struct clk_hw_omap *clk, u8 clken_bits)
|
||||
{
|
||||
const struct dpll_data *dd;
|
||||
u32 v;
|
||||
|
@ -56,7 +57,7 @@ static void _omap3_dpll_write_clken(struct clk *clk, u8 clken_bits)
|
|||
}
|
||||
|
||||
/* _omap3_wait_dpll_status: wait for a DPLL to enter a specific state */
|
||||
static int _omap3_wait_dpll_status(struct clk *clk, u8 state)
|
||||
static int _omap3_wait_dpll_status(struct clk_hw_omap *clk, u8 state)
|
||||
{
|
||||
const struct dpll_data *dd;
|
||||
int i = 0;
|
||||
|
@ -64,7 +65,7 @@ static int _omap3_wait_dpll_status(struct clk *clk, u8 state)
|
|||
const char *clk_name;
|
||||
|
||||
dd = clk->dpll_data;
|
||||
clk_name = __clk_get_name(clk);
|
||||
clk_name = __clk_get_name(clk->hw.clk);
|
||||
|
||||
state <<= __ffs(dd->idlest_mask);
|
||||
|
||||
|
@ -88,7 +89,7 @@ static int _omap3_wait_dpll_status(struct clk *clk, u8 state)
|
|||
}
|
||||
|
||||
/* From 3430 TRM ES2 4.7.6.2 */
|
||||
static u16 _omap3_dpll_compute_freqsel(struct clk *clk, u8 n)
|
||||
static u16 _omap3_dpll_compute_freqsel(struct clk_hw_omap *clk, u8 n)
|
||||
{
|
||||
unsigned long fint;
|
||||
u16 f = 0;
|
||||
|
@ -133,14 +134,14 @@ static u16 _omap3_dpll_compute_freqsel(struct clk *clk, u8 n)
|
|||
* locked successfully, return 0; if the DPLL did not lock in the time
|
||||
* allotted, or DPLL3 was passed in, return -EINVAL.
|
||||
*/
|
||||
static int _omap3_noncore_dpll_lock(struct clk *clk)
|
||||
static int _omap3_noncore_dpll_lock(struct clk_hw_omap *clk)
|
||||
{
|
||||
const struct dpll_data *dd;
|
||||
u8 ai;
|
||||
u8 state = 1;
|
||||
int r = 0;
|
||||
|
||||
pr_debug("clock: locking DPLL %s\n", __clk_get_name(clk));
|
||||
pr_debug("clock: locking DPLL %s\n", __clk_get_name(clk->hw.clk));
|
||||
|
||||
dd = clk->dpll_data;
|
||||
state <<= __ffs(dd->idlest_mask);
|
||||
|
@ -178,7 +179,7 @@ done:
|
|||
* DPLL3 was passed in, or the DPLL does not support low-power bypass,
|
||||
* return -EINVAL.
|
||||
*/
|
||||
static int _omap3_noncore_dpll_bypass(struct clk *clk)
|
||||
static int _omap3_noncore_dpll_bypass(struct clk_hw_omap *clk)
|
||||
{
|
||||
int r;
|
||||
u8 ai;
|
||||
|
@ -187,7 +188,7 @@ static int _omap3_noncore_dpll_bypass(struct clk *clk)
|
|||
return -EINVAL;
|
||||
|
||||
pr_debug("clock: configuring DPLL %s for low-power bypass\n",
|
||||
__clk_get_name(clk));
|
||||
__clk_get_name(clk->hw.clk));
|
||||
|
||||
ai = omap3_dpll_autoidle_read(clk);
|
||||
|
||||
|
@ -210,14 +211,14 @@ static int _omap3_noncore_dpll_bypass(struct clk *clk)
|
|||
* code. If DPLL3 was passed in, or the DPLL does not support
|
||||
* low-power stop, return -EINVAL; otherwise, return 0.
|
||||
*/
|
||||
static int _omap3_noncore_dpll_stop(struct clk *clk)
|
||||
static int _omap3_noncore_dpll_stop(struct clk_hw_omap *clk)
|
||||
{
|
||||
u8 ai;
|
||||
|
||||
if (!(clk->dpll_data->modes & (1 << DPLL_LOW_POWER_STOP)))
|
||||
return -EINVAL;
|
||||
|
||||
pr_debug("clock: stopping DPLL %s\n", __clk_get_name(clk));
|
||||
pr_debug("clock: stopping DPLL %s\n", __clk_get_name(clk->hw.clk));
|
||||
|
||||
ai = omap3_dpll_autoidle_read(clk);
|
||||
|
||||
|
@ -241,11 +242,11 @@ static int _omap3_noncore_dpll_stop(struct clk *clk)
|
|||
* XXX This code is not needed for 3430/AM35xx; can it be optimized
|
||||
* out in non-multi-OMAP builds for those chips?
|
||||
*/
|
||||
static void _lookup_dco(struct clk *clk, u8 *dco, u16 m, u8 n)
|
||||
static void _lookup_dco(struct clk_hw_omap *clk, u8 *dco, u16 m, u8 n)
|
||||
{
|
||||
unsigned long fint, clkinp; /* watch out for overflow */
|
||||
|
||||
clkinp = __clk_get_rate(__clk_get_parent(clk));
|
||||
clkinp = __clk_get_rate(__clk_get_parent(clk->hw.clk));
|
||||
fint = (clkinp / n) * m;
|
||||
|
||||
if (fint < 1000000000)
|
||||
|
@ -266,12 +267,12 @@ static void _lookup_dco(struct clk *clk, u8 *dco, u16 m, u8 n)
|
|||
* XXX This code is not needed for 3430/AM35xx; can it be optimized
|
||||
* out in non-multi-OMAP builds for those chips?
|
||||
*/
|
||||
static void _lookup_sddiv(struct clk *clk, u8 *sd_div, u16 m, u8 n)
|
||||
static void _lookup_sddiv(struct clk_hw_omap *clk, u8 *sd_div, u16 m, u8 n)
|
||||
{
|
||||
unsigned long clkinp, sd; /* watch out for overflow */
|
||||
int mod1, mod2;
|
||||
|
||||
clkinp = __clk_get_rate(__clk_get_parent(clk));
|
||||
clkinp = __clk_get_rate(__clk_get_parent(clk->hw.clk));
|
||||
|
||||
/*
|
||||
* target sigma-delta to near 250MHz
|
||||
|
@ -298,7 +299,8 @@ static void _lookup_sddiv(struct clk *clk, u8 *sd_div, u16 m, u8 n)
|
|||
* Program the DPLL with the supplied M, N values, and wait for the DPLL to
|
||||
* lock.. Returns -EINVAL upon error, or 0 upon success.
|
||||
*/
|
||||
static int omap3_noncore_dpll_program(struct clk *clk, u16 m, u8 n, u16 freqsel)
|
||||
static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 m, u8 n,
|
||||
u16 freqsel)
|
||||
{
|
||||
struct dpll_data *dd = clk->dpll_data;
|
||||
u8 dco, sd_div;
|
||||
|
@ -355,8 +357,10 @@ static int omap3_noncore_dpll_program(struct clk *clk, u16 m, u8 n, u16 freqsel)
|
|||
*
|
||||
* Recalculate and propagate the DPLL rate.
|
||||
*/
|
||||
unsigned long omap3_dpll_recalc(struct clk *clk)
|
||||
unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate)
|
||||
{
|
||||
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
|
||||
|
||||
return omap2_get_dpll_rate(clk);
|
||||
}
|
||||
|
||||
|
@ -376,8 +380,9 @@ unsigned long omap3_dpll_recalc(struct clk *clk)
|
|||
* support low-power stop, or if the DPLL took too long to enter
|
||||
* bypass or lock, return -EINVAL; otherwise, return 0.
|
||||
*/
|
||||
int omap3_noncore_dpll_enable(struct clk *clk)
|
||||
int omap3_noncore_dpll_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
|
||||
int r;
|
||||
struct dpll_data *dd;
|
||||
struct clk *parent;
|
||||
|
@ -386,22 +391,26 @@ int omap3_noncore_dpll_enable(struct clk *clk)
|
|||
if (!dd)
|
||||
return -EINVAL;
|
||||
|
||||
parent = __clk_get_parent(clk);
|
||||
if (clk->clkdm) {
|
||||
r = clkdm_clk_enable(clk->clkdm, hw->clk);
|
||||
if (r) {
|
||||
WARN(1,
|
||||
"%s: could not enable %s's clockdomain %s: %d\n",
|
||||
__func__, __clk_get_name(hw->clk),
|
||||
clk->clkdm->name, r);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
if (__clk_get_rate(clk) == __clk_get_rate(dd->clk_bypass)) {
|
||||
parent = __clk_get_parent(hw->clk);
|
||||
|
||||
if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
|
||||
WARN_ON(parent != dd->clk_bypass);
|
||||
r = _omap3_noncore_dpll_bypass(clk);
|
||||
} else {
|
||||
WARN_ON(parent != dd->clk_ref);
|
||||
r = _omap3_noncore_dpll_lock(clk);
|
||||
}
|
||||
/*
|
||||
*FIXME: this is dubious - if clk->rate has changed, what about
|
||||
* propagating?
|
||||
*/
|
||||
if (!r)
|
||||
clk->rate = (clk->recalc) ? clk->recalc(clk) :
|
||||
omap2_get_dpll_rate(clk);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -413,9 +422,13 @@ int omap3_noncore_dpll_enable(struct clk *clk)
|
|||
* Instructs a non-CORE DPLL to enter low-power stop. This function is
|
||||
* intended for use in struct clkops. No return value.
|
||||
*/
|
||||
void omap3_noncore_dpll_disable(struct clk *clk)
|
||||
void omap3_noncore_dpll_disable(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
|
||||
|
||||
_omap3_noncore_dpll_stop(clk);
|
||||
if (clk->clkdm)
|
||||
clkdm_clk_disable(clk->clkdm, hw->clk);
|
||||
}
|
||||
|
||||
|
||||
|
@ -432,80 +445,72 @@ void omap3_noncore_dpll_disable(struct clk *clk)
|
|||
* target rate if it hasn't been done already, then program and lock
|
||||
* the DPLL. Returns -EINVAL upon error, or 0 upon success.
|
||||
*/
|
||||
int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
|
||||
int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
|
||||
struct clk *new_parent = NULL;
|
||||
unsigned long hw_rate, bypass_rate;
|
||||
u16 freqsel = 0;
|
||||
struct dpll_data *dd;
|
||||
int ret;
|
||||
|
||||
if (!clk || !rate)
|
||||
if (!hw || !rate)
|
||||
return -EINVAL;
|
||||
|
||||
dd = clk->dpll_data;
|
||||
if (!dd)
|
||||
return -EINVAL;
|
||||
|
||||
hw_rate = (clk->recalc) ? clk->recalc(clk) : omap2_get_dpll_rate(clk);
|
||||
if (rate == hw_rate)
|
||||
return 0;
|
||||
__clk_prepare(dd->clk_bypass);
|
||||
clk_enable(dd->clk_bypass);
|
||||
__clk_prepare(dd->clk_ref);
|
||||
clk_enable(dd->clk_ref);
|
||||
|
||||
/*
|
||||
* Ensure both the bypass and ref clocks are enabled prior to
|
||||
* doing anything; we need the bypass clock running to reprogram
|
||||
* the DPLL.
|
||||
*/
|
||||
omap2_clk_enable(dd->clk_bypass);
|
||||
omap2_clk_enable(dd->clk_ref);
|
||||
|
||||
bypass_rate = __clk_get_rate(dd->clk_bypass);
|
||||
if (bypass_rate == rate &&
|
||||
(clk->dpll_data->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
|
||||
pr_debug("clock: %s: set rate: entering bypass.\n", clk->name);
|
||||
if (__clk_get_rate(dd->clk_bypass) == rate &&
|
||||
(dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
|
||||
pr_debug("%s: %s: set rate: entering bypass.\n",
|
||||
__func__, __clk_get_name(hw->clk));
|
||||
|
||||
ret = _omap3_noncore_dpll_bypass(clk);
|
||||
if (!ret)
|
||||
new_parent = dd->clk_bypass;
|
||||
} else {
|
||||
if (dd->last_rounded_rate != rate)
|
||||
rate = clk->round_rate(clk, rate);
|
||||
rate = __clk_round_rate(hw->clk, rate);
|
||||
|
||||
if (dd->last_rounded_rate == 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* No freqsel on OMAP4 and OMAP3630 */
|
||||
if (!soc_is_am33xx() && !cpu_is_omap44xx() && !cpu_is_omap3630()) {
|
||||
if (!cpu_is_omap44xx() && !cpu_is_omap3630()) {
|
||||
freqsel = _omap3_dpll_compute_freqsel(clk,
|
||||
dd->last_rounded_n);
|
||||
if (!freqsel)
|
||||
WARN_ON(1);
|
||||
}
|
||||
|
||||
pr_debug("clock: %s: set rate: locking rate to %lu.\n",
|
||||
__clk_get_name(clk), rate);
|
||||
pr_debug("%s: %s: set rate: locking rate to %lu.\n",
|
||||
__func__, __clk_get_name(hw->clk), rate);
|
||||
|
||||
ret = omap3_noncore_dpll_program(clk, dd->last_rounded_m,
|
||||
dd->last_rounded_n, freqsel);
|
||||
dd->last_rounded_n, freqsel);
|
||||
if (!ret)
|
||||
new_parent = dd->clk_ref;
|
||||
}
|
||||
if (!ret) {
|
||||
/*
|
||||
* Switch the parent clock in the hierarchy, and make sure
|
||||
* that the new parent's usecount is correct. Note: we
|
||||
* enable the new parent before disabling the old to avoid
|
||||
* any unnecessary hardware disable->enable transitions.
|
||||
*/
|
||||
if (clk->usecount) {
|
||||
omap2_clk_enable(new_parent);
|
||||
omap2_clk_disable(clk->parent);
|
||||
}
|
||||
clk_reparent(clk, new_parent);
|
||||
clk->rate = rate;
|
||||
}
|
||||
omap2_clk_disable(dd->clk_ref);
|
||||
omap2_clk_disable(dd->clk_bypass);
|
||||
/*
|
||||
* FIXME - this is all wrong. common code handles reparenting and
|
||||
* migrating prepare/enable counts. dplls should be a multiplexer
|
||||
* clock and this should be a set_parent operation so that all of that
|
||||
* stuff is inherited for free
|
||||
*/
|
||||
|
||||
if (!ret)
|
||||
__clk_reparent(hw->clk, new_parent);
|
||||
|
||||
clk_disable(dd->clk_ref);
|
||||
__clk_unprepare(dd->clk_ref);
|
||||
clk_disable(dd->clk_bypass);
|
||||
__clk_unprepare(dd->clk_bypass);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -520,7 +525,7 @@ int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
|
|||
* -EINVAL if passed a null pointer or if the struct clk does not
|
||||
* appear to refer to a DPLL.
|
||||
*/
|
||||
u32 omap3_dpll_autoidle_read(struct clk *clk)
|
||||
u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk)
|
||||
{
|
||||
const struct dpll_data *dd;
|
||||
u32 v;
|
||||
|
@ -549,7 +554,7 @@ u32 omap3_dpll_autoidle_read(struct clk *clk)
|
|||
* OMAP3430. The DPLL will enter low-power stop when its downstream
|
||||
* clocks are gated. No return value.
|
||||
*/
|
||||
void omap3_dpll_allow_idle(struct clk *clk)
|
||||
void omap3_dpll_allow_idle(struct clk_hw_omap *clk)
|
||||
{
|
||||
const struct dpll_data *dd;
|
||||
u32 v;
|
||||
|
@ -559,11 +564,8 @@ void omap3_dpll_allow_idle(struct clk *clk)
|
|||
|
||||
dd = clk->dpll_data;
|
||||
|
||||
if (!dd->autoidle_reg) {
|
||||
pr_debug("clock: DPLL %s: autoidle not supported\n",
|
||||
__clk_get_name(clk));
|
||||
if (!dd->autoidle_reg)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* REVISIT: CORE DPLL can optionally enter low-power bypass
|
||||
|
@ -583,7 +585,7 @@ void omap3_dpll_allow_idle(struct clk *clk)
|
|||
*
|
||||
* Disable DPLL automatic idle control. No return value.
|
||||
*/
|
||||
void omap3_dpll_deny_idle(struct clk *clk)
|
||||
void omap3_dpll_deny_idle(struct clk_hw_omap *clk)
|
||||
{
|
||||
const struct dpll_data *dd;
|
||||
u32 v;
|
||||
|
@ -593,11 +595,8 @@ void omap3_dpll_deny_idle(struct clk *clk)
|
|||
|
||||
dd = clk->dpll_data;
|
||||
|
||||
if (!dd->autoidle_reg) {
|
||||
pr_debug("clock: DPLL %s: autoidle not supported\n",
|
||||
__clk_get_name(clk));
|
||||
if (!dd->autoidle_reg)
|
||||
return;
|
||||
}
|
||||
|
||||
v = __raw_readl(dd->autoidle_reg);
|
||||
v &= ~dd->autoidle_mask;
|
||||
|
@ -615,18 +614,25 @@ void omap3_dpll_deny_idle(struct clk *clk)
|
|||
* Using parent clock DPLL data, look up DPLL state. If locked, set our
|
||||
* rate to the dpll_clk * 2; otherwise, just use dpll_clk.
|
||||
*/
|
||||
unsigned long omap3_clkoutx2_recalc(struct clk *clk)
|
||||
unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
const struct dpll_data *dd;
|
||||
unsigned long rate;
|
||||
u32 v;
|
||||
struct clk *pclk;
|
||||
unsigned long parent_rate;
|
||||
struct clk_hw_omap *pclk = NULL;
|
||||
struct clk *parent;
|
||||
|
||||
/* Walk up the parents of clk, looking for a DPLL */
|
||||
pclk = __clk_get_parent(clk);
|
||||
while (pclk && !pclk->dpll_data)
|
||||
pclk = __clk_get_parent(pclk);
|
||||
do {
|
||||
do {
|
||||
parent = __clk_get_parent(hw->clk);
|
||||
hw = __clk_get_hw(parent);
|
||||
} while (hw && (__clk_get_flags(hw->clk) & CLK_IS_BASIC));
|
||||
if (!hw)
|
||||
break;
|
||||
pclk = to_clk_hw_omap(hw);
|
||||
} while (pclk && !pclk->dpll_data);
|
||||
|
||||
/* clk does not have a DPLL as a parent? error in the clock data */
|
||||
if (!pclk) {
|
||||
|
@ -638,7 +644,6 @@ unsigned long omap3_clkoutx2_recalc(struct clk *clk)
|
|||
|
||||
WARN_ON(!dd->enable_mask);
|
||||
|
||||
parent_rate = __clk_get_rate(__clk_get_parent(clk));
|
||||
v = __raw_readl(dd->control_reg) & dd->enable_mask;
|
||||
v >>= __ffs(dd->enable_mask);
|
||||
if ((v != OMAP3XXX_EN_DPLL_LOCKED) || (dd->flags & DPLL_J_TYPE))
|
||||
|
@ -649,15 +654,7 @@ unsigned long omap3_clkoutx2_recalc(struct clk *clk)
|
|||
}
|
||||
|
||||
/* OMAP3/4 non-CORE DPLL clkops */
|
||||
|
||||
const struct clkops clkops_omap3_noncore_dpll_ops = {
|
||||
.enable = omap3_noncore_dpll_enable,
|
||||
.disable = omap3_noncore_dpll_disable,
|
||||
.allow_idle = omap3_dpll_allow_idle,
|
||||
.deny_idle = omap3_dpll_deny_idle,
|
||||
};
|
||||
|
||||
const struct clkops clkops_omap3_core_dpll_ops = {
|
||||
const struct clk_hw_omap_ops clkhwops_omap3_dpll = {
|
||||
.allow_idle = omap3_dpll_allow_idle,
|
||||
.deny_idle = omap3_dpll_deny_idle,
|
||||
};
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include "cm-regbits-44xx.h"
|
||||
|
||||
/* Supported only on OMAP4 */
|
||||
int omap4_dpllmx_gatectrl_read(struct clk *clk)
|
||||
int omap4_dpllmx_gatectrl_read(struct clk_hw_omap *clk)
|
||||
{
|
||||
u32 v;
|
||||
u32 mask;
|
||||
|
@ -40,7 +40,7 @@ int omap4_dpllmx_gatectrl_read(struct clk *clk)
|
|||
return v;
|
||||
}
|
||||
|
||||
void omap4_dpllmx_allow_gatectrl(struct clk *clk)
|
||||
void omap4_dpllmx_allow_gatectrl(struct clk_hw_omap *clk)
|
||||
{
|
||||
u32 v;
|
||||
u32 mask;
|
||||
|
@ -58,7 +58,7 @@ void omap4_dpllmx_allow_gatectrl(struct clk *clk)
|
|||
__raw_writel(v, clk->clksel_reg);
|
||||
}
|
||||
|
||||
void omap4_dpllmx_deny_gatectrl(struct clk *clk)
|
||||
void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk)
|
||||
{
|
||||
u32 v;
|
||||
u32 mask;
|
||||
|
@ -76,9 +76,9 @@ void omap4_dpllmx_deny_gatectrl(struct clk *clk)
|
|||
__raw_writel(v, clk->clksel_reg);
|
||||
}
|
||||
|
||||
const struct clkops clkops_omap4_dpllmx_ops = {
|
||||
const struct clk_hw_omap_ops clkhwops_omap4_dpllmx = {
|
||||
.allow_idle = omap4_dpllmx_allow_gatectrl,
|
||||
.deny_idle = omap4_dpllmx_deny_gatectrl,
|
||||
.deny_idle = omap4_dpllmx_deny_gatectrl,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -90,8 +90,10 @@ const struct clkops clkops_omap4_dpllmx_ops = {
|
|||
* OMAP4 ABE DPLL. Returns the DPLL's output rate (before M-dividers)
|
||||
* upon success, or 0 upon error.
|
||||
*/
|
||||
unsigned long omap4_dpll_regm4xen_recalc(struct clk *clk)
|
||||
unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
|
||||
u32 v;
|
||||
unsigned long rate;
|
||||
struct dpll_data *dd;
|
||||
|
@ -123,8 +125,11 @@ unsigned long omap4_dpll_regm4xen_recalc(struct clk *clk)
|
|||
* M-dividers) upon success, -EINVAL if @clk is null or not a DPLL, or
|
||||
* ~0 if an error occurred in omap2_dpll_round_rate().
|
||||
*/
|
||||
long omap4_dpll_regm4xen_round_rate(struct clk *clk, unsigned long target_rate)
|
||||
long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
|
||||
unsigned long target_rate,
|
||||
unsigned long *parent_rate)
|
||||
{
|
||||
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
|
||||
u32 v;
|
||||
struct dpll_data *dd;
|
||||
long r;
|
||||
|
@ -140,7 +145,7 @@ long omap4_dpll_regm4xen_round_rate(struct clk *clk, unsigned long target_rate)
|
|||
if (v)
|
||||
target_rate = target_rate / OMAP4430_REGM4XEN_MULT;
|
||||
|
||||
r = omap2_dpll_round_rate(clk, target_rate);
|
||||
r = omap2_dpll_round_rate(hw, target_rate, NULL);
|
||||
if (r == ~0)
|
||||
return r;
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include <asm/tlb.h>
|
||||
#include <asm/mach/map.h>
|
||||
|
||||
#include <plat-omap/dma-omap.h>
|
||||
#include <linux/omap-dma.h>
|
||||
|
||||
#include "omap_hwmod.h"
|
||||
#include "soc.h"
|
||||
|
@ -50,6 +50,9 @@
|
|||
#include "prcm_mpu44xx.h"
|
||||
#include "prminst44xx.h"
|
||||
#include "cminst44xx.h"
|
||||
#include "prm2xxx.h"
|
||||
#include "prm3xxx.h"
|
||||
#include "prm44xx.h"
|
||||
|
||||
/*
|
||||
* The machine specific code may provide the extra mapping besides the
|
||||
|
@ -387,6 +390,7 @@ void __init omap2420_init_early(void)
|
|||
omap2_set_globals_prm(OMAP2_L4_IO_ADDRESS(OMAP2420_PRM_BASE));
|
||||
omap2_set_globals_cm(OMAP2_L4_IO_ADDRESS(OMAP2420_CM_BASE), NULL);
|
||||
omap2xxx_check_revision();
|
||||
omap2xxx_prm_init();
|
||||
omap2xxx_cm_init();
|
||||
omap2xxx_voltagedomains_init();
|
||||
omap242x_powerdomains_init();
|
||||
|
@ -401,6 +405,7 @@ void __init omap2420_init_late(void)
|
|||
omap_mux_late_init();
|
||||
omap2_common_pm_late_init();
|
||||
omap2_pm_init();
|
||||
omap2_clk_enable_autoidle_all();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -415,6 +420,7 @@ void __init omap2430_init_early(void)
|
|||
omap2_set_globals_prm(OMAP2_L4_IO_ADDRESS(OMAP2430_PRM_BASE));
|
||||
omap2_set_globals_cm(OMAP2_L4_IO_ADDRESS(OMAP2430_CM_BASE), NULL);
|
||||
omap2xxx_check_revision();
|
||||
omap2xxx_prm_init();
|
||||
omap2xxx_cm_init();
|
||||
omap2xxx_voltagedomains_init();
|
||||
omap243x_powerdomains_init();
|
||||
|
@ -429,6 +435,7 @@ void __init omap2430_init_late(void)
|
|||
omap_mux_late_init();
|
||||
omap2_common_pm_late_init();
|
||||
omap2_pm_init();
|
||||
omap2_clk_enable_autoidle_all();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -448,6 +455,7 @@ void __init omap3_init_early(void)
|
|||
omap2_set_globals_cm(OMAP2_L4_IO_ADDRESS(OMAP3430_CM_BASE), NULL);
|
||||
omap3xxx_check_revision();
|
||||
omap3xxx_check_features();
|
||||
omap3xxx_prm_init();
|
||||
omap3xxx_cm_init();
|
||||
omap3xxx_voltagedomains_init();
|
||||
omap3xxx_powerdomains_init();
|
||||
|
@ -500,6 +508,7 @@ void __init omap3_init_late(void)
|
|||
omap_mux_late_init();
|
||||
omap2_common_pm_late_init();
|
||||
omap3_pm_init();
|
||||
omap2_clk_enable_autoidle_all();
|
||||
}
|
||||
|
||||
void __init omap3430_init_late(void)
|
||||
|
@ -507,6 +516,7 @@ void __init omap3430_init_late(void)
|
|||
omap_mux_late_init();
|
||||
omap2_common_pm_late_init();
|
||||
omap3_pm_init();
|
||||
omap2_clk_enable_autoidle_all();
|
||||
}
|
||||
|
||||
void __init omap35xx_init_late(void)
|
||||
|
@ -514,6 +524,7 @@ void __init omap35xx_init_late(void)
|
|||
omap_mux_late_init();
|
||||
omap2_common_pm_late_init();
|
||||
omap3_pm_init();
|
||||
omap2_clk_enable_autoidle_all();
|
||||
}
|
||||
|
||||
void __init omap3630_init_late(void)
|
||||
|
@ -521,6 +532,7 @@ void __init omap3630_init_late(void)
|
|||
omap_mux_late_init();
|
||||
omap2_common_pm_late_init();
|
||||
omap3_pm_init();
|
||||
omap2_clk_enable_autoidle_all();
|
||||
}
|
||||
|
||||
void __init am35xx_init_late(void)
|
||||
|
@ -528,6 +540,7 @@ void __init am35xx_init_late(void)
|
|||
omap_mux_late_init();
|
||||
omap2_common_pm_late_init();
|
||||
omap3_pm_init();
|
||||
omap2_clk_enable_autoidle_all();
|
||||
}
|
||||
|
||||
void __init ti81xx_init_late(void)
|
||||
|
@ -535,6 +548,7 @@ void __init ti81xx_init_late(void)
|
|||
omap_mux_late_init();
|
||||
omap2_common_pm_late_init();
|
||||
omap3_pm_init();
|
||||
omap2_clk_enable_autoidle_all();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -573,6 +587,7 @@ void __init omap4430_init_early(void)
|
|||
omap_cm_base_init();
|
||||
omap4xxx_check_revision();
|
||||
omap4xxx_check_features();
|
||||
omap44xx_prm_init();
|
||||
omap44xx_voltagedomains_init();
|
||||
omap44xx_powerdomains_init();
|
||||
omap44xx_clockdomains_init();
|
||||
|
@ -586,6 +601,7 @@ void __init omap4430_init_late(void)
|
|||
omap_mux_late_init();
|
||||
omap2_common_pm_late_init();
|
||||
omap4_pm_init();
|
||||
omap2_clk_enable_autoidle_all();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include <linux/platform_data/asoc-ti-mcbsp.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include <plat-omap/dma-omap.h>
|
||||
#include <linux/omap-dma.h>
|
||||
|
||||
#include "omap_device.h"
|
||||
|
||||
|
|
|
@ -441,19 +441,21 @@ int omap_device_get_context_loss_count(struct platform_device *pdev)
|
|||
/**
|
||||
* omap_device_count_resources - count number of struct resource entries needed
|
||||
* @od: struct omap_device *
|
||||
* @flags: Type of resources to include when counting (IRQ/DMA/MEM)
|
||||
*
|
||||
* Count the number of struct resource entries needed for this
|
||||
* omap_device @od. Used by omap_device_build_ss() to determine how
|
||||
* much memory to allocate before calling
|
||||
* omap_device_fill_resources(). Returns the count.
|
||||
*/
|
||||
static int omap_device_count_resources(struct omap_device *od)
|
||||
static int omap_device_count_resources(struct omap_device *od,
|
||||
unsigned long flags)
|
||||
{
|
||||
int c = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < od->hwmods_cnt; i++)
|
||||
c += omap_hwmod_count_resources(od->hwmods[i]);
|
||||
c += omap_hwmod_count_resources(od->hwmods[i], flags);
|
||||
|
||||
pr_debug("omap_device: %s: counted %d total resources across %d hwmods\n",
|
||||
od->pdev->name, c, od->hwmods_cnt);
|
||||
|
@ -557,52 +559,73 @@ struct omap_device *omap_device_alloc(struct platform_device *pdev,
|
|||
od->hwmods = hwmods;
|
||||
od->pdev = pdev;
|
||||
|
||||
res_count = omap_device_count_resources(od);
|
||||
/*
|
||||
* Non-DT Boot:
|
||||
* Here, pdev->num_resources = 0, and we should get all the
|
||||
* resources from hwmod.
|
||||
*
|
||||
* DT Boot:
|
||||
* OF framework will construct the resource structure (currently
|
||||
* does for MEM & IRQ resource) and we should respect/use these
|
||||
* resources, killing hwmod dependency.
|
||||
* If pdev->num_resources > 0, we assume that MEM & IRQ resources
|
||||
* have been allocated by OF layer already (through DTB).
|
||||
*
|
||||
* Non-DT Boot:
|
||||
* Here, pdev->num_resources = 0, and we should get all the
|
||||
* resources from hwmod.
|
||||
* As preparation for the future we examine the OF provided resources
|
||||
* to see if we have DMA resources provided already. In this case
|
||||
* there is no need to update the resources for the device, we use the
|
||||
* OF provided ones.
|
||||
*
|
||||
* TODO: Once DMA resource is available from OF layer, we should
|
||||
* kill filling any resources from hwmod.
|
||||
*/
|
||||
if (res_count > pdev->num_resources) {
|
||||
/* Allocate resources memory to account for new resources */
|
||||
res = kzalloc(sizeof(struct resource) * res_count, GFP_KERNEL);
|
||||
if (!res)
|
||||
goto oda_exit3;
|
||||
if (!pdev->num_resources) {
|
||||
/* Count all resources for the device */
|
||||
res_count = omap_device_count_resources(od, IORESOURCE_IRQ |
|
||||
IORESOURCE_DMA |
|
||||
IORESOURCE_MEM);
|
||||
} else {
|
||||
/* Take a look if we already have DMA resource via DT */
|
||||
for (i = 0; i < pdev->num_resources; i++) {
|
||||
struct resource *r = &pdev->resource[i];
|
||||
|
||||
/*
|
||||
* If pdev->num_resources > 0, then assume that,
|
||||
* MEM and IRQ resources will only come from DT and only
|
||||
* fill DMA resource from hwmod layer.
|
||||
*/
|
||||
if (pdev->num_resources && pdev->resource) {
|
||||
dev_dbg(&pdev->dev, "%s(): resources already allocated %d\n",
|
||||
__func__, res_count);
|
||||
memcpy(res, pdev->resource,
|
||||
sizeof(struct resource) * pdev->num_resources);
|
||||
_od_fill_dma_resources(od, &res[pdev->num_resources]);
|
||||
} else {
|
||||
dev_dbg(&pdev->dev, "%s(): using resources from hwmod %d\n",
|
||||
__func__, res_count);
|
||||
omap_device_fill_resources(od, res);
|
||||
/* We have it, no need to touch the resources */
|
||||
if (r->flags == IORESOURCE_DMA)
|
||||
goto have_everything;
|
||||
}
|
||||
/* Count only DMA resources for the device */
|
||||
res_count = omap_device_count_resources(od, IORESOURCE_DMA);
|
||||
/* The device has no DMA resource, no need for update */
|
||||
if (!res_count)
|
||||
goto have_everything;
|
||||
|
||||
ret = platform_device_add_resources(pdev, res, res_count);
|
||||
kfree(res);
|
||||
|
||||
if (ret)
|
||||
goto oda_exit3;
|
||||
res_count += pdev->num_resources;
|
||||
}
|
||||
|
||||
/* Allocate resources memory to account for new resources */
|
||||
res = kzalloc(sizeof(struct resource) * res_count, GFP_KERNEL);
|
||||
if (!res)
|
||||
goto oda_exit3;
|
||||
|
||||
if (!pdev->num_resources) {
|
||||
dev_dbg(&pdev->dev, "%s: using %d resources from hwmod\n",
|
||||
__func__, res_count);
|
||||
omap_device_fill_resources(od, res);
|
||||
} else {
|
||||
dev_dbg(&pdev->dev,
|
||||
"%s: appending %d DMA resources from hwmod\n",
|
||||
__func__, res_count - pdev->num_resources);
|
||||
memcpy(res, pdev->resource,
|
||||
sizeof(struct resource) * pdev->num_resources);
|
||||
_od_fill_dma_resources(od, &res[pdev->num_resources]);
|
||||
}
|
||||
|
||||
ret = platform_device_add_resources(pdev, res, res_count);
|
||||
kfree(res);
|
||||
|
||||
if (ret)
|
||||
goto oda_exit3;
|
||||
|
||||
have_everything:
|
||||
if (!pm_lats) {
|
||||
pm_lats = omap_default_latency;
|
||||
pm_lats_cnt = ARRAY_SIZE(omap_default_latency);
|
||||
|
|
|
@ -130,7 +130,7 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/list.h>
|
||||
|
@ -187,6 +187,8 @@ struct omap_hwmod_soc_ops {
|
|||
int (*is_hardreset_asserted)(struct omap_hwmod *oh,
|
||||
struct omap_hwmod_rst_info *ohri);
|
||||
int (*init_clkdm)(struct omap_hwmod *oh);
|
||||
void (*update_context_lost)(struct omap_hwmod *oh);
|
||||
int (*get_context_lost)(struct omap_hwmod *oh);
|
||||
};
|
||||
|
||||
/* soc_ops: adapts the omap_hwmod code to the currently-booted SoC */
|
||||
|
@ -646,6 +648,19 @@ static int _disable_wakeup(struct omap_hwmod *oh, u32 *v)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct clockdomain *_get_clkdm(struct omap_hwmod *oh)
|
||||
{
|
||||
struct clk_hw_omap *clk;
|
||||
|
||||
if (oh->clkdm) {
|
||||
return oh->clkdm;
|
||||
} else if (oh->_clk) {
|
||||
clk = to_clk_hw_omap(__clk_get_hw(oh->_clk));
|
||||
return clk->clkdm;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* _add_initiator_dep: prevent @oh from smart-idling while @init_oh is active
|
||||
* @oh: struct omap_hwmod *
|
||||
|
@ -661,13 +676,18 @@ static int _disable_wakeup(struct omap_hwmod *oh, u32 *v)
|
|||
*/
|
||||
static int _add_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
|
||||
{
|
||||
if (!oh->_clk)
|
||||
struct clockdomain *clkdm, *init_clkdm;
|
||||
|
||||
clkdm = _get_clkdm(oh);
|
||||
init_clkdm = _get_clkdm(init_oh);
|
||||
|
||||
if (!clkdm || !init_clkdm)
|
||||
return -EINVAL;
|
||||
|
||||
if (oh->_clk->clkdm && oh->_clk->clkdm->flags & CLKDM_NO_AUTODEPS)
|
||||
if (clkdm && clkdm->flags & CLKDM_NO_AUTODEPS)
|
||||
return 0;
|
||||
|
||||
return clkdm_add_sleepdep(oh->_clk->clkdm, init_oh->_clk->clkdm);
|
||||
return clkdm_add_sleepdep(clkdm, init_clkdm);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -685,13 +705,18 @@ static int _add_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
|
|||
*/
|
||||
static int _del_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
|
||||
{
|
||||
if (!oh->_clk)
|
||||
struct clockdomain *clkdm, *init_clkdm;
|
||||
|
||||
clkdm = _get_clkdm(oh);
|
||||
init_clkdm = _get_clkdm(init_oh);
|
||||
|
||||
if (!clkdm || !init_clkdm)
|
||||
return -EINVAL;
|
||||
|
||||
if (oh->_clk->clkdm && oh->_clk->clkdm->flags & CLKDM_NO_AUTODEPS)
|
||||
if (clkdm && clkdm->flags & CLKDM_NO_AUTODEPS)
|
||||
return 0;
|
||||
|
||||
return clkdm_del_sleepdep(oh->_clk->clkdm, init_oh->_clk->clkdm);
|
||||
return clkdm_del_sleepdep(clkdm, init_clkdm);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -725,7 +750,7 @@ static int _init_main_clk(struct omap_hwmod *oh)
|
|||
*/
|
||||
clk_prepare(oh->_clk);
|
||||
|
||||
if (!oh->_clk->clkdm)
|
||||
if (!_get_clkdm(oh))
|
||||
pr_debug("omap_hwmod: %s: missing clockdomain for %s.\n",
|
||||
oh->name, oh->main_clk);
|
||||
|
||||
|
@ -1308,6 +1333,7 @@ static void _enable_sysc(struct omap_hwmod *oh)
|
|||
u8 idlemode, sf;
|
||||
u32 v;
|
||||
bool clkdm_act;
|
||||
struct clockdomain *clkdm;
|
||||
|
||||
if (!oh->class->sysc)
|
||||
return;
|
||||
|
@ -1327,11 +1353,9 @@ static void _enable_sysc(struct omap_hwmod *oh)
|
|||
v = oh->_sysc_cache;
|
||||
sf = oh->class->sysc->sysc_flags;
|
||||
|
||||
clkdm = _get_clkdm(oh);
|
||||
if (sf & SYSC_HAS_SIDLEMODE) {
|
||||
clkdm_act = ((oh->clkdm &&
|
||||
oh->clkdm->flags & CLKDM_ACTIVE_WITH_MPU) ||
|
||||
(oh->_clk && oh->_clk->clkdm &&
|
||||
oh->_clk->clkdm->flags & CLKDM_ACTIVE_WITH_MPU));
|
||||
clkdm_act = (clkdm && clkdm->flags & CLKDM_ACTIVE_WITH_MPU);
|
||||
if (clkdm_act && !(oh->class->sysc->idlemodes &
|
||||
(SIDLE_SMART | SIDLE_SMART_WKUP)))
|
||||
idlemode = HWMOD_IDLEMODE_FORCE;
|
||||
|
@ -1533,11 +1557,12 @@ static int _init_clocks(struct omap_hwmod *oh, void *data)
|
|||
|
||||
pr_debug("omap_hwmod: %s: looking up clocks\n", oh->name);
|
||||
|
||||
if (soc_ops.init_clkdm)
|
||||
ret |= soc_ops.init_clkdm(oh);
|
||||
|
||||
ret |= _init_main_clk(oh);
|
||||
ret |= _init_interface_clks(oh);
|
||||
ret |= _init_opt_clks(oh);
|
||||
if (soc_ops.init_clkdm)
|
||||
ret |= soc_ops.init_clkdm(oh);
|
||||
|
||||
if (!ret)
|
||||
oh->_state = _HWMOD_STATE_CLKS_INITED;
|
||||
|
@ -1991,6 +2016,42 @@ static void _reconfigure_io_chain(void)
|
|||
spin_unlock_irqrestore(&io_chain_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* _omap4_update_context_lost - increment hwmod context loss counter if
|
||||
* hwmod context was lost, and clear hardware context loss reg
|
||||
* @oh: hwmod to check for context loss
|
||||
*
|
||||
* If the PRCM indicates that the hwmod @oh lost context, increment
|
||||
* our in-memory context loss counter, and clear the RM_*_CONTEXT
|
||||
* bits. No return value.
|
||||
*/
|
||||
static void _omap4_update_context_lost(struct omap_hwmod *oh)
|
||||
{
|
||||
if (oh->prcm.omap4.flags & HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT)
|
||||
return;
|
||||
|
||||
if (!prm_was_any_context_lost_old(oh->clkdm->pwrdm.ptr->prcm_partition,
|
||||
oh->clkdm->pwrdm.ptr->prcm_offs,
|
||||
oh->prcm.omap4.context_offs))
|
||||
return;
|
||||
|
||||
oh->prcm.omap4.context_lost_counter++;
|
||||
prm_clear_context_loss_flags_old(oh->clkdm->pwrdm.ptr->prcm_partition,
|
||||
oh->clkdm->pwrdm.ptr->prcm_offs,
|
||||
oh->prcm.omap4.context_offs);
|
||||
}
|
||||
|
||||
/**
|
||||
* _omap4_get_context_lost - get context loss counter for a hwmod
|
||||
* @oh: hwmod to get context loss counter for
|
||||
*
|
||||
* Returns the in-memory context loss counter for a hwmod.
|
||||
*/
|
||||
static int _omap4_get_context_lost(struct omap_hwmod *oh)
|
||||
{
|
||||
return oh->prcm.omap4.context_lost_counter;
|
||||
}
|
||||
|
||||
/**
|
||||
* _enable - enable an omap_hwmod
|
||||
* @oh: struct omap_hwmod *
|
||||
|
@ -2074,6 +2135,9 @@ static int _enable(struct omap_hwmod *oh)
|
|||
if (soc_ops.enable_module)
|
||||
soc_ops.enable_module(oh);
|
||||
|
||||
if (soc_ops.update_context_lost)
|
||||
soc_ops.update_context_lost(oh);
|
||||
|
||||
r = (soc_ops.wait_target_ready) ? soc_ops.wait_target_ready(oh) :
|
||||
-EINVAL;
|
||||
if (!r) {
|
||||
|
@ -3398,7 +3462,7 @@ int omap_hwmod_reset(struct omap_hwmod *oh)
|
|||
/**
|
||||
* omap_hwmod_count_resources - count number of struct resources needed by hwmod
|
||||
* @oh: struct omap_hwmod *
|
||||
* @res: pointer to the first element of an array of struct resource to fill
|
||||
* @flags: Type of resources to include when counting (IRQ/DMA/MEM)
|
||||
*
|
||||
* Count the number of struct resource array elements necessary to
|
||||
* contain omap_hwmod @oh resources. Intended to be called by code
|
||||
|
@ -3411,20 +3475,25 @@ int omap_hwmod_reset(struct omap_hwmod *oh)
|
|||
* resource IDs.
|
||||
*
|
||||
*/
|
||||
int omap_hwmod_count_resources(struct omap_hwmod *oh)
|
||||
int omap_hwmod_count_resources(struct omap_hwmod *oh, unsigned long flags)
|
||||
{
|
||||
struct omap_hwmod_ocp_if *os;
|
||||
struct list_head *p;
|
||||
int ret;
|
||||
int i = 0;
|
||||
int ret = 0;
|
||||
|
||||
ret = _count_mpu_irqs(oh) + _count_sdma_reqs(oh);
|
||||
if (flags & IORESOURCE_IRQ)
|
||||
ret += _count_mpu_irqs(oh);
|
||||
|
||||
p = oh->slave_ports.next;
|
||||
if (flags & IORESOURCE_DMA)
|
||||
ret += _count_sdma_reqs(oh);
|
||||
|
||||
while (i < oh->slaves_cnt) {
|
||||
os = _fetch_next_ocp_if(&p, &i);
|
||||
ret += _count_ocp_if_addr_spaces(os);
|
||||
if (flags & IORESOURCE_MEM) {
|
||||
int i = 0;
|
||||
struct omap_hwmod_ocp_if *os;
|
||||
struct list_head *p = oh->slave_ports.next;
|
||||
|
||||
while (i < oh->slaves_cnt) {
|
||||
os = _fetch_next_ocp_if(&p, &i);
|
||||
ret += _count_ocp_if_addr_spaces(os);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -3591,10 +3660,15 @@ struct powerdomain *omap_hwmod_get_pwrdm(struct omap_hwmod *oh)
|
|||
{
|
||||
struct clk *c;
|
||||
struct omap_hwmod_ocp_if *oi;
|
||||
struct clockdomain *clkdm;
|
||||
struct clk_hw_omap *clk;
|
||||
|
||||
if (!oh)
|
||||
return NULL;
|
||||
|
||||
if (oh->clkdm)
|
||||
return oh->clkdm->pwrdm.ptr;
|
||||
|
||||
if (oh->_clk) {
|
||||
c = oh->_clk;
|
||||
} else {
|
||||
|
@ -3604,11 +3678,12 @@ struct powerdomain *omap_hwmod_get_pwrdm(struct omap_hwmod *oh)
|
|||
c = oi->_clk;
|
||||
}
|
||||
|
||||
if (!c->clkdm)
|
||||
clk = to_clk_hw_omap(__clk_get_hw(c));
|
||||
clkdm = clk->clkdm;
|
||||
if (!clkdm)
|
||||
return NULL;
|
||||
|
||||
return c->clkdm->pwrdm.ptr;
|
||||
|
||||
return clkdm->pwrdm.ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3913,17 +3988,21 @@ ohsps_unlock:
|
|||
* omap_hwmod_get_context_loss_count - get lost context count
|
||||
* @oh: struct omap_hwmod *
|
||||
*
|
||||
* Query the powerdomain of of @oh to get the context loss
|
||||
* count for this device.
|
||||
* Returns the context loss count of associated @oh
|
||||
* upon success, or zero if no context loss data is available.
|
||||
*
|
||||
* Returns the context loss count of the powerdomain assocated with @oh
|
||||
* upon success, or zero if no powerdomain exists for @oh.
|
||||
* On OMAP4, this queries the per-hwmod context loss register,
|
||||
* assuming one exists. If not, or on OMAP2/3, this queries the
|
||||
* enclosing powerdomain context loss count.
|
||||
*/
|
||||
int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh)
|
||||
{
|
||||
struct powerdomain *pwrdm;
|
||||
int ret = 0;
|
||||
|
||||
if (soc_ops.get_context_lost)
|
||||
return soc_ops.get_context_lost(oh);
|
||||
|
||||
pwrdm = omap_hwmod_get_pwrdm(oh);
|
||||
if (pwrdm)
|
||||
ret = pwrdm_get_context_loss_count(pwrdm);
|
||||
|
@ -4038,6 +4117,8 @@ void __init omap_hwmod_init(void)
|
|||
soc_ops.deassert_hardreset = _omap4_deassert_hardreset;
|
||||
soc_ops.is_hardreset_asserted = _omap4_is_hardreset_asserted;
|
||||
soc_ops.init_clkdm = _init_clkdm;
|
||||
soc_ops.update_context_lost = _omap4_update_context_lost;
|
||||
soc_ops.get_context_lost = _omap4_get_context_lost;
|
||||
} else if (soc_is_am33xx()) {
|
||||
soc_ops.enable_module = _am33xx_enable_module;
|
||||
soc_ops.disable_module = _am33xx_disable_module;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* omap_hwmod macros, structures
|
||||
*
|
||||
* Copyright (C) 2009-2011 Nokia Corporation
|
||||
* Copyright (C) 2012 Texas Instruments, Inc.
|
||||
* Copyright (C) 2011-2012 Texas Instruments, Inc.
|
||||
* Paul Walmsley
|
||||
*
|
||||
* Created in collaboration with (alphabetical order): Benoît Cousson,
|
||||
|
@ -394,12 +394,15 @@ struct omap_hwmod_omap2_prcm {
|
|||
|
||||
/**
|
||||
* struct omap_hwmod_omap4_prcm - OMAP4-specific PRCM data
|
||||
* @clkctrl_reg: PRCM address of the clock control register
|
||||
* @rstctrl_reg: address of the XXX_RSTCTRL register located in the PRM
|
||||
* @clkctrl_offs: offset of the PRCM clock control register
|
||||
* @rstctrl_offs: offset of the XXX_RSTCTRL register located in the PRM
|
||||
* @context_offs: offset of the RM_*_CONTEXT register
|
||||
* @lostcontext_mask: bitmask for selecting bits from RM_*_CONTEXT register
|
||||
* @rstst_reg: (AM33XX only) address of the XXX_RSTST register in the PRM
|
||||
* @submodule_wkdep_bit: bit shift of the WKDEP range
|
||||
* @flags: PRCM register capabilities for this IP block
|
||||
* @modulemode: allowable modulemodes
|
||||
* @context_lost_counter: Count of module level context lost
|
||||
*
|
||||
* If @lostcontext_mask is not defined, context loss check code uses
|
||||
* whole register without masking. @lostcontext_mask should only be
|
||||
|
@ -415,6 +418,7 @@ struct omap_hwmod_omap4_prcm {
|
|||
u8 submodule_wkdep_bit;
|
||||
u8 modulemode;
|
||||
u8 flags;
|
||||
int context_lost_counter;
|
||||
};
|
||||
|
||||
|
||||
|
@ -633,7 +637,7 @@ void omap_hwmod_write(u32 v, struct omap_hwmod *oh, u16 reg_offs);
|
|||
u32 omap_hwmod_read(struct omap_hwmod *oh, u16 reg_offs);
|
||||
int omap_hwmod_softreset(struct omap_hwmod *oh);
|
||||
|
||||
int omap_hwmod_count_resources(struct omap_hwmod *oh);
|
||||
int omap_hwmod_count_resources(struct omap_hwmod *oh, unsigned long flags);
|
||||
int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res);
|
||||
int omap_hwmod_fill_dma_resources(struct omap_hwmod *oh, struct resource *res);
|
||||
int omap_hwmod_get_resource_byname(struct omap_hwmod *oh, unsigned int type,
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
|
||||
#include <linux/i2c-omap.h>
|
||||
#include <linux/platform_data/spi-omap2-mcspi.h>
|
||||
|
||||
#include <plat-omap/dma-omap.h>
|
||||
#include <linux/omap-dma.h>
|
||||
#include <plat/dmtimer.h>
|
||||
|
||||
#include "omap_hwmod.h"
|
||||
#include "l3_2xxx.h"
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
#include <linux/i2c-omap.h>
|
||||
#include <linux/platform_data/asoc-ti-mcbsp.h>
|
||||
#include <linux/platform_data/spi-omap2-mcspi.h>
|
||||
|
||||
#include <plat-omap/dma-omap.h>
|
||||
#include <linux/omap-dma.h>
|
||||
#include <plat/dmtimer.h>
|
||||
|
||||
#include "omap_hwmod.h"
|
||||
#include "mmc.h"
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <plat-omap/dma-omap.h>
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/omap-dma.h>
|
||||
|
||||
#include "omap_hwmod.h"
|
||||
#include "hdq1w.h"
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/platform_data/gpio-omap.h>
|
||||
#include <plat-omap/dma-omap.h>
|
||||
#include <linux/omap-dma.h>
|
||||
#include <plat/dmtimer.h>
|
||||
#include <linux/platform_data/spi-omap2-mcspi.h>
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include <linux/power/smartreflex.h>
|
||||
#include <linux/platform_data/gpio-omap.h>
|
||||
|
||||
#include <plat-omap/dma-omap.h>
|
||||
#include <linux/omap-dma.h>
|
||||
#include "l3_3xxx.h"
|
||||
#include "l4_3xxx.h"
|
||||
#include <linux/platform_data/asoc-ti-mcbsp.h>
|
||||
|
|
|
@ -21,9 +21,10 @@
|
|||
#include <linux/io.h>
|
||||
#include <linux/platform_data/gpio-omap.h>
|
||||
#include <linux/power/smartreflex.h>
|
||||
#include <linux/platform_data/omap_ocp2scp.h>
|
||||
#include <linux/i2c-omap.h>
|
||||
|
||||
#include <plat-omap/dma-omap.h>
|
||||
#include <linux/omap-dma.h>
|
||||
|
||||
#include <linux/platform_data/omap_ocp2scp.h>
|
||||
#include <linux/platform_data/spi-omap2-mcspi.h>
|
||||
|
|
|
@ -89,8 +89,11 @@ extern struct omap_volt_data omap34xx_vddcore_volt_data[];
|
|||
extern struct omap_volt_data omap36xx_vddmpu_volt_data[];
|
||||
extern struct omap_volt_data omap36xx_vddcore_volt_data[];
|
||||
|
||||
extern struct omap_volt_data omap44xx_vdd_mpu_volt_data[];
|
||||
extern struct omap_volt_data omap44xx_vdd_iva_volt_data[];
|
||||
extern struct omap_volt_data omap44xx_vdd_core_volt_data[];
|
||||
extern struct omap_volt_data omap443x_vdd_mpu_volt_data[];
|
||||
extern struct omap_volt_data omap443x_vdd_iva_volt_data[];
|
||||
extern struct omap_volt_data omap443x_vdd_core_volt_data[];
|
||||
extern struct omap_volt_data omap446x_vdd_mpu_volt_data[];
|
||||
extern struct omap_volt_data omap446x_vdd_iva_volt_data[];
|
||||
extern struct omap_volt_data omap446x_vdd_core_volt_data[];
|
||||
|
||||
#endif /* __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H */
|
||||
|
|
|
@ -33,6 +33,38 @@
|
|||
#include "control.h"
|
||||
#include "usb.h"
|
||||
|
||||
#define CONTROL_DEV_CONF 0x300
|
||||
#define PHY_PD 0x1
|
||||
|
||||
/**
|
||||
* omap4430_phy_power_down: disable MUSB PHY during early init
|
||||
*
|
||||
* OMAP4 MUSB PHY module is enabled by default on reset, but this will
|
||||
* prevent core retention if not disabled by SW. USB driver will
|
||||
* later on enable this, once and if the driver needs it.
|
||||
*/
|
||||
static int __init omap4430_phy_power_down(void)
|
||||
{
|
||||
void __iomem *ctrl_base;
|
||||
|
||||
if (!cpu_is_omap44xx())
|
||||
return 0;
|
||||
|
||||
ctrl_base = ioremap(OMAP443X_SCM_BASE, SZ_1K);
|
||||
if (!ctrl_base) {
|
||||
pr_err("control module ioremap failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Power down the phy */
|
||||
__raw_writel(PHY_PD, ctrl_base + CONTROL_DEV_CONF);
|
||||
|
||||
iounmap(ctrl_base);
|
||||
|
||||
return 0;
|
||||
}
|
||||
early_initcall(omap4430_phy_power_down);
|
||||
|
||||
void am35x_musb_reset(void)
|
||||
{
|
||||
u32 regval;
|
||||
|
|
|
@ -31,16 +31,6 @@
|
|||
#define OMAP3_VP_VSTEPMAX_VSTEPMAX 0x04
|
||||
#define OMAP3_VP_VLIMITTO_TIMEOUT_US 200
|
||||
|
||||
#define OMAP3430_VP1_VLIMITTO_VDDMIN 0x14
|
||||
#define OMAP3430_VP1_VLIMITTO_VDDMAX 0x42
|
||||
#define OMAP3430_VP2_VLIMITTO_VDDMIN 0x18
|
||||
#define OMAP3430_VP2_VLIMITTO_VDDMAX 0x2c
|
||||
|
||||
#define OMAP3630_VP1_VLIMITTO_VDDMIN 0x18
|
||||
#define OMAP3630_VP1_VLIMITTO_VDDMAX 0x3c
|
||||
#define OMAP3630_VP2_VLIMITTO_VDDMIN 0x18
|
||||
#define OMAP3630_VP2_VLIMITTO_VDDMAX 0x30
|
||||
|
||||
#define OMAP4_SRI2C_SLAVE_ADDR 0x12
|
||||
#define OMAP4_VDD_MPU_SR_VOLT_REG 0x55
|
||||
#define OMAP4_VDD_MPU_SR_CMD_REG 0x56
|
||||
|
@ -54,13 +44,6 @@
|
|||
#define OMAP4_VP_VSTEPMAX_VSTEPMAX 0x04
|
||||
#define OMAP4_VP_VLIMITTO_TIMEOUT_US 200
|
||||
|
||||
#define OMAP4_VP_MPU_VLIMITTO_VDDMIN 0xA
|
||||
#define OMAP4_VP_MPU_VLIMITTO_VDDMAX 0x39
|
||||
#define OMAP4_VP_IVA_VLIMITTO_VDDMIN 0xA
|
||||
#define OMAP4_VP_IVA_VLIMITTO_VDDMAX 0x2D
|
||||
#define OMAP4_VP_CORE_VLIMITTO_VDDMIN 0xA
|
||||
#define OMAP4_VP_CORE_VLIMITTO_VDDMAX 0x28
|
||||
|
||||
static bool is_offset_valid;
|
||||
static u8 smps_offset;
|
||||
/*
|
||||
|
@ -159,16 +142,11 @@ static u8 twl6030_uv_to_vsel(unsigned long uv)
|
|||
static struct omap_voltdm_pmic omap3_mpu_pmic = {
|
||||
.slew_rate = 4000,
|
||||
.step_size = 12500,
|
||||
.on_volt = 1200000,
|
||||
.onlp_volt = 1000000,
|
||||
.ret_volt = 975000,
|
||||
.off_volt = 600000,
|
||||
.volt_setup_time = 0xfff,
|
||||
.vp_erroroffset = OMAP3_VP_CONFIG_ERROROFFSET,
|
||||
.vp_vstepmin = OMAP3_VP_VSTEPMIN_VSTEPMIN,
|
||||
.vp_vstepmax = OMAP3_VP_VSTEPMAX_VSTEPMAX,
|
||||
.vp_vddmin = OMAP3430_VP1_VLIMITTO_VDDMIN,
|
||||
.vp_vddmax = OMAP3430_VP1_VLIMITTO_VDDMAX,
|
||||
.vddmin = 600000,
|
||||
.vddmax = 1450000,
|
||||
.vp_timeout_us = OMAP3_VP_VLIMITTO_TIMEOUT_US,
|
||||
.i2c_slave_addr = OMAP3_SRI2C_SLAVE_ADDR,
|
||||
.volt_reg_addr = OMAP3_VDD_MPU_SR_CONTROL_REG,
|
||||
|
@ -180,16 +158,11 @@ static struct omap_voltdm_pmic omap3_mpu_pmic = {
|
|||
static struct omap_voltdm_pmic omap3_core_pmic = {
|
||||
.slew_rate = 4000,
|
||||
.step_size = 12500,
|
||||
.on_volt = 1200000,
|
||||
.onlp_volt = 1000000,
|
||||
.ret_volt = 975000,
|
||||
.off_volt = 600000,
|
||||
.volt_setup_time = 0xfff,
|
||||
.vp_erroroffset = OMAP3_VP_CONFIG_ERROROFFSET,
|
||||
.vp_vstepmin = OMAP3_VP_VSTEPMIN_VSTEPMIN,
|
||||
.vp_vstepmax = OMAP3_VP_VSTEPMAX_VSTEPMAX,
|
||||
.vp_vddmin = OMAP3430_VP2_VLIMITTO_VDDMIN,
|
||||
.vp_vddmax = OMAP3430_VP2_VLIMITTO_VDDMAX,
|
||||
.vddmin = 600000,
|
||||
.vddmax = 1450000,
|
||||
.vp_timeout_us = OMAP3_VP_VLIMITTO_TIMEOUT_US,
|
||||
.i2c_slave_addr = OMAP3_SRI2C_SLAVE_ADDR,
|
||||
.volt_reg_addr = OMAP3_VDD_CORE_SR_CONTROL_REG,
|
||||
|
@ -201,21 +174,17 @@ static struct omap_voltdm_pmic omap3_core_pmic = {
|
|||
static struct omap_voltdm_pmic omap4_mpu_pmic = {
|
||||
.slew_rate = 4000,
|
||||
.step_size = 12660,
|
||||
.on_volt = 1375000,
|
||||
.onlp_volt = 1375000,
|
||||
.ret_volt = 830000,
|
||||
.off_volt = 0,
|
||||
.volt_setup_time = 0,
|
||||
.vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
|
||||
.vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
|
||||
.vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
|
||||
.vp_vddmin = OMAP4_VP_MPU_VLIMITTO_VDDMIN,
|
||||
.vp_vddmax = OMAP4_VP_MPU_VLIMITTO_VDDMAX,
|
||||
.vddmin = 0,
|
||||
.vddmax = 2100000,
|
||||
.vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
|
||||
.i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR,
|
||||
.volt_reg_addr = OMAP4_VDD_MPU_SR_VOLT_REG,
|
||||
.cmd_reg_addr = OMAP4_VDD_MPU_SR_CMD_REG,
|
||||
.i2c_high_speed = true,
|
||||
.i2c_pad_load = 3,
|
||||
.vsel_to_uv = twl6030_vsel_to_uv,
|
||||
.uv_to_vsel = twl6030_uv_to_vsel,
|
||||
};
|
||||
|
@ -223,21 +192,17 @@ static struct omap_voltdm_pmic omap4_mpu_pmic = {
|
|||
static struct omap_voltdm_pmic omap4_iva_pmic = {
|
||||
.slew_rate = 4000,
|
||||
.step_size = 12660,
|
||||
.on_volt = 1188000,
|
||||
.onlp_volt = 1188000,
|
||||
.ret_volt = 830000,
|
||||
.off_volt = 0,
|
||||
.volt_setup_time = 0,
|
||||
.vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
|
||||
.vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
|
||||
.vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
|
||||
.vp_vddmin = OMAP4_VP_IVA_VLIMITTO_VDDMIN,
|
||||
.vp_vddmax = OMAP4_VP_IVA_VLIMITTO_VDDMAX,
|
||||
.vddmin = 0,
|
||||
.vddmax = 2100000,
|
||||
.vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
|
||||
.i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR,
|
||||
.volt_reg_addr = OMAP4_VDD_IVA_SR_VOLT_REG,
|
||||
.cmd_reg_addr = OMAP4_VDD_IVA_SR_CMD_REG,
|
||||
.i2c_high_speed = true,
|
||||
.i2c_pad_load = 3,
|
||||
.vsel_to_uv = twl6030_vsel_to_uv,
|
||||
.uv_to_vsel = twl6030_uv_to_vsel,
|
||||
};
|
||||
|
@ -245,20 +210,17 @@ static struct omap_voltdm_pmic omap4_iva_pmic = {
|
|||
static struct omap_voltdm_pmic omap4_core_pmic = {
|
||||
.slew_rate = 4000,
|
||||
.step_size = 12660,
|
||||
.on_volt = 1200000,
|
||||
.onlp_volt = 1200000,
|
||||
.ret_volt = 830000,
|
||||
.off_volt = 0,
|
||||
.volt_setup_time = 0,
|
||||
.vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
|
||||
.vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
|
||||
.vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
|
||||
.vp_vddmin = OMAP4_VP_CORE_VLIMITTO_VDDMIN,
|
||||
.vp_vddmax = OMAP4_VP_CORE_VLIMITTO_VDDMAX,
|
||||
.vddmin = 0,
|
||||
.vddmax = 2100000,
|
||||
.vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
|
||||
.i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR,
|
||||
.volt_reg_addr = OMAP4_VDD_CORE_SR_VOLT_REG,
|
||||
.cmd_reg_addr = OMAP4_VDD_CORE_SR_CMD_REG,
|
||||
.i2c_high_speed = true,
|
||||
.i2c_pad_load = 3,
|
||||
.vsel_to_uv = twl6030_vsel_to_uv,
|
||||
.uv_to_vsel = twl6030_uv_to_vsel,
|
||||
};
|
||||
|
@ -289,13 +251,6 @@ int __init omap3_twl_init(void)
|
|||
if (!cpu_is_omap34xx())
|
||||
return -ENODEV;
|
||||
|
||||
if (cpu_is_omap3630()) {
|
||||
omap3_mpu_pmic.vp_vddmin = OMAP3630_VP1_VLIMITTO_VDDMIN;
|
||||
omap3_mpu_pmic.vp_vddmax = OMAP3630_VP1_VLIMITTO_VDDMAX;
|
||||
omap3_core_pmic.vp_vddmin = OMAP3630_VP2_VLIMITTO_VDDMIN;
|
||||
omap3_core_pmic.vp_vddmax = OMAP3630_VP2_VLIMITTO_VDDMAX;
|
||||
}
|
||||
|
||||
/*
|
||||
* The smartreflex bit on twl4030 specifies if the setting of voltage
|
||||
* is done over the I2C_SR path. Since this setting is independent of
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* OMAP4 OPP table definitions.
|
||||
*
|
||||
* Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* Copyright (C) 2010-2012 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* Nishanth Menon
|
||||
* Kevin Hilman
|
||||
* Thara Gopinath
|
||||
|
@ -35,7 +35,7 @@
|
|||
#define OMAP4430_VDD_MPU_OPPTURBO_UV 1313000
|
||||
#define OMAP4430_VDD_MPU_OPPNITRO_UV 1375000
|
||||
|
||||
struct omap_volt_data omap44xx_vdd_mpu_volt_data[] = {
|
||||
struct omap_volt_data omap443x_vdd_mpu_volt_data[] = {
|
||||
VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP50_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP50, 0xf4, 0x0c),
|
||||
VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP100_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP100, 0xf9, 0x16),
|
||||
VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPTURBO, 0xfa, 0x23),
|
||||
|
@ -47,7 +47,7 @@ struct omap_volt_data omap44xx_vdd_mpu_volt_data[] = {
|
|||
#define OMAP4430_VDD_IVA_OPP100_UV 1188000
|
||||
#define OMAP4430_VDD_IVA_OPPTURBO_UV 1300000
|
||||
|
||||
struct omap_volt_data omap44xx_vdd_iva_volt_data[] = {
|
||||
struct omap_volt_data omap443x_vdd_iva_volt_data[] = {
|
||||
VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP50_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP50, 0xf4, 0x0c),
|
||||
VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP100_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP100, 0xf9, 0x16),
|
||||
VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_IVA_OPPTURBO, 0xfa, 0x23),
|
||||
|
@ -57,14 +57,14 @@ struct omap_volt_data omap44xx_vdd_iva_volt_data[] = {
|
|||
#define OMAP4430_VDD_CORE_OPP50_UV 1025000
|
||||
#define OMAP4430_VDD_CORE_OPP100_UV 1200000
|
||||
|
||||
struct omap_volt_data omap44xx_vdd_core_volt_data[] = {
|
||||
struct omap_volt_data omap443x_vdd_core_volt_data[] = {
|
||||
VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP50_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP50, 0xf4, 0x0c),
|
||||
VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP100_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP100, 0xf9, 0x16),
|
||||
VOLT_DATA_DEFINE(0, 0, 0, 0),
|
||||
};
|
||||
|
||||
|
||||
static struct omap_opp_def __initdata omap44xx_opp_def_list[] = {
|
||||
static struct omap_opp_def __initdata omap443x_opp_def_list[] = {
|
||||
/* MPU OPP1 - OPP50 */
|
||||
OPP_INITIALIZER("mpu", true, 300000000, OMAP4430_VDD_MPU_OPP50_UV),
|
||||
/* MPU OPP2 - OPP100 */
|
||||
|
@ -86,6 +86,82 @@ static struct omap_opp_def __initdata omap44xx_opp_def_list[] = {
|
|||
/* TODO: add DSP, aess, fdif, gpu */
|
||||
};
|
||||
|
||||
#define OMAP4460_VDD_MPU_OPP50_UV 1025000
|
||||
#define OMAP4460_VDD_MPU_OPP100_UV 1200000
|
||||
#define OMAP4460_VDD_MPU_OPPTURBO_UV 1313000
|
||||
#define OMAP4460_VDD_MPU_OPPNITRO_UV 1375000
|
||||
|
||||
struct omap_volt_data omap446x_vdd_mpu_volt_data[] = {
|
||||
VOLT_DATA_DEFINE(OMAP4460_VDD_MPU_OPP50_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP50, 0xf4, 0x0c),
|
||||
VOLT_DATA_DEFINE(OMAP4460_VDD_MPU_OPP100_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP100, 0xf9, 0x16),
|
||||
VOLT_DATA_DEFINE(OMAP4460_VDD_MPU_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPTURBO, 0xfa, 0x23),
|
||||
VOLT_DATA_DEFINE(OMAP4460_VDD_MPU_OPPNITRO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPNITRO, 0xfa, 0x27),
|
||||
VOLT_DATA_DEFINE(0, 0, 0, 0),
|
||||
};
|
||||
|
||||
#define OMAP4460_VDD_IVA_OPP50_UV 1025000
|
||||
#define OMAP4460_VDD_IVA_OPP100_UV 1200000
|
||||
#define OMAP4460_VDD_IVA_OPPTURBO_UV 1313000
|
||||
#define OMAP4460_VDD_IVA_OPPNITRO_UV 1375000
|
||||
|
||||
struct omap_volt_data omap446x_vdd_iva_volt_data[] = {
|
||||
VOLT_DATA_DEFINE(OMAP4460_VDD_IVA_OPP50_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP50, 0xf4, 0x0c),
|
||||
VOLT_DATA_DEFINE(OMAP4460_VDD_IVA_OPP100_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP100, 0xf9, 0x16),
|
||||
VOLT_DATA_DEFINE(OMAP4460_VDD_IVA_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_IVA_OPPTURBO, 0xfa, 0x23),
|
||||
VOLT_DATA_DEFINE(OMAP4460_VDD_IVA_OPPNITRO_UV, OMAP44XX_CONTROL_FUSE_IVA_OPPNITRO, 0xfa, 0x23),
|
||||
VOLT_DATA_DEFINE(0, 0, 0, 0),
|
||||
};
|
||||
|
||||
#define OMAP4460_VDD_CORE_OPP50_UV 1025000
|
||||
#define OMAP4460_VDD_CORE_OPP100_UV 1200000
|
||||
#define OMAP4460_VDD_CORE_OPP100_OV_UV 1250000
|
||||
|
||||
struct omap_volt_data omap446x_vdd_core_volt_data[] = {
|
||||
VOLT_DATA_DEFINE(OMAP4460_VDD_CORE_OPP50_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP50, 0xf4, 0x0c),
|
||||
VOLT_DATA_DEFINE(OMAP4460_VDD_CORE_OPP100_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP100, 0xf9, 0x16),
|
||||
VOLT_DATA_DEFINE(OMAP4460_VDD_CORE_OPP100_OV_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP100OV, 0xf9, 0x16),
|
||||
VOLT_DATA_DEFINE(0, 0, 0, 0),
|
||||
};
|
||||
|
||||
static struct omap_opp_def __initdata omap446x_opp_def_list[] = {
|
||||
/* MPU OPP1 - OPP50 */
|
||||
OPP_INITIALIZER("mpu", true, 350000000, OMAP4460_VDD_MPU_OPP50_UV),
|
||||
/* MPU OPP2 - OPP100 */
|
||||
OPP_INITIALIZER("mpu", true, 700000000, OMAP4460_VDD_MPU_OPP100_UV),
|
||||
/* MPU OPP3 - OPP-Turbo */
|
||||
OPP_INITIALIZER("mpu", true, 920000000, OMAP4460_VDD_MPU_OPPTURBO_UV),
|
||||
/*
|
||||
* MPU OPP4 - OPP-Nitro + Disabled as the reference schematics
|
||||
* recommends TPS623631 - confirm and enable the opp in board file
|
||||
* XXX: May be we should enable these based on mpu capability and
|
||||
* Exception board files disable it...
|
||||
*/
|
||||
OPP_INITIALIZER("mpu", false, 1200000000, OMAP4460_VDD_MPU_OPPNITRO_UV),
|
||||
/* MPU OPP4 - OPP-Nitro SpeedBin */
|
||||
OPP_INITIALIZER("mpu", false, 1500000000, OMAP4460_VDD_MPU_OPPNITRO_UV),
|
||||
/* L3 OPP1 - OPP50 */
|
||||
OPP_INITIALIZER("l3_main_1", true, 100000000, OMAP4460_VDD_CORE_OPP50_UV),
|
||||
/* L3 OPP2 - OPP100 */
|
||||
OPP_INITIALIZER("l3_main_1", true, 200000000, OMAP4460_VDD_CORE_OPP100_UV),
|
||||
/* IVA OPP1 - OPP50 */
|
||||
OPP_INITIALIZER("iva", true, 133000000, OMAP4460_VDD_IVA_OPP50_UV),
|
||||
/* IVA OPP2 - OPP100 */
|
||||
OPP_INITIALIZER("iva", true, 266100000, OMAP4460_VDD_IVA_OPP100_UV),
|
||||
/*
|
||||
* IVA OPP3 - OPP-Turbo + Disabled as the reference schematics
|
||||
* recommends Phoenix VCORE2 which can supply only 600mA - so the ones
|
||||
* above this OPP frequency, even though OMAP is capable, should be
|
||||
* enabled by board file which is sure of the chip power capability
|
||||
*/
|
||||
OPP_INITIALIZER("iva", false, 332000000, OMAP4460_VDD_IVA_OPPTURBO_UV),
|
||||
/* IVA OPP4 - OPP-Nitro */
|
||||
OPP_INITIALIZER("iva", false, 430000000, OMAP4460_VDD_IVA_OPPNITRO_UV),
|
||||
/* IVA OPP5 - OPP-Nitro SpeedBin*/
|
||||
OPP_INITIALIZER("iva", false, 500000000, OMAP4460_VDD_IVA_OPPNITRO_UV),
|
||||
|
||||
/* TODO: add DSP, aess, fdif, gpu */
|
||||
};
|
||||
|
||||
/**
|
||||
* omap4_opp_init() - initialize omap4 opp table
|
||||
*/
|
||||
|
@ -93,12 +169,12 @@ int __init omap4_opp_init(void)
|
|||
{
|
||||
int r = -ENODEV;
|
||||
|
||||
if (!cpu_is_omap443x())
|
||||
return r;
|
||||
|
||||
r = omap_init_opp_table(omap44xx_opp_def_list,
|
||||
ARRAY_SIZE(omap44xx_opp_def_list));
|
||||
|
||||
if (cpu_is_omap443x())
|
||||
r = omap_init_opp_table(omap443x_opp_def_list,
|
||||
ARRAY_SIZE(omap443x_opp_def_list));
|
||||
else if (cpu_is_omap446x())
|
||||
r = omap_init_opp_table(omap446x_opp_def_list,
|
||||
ARRAY_SIZE(omap446x_opp_def_list));
|
||||
return r;
|
||||
}
|
||||
device_initcall(omap4_opp_init);
|
||||
|
|
|
@ -40,6 +40,38 @@ static struct omap_device_pm_latency *pm_lats;
|
|||
*/
|
||||
int (*omap_pm_suspend)(void);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
/**
|
||||
* struct omap2_oscillator - Describe the board main oscillator latencies
|
||||
* @startup_time: oscillator startup latency
|
||||
* @shutdown_time: oscillator shutdown latency
|
||||
*/
|
||||
struct omap2_oscillator {
|
||||
u32 startup_time;
|
||||
u32 shutdown_time;
|
||||
};
|
||||
|
||||
static struct omap2_oscillator oscillator = {
|
||||
.startup_time = ULONG_MAX,
|
||||
.shutdown_time = ULONG_MAX,
|
||||
};
|
||||
|
||||
void omap_pm_setup_oscillator(u32 tstart, u32 tshut)
|
||||
{
|
||||
oscillator.startup_time = tstart;
|
||||
oscillator.shutdown_time = tshut;
|
||||
}
|
||||
|
||||
void omap_pm_get_oscillator(u32 *tstart, u32 *tshut)
|
||||
{
|
||||
if (!tstart || !tshut)
|
||||
return;
|
||||
|
||||
*tstart = oscillator.startup_time;
|
||||
*tshut = oscillator.shutdown_time;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int __init _init_omap_device(char *name)
|
||||
{
|
||||
struct omap_hwmod *oh;
|
||||
|
|
|
@ -138,4 +138,14 @@ static inline int omap4_twl_init(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
extern void omap_pm_setup_oscillator(u32 tstart, u32 tshut);
|
||||
extern void omap_pm_get_oscillator(u32 *tstart, u32 *tshut);
|
||||
extern void omap_pm_setup_sr_i2c_pcb_length(u32 mm);
|
||||
#else
|
||||
static inline void omap_pm_setup_oscillator(u32 tstart, u32 tshut) { }
|
||||
static inline void omap_pm_get_oscillator(u32 *tstart, u32 *tshut) { *tstart = *tshut = 0; }
|
||||
static inline void omap_pm_setup_sr_i2c_pcb_length(u32 mm) { }
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include <linux/sysfs.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/gpio.h>
|
||||
|
@ -38,7 +38,7 @@
|
|||
#include <asm/mach-types.h>
|
||||
#include <asm/system_misc.h>
|
||||
|
||||
#include <plat-omap/dma-omap.h>
|
||||
#include <linux/omap-dma.h>
|
||||
|
||||
#include "soc.h"
|
||||
#include "common.h"
|
||||
|
@ -203,7 +203,7 @@ static int omap2_can_sleep(void)
|
|||
{
|
||||
if (omap2_fclks_active())
|
||||
return 0;
|
||||
if (osc_ck->usecount > 1)
|
||||
if (__clk_is_enabled(osc_ck))
|
||||
return 0;
|
||||
if (omap_dma_running())
|
||||
return 0;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/omap-dma.h>
|
||||
#include <linux/platform_data/gpio-omap.h>
|
||||
|
||||
#include <trace/events/power.h>
|
||||
|
@ -38,8 +39,6 @@
|
|||
|
||||
#include "clockdomain.h"
|
||||
#include "powerdomain.h"
|
||||
#include <plat-omap/dma-omap.h>
|
||||
|
||||
#include "soc.h"
|
||||
#include "common.h"
|
||||
#include "cm3xxx.h"
|
||||
|
|
|
@ -101,13 +101,6 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
|
|||
if (!strncmp(pwrdm->name, "cpu", 3))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* FIXME: Remove this check when core retention is supported
|
||||
* Only MPUSS power domain is added in the list.
|
||||
*/
|
||||
if (strcmp(pwrdm->name, "mpu_pwrdm"))
|
||||
return 0;
|
||||
|
||||
pwrst = kmalloc(sizeof(struct power_state), GFP_ATOMIC);
|
||||
if (!pwrst)
|
||||
return -ENOMEM;
|
||||
|
|
|
@ -107,12 +107,14 @@
|
|||
#define OMAP2420_CLKOUT2_EN_MASK (1 << 15)
|
||||
#define OMAP2420_CLKOUT2_DIV_SHIFT 11
|
||||
#define OMAP2420_CLKOUT2_DIV_MASK (0x7 << 11)
|
||||
#define OMAP2420_CLKOUT2_DIV_WIDTH 3
|
||||
#define OMAP2420_CLKOUT2_SOURCE_SHIFT 8
|
||||
#define OMAP2420_CLKOUT2_SOURCE_MASK (0x3 << 8)
|
||||
#define OMAP24XX_CLKOUT_EN_SHIFT 7
|
||||
#define OMAP24XX_CLKOUT_EN_MASK (1 << 7)
|
||||
#define OMAP24XX_CLKOUT_DIV_SHIFT 3
|
||||
#define OMAP24XX_CLKOUT_DIV_MASK (0x7 << 3)
|
||||
#define OMAP24XX_CLKOUT_DIV_WIDTH 3
|
||||
#define OMAP24XX_CLKOUT_SOURCE_SHIFT 0
|
||||
#define OMAP24XX_CLKOUT_SOURCE_MASK (0x3 << 0)
|
||||
|
||||
|
|
|
@ -384,6 +384,7 @@
|
|||
/* PRM_CLKSEL */
|
||||
#define OMAP3430_SYS_CLKIN_SEL_SHIFT 0
|
||||
#define OMAP3430_SYS_CLKIN_SEL_MASK (0x7 << 0)
|
||||
#define OMAP3430_SYS_CLKIN_SEL_WIDTH 3
|
||||
|
||||
/* PRM_CLKOUT_CTRL */
|
||||
#define OMAP3430_CLKOUT_EN_MASK (1 << 7)
|
||||
|
|
|
@ -114,16 +114,25 @@ struct prm_reset_src_map {
|
|||
|
||||
/**
|
||||
* struct prm_ll_data - fn ptrs to per-SoC PRM function implementations
|
||||
* @read_reset_sources: ptr to the Soc PRM-specific get_reset_source impl
|
||||
* @read_reset_sources: ptr to the SoC PRM-specific get_reset_source impl
|
||||
* @was_any_context_lost_old: ptr to the SoC PRM context loss test fn
|
||||
* @clear_context_loss_flags_old: ptr to the SoC PRM context loss flag clear fn
|
||||
*
|
||||
* XXX @was_any_context_lost_old and @clear_context_loss_flags_old are
|
||||
* deprecated.
|
||||
*/
|
||||
struct prm_ll_data {
|
||||
u32 (*read_reset_sources)(void);
|
||||
bool (*was_any_context_lost_old)(u8 part, s16 inst, u16 idx);
|
||||
void (*clear_context_loss_flags_old)(u8 part, s16 inst, u16 idx);
|
||||
};
|
||||
|
||||
extern int prm_register(struct prm_ll_data *pld);
|
||||
extern int prm_unregister(struct prm_ll_data *pld);
|
||||
|
||||
extern u32 prm_read_reset_sources(void);
|
||||
extern bool prm_was_any_context_lost_old(u8 part, s16 inst, u16 idx);
|
||||
extern void prm_clear_context_loss_flags_old(u8 part, s16 inst, u16 idx);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -118,14 +118,13 @@ static struct prm_ll_data omap2xxx_prm_ll_data = {
|
|||
.read_reset_sources = &omap2xxx_prm_read_reset_sources,
|
||||
};
|
||||
|
||||
static int __init omap2xxx_prm_init(void)
|
||||
int __init omap2xxx_prm_init(void)
|
||||
{
|
||||
if (!cpu_is_omap24xx())
|
||||
return 0;
|
||||
|
||||
return prm_register(&omap2xxx_prm_ll_data);
|
||||
}
|
||||
subsys_initcall(omap2xxx_prm_init);
|
||||
|
||||
static void __exit omap2xxx_prm_exit(void)
|
||||
{
|
||||
|
|
|
@ -126,8 +126,7 @@ extern int omap2xxx_clkdm_wakeup(struct clockdomain *clkdm);
|
|||
|
||||
extern void omap2xxx_prm_dpll_reset(void);
|
||||
|
||||
extern int __init prm2xxx_init(void);
|
||||
extern int __exit prm2xxx_exit(void);
|
||||
extern int __init omap2xxx_prm_init(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -152,6 +152,7 @@ extern int omap2_clkdm_clear_all_wkdeps(struct clockdomain *clkdm);
|
|||
/* Named PRCM_CLKSRC_CTRL on the 24XX */
|
||||
#define OMAP_SYSCLKDIV_SHIFT 6
|
||||
#define OMAP_SYSCLKDIV_MASK (0x3 << 6)
|
||||
#define OMAP_SYSCLKDIV_WIDTH 2
|
||||
#define OMAP_AUTOEXTCLKMODE_SHIFT 3
|
||||
#define OMAP_AUTOEXTCLKMODE_MASK (0x3 << 3)
|
||||
#define OMAP_SYSCLKSEL_SHIFT 0
|
||||
|
|
|
@ -383,27 +383,30 @@ static struct prm_ll_data omap3xxx_prm_ll_data = {
|
|||
.read_reset_sources = &omap3xxx_prm_read_reset_sources,
|
||||
};
|
||||
|
||||
static int __init omap3xxx_prm_init(void)
|
||||
int __init omap3xxx_prm_init(void)
|
||||
{
|
||||
if (!cpu_is_omap34xx())
|
||||
return 0;
|
||||
|
||||
return prm_register(&omap3xxx_prm_ll_data);
|
||||
}
|
||||
|
||||
static int __init omap3xxx_prm_late_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!cpu_is_omap34xx())
|
||||
return 0;
|
||||
|
||||
ret = prm_register(&omap3xxx_prm_ll_data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
omap3xxx_prm_enable_io_wakeup();
|
||||
ret = omap_prcm_register_chain_handler(&omap3_prcm_irq_setup);
|
||||
if (!ret)
|
||||
irq_set_status_flags(omap_prcm_event_to_irq("io"),
|
||||
IRQ_NOAUTOEN);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
subsys_initcall(omap3xxx_prm_init);
|
||||
subsys_initcall(omap3xxx_prm_late_init);
|
||||
|
||||
static void __exit omap3xxx_prm_exit(void)
|
||||
{
|
||||
|
|
|
@ -154,6 +154,7 @@ extern void omap3xxx_prm_restore_irqen(u32 *saved_mask);
|
|||
|
||||
extern void omap3xxx_prm_dpll3_reset(void);
|
||||
|
||||
extern int __init omap3xxx_prm_init(void);
|
||||
extern u32 omap3xxx_prm_get_reset_sources(void);
|
||||
|
||||
#endif /* __ASSEMBLER */
|
||||
|
|
|
@ -346,6 +346,37 @@ static u32 omap44xx_prm_read_reset_sources(void)
|
|||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* omap44xx_prm_was_any_context_lost_old - was module hardware context lost?
|
||||
* @part: PRM partition ID (e.g., OMAP4430_PRM_PARTITION)
|
||||
* @inst: PRM instance offset (e.g., OMAP4430_PRM_MPU_INST)
|
||||
* @idx: CONTEXT register offset
|
||||
*
|
||||
* Return 1 if any bits were set in the *_CONTEXT_* register
|
||||
* identified by (@part, @inst, @idx), which means that some context
|
||||
* was lost for that module; otherwise, return 0.
|
||||
*/
|
||||
static bool omap44xx_prm_was_any_context_lost_old(u8 part, s16 inst, u16 idx)
|
||||
{
|
||||
return (omap4_prminst_read_inst_reg(part, inst, idx)) ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* omap44xx_prm_clear_context_lost_flags_old - clear context loss flags
|
||||
* @part: PRM partition ID (e.g., OMAP4430_PRM_PARTITION)
|
||||
* @inst: PRM instance offset (e.g., OMAP4430_PRM_MPU_INST)
|
||||
* @idx: CONTEXT register offset
|
||||
*
|
||||
* Clear hardware context loss bits for the module identified by
|
||||
* (@part, @inst, @idx). No return value. XXX Writes to reserved bits;
|
||||
* is there a way to avoid this?
|
||||
*/
|
||||
static void omap44xx_prm_clear_context_loss_flags_old(u8 part, s16 inst,
|
||||
u16 idx)
|
||||
{
|
||||
omap4_prminst_write_inst_reg(0xffffffff, part, inst, idx);
|
||||
}
|
||||
|
||||
/* Powerdomain low-level functions */
|
||||
|
||||
static int omap4_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
|
||||
|
@ -613,24 +644,28 @@ struct pwrdm_ops omap4_pwrdm_operations = {
|
|||
*/
|
||||
static struct prm_ll_data omap44xx_prm_ll_data = {
|
||||
.read_reset_sources = &omap44xx_prm_read_reset_sources,
|
||||
.was_any_context_lost_old = &omap44xx_prm_was_any_context_lost_old,
|
||||
.clear_context_loss_flags_old = &omap44xx_prm_clear_context_loss_flags_old,
|
||||
};
|
||||
|
||||
static int __init omap44xx_prm_init(void)
|
||||
int __init omap44xx_prm_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!cpu_is_omap44xx())
|
||||
return 0;
|
||||
|
||||
ret = prm_register(&omap44xx_prm_ll_data);
|
||||
if (ret)
|
||||
return ret;
|
||||
return prm_register(&omap44xx_prm_ll_data);
|
||||
}
|
||||
|
||||
static int __init omap44xx_prm_late_init(void)
|
||||
{
|
||||
if (!cpu_is_omap44xx())
|
||||
return 0;
|
||||
|
||||
omap44xx_prm_enable_io_wakeup();
|
||||
|
||||
return omap_prcm_register_chain_handler(&omap4_prcm_irq_setup);
|
||||
}
|
||||
subsys_initcall(omap44xx_prm_init);
|
||||
subsys_initcall(omap44xx_prm_late_init);
|
||||
|
||||
static void __exit omap44xx_prm_exit(void)
|
||||
{
|
||||
|
|
|
@ -771,6 +771,7 @@ extern void omap44xx_prm_ocp_barrier(void);
|
|||
extern void omap44xx_prm_save_and_clear_irqen(u32 *saved_mask);
|
||||
extern void omap44xx_prm_restore_irqen(u32 *saved_mask);
|
||||
|
||||
extern int __init omap44xx_prm_init(void);
|
||||
extern u32 omap44xx_prm_get_reset_sources(void);
|
||||
|
||||
# endif
|
||||
|
|
|
@ -364,6 +364,51 @@ u32 prm_read_reset_sources(void)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* prm_was_any_context_lost_old - was device context lost? (old API)
|
||||
* @part: PRM partition ID (e.g., OMAP4430_PRM_PARTITION)
|
||||
* @inst: PRM instance offset (e.g., OMAP4430_PRM_MPU_INST)
|
||||
* @idx: CONTEXT register offset
|
||||
*
|
||||
* Return 1 if any bits were set in the *_CONTEXT_* register
|
||||
* identified by (@part, @inst, @idx), which means that some context
|
||||
* was lost for that module; otherwise, return 0. XXX Deprecated;
|
||||
* callers need to use a less-SoC-dependent way to identify hardware
|
||||
* IP blocks.
|
||||
*/
|
||||
bool prm_was_any_context_lost_old(u8 part, s16 inst, u16 idx)
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
if (prm_ll_data->was_any_context_lost_old)
|
||||
ret = prm_ll_data->was_any_context_lost_old(part, inst, idx);
|
||||
else
|
||||
WARN_ONCE(1, "prm: %s: no mapping function defined\n",
|
||||
__func__);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* prm_clear_context_lost_flags_old - clear context loss flags (old API)
|
||||
* @part: PRM partition ID (e.g., OMAP4430_PRM_PARTITION)
|
||||
* @inst: PRM instance offset (e.g., OMAP4430_PRM_MPU_INST)
|
||||
* @idx: CONTEXT register offset
|
||||
*
|
||||
* Clear hardware context loss bits for the module identified by
|
||||
* (@part, @inst, @idx). No return value. XXX Deprecated; callers
|
||||
* need to use a less-SoC-dependent way to identify hardware IP
|
||||
* blocks.
|
||||
*/
|
||||
void prm_clear_context_loss_flags_old(u8 part, s16 inst, u16 idx)
|
||||
{
|
||||
if (prm_ll_data->clear_context_loss_flags_old)
|
||||
prm_ll_data->clear_context_loss_flags_old(part, inst, idx);
|
||||
else
|
||||
WARN_ONCE(1, "prm: %s: no mapping function defined\n",
|
||||
__func__);
|
||||
}
|
||||
|
||||
/**
|
||||
* prm_register - register per-SoC low-level data with the PRM
|
||||
* @pld: low-level per-SoC OMAP PRM data & function pointers to register
|
||||
|
|
|
@ -127,12 +127,14 @@
|
|||
/* AUXCLKREQ0 */
|
||||
#define OMAP4_MAPPING_SHIFT 2
|
||||
#define OMAP4_MAPPING_MASK (0x7 << 2)
|
||||
#define OMAP4_MAPPING_WIDTH 3
|
||||
#define OMAP4_ACCURACY_SHIFT 1
|
||||
#define OMAP4_ACCURACY_MASK (1 << 1)
|
||||
|
||||
/* AUXCLK0 */
|
||||
#define OMAP4_CLKDIV_SHIFT 16
|
||||
#define OMAP4_CLKDIV_MASK (0xf << 16)
|
||||
#define OMAP4_CLKDIV_WIDTH 4
|
||||
#define OMAP4_DISABLECLK_SHIFT 9
|
||||
#define OMAP4_DISABLECLK_MASK (1 << 9)
|
||||
#define OMAP4_ENABLE_SHIFT 8
|
||||
|
|
|
@ -26,9 +26,9 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/omap-dma.h>
|
||||
|
||||
#include <plat/omap-serial.h>
|
||||
#include <plat-omap/dma-omap.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "omap_hwmod.h"
|
||||
|
|
|
@ -121,6 +121,19 @@ static int __init sr_dev_init(struct omap_hwmod *oh, void *user)
|
|||
sr_data->senn_mod = 0x1;
|
||||
sr_data->senp_mod = 0x1;
|
||||
|
||||
if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
|
||||
sr_data->err_weight = OMAP3430_SR_ERRWEIGHT;
|
||||
sr_data->err_maxlimit = OMAP3430_SR_ERRMAXLIMIT;
|
||||
sr_data->accum_data = OMAP3430_SR_ACCUMDATA;
|
||||
if (!(strcmp(sr_data->name, "smartreflex_mpu"))) {
|
||||
sr_data->senn_avgweight = OMAP3430_SR1_SENNAVGWEIGHT;
|
||||
sr_data->senp_avgweight = OMAP3430_SR1_SENPAVGWEIGHT;
|
||||
} else {
|
||||
sr_data->senn_avgweight = OMAP3430_SR2_SENNAVGWEIGHT;
|
||||
sr_data->senp_avgweight = OMAP3430_SR2_SENPAVGWEIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
sr_data->voltdm = voltdm_lookup(sr_dev_attr->sensor_voltdm_name);
|
||||
if (!sr_data->voltdm) {
|
||||
pr_err("%s: Unable to get voltage domain pointer for VDD %s\n",
|
||||
|
|
|
@ -11,13 +11,20 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/div64.h>
|
||||
|
||||
#include "iomap.h"
|
||||
#include "soc.h"
|
||||
#include "voltage.h"
|
||||
#include "vc.h"
|
||||
#include "prm-regbits-34xx.h"
|
||||
#include "prm-regbits-44xx.h"
|
||||
#include "prm44xx.h"
|
||||
#include "pm.h"
|
||||
#include "scrm44xx.h"
|
||||
#include "control.h"
|
||||
|
||||
/**
|
||||
* struct omap_vc_channel_cfg - describe the cfg_channel bitfield
|
||||
|
@ -63,6 +70,9 @@ static struct omap_vc_channel_cfg vc_mutant_channel_cfg = {
|
|||
};
|
||||
|
||||
static struct omap_vc_channel_cfg *vc_cfg_bits;
|
||||
|
||||
/* Default I2C trace length on pcb, 6.3cm. Used for capacitance calculations. */
|
||||
static u32 sr_i2c_pcb_length = 63;
|
||||
#define CFG_CHANNEL_MASK 0x1f
|
||||
|
||||
/**
|
||||
|
@ -135,6 +145,8 @@ int omap_vc_pre_scale(struct voltagedomain *voltdm,
|
|||
vc_cmdval |= (*target_vsel << vc->common->cmd_on_shift);
|
||||
voltdm->write(vc_cmdval, vc->cmdval_reg);
|
||||
|
||||
voltdm->vc_param->on = target_volt;
|
||||
|
||||
omap_vp_update_errorgain(voltdm, target_volt);
|
||||
|
||||
return 0;
|
||||
|
@ -202,46 +214,389 @@ int omap_vc_bypass_scale(struct voltagedomain *voltdm,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void __init omap3_vfsm_init(struct voltagedomain *voltdm)
|
||||
/* Convert microsecond value to number of 32kHz clock cycles */
|
||||
static inline u32 omap_usec_to_32k(u32 usec)
|
||||
{
|
||||
return DIV_ROUND_UP_ULL(32768ULL * (u64)usec, 1000000ULL);
|
||||
}
|
||||
|
||||
/* Set oscillator setup time for omap3 */
|
||||
static void omap3_set_clksetup(u32 usec, struct voltagedomain *voltdm)
|
||||
{
|
||||
voltdm->write(omap_usec_to_32k(usec), OMAP3_PRM_CLKSETUP_OFFSET);
|
||||
}
|
||||
|
||||
/**
|
||||
* omap3_set_i2c_timings - sets i2c sleep timings for a channel
|
||||
* @voltdm: channel to configure
|
||||
* @off_mode: select whether retention or off mode values used
|
||||
*
|
||||
* Calculates and sets up voltage controller to use I2C based
|
||||
* voltage scaling for sleep modes. This can be used for either off mode
|
||||
* or retention. Off mode has additionally an option to use sys_off_mode
|
||||
* pad, which uses a global signal to program the whole power IC to
|
||||
* off-mode.
|
||||
*/
|
||||
static void omap3_set_i2c_timings(struct voltagedomain *voltdm, bool off_mode)
|
||||
{
|
||||
unsigned long voltsetup1;
|
||||
u32 tgt_volt;
|
||||
|
||||
/*
|
||||
* Voltage Manager FSM parameters init
|
||||
* XXX This data should be passed in from the board file
|
||||
* Oscillator is shut down only if we are using sys_off_mode pad,
|
||||
* thus we set a minimal setup time here
|
||||
*/
|
||||
voltdm->write(OMAP3_CLKSETUP, OMAP3_PRM_CLKSETUP_OFFSET);
|
||||
voltdm->write(OMAP3_VOLTOFFSET, OMAP3_PRM_VOLTOFFSET_OFFSET);
|
||||
voltdm->write(OMAP3_VOLTSETUP2, OMAP3_PRM_VOLTSETUP2_OFFSET);
|
||||
omap3_set_clksetup(1, voltdm);
|
||||
|
||||
if (off_mode)
|
||||
tgt_volt = voltdm->vc_param->off;
|
||||
else
|
||||
tgt_volt = voltdm->vc_param->ret;
|
||||
|
||||
voltsetup1 = (voltdm->vc_param->on - tgt_volt) /
|
||||
voltdm->pmic->slew_rate;
|
||||
|
||||
voltsetup1 = voltsetup1 * voltdm->sys_clk.rate / 8 / 1000000 + 1;
|
||||
|
||||
voltdm->rmw(voltdm->vfsm->voltsetup_mask,
|
||||
voltsetup1 << __ffs(voltdm->vfsm->voltsetup_mask),
|
||||
voltdm->vfsm->voltsetup_reg);
|
||||
|
||||
/*
|
||||
* pmic is not controlling the voltage scaling during retention,
|
||||
* thus set voltsetup2 to 0
|
||||
*/
|
||||
voltdm->write(0, OMAP3_PRM_VOLTSETUP2_OFFSET);
|
||||
}
|
||||
|
||||
/**
|
||||
* omap3_set_off_timings - sets off-mode timings for a channel
|
||||
* @voltdm: channel to configure
|
||||
*
|
||||
* Calculates and sets up off-mode timings for a channel. Off-mode
|
||||
* can use either I2C based voltage scaling, or alternatively
|
||||
* sys_off_mode pad can be used to send a global command to power IC.
|
||||
* This function first checks which mode is being used, and calls
|
||||
* omap3_set_i2c_timings() if the system is using I2C control mode.
|
||||
* sys_off_mode has the additional benefit that voltages can be
|
||||
* scaled to zero volt level with TWL4030 / TWL5030, I2C can only
|
||||
* scale to 600mV.
|
||||
*/
|
||||
static void omap3_set_off_timings(struct voltagedomain *voltdm)
|
||||
{
|
||||
unsigned long clksetup;
|
||||
unsigned long voltsetup2;
|
||||
unsigned long voltsetup2_old;
|
||||
u32 val;
|
||||
u32 tstart, tshut;
|
||||
|
||||
/* check if sys_off_mode is used to control off-mode voltages */
|
||||
val = voltdm->read(OMAP3_PRM_VOLTCTRL_OFFSET);
|
||||
if (!(val & OMAP3430_SEL_OFF_MASK)) {
|
||||
/* No, omap is controlling them over I2C */
|
||||
omap3_set_i2c_timings(voltdm, true);
|
||||
return;
|
||||
}
|
||||
|
||||
omap_pm_get_oscillator(&tstart, &tshut);
|
||||
omap3_set_clksetup(tstart, voltdm);
|
||||
|
||||
clksetup = voltdm->read(OMAP3_PRM_CLKSETUP_OFFSET);
|
||||
|
||||
/* voltsetup 2 in us */
|
||||
voltsetup2 = voltdm->vc_param->on / voltdm->pmic->slew_rate;
|
||||
|
||||
/* convert to 32k clk cycles */
|
||||
voltsetup2 = DIV_ROUND_UP(voltsetup2 * 32768, 1000000);
|
||||
|
||||
voltsetup2_old = voltdm->read(OMAP3_PRM_VOLTSETUP2_OFFSET);
|
||||
|
||||
/*
|
||||
* Update voltsetup2 if higher than current value (needed because
|
||||
* we have multiple channels with different ramp times), also
|
||||
* update voltoffset always to value recommended by TRM
|
||||
*/
|
||||
if (voltsetup2 > voltsetup2_old) {
|
||||
voltdm->write(voltsetup2, OMAP3_PRM_VOLTSETUP2_OFFSET);
|
||||
voltdm->write(clksetup - voltsetup2,
|
||||
OMAP3_PRM_VOLTOFFSET_OFFSET);
|
||||
} else
|
||||
voltdm->write(clksetup - voltsetup2_old,
|
||||
OMAP3_PRM_VOLTOFFSET_OFFSET);
|
||||
|
||||
/*
|
||||
* omap is not controlling voltage scaling during off-mode,
|
||||
* thus set voltsetup1 to 0
|
||||
*/
|
||||
voltdm->rmw(voltdm->vfsm->voltsetup_mask, 0,
|
||||
voltdm->vfsm->voltsetup_reg);
|
||||
|
||||
/* voltoffset must be clksetup minus voltsetup2 according to TRM */
|
||||
voltdm->write(clksetup - voltsetup2, OMAP3_PRM_VOLTOFFSET_OFFSET);
|
||||
}
|
||||
|
||||
static void __init omap3_vc_init_channel(struct voltagedomain *voltdm)
|
||||
{
|
||||
static bool is_initialized;
|
||||
|
||||
if (is_initialized)
|
||||
return;
|
||||
|
||||
omap3_vfsm_init(voltdm);
|
||||
|
||||
is_initialized = true;
|
||||
omap3_set_off_timings(voltdm);
|
||||
}
|
||||
|
||||
/**
|
||||
* omap4_calc_volt_ramp - calculates voltage ramping delays on omap4
|
||||
* @voltdm: channel to calculate values for
|
||||
* @voltage_diff: voltage difference in microvolts
|
||||
*
|
||||
* Calculates voltage ramp prescaler + counter values for a voltage
|
||||
* difference on omap4. Returns a field value suitable for writing to
|
||||
* VOLTSETUP register for a channel in following format:
|
||||
* bits[8:9] prescaler ... bits[0:5] counter. See OMAP4 TRM for reference.
|
||||
*/
|
||||
static u32 omap4_calc_volt_ramp(struct voltagedomain *voltdm, u32 voltage_diff)
|
||||
{
|
||||
u32 prescaler;
|
||||
u32 cycles;
|
||||
u32 time;
|
||||
|
||||
time = voltage_diff / voltdm->pmic->slew_rate;
|
||||
|
||||
cycles = voltdm->sys_clk.rate / 1000 * time / 1000;
|
||||
|
||||
cycles /= 64;
|
||||
prescaler = 0;
|
||||
|
||||
/* shift to next prescaler until no overflow */
|
||||
|
||||
/* scale for div 256 = 64 * 4 */
|
||||
if (cycles > 63) {
|
||||
cycles /= 4;
|
||||
prescaler++;
|
||||
}
|
||||
|
||||
/* scale for div 512 = 256 * 2 */
|
||||
if (cycles > 63) {
|
||||
cycles /= 2;
|
||||
prescaler++;
|
||||
}
|
||||
|
||||
/* scale for div 2048 = 512 * 4 */
|
||||
if (cycles > 63) {
|
||||
cycles /= 4;
|
||||
prescaler++;
|
||||
}
|
||||
|
||||
/* check for overflow => invalid ramp time */
|
||||
if (cycles > 63) {
|
||||
pr_warn("%s: invalid setuptime for vdd_%s\n", __func__,
|
||||
voltdm->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cycles++;
|
||||
|
||||
return (prescaler << OMAP4430_RAMP_UP_PRESCAL_SHIFT) |
|
||||
(cycles << OMAP4430_RAMP_UP_COUNT_SHIFT);
|
||||
}
|
||||
|
||||
/**
|
||||
* omap4_usec_to_val_scrm - convert microsecond value to SCRM module bitfield
|
||||
* @usec: microseconds
|
||||
* @shift: number of bits to shift left
|
||||
* @mask: bitfield mask
|
||||
*
|
||||
* Converts microsecond value to OMAP4 SCRM bitfield. Bitfield is
|
||||
* shifted to requested position, and checked agains the mask value.
|
||||
* If larger, forced to the max value of the field (i.e. the mask itself.)
|
||||
* Returns the SCRM bitfield value.
|
||||
*/
|
||||
static u32 omap4_usec_to_val_scrm(u32 usec, int shift, u32 mask)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = omap_usec_to_32k(usec) << shift;
|
||||
|
||||
/* Check for overflow, if yes, force to max value */
|
||||
if (val > mask)
|
||||
val = mask;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* omap4_set_timings - set voltage ramp timings for a channel
|
||||
* @voltdm: channel to configure
|
||||
* @off_mode: whether off-mode values are used
|
||||
*
|
||||
* Calculates and sets the voltage ramp up / down values for a channel.
|
||||
*/
|
||||
static void omap4_set_timings(struct voltagedomain *voltdm, bool off_mode)
|
||||
{
|
||||
u32 val;
|
||||
u32 ramp;
|
||||
int offset;
|
||||
u32 tstart, tshut;
|
||||
|
||||
if (off_mode) {
|
||||
ramp = omap4_calc_volt_ramp(voltdm,
|
||||
voltdm->vc_param->on - voltdm->vc_param->off);
|
||||
offset = voltdm->vfsm->voltsetup_off_reg;
|
||||
} else {
|
||||
ramp = omap4_calc_volt_ramp(voltdm,
|
||||
voltdm->vc_param->on - voltdm->vc_param->ret);
|
||||
offset = voltdm->vfsm->voltsetup_reg;
|
||||
}
|
||||
|
||||
if (!ramp)
|
||||
return;
|
||||
|
||||
val = voltdm->read(offset);
|
||||
|
||||
val |= ramp << OMAP4430_RAMP_DOWN_COUNT_SHIFT;
|
||||
|
||||
val |= ramp << OMAP4430_RAMP_UP_COUNT_SHIFT;
|
||||
|
||||
voltdm->write(val, offset);
|
||||
|
||||
omap_pm_get_oscillator(&tstart, &tshut);
|
||||
|
||||
val = omap4_usec_to_val_scrm(tstart, OMAP4_SETUPTIME_SHIFT,
|
||||
OMAP4_SETUPTIME_MASK);
|
||||
val |= omap4_usec_to_val_scrm(tshut, OMAP4_DOWNTIME_SHIFT,
|
||||
OMAP4_DOWNTIME_MASK);
|
||||
|
||||
__raw_writel(val, OMAP4_SCRM_CLKSETUPTIME);
|
||||
}
|
||||
|
||||
/* OMAP4 specific voltage init functions */
|
||||
static void __init omap4_vc_init_channel(struct voltagedomain *voltdm)
|
||||
{
|
||||
static bool is_initialized;
|
||||
u32 vc_val;
|
||||
|
||||
if (is_initialized)
|
||||
return;
|
||||
|
||||
/* XXX These are magic numbers and do not belong! */
|
||||
vc_val = (0x60 << OMAP4430_SCLL_SHIFT | 0x26 << OMAP4430_SCLH_SHIFT);
|
||||
voltdm->write(vc_val, OMAP4_PRM_VC_CFG_I2C_CLK_OFFSET);
|
||||
|
||||
is_initialized = true;
|
||||
omap4_set_timings(voltdm, true);
|
||||
omap4_set_timings(voltdm, false);
|
||||
}
|
||||
|
||||
struct i2c_init_data {
|
||||
u8 loadbits;
|
||||
u8 load;
|
||||
u8 hsscll_38_4;
|
||||
u8 hsscll_26;
|
||||
u8 hsscll_19_2;
|
||||
u8 hsscll_16_8;
|
||||
u8 hsscll_12;
|
||||
};
|
||||
|
||||
static const __initdata struct i2c_init_data omap4_i2c_timing_data[] = {
|
||||
{
|
||||
.load = 50,
|
||||
.loadbits = 0x3,
|
||||
.hsscll_38_4 = 13,
|
||||
.hsscll_26 = 11,
|
||||
.hsscll_19_2 = 9,
|
||||
.hsscll_16_8 = 9,
|
||||
.hsscll_12 = 8,
|
||||
},
|
||||
{
|
||||
.load = 25,
|
||||
.loadbits = 0x2,
|
||||
.hsscll_38_4 = 13,
|
||||
.hsscll_26 = 11,
|
||||
.hsscll_19_2 = 9,
|
||||
.hsscll_16_8 = 9,
|
||||
.hsscll_12 = 8,
|
||||
},
|
||||
{
|
||||
.load = 12,
|
||||
.loadbits = 0x1,
|
||||
.hsscll_38_4 = 11,
|
||||
.hsscll_26 = 10,
|
||||
.hsscll_19_2 = 9,
|
||||
.hsscll_16_8 = 9,
|
||||
.hsscll_12 = 8,
|
||||
},
|
||||
{
|
||||
.load = 0,
|
||||
.loadbits = 0x0,
|
||||
.hsscll_38_4 = 12,
|
||||
.hsscll_26 = 10,
|
||||
.hsscll_19_2 = 9,
|
||||
.hsscll_16_8 = 8,
|
||||
.hsscll_12 = 8,
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* omap4_vc_i2c_timing_init - sets up board I2C timing parameters
|
||||
* @voltdm: voltagedomain pointer to get data from
|
||||
*
|
||||
* Use PMIC + board supplied settings for calculating the total I2C
|
||||
* channel capacitance and set the timing parameters based on this.
|
||||
* Pre-calculated values are provided in data tables, as it is not
|
||||
* too straightforward to calculate these runtime.
|
||||
*/
|
||||
static void __init omap4_vc_i2c_timing_init(struct voltagedomain *voltdm)
|
||||
{
|
||||
u32 capacitance;
|
||||
u32 val;
|
||||
u16 hsscll;
|
||||
const struct i2c_init_data *i2c_data;
|
||||
|
||||
if (!voltdm->pmic->i2c_high_speed) {
|
||||
pr_warn("%s: only high speed supported!\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
/* PCB trace capacitance, 0.125pF / mm => mm / 8 */
|
||||
capacitance = DIV_ROUND_UP(sr_i2c_pcb_length, 8);
|
||||
|
||||
/* OMAP pad capacitance */
|
||||
capacitance += 4;
|
||||
|
||||
/* PMIC pad capacitance */
|
||||
capacitance += voltdm->pmic->i2c_pad_load;
|
||||
|
||||
/* Search for capacitance match in the table */
|
||||
i2c_data = omap4_i2c_timing_data;
|
||||
|
||||
while (i2c_data->load > capacitance)
|
||||
i2c_data++;
|
||||
|
||||
/* Select proper values based on sysclk frequency */
|
||||
switch (voltdm->sys_clk.rate) {
|
||||
case 38400000:
|
||||
hsscll = i2c_data->hsscll_38_4;
|
||||
break;
|
||||
case 26000000:
|
||||
hsscll = i2c_data->hsscll_26;
|
||||
break;
|
||||
case 19200000:
|
||||
hsscll = i2c_data->hsscll_19_2;
|
||||
break;
|
||||
case 16800000:
|
||||
hsscll = i2c_data->hsscll_16_8;
|
||||
break;
|
||||
case 12000000:
|
||||
hsscll = i2c_data->hsscll_12;
|
||||
break;
|
||||
default:
|
||||
pr_warn("%s: unsupported sysclk rate: %d!\n", __func__,
|
||||
voltdm->sys_clk.rate);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Loadbits define pull setup for the I2C channels */
|
||||
val = i2c_data->loadbits << 25 | i2c_data->loadbits << 29;
|
||||
|
||||
/* Write to SYSCTRL_PADCONF_WKUP_CTRL_I2C_2 to setup I2C pull */
|
||||
__raw_writel(val, OMAP2_L4_IO_ADDRESS(OMAP4_CTRL_MODULE_PAD_WKUP +
|
||||
OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_I2C_2));
|
||||
|
||||
/* HSSCLH can always be zero */
|
||||
val = hsscll << OMAP4430_HSSCLL_SHIFT;
|
||||
val |= (0x28 << OMAP4430_SCLL_SHIFT | 0x2c << OMAP4430_SCLH_SHIFT);
|
||||
|
||||
/* Write setup times to I2C config register */
|
||||
voltdm->write(val, OMAP4_PRM_VC_CFG_I2C_CLK_OFFSET);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* omap_vc_i2c_init - initialize I2C interface to PMIC
|
||||
* @voltdm: voltage domain containing VC data
|
||||
|
@ -281,9 +636,51 @@ static void __init omap_vc_i2c_init(struct voltagedomain *voltdm)
|
|||
mcode << __ffs(vc->common->i2c_mcode_mask),
|
||||
vc->common->i2c_cfg_reg);
|
||||
|
||||
if (cpu_is_omap44xx())
|
||||
omap4_vc_i2c_timing_init(voltdm);
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* omap_vc_calc_vsel - calculate vsel value for a channel
|
||||
* @voltdm: channel to calculate value for
|
||||
* @uvolt: microvolt value to convert to vsel
|
||||
*
|
||||
* Converts a microvolt value to vsel value for the used PMIC.
|
||||
* This checks whether the microvolt value is out of bounds, and
|
||||
* adjusts the value accordingly. If unsupported value detected,
|
||||
* warning is thrown.
|
||||
*/
|
||||
static u8 omap_vc_calc_vsel(struct voltagedomain *voltdm, u32 uvolt)
|
||||
{
|
||||
if (voltdm->pmic->vddmin > uvolt)
|
||||
uvolt = voltdm->pmic->vddmin;
|
||||
if (voltdm->pmic->vddmax < uvolt) {
|
||||
WARN(1, "%s: voltage not supported by pmic: %u vs max %u\n",
|
||||
__func__, uvolt, voltdm->pmic->vddmax);
|
||||
/* Lets try maximum value anyway */
|
||||
uvolt = voltdm->pmic->vddmax;
|
||||
}
|
||||
|
||||
return voltdm->pmic->uv_to_vsel(uvolt);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
/**
|
||||
* omap_pm_setup_sr_i2c_pcb_length - set length of SR I2C traces on PCB
|
||||
* @mm: length of the PCB trace in millimetres
|
||||
*
|
||||
* Sets the PCB trace length for the I2C channel. By default uses 63mm.
|
||||
* This is needed for properly calculating the capacitance value for
|
||||
* the PCB trace, and for setting the SR I2C channel timing parameters.
|
||||
*/
|
||||
void __init omap_pm_setup_sr_i2c_pcb_length(u32 mm)
|
||||
{
|
||||
sr_i2c_pcb_length = mm;
|
||||
}
|
||||
#endif
|
||||
|
||||
void __init omap_vc_init_channel(struct voltagedomain *voltdm)
|
||||
{
|
||||
struct omap_vc_channel *vc = voltdm->vc;
|
||||
|
@ -311,7 +708,6 @@ void __init omap_vc_init_channel(struct voltagedomain *voltdm)
|
|||
vc->i2c_slave_addr = voltdm->pmic->i2c_slave_addr;
|
||||
vc->volt_reg_addr = voltdm->pmic->volt_reg_addr;
|
||||
vc->cmd_reg_addr = voltdm->pmic->cmd_reg_addr;
|
||||
vc->setup_time = voltdm->pmic->volt_setup_time;
|
||||
|
||||
/* Configure the i2c slave address for this VC */
|
||||
voltdm->rmw(vc->smps_sa_mask,
|
||||
|
@ -331,14 +727,18 @@ void __init omap_vc_init_channel(struct voltagedomain *voltdm)
|
|||
voltdm->rmw(vc->smps_cmdra_mask,
|
||||
vc->cmd_reg_addr << __ffs(vc->smps_cmdra_mask),
|
||||
vc->smps_cmdra_reg);
|
||||
vc->cfg_channel |= vc_cfg_bits->rac | vc_cfg_bits->racen;
|
||||
vc->cfg_channel |= vc_cfg_bits->rac;
|
||||
}
|
||||
|
||||
if (vc->cmd_reg_addr == vc->volt_reg_addr)
|
||||
vc->cfg_channel |= vc_cfg_bits->racen;
|
||||
|
||||
/* Set up the on, inactive, retention and off voltage */
|
||||
on_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->on_volt);
|
||||
onlp_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->onlp_volt);
|
||||
ret_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->ret_volt);
|
||||
off_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->off_volt);
|
||||
on_vsel = omap_vc_calc_vsel(voltdm, voltdm->vc_param->on);
|
||||
onlp_vsel = omap_vc_calc_vsel(voltdm, voltdm->vc_param->onlp);
|
||||
ret_vsel = omap_vc_calc_vsel(voltdm, voltdm->vc_param->ret);
|
||||
off_vsel = omap_vc_calc_vsel(voltdm, voltdm->vc_param->off);
|
||||
|
||||
val = ((on_vsel << vc->common->cmd_on_shift) |
|
||||
(onlp_vsel << vc->common->cmd_onlp_shift) |
|
||||
(ret_vsel << vc->common->cmd_ret_shift) |
|
||||
|
@ -349,11 +749,6 @@ void __init omap_vc_init_channel(struct voltagedomain *voltdm)
|
|||
/* Channel configuration */
|
||||
omap_vc_config_channel(voltdm);
|
||||
|
||||
/* Configure the setup times */
|
||||
voltdm->rmw(voltdm->vfsm->voltsetup_mask,
|
||||
vc->setup_time << __ffs(voltdm->vfsm->voltsetup_mask),
|
||||
voltdm->vfsm->voltsetup_reg);
|
||||
|
||||
omap_vc_i2c_init(voltdm);
|
||||
|
||||
if (cpu_is_omap34xx())
|
||||
|
|
|
@ -86,7 +86,6 @@ struct omap_vc_channel {
|
|||
u16 i2c_slave_addr;
|
||||
u16 volt_reg_addr;
|
||||
u16 cmd_reg_addr;
|
||||
u16 setup_time;
|
||||
u8 cfg_channel;
|
||||
bool i2c_high_speed;
|
||||
|
||||
|
@ -111,6 +110,13 @@ extern struct omap_vc_channel omap4_vc_mpu;
|
|||
extern struct omap_vc_channel omap4_vc_iva;
|
||||
extern struct omap_vc_channel omap4_vc_core;
|
||||
|
||||
extern struct omap_vc_param omap3_mpu_vc_data;
|
||||
extern struct omap_vc_param omap3_core_vc_data;
|
||||
|
||||
extern struct omap_vc_param omap4_mpu_vc_data;
|
||||
extern struct omap_vc_param omap4_iva_vc_data;
|
||||
extern struct omap_vc_param omap4_core_vc_data;
|
||||
|
||||
void omap_vc_init_channel(struct voltagedomain *voltdm);
|
||||
int omap_vc_pre_scale(struct voltagedomain *voltdm,
|
||||
unsigned long target_volt,
|
||||
|
|
|
@ -71,3 +71,25 @@ struct omap_vc_channel omap3_vc_core = {
|
|||
.smps_cmdra_mask = OMAP3430_CMDRA1_MASK,
|
||||
.cfg_channel_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA1_SHIFT,
|
||||
};
|
||||
|
||||
/*
|
||||
* Voltage levels for different operating modes: on, sleep, retention and off
|
||||
*/
|
||||
#define OMAP3_ON_VOLTAGE_UV 1200000
|
||||
#define OMAP3_ONLP_VOLTAGE_UV 1000000
|
||||
#define OMAP3_RET_VOLTAGE_UV 975000
|
||||
#define OMAP3_OFF_VOLTAGE_UV 600000
|
||||
|
||||
struct omap_vc_param omap3_mpu_vc_data = {
|
||||
.on = OMAP3_ON_VOLTAGE_UV,
|
||||
.onlp = OMAP3_ONLP_VOLTAGE_UV,
|
||||
.ret = OMAP3_RET_VOLTAGE_UV,
|
||||
.off = OMAP3_OFF_VOLTAGE_UV,
|
||||
};
|
||||
|
||||
struct omap_vc_param omap3_core_vc_data = {
|
||||
.on = OMAP3_ON_VOLTAGE_UV,
|
||||
.onlp = OMAP3_ONLP_VOLTAGE_UV,
|
||||
.ret = OMAP3_RET_VOLTAGE_UV,
|
||||
.off = OMAP3_OFF_VOLTAGE_UV,
|
||||
};
|
||||
|
|
|
@ -87,3 +87,31 @@ struct omap_vc_channel omap4_vc_core = {
|
|||
.cfg_channel_sa_shift = OMAP4430_SA_VDD_CORE_L_SHIFT,
|
||||
};
|
||||
|
||||
/*
|
||||
* Voltage levels for different operating modes: on, sleep, retention and off
|
||||
*/
|
||||
#define OMAP4_ON_VOLTAGE_UV 1375000
|
||||
#define OMAP4_ONLP_VOLTAGE_UV 1375000
|
||||
#define OMAP4_RET_VOLTAGE_UV 837500
|
||||
#define OMAP4_OFF_VOLTAGE_UV 0
|
||||
|
||||
struct omap_vc_param omap4_mpu_vc_data = {
|
||||
.on = OMAP4_ON_VOLTAGE_UV,
|
||||
.onlp = OMAP4_ONLP_VOLTAGE_UV,
|
||||
.ret = OMAP4_RET_VOLTAGE_UV,
|
||||
.off = OMAP4_OFF_VOLTAGE_UV,
|
||||
};
|
||||
|
||||
struct omap_vc_param omap4_iva_vc_data = {
|
||||
.on = OMAP4_ON_VOLTAGE_UV,
|
||||
.onlp = OMAP4_ONLP_VOLTAGE_UV,
|
||||
.ret = OMAP4_RET_VOLTAGE_UV,
|
||||
.off = OMAP4_OFF_VOLTAGE_UV,
|
||||
};
|
||||
|
||||
struct omap_vc_param omap4_core_vc_data = {
|
||||
.on = OMAP4_ON_VOLTAGE_UV,
|
||||
.onlp = OMAP4_ONLP_VOLTAGE_UV,
|
||||
.ret = OMAP4_RET_VOLTAGE_UV,
|
||||
.off = OMAP4_OFF_VOLTAGE_UV,
|
||||
};
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue