112 lines
3.3 KiB
C
Executable File
112 lines
3.3 KiB
C
Executable File
/*
|
|
* Copyright (c) 2012 Samsung Electronics Co., Ltd.
|
|
* http://www.samsung.com/
|
|
*
|
|
* EXYNOS - PPMU support
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/types.h>
|
|
#include <linux/io.h>
|
|
|
|
#include "exynos_ppmu.h"
|
|
|
|
#define PPMU_PMNC 0x4
|
|
#define PPMU_CNTENS 0x8
|
|
#define PPMU_CNT_AUTO 0x30
|
|
#define PPMU_PMCNT0_HIGH 0x004C
|
|
#define PPMU_PMCNT1_HIGH 0x0050
|
|
#define PPMU_PMCNT2_HIGH 0x0054
|
|
#define PPMU_PMCNT3_HIGH 0x0044
|
|
#define PPMU_CCNT_HIGH 0x0058
|
|
#define PPMU_PMCNT0_LOW 0x0034
|
|
#define PPMU_PMCNT1_LOW 0x0038
|
|
#define PPMU_PMCNT2_LOW 0x003C
|
|
#define PPMU_PMCNT3_LOW 0x0040
|
|
#define PPMU_CCNT_LOW 0x0048
|
|
#define PPMU_CH_EV0_TYPE 0x200
|
|
#define PPMU_CH_EV1_TYPE 0x204
|
|
#define PPMU_CH_EV2_TYPE 0x208
|
|
#define PPMU_CH_EV3_TYPE 0x20c
|
|
#define PPMU_SM_ID_V 0x220
|
|
#define PPMU_SM_ID_A 0x224
|
|
|
|
#define EVENT_RD_ACTIVATED 0x0
|
|
#define EVENT_WR_ACTIVATED 0x1
|
|
#define EVENT_RD_DATA 0x4
|
|
#define EVENT3_RD_DATA 0x4
|
|
#define EVENT3_WR_DATA 0x5
|
|
#define EVENT3_RW_DATA 0x22
|
|
|
|
|
|
/* 0x1: disable Q channel */
|
|
/* auto mode */
|
|
#define BIT_REGVALUE ((0x1<<24) | (0x1<<20))
|
|
#define BIT_CH_CCNT (0x1<<31)
|
|
#define BIT_CH_PMCNT0 (0x1<<0)
|
|
#define BIT_CH_PMCNT1 (0x1<<1)
|
|
#define BIT_CH_PMCNT2 (0x1<<2)
|
|
#define BIT_CH_PMCNT3 (0x1<<3)
|
|
#define BIT_CH_ALL (BIT_CH_CCNT | BIT_CH_PMCNT0 | \
|
|
BIT_CH_PMCNT1 | BIT_CH_PMCNT2 | \
|
|
BIT_CH_PMCNT3)
|
|
|
|
void exynos_read_ppmu(struct ppmu_data *ppmu, void __iomem *ppmu_base,
|
|
u32 channel)
|
|
{
|
|
if (!channel)
|
|
channel = BIT_CH_ALL;
|
|
if (channel & BIT_CH_CCNT)
|
|
ppmu->ccnt = __raw_readl(ppmu_base + PPMU_CCNT_LOW);
|
|
if (channel & BIT_CH_PMCNT0)
|
|
ppmu->pmcnt0 = __raw_readl(ppmu_base + PPMU_PMCNT0_LOW);
|
|
if (channel & BIT_CH_PMCNT1)
|
|
ppmu->pmcnt1 = __raw_readl(ppmu_base + PPMU_PMCNT1_LOW);
|
|
if (channel & BIT_CH_PMCNT2)
|
|
ppmu->pmcnt2 = __raw_readl(ppmu_base + PPMU_PMCNT2_LOW);
|
|
if (channel & BIT_CH_PMCNT3)
|
|
ppmu->pmcnt3 = __raw_readl(ppmu_base + PPMU_PMCNT3_LOW);
|
|
}
|
|
|
|
void exynos_init_ppmu(void __iomem *ppmu_base, u32 mask_v, u32 mask_a)
|
|
{
|
|
|
|
__raw_writel(BIT_REGVALUE | 0x6, ppmu_base + PPMU_PMNC);
|
|
/* Count Enable CCNT, PMCNTTx */
|
|
__raw_writel(BIT_CH_ALL, ppmu_base + PPMU_CNTENS);
|
|
__raw_writel(EVENT_RD_ACTIVATED, ppmu_base + PPMU_CH_EV0_TYPE);
|
|
__raw_writel(EVENT_WR_ACTIVATED, ppmu_base + PPMU_CH_EV1_TYPE);
|
|
__raw_writel(EVENT_RD_DATA, ppmu_base + PPMU_CH_EV2_TYPE);
|
|
__raw_writel(EVENT3_WR_DATA, ppmu_base + PPMU_CH_EV3_TYPE);
|
|
if (mask_v) {
|
|
__raw_writel(mask_v, ppmu_base + PPMU_SM_ID_V);
|
|
__raw_writel(mask_a, ppmu_base + PPMU_SM_ID_A);
|
|
}
|
|
}
|
|
|
|
void exynos_reset_ppmu(void __iomem *ppmu_base, u32 channel)
|
|
{
|
|
if (!channel)
|
|
channel = BIT_CH_ALL;
|
|
__raw_writel(channel, ppmu_base + PPMU_CNT_AUTO);
|
|
}
|
|
|
|
void exynos_start_ppmu(void __iomem *ppmu_base)
|
|
{
|
|
__raw_writel(BIT_REGVALUE | 0x1, ppmu_base + PPMU_PMNC);
|
|
}
|
|
|
|
void exynos_stop_ppmu(void __iomem *ppmu_base)
|
|
{
|
|
__raw_writel(BIT_REGVALUE, ppmu_base + PPMU_PMNC);
|
|
}
|
|
|
|
void exynos_exit_ppmu(void __iomem *ppmu_base)
|
|
{
|
|
__raw_writel(BIT_REGVALUE, ppmu_base + PPMU_PMNC);
|
|
}
|