blob: bbb0ce3d7e5c854152eca7b6cee68a5e599dd769 [file] [log] [blame]
/*
* Copyright (C) 2018 MediaTek Inc.
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; 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/of.h>
#include <linux/of_address.h>
#include <asm/io.h>
#include <mt-plat/sync_write.h>
#include <mt-plat/mtk_io.h>
/* #include "mtk_typedefs.h" */
#include "core_plf_init.h"
#include "mtk_emi_bm.h"
#include "met_drv.h"
#include "interface.h"
#ifdef CONFIG_MTK_TINYSYS_SSPM_SUPPORT
#include "sspm/ondiemet_sspm.h"
#endif
#undef DEBUG
#define emi_readl readl
#define emi_reg_sync_writel mt_reg_sync_writel
#define MASK_MASTER 0xFF
#define MASK_TRANS_TYPE 0xFF
static void __iomem *BaseAddrEMI;
const unsigned int emi_config[] = {
EMI_BMEN,
EMI_MSEL,
EMI_MSEL2,
EMI_MSEL3,
EMI_MSEL4,
EMI_MSEL5,
EMI_MSEL6,
EMI_MSEL7,
EMI_MSEL8,
EMI_MSEL9,
EMI_MSEL10,
EMI_BMID0,
EMI_BMID1,
EMI_BMID2,
EMI_BMID3,
EMI_BMID4,
EMI_BMID5,
EMI_BMID6,
EMI_BMID7,
EMI_BMID8,
EMI_BMID9,
EMI_BMID10,
EMI_BMEN1,
EMI_BMEN2,
EMI_BMRW0,
EMI_BMRW1
};
#define EMI_CONFIG_MX_NR (sizeof(emi_config)/sizeof(unsigned int))
static unsigned int emi_config_val[EMI_CONFIG_MX_NR];
int MET_BM_Init(void)
{
/*emi*/
if (mt_cen_emi_base_get_symbol) {
BaseAddrEMI = mt_cen_emi_base_get_symbol();
} else {
pr_debug("mt_cen_emi_base_get_symbol = NULL\n");
PR_BOOTMSG_ONCE("mt_cen_emi_base_get_symbol = NULL\n");
BaseAddrEMI = 0;
}
if (BaseAddrEMI == 0) {
pr_debug("BaseAddrEMI = 0\n");
PR_BOOTMSG_ONCE("BaseAddrEMI = 0\n");
return -1;
}
pr_debug("MET EMI: map emi to %p\n", BaseAddrEMI);
PR_BOOTMSG("MET EMI: map emi to %p\n", BaseAddrEMI);
return 0;
}
void MET_BM_DeInit(void)
{
}
void MET_BM_SaveCfg(void)
{
int i;
for (i = 0; i < EMI_CONFIG_MX_NR; i++)
emi_config_val[i] = emi_readl(IOMEM(ADDR_EMI + emi_config[i]));
}
void MET_BM_RestoreCfg(void)
{
int i;
for (i = 0; i < EMI_CONFIG_MX_NR; i++)
emi_reg_sync_writel(emi_config_val[i], ADDR_EMI + emi_config[i]);
}
int MET_BM_SetMonitorCounter(const unsigned int counter_num,
const unsigned int master, const unsigned int trans_type)
{
unsigned int value, addr;
const unsigned int iMask = (MASK_TRANS_TYPE << 8) | MASK_MASTER;
if (counter_num < 1 || counter_num > BM_COUNTER_MAX)
return BM_ERR_WRONG_REQ;
if (counter_num == 1) {
addr = EMI_BMEN;
value = (emi_readl(IOMEM(ADDR_EMI + addr)) & ~(iMask << 16)) |
((trans_type & MASK_TRANS_TYPE) << 24) | ((master & MASK_MASTER) << 16);
} else {
addr = (counter_num <= 3) ? EMI_MSEL : (EMI_MSEL2 + (counter_num / 2 - 2) * 8);
value = emi_readl(IOMEM(ADDR_EMI + addr)) & ~(iMask << ((counter_num % 2) * 16));
value |= (((trans_type & MASK_TRANS_TYPE) << 8) |
(master & MASK_MASTER)) << ((counter_num % 2) * 16);
}
emi_reg_sync_writel(value, ADDR_EMI + addr);
return BM_REQ_OK;
}
int MET_BM_SetTtypeCounterRW(unsigned int bmrw0_val, unsigned int bmrw1_val)
{
unsigned int value_origin;
value_origin = emi_readl(IOMEM(ADDR_EMI + EMI_BMRW0));
MET_TRACE("[MET_EMI_settype1] value_origin: %x\n", value_origin);
if (value_origin != bmrw0_val) {
emi_reg_sync_writel(bmrw0_val, ADDR_EMI + EMI_BMRW0);
MET_TRACE("[MET_EMI_settype1] bmrw0_val: %x, value_origin: %x\n", bmrw0_val,
value_origin);
}
value_origin = emi_readl(IOMEM(ADDR_EMI + EMI_BMRW1));
MET_TRACE("[MET_EMI_settype2] value_origin: %x\n", value_origin);
if (value_origin != bmrw1_val) {
emi_reg_sync_writel(bmrw1_val, ADDR_EMI + EMI_BMRW1);
MET_TRACE("[MET_EMI_settype2] bmrw0_val: %x, value_origin: %x\n", bmrw1_val,
value_origin);
}
return BM_REQ_OK;
}
int MET_BM_Set_WsctTsct_id_sel(unsigned int counter_num, unsigned int enable)
{
unsigned int value;
if (counter_num > 3)
return BM_ERR_WRONG_REQ;
value =
((emi_readl(IOMEM(ADDR_EMI + EMI_BMEN2)) & (~(1 << (28 + counter_num)))) |
(enable << (28 + counter_num)));
emi_reg_sync_writel(value, ADDR_EMI + EMI_BMEN2);
return BM_REQ_OK;
}
int MET_BM_SetbusID_En(const unsigned int counter_num,
const unsigned int enable)
{
unsigned int value;
if ((counter_num < 1 || counter_num > BM_COUNTER_MAX) || (enable > 1))
return BM_ERR_WRONG_REQ;
if (enable == 0) {
value = (emi_readl(IOMEM(ADDR_EMI + EMI_BMEN2))
& ~(1 << (counter_num - 1)));
} else {
value = (emi_readl(IOMEM(ADDR_EMI + EMI_BMEN2))
| (1 << (counter_num - 1)));
}
emi_reg_sync_writel(value, ADDR_EMI + EMI_BMEN2);
return BM_REQ_OK;
}
int MET_BM_SetbusID(const unsigned int counter_num,
const unsigned int id)
{
unsigned int value, addr, shift_num;
if ((counter_num < 1 || counter_num > BM_COUNTER_MAX))
return BM_ERR_WRONG_REQ;
addr = EMI_BMID0 + (counter_num - 1) / 2 * 4;
shift_num = ((counter_num - 1) % 2) * 16;
value = emi_readl(IOMEM(ADDR_EMI + addr)) & ~(EMI_BMID_MASK << shift_num);
if (id <= 0xffff)
value |= id << shift_num;
emi_reg_sync_writel(value, ADDR_EMI + addr);
return BM_REQ_OK;
}
int MET_BM_SetUltraHighFilter(const unsigned int counter_num, const unsigned int enable)
{
unsigned int value;
if ((counter_num < 1 || counter_num > BM_COUNTER_MAX) || (enable > 1))
return BM_ERR_WRONG_REQ;
value = (emi_readl(IOMEM(ADDR_EMI + EMI_BMEN1))
& ~(1 << (counter_num - 1)))
| (enable << (counter_num - 1));
emi_reg_sync_writel(value, ADDR_EMI + EMI_BMEN1);
return BM_REQ_OK;
}
int MET_BM_SetLatencyCounter(unsigned int enable)
{
unsigned int value;
value = emi_readl(IOMEM(ADDR_EMI + EMI_BMEN2)) & ~(0x3 << 24);
if (enable == 1)
value |= (0x2 << 24);
emi_reg_sync_writel(value, ADDR_EMI + EMI_BMEN2);
return BM_REQ_OK;
}