blob: 551373c8aec40f05fadd67d75aa34593bfac64fc [file] [log] [blame]
/*
* 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);
}