mirror of
https://github.com/torvalds/linux.git
synced 2026-06-11 08:03:05 +02:00
[ARM] tegra: nvrm: add basic implementation of clock controls
add support for enabling, disabling and configuring the ISP, VI and CSI clocks from user-space through the RM APIs Change-Id: I652af05d5406928721ac62371b85cb3e2cbb3f6b Signed-off-by: Gary King <gking@nvidia.com>
This commit is contained in:
parent
11d90deeb8
commit
e562176306
|
|
@ -12,4 +12,5 @@ ccflags-y += -Iarch/arm/mach-tegra/nv/nvrm/core
|
|||
|
||||
obj-y += nvrm_rmctrace.o
|
||||
obj-y += nvrm_transport.o
|
||||
obj-y += nvrm_module_stub.o
|
||||
obj-y += nvrm_module_stub.o
|
||||
obj-y += nvrm_power.o
|
||||
|
|
@ -12,11 +12,14 @@
|
|||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/delay.h>
|
||||
#include <mach/iomap.h>
|
||||
|
||||
#include "nvcommon.h"
|
||||
#include "nvrm_module.h"
|
||||
#include "../../../../clock.h"
|
||||
|
||||
NvError NvRmModuleGetCapabilities( NvRmDeviceHandle hDeviceHandle,
|
||||
NvRmModuleID Module, NvRmModuleCapability * pCaps, NvU32 NumCaps,
|
||||
|
|
@ -160,18 +163,37 @@ void NvRmModuleGetBaseAddress( NvRmDeviceHandle hRmDeviceHandle, NvRmModuleID Mo
|
|||
printk("%s module %d 0x%08x x %dK\n", __func__, Module, *pBaseAddress, *pSize / 1024);
|
||||
}
|
||||
|
||||
#define is_avp(_mod) (NVRM_MODULE_ID_MODULE(_mod)==NvRmModuleID_Avp)
|
||||
#define is_csi(_mod) (NVRM_MODULE_ID_MODULE(_mod)==NvRmModuleID_Csi)
|
||||
#define is_isp(_mod) (NVRM_MODULE_ID_MODULE(_mod)==NvRmModuleID_Isp)
|
||||
#define is_vi(_mod) (NVRM_MODULE_ID_MODULE(_mod)==NvRmModuleID_Vi)
|
||||
|
||||
void NvRmModuleReset(NvRmDeviceHandle hRmDevice, NvRmModuleID Module)
|
||||
{
|
||||
struct clk *clk = NULL;
|
||||
void __iomem *clk_rst = IO_ADDRESS(TEGRA_CLK_RESET_BASE);
|
||||
if (NVRM_MODULE_ID_MODULE(Module) != NvRmModuleID_Avp ||
|
||||
NVRM_MODULE_ID_INSTANCE(Module) != 0) {
|
||||
|
||||
if (is_avp(Module)) {
|
||||
writel(1<<1, clk_rst + 0x300);
|
||||
udelay(10);
|
||||
writel(1<<1, clk_rst + 0x304);
|
||||
} else if (is_csi(Module))
|
||||
clk = clk_get_sys("csi", NULL);
|
||||
else if (is_vi(Module))
|
||||
clk = clk_get_sys("vi", NULL);
|
||||
else if (is_isp(Module))
|
||||
clk = clk_get_sys("isp", NULL);
|
||||
else {
|
||||
printk("%s MOD[%lu] INST[%lu] not implemented\n", __func__,
|
||||
NVRM_MODULE_ID_MODULE(Module),
|
||||
NVRM_MODULE_ID_INSTANCE(Module));
|
||||
return;
|
||||
}
|
||||
|
||||
writel(1<<1, clk_rst + 0x300);
|
||||
udelay(10);
|
||||
writel(1<<1, clk_rst + 0x304);
|
||||
if (clk) {
|
||||
tegra2_periph_reset_assert(clk);
|
||||
udelay(10);
|
||||
tegra2_periph_reset_deassert(clk);
|
||||
clk_put(clk);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
185
arch/arm/mach-tegra/nv/nvrm/core/common/nvrm_power.c
Normal file
185
arch/arm/mach-tegra/nv/nvrm/core/common/nvrm_power.c
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
* Copyright (c) 2010 NVIDIA Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NVIDIA Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <mach/iomap.h>
|
||||
|
||||
#include "nvcommon.h"
|
||||
#include "nvrm_power.h"
|
||||
#include "../../../../clock.h"
|
||||
|
||||
#define is_vi(module) (NVRM_MODULE_ID_MODULE(module)==NvRmModuleID_Vi)
|
||||
|
||||
#define is_csi(module) (NVRM_MODULE_ID_MODULE(module)==NvRmModuleID_Csi)
|
||||
|
||||
#define is_isp(module) (NVRM_MODULE_ID_MODULE(module)==NvRmModuleID_Isp)
|
||||
|
||||
#define CLK_VI_CORE_EXTERNAL (1<<24)
|
||||
#define CLK_VI_PAD_INTERNAL (1<<25)
|
||||
|
||||
NvError NvRmPowerModuleClockConfig(
|
||||
NvRmDeviceHandle hRmDeviceHandle,
|
||||
NvRmModuleID ModuleId,
|
||||
NvU32 ClientId,
|
||||
NvRmFreqKHz MinFreq,
|
||||
NvRmFreqKHz MaxFreq,
|
||||
const NvRmFreqKHz *PrefFreqList,
|
||||
NvU32 PrefFreqListCount,
|
||||
NvRmFreqKHz *CurrentFreq,
|
||||
NvU32 flags)
|
||||
{
|
||||
struct clk *clk = NULL;
|
||||
const char *name;
|
||||
unsigned long rate;
|
||||
int ret;
|
||||
|
||||
if (CurrentFreq)
|
||||
*CurrentFreq = 0;
|
||||
|
||||
if (!is_vi(ModuleId))
|
||||
return NvSuccess;
|
||||
|
||||
if (flags & NvRmClockConfig_SubConfig)
|
||||
name = "vi_sensor";
|
||||
else
|
||||
name = "vi";
|
||||
|
||||
clk = clk_get_sys(name, NULL);
|
||||
|
||||
if (IS_ERR_OR_NULL(clk)) {
|
||||
pr_err("%s: failed to get struct clk %s\n", __func__, name);
|
||||
return NvSuccess;
|
||||
}
|
||||
|
||||
if (PrefFreqListCount)
|
||||
rate = *PrefFreqList * 1000;
|
||||
else if (MaxFreq != NvRmFreqUnspecified)
|
||||
rate = MaxFreq * 1000;
|
||||
else if (MinFreq != NvRmFreqUnspecified)
|
||||
rate = MinFreq * 1000;
|
||||
else
|
||||
rate = INT_MAX;
|
||||
|
||||
ret = clk_set_rate(clk, rate);
|
||||
if (ret) {
|
||||
pr_err("%s: err %d setting %s to %luHz\n", __func__, ret, name, rate);
|
||||
clk_put(clk);
|
||||
return NvError_BadParameter;
|
||||
}
|
||||
|
||||
rate = clk_get_rate(clk);
|
||||
if (CurrentFreq)
|
||||
*CurrentFreq = (rate+500) / 1000;
|
||||
|
||||
|
||||
if (!(flags & NvRmClockConfig_SubConfig)) {
|
||||
void __iomem *car = IO_ADDRESS(TEGRA_CLK_RESET_BASE);
|
||||
u32 val;
|
||||
|
||||
if ((flags & NvRmClockConfig_InternalClockForPads) &&
|
||||
(flags & NvRmClockConfig_ExternalClockForCore)) {
|
||||
pr_err("%s: invalid VI flag combination: %08x\n", __func__, flags);
|
||||
clk_put(clk);
|
||||
return NvError_BadParameter;
|
||||
}
|
||||
val = readl(car + clk->reg);
|
||||
val &= ~(CLK_VI_CORE_EXTERNAL | CLK_VI_PAD_INTERNAL);
|
||||
if (flags & NvRmClockConfig_InternalClockForPads)
|
||||
val |= CLK_VI_PAD_INTERNAL;
|
||||
else if (flags & NvRmClockConfig_ExternalClockForCore)
|
||||
val |= CLK_VI_CORE_EXTERNAL;
|
||||
writel(val, car + clk->reg);
|
||||
}
|
||||
|
||||
clk_put(clk);
|
||||
return NvSuccess;
|
||||
}
|
||||
|
||||
NvError NvRmPowerModuleClockControl(
|
||||
NvRmDeviceHandle hRmDeviceHandle,
|
||||
NvRmModuleID ModuleId,
|
||||
NvU32 ClientId,
|
||||
NvBool Enable)
|
||||
{
|
||||
const char *vi_names[] = { "vi", "vi_sensor", "csus", NULL };
|
||||
const char *csi_names[] = { "csi", NULL };
|
||||
const char *isp_names[] = { "isp", NULL };
|
||||
const char **names = NULL;
|
||||
|
||||
if (is_vi(ModuleId))
|
||||
names = vi_names;
|
||||
else if (is_csi(ModuleId))
|
||||
names = csi_names;
|
||||
else if (is_isp(ModuleId))
|
||||
names = isp_names;
|
||||
|
||||
if (!names) {
|
||||
pr_err("%s: MOD[%lu] INST[%lu] not supported\n", __func__,
|
||||
NVRM_MODULE_ID_MODULE(ModuleId),
|
||||
NVRM_MODULE_ID_INSTANCE(ModuleId));
|
||||
return NvSuccess;
|
||||
}
|
||||
|
||||
for ( ; *names ; names++) {
|
||||
struct clk *clk = clk_get_sys(*names, NULL);
|
||||
|
||||
if (IS_ERR_OR_NULL(clk)) {
|
||||
pr_err("%s: unable to get struct clk for %s\n", __func__, *names);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Enable)
|
||||
clk_enable(clk);
|
||||
else
|
||||
clk_disable(clk);
|
||||
}
|
||||
|
||||
return NvSuccess;
|
||||
}
|
||||
|
||||
NvError NvRmPowerVoltageControl(
|
||||
NvRmDeviceHandle hRmDeviceHandle,
|
||||
NvRmModuleID ModuleId,
|
||||
NvU32 ClientId,
|
||||
NvRmMilliVolts MinVolts,
|
||||
NvRmMilliVolts MaxVolts,
|
||||
const NvRmMilliVolts * PrefVoltageList,
|
||||
NvU32 PrefVoltageListCount,
|
||||
NvRmMilliVolts * CurrentVolts)
|
||||
{
|
||||
return NvSuccess;
|
||||
}
|
||||
|
|
@ -21,7 +21,7 @@ obj-y += NvRm_Dispatch.o
|
|||
#obj-y += nvrm_memmgr_dispatch.o
|
||||
obj-y += nvrm_module_dispatch.o
|
||||
#obj-y += nvrm_pinmux_dispatch.o
|
||||
#obj-y += nvrm_power_dispatch.o
|
||||
obj-y += nvrm_power_dispatch.o
|
||||
#obj-y += nvrm_spi_dispatch.o
|
||||
#obj-y += nvrm_pmu_dispatch.o
|
||||
#obj-y += nvrm_keylist_dispatch.o
|
||||
|
|
|
|||
|
|
@ -162,12 +162,6 @@ NvError nvrm_dma_Dispatch( NvU32 function, void *InBuffer, NvU32 InSize, void *O
|
|||
return NvSuccess;
|
||||
}
|
||||
|
||||
NvError nvrm_power_Dispatch( NvU32 function, void *InBuffer, NvU32 InSize, void *OutBuffer, NvU32 OutSize, NvDispatchCtx* Ctx )
|
||||
{
|
||||
printk("NVRM: %s %d\n", __func__, function);
|
||||
return NvSuccess;
|
||||
}
|
||||
|
||||
NvError nvrm_gpio_Dispatch( NvU32 function, void *InBuffer, NvU32 InSize, void *OutBuffer, NvU32 OutSize, NvDispatchCtx* Ctx )
|
||||
{
|
||||
printk("NVRM: %s %d\n", __func__, function);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user