blob: d7ecb7ca38a4c06a071afc10678051273224ba6d [file] [log] [blame]
#include <linux/kernel.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/io.h>
#include <asm/cacheflush.h>
#include <asm/uaccess.h>
#include <asm/io.h>
//#include <mt-plat/sync_write.h>
//#include <mt-plat/mtk_io.h>
//#include "x_hal_io.h"
//#include "x_hal_5381.h"
#include "mtk_typedefs.h"
#include "core_plf_init.h"
#include "mtk_emi_bm.h"
#include "mtk_dramc.h"
#include "met_drv.h"
#include "interface.h"
#define IOMEM(x) ((void __force __iomem *)(x))
#define mt_reg_sync_writel(v, a) \
do { \
__raw_writel((v), (void __force __iomem *)((a))); \
mb(); \
} while (0)
#if 0
#undef MET_BOOT_MSG
#if defined(MET_BOOT_MSG)
extern char met_boot_msg_tmp[256];
extern int pr_bootmsg(int str_len, char *str);
#define PR_BOOTMSG(fmt, args...) { \
int str_len = snprintf(met_boot_msg_tmp, sizeof(met_boot_msg_tmp), \
fmt, ##args); \
pr_bootmsg(str_len, met_boot_msg_tmp); }
#define PR_BOOTMSG_ONCE(fmt, args...) { \
static int once; \
if (!once) { \
int str_len = snprintf(met_boot_msg_tmp, \
sizeof(met_boot_msg_tmp), \
fmt, ##args); \
pr_bootmsg(str_len, met_boot_msg_tmp); \
once = 1; \
} }
#else
#define pr_bootmsg(str_len, str)
#define PR_BOOTMSG(fmt, args...)
#define PR_BOOTMSG_ONCE(fmt, args...)
#endif
#endif
//static unsigned long gEMIBaseAddr = EMI_REG_BASE;
/* MET internal define */
#ifndef DRAMC0_NAO_BASE
#define DRAMC0_NAO_BASE (IO_VIRT + 0x204000)
#endif
#ifndef DRAMC1_NAO_BASE
#define DRAMC1_NAO_BASE (IO_VIRT + 0x20C000)
#endif
#ifndef DRAMC2_NAO_BASE
#define DRAMC2_NAO_BASE (IO_VIRT + 0x214000)
#endif
#ifndef DRAMC3_NAO_BASE
#define DRAMC3_NAO_BASE (IO_VIRT + 0x21C000)
#endif
static unsigned long gDRAMCBaseAddr[] =
{
DRAMC0_NAO_BASE,
DRAMC1_NAO_BASE,
DRAMC2_NAO_BASE,
DRAMC3_NAO_BASE,
};
#define MX_DRAMC_CHAN_NR (sizeof(gDRAMCBaseAddr)/sizeof(gDRAMCBaseAddr[0]))
/* GET EMI Base Address */
#if 0
unsigned long get_emi_base_addr(void)
{
return gEMIBaseAddr;
}
#endif
unsigned long get_dram_nao_base_addr(int idx)
{
if (idx >= MX_DRAMC_CHAN_NR) {
METERROR("Invalid DRAMC idx: %d !\n", idx);
PR_BOOTMSG_ONCE("Invalid DRAMC idx: %d !\n", idx);
return 0;
}
return gDRAMCBaseAddr[idx];
}
#undef DEBUG
#undef debug_reg
#ifdef debug_reg
static inline unsigned int emi_readl(void __iomem *padr)
{
unsigned int tmp;
tmp = readl(padr);
MET_TRACE("[MET_EMI] RD_Reg: %p: %08x\n", padr, tmp);
return tmp;
}
static inline void __emi_reg_sync_writel(unsigned int data, void __iomem *padr)
{
unsigned int tmp;
mt_reg_sync_writel(data, padr);
tmp = readl(padr);
MET_TRACE("[MET_EMI] WR_Reg: %p: %08x, %08x\n", padr, data, tmp);
}
#define emi_reg_sync_writel(data, adr) __emi_reg_sync_writel(data, IOMEM(adr))
#else
#define emi_readl readl
#define emi_reg_sync_writel mt_reg_sync_writel
#endif
#define MASK_MASTER 0xFF
#define MASK_TRANS_TYPE 0xFF
static void __iomem *BaseAddrEMI;
static void __iomem *BaseAddrDRAMC0;
static void __iomem *BaseAddrDRAMC1;
static void __iomem *BaseAddrDRAMC2;
static void __iomem *BaseAddrDRAMC3;
static void __iomem *AddrDramDatarate;
/*
* MET_REG_BSET/MET_REG_BCLR:
* reading value before set and clear
*/
static inline void MET_REG_BSET(unsigned long reg, u32 shift)
{
volatile unsigned int read_val = 0;
read_val = emi_readl(IOMEM(reg));
emi_reg_sync_writel(read_val | (1<<shift), reg);
}
static inline void MET_REG_BCLR(unsigned long reg, u32 shift)
{
volatile unsigned int read_val = 0;
read_val = emi_readl(IOMEM(reg));
emi_reg_sync_writel(read_val & (~((1<<shift) & 0xFFFFFFFF)), reg);
}
#define GET_EMI_FROM_DTS
//#undef GET_EMI_FROM_DTS
int MET_BM_Init(void)
{
#ifdef GET_EMI_FROM_DTS
struct device_node *node;
/* Device Tree Path */
node = of_find_compatible_node(NULL, NULL, of_emi_desc);
if (!node) {
METINFO("node of_emi_desc not found\n");
PR_BOOTMSG_ONCE("node of_emi_desc not found\n");
return -1;
}
BaseAddrEMI = (void *)of_iomap(node, 0);
#else
BaseAddrEMI = (void*)get_emi_base_addr();
#endif
if (BaseAddrEMI == 0) {
METERROR("BaseAddrEMI = 0\n");
PR_BOOTMSG_ONCE("BaseAddrEMI = 0\n");
return -1;
}
METINFO("MET EMI: map emi to %p\n", BaseAddrEMI);
PR_BOOTMSG("MET EMI: map emi to %p\n", BaseAddrEMI);
#ifdef GET_EMI_FROM_DTS
/* DRAMC TBD */
/* MAP NAO (NON-AO) DRAMC address */
node = of_find_compatible_node(NULL, NULL, of_dramc_desc);
if (!node) {
METINFO("node of_dramc_desc not found\n");
PR_BOOTMSG_ONCE("node of_dramc_desc not found\n");
return -1;
}
BaseAddrDRAMC0 = (void *)of_iomap(node, 0);
BaseAddrDRAMC1 = (void *)of_iomap(node, 1);
BaseAddrDRAMC2 = (void *)of_iomap(node, 2);
BaseAddrDRAMC3 = (void *)of_iomap(node, 3);
#else
BaseAddrDRAMC0 = (void *) get_dram_nao_base_addr(0);
BaseAddrDRAMC1 = (void *) get_dram_nao_base_addr(1);
BaseAddrDRAMC2 = (void *) get_dram_nao_base_addr(2);
BaseAddrDRAMC3 = (void *) get_dram_nao_base_addr(3);
#endif
AddrDramDatarate = ioremap_nocache(0x10100000, 0x1000);
if (AddrDramDatarate == NULL) {
pr_err("ioremap AddrDramDatarate fail ...\n");
return -1;
}
if (BaseAddrDRAMC0 == 0
|| BaseAddrDRAMC1 == 0
|| BaseAddrDRAMC2 == 0
|| BaseAddrDRAMC3 == 0
) {
METERROR("BaseAddrDRAMC0 = %p\n", BaseAddrDRAMC0);
METERROR("BaseAddrDRAMC1 = %p\n", BaseAddrDRAMC1);
METERROR("BaseAddrDRAMC2 = %p\n", BaseAddrDRAMC2);
METERROR("BaseAddrDRAMC3 = %p\n", BaseAddrDRAMC3);
PR_BOOTMSG_ONCE("BaseAddrDRAMC0 = %p\n", BaseAddrDRAMC0);
PR_BOOTMSG_ONCE("BaseAddrDRAMC1 = %p\n", BaseAddrDRAMC1);
PR_BOOTMSG_ONCE("BaseAddrDRAMC2 = %p\n", BaseAddrDRAMC2);
PR_BOOTMSG_ONCE("BaseAddrDRAMC3 = %p\n", BaseAddrDRAMC3);
return -1;
}
METINFO("MET EMI: map nao dramcA to %p\n", BaseAddrDRAMC0);
METINFO("MET EMI: map nao dramcB to %p\n", BaseAddrDRAMC1);
METINFO("MET EMI: map nao dramcC to %p\n", BaseAddrDRAMC2);
METINFO("MET EMI: map nao dramcD to %p\n", BaseAddrDRAMC3);
PR_BOOTMSG("MET EMI: map nao dramcA to %p\n", BaseAddrDRAMC0);
PR_BOOTMSG("MET EMI: map nao dramcB to %p\n", BaseAddrDRAMC1);
PR_BOOTMSG("MET EMI: map nao dramcC to %p\n", BaseAddrDRAMC2);
PR_BOOTMSG("MET EMI: map nao dramcD to %p\n", BaseAddrDRAMC3);
return 0;
}
void MET_BM_DeInit(void)
{
}
void MET_BM_Enable(const unsigned int enable)
{
volatile unsigned long int value_check;
int i = 0;
while (i < 100) {
if (enable == 0) {
/* SET BIT IDLE */
MET_REG_BSET(ADDR_EMI+EMI_BMEN, BUS_MON_IDLE_SHIFT);
/* CLR BIT EN */
MET_REG_BCLR(ADDR_EMI+EMI_BMEN, BUS_MON_EN_SHIFT);
/* CLR BIT IDLE */
MET_REG_BCLR(ADDR_EMI+EMI_BMEN, BUS_MON_IDLE_SHIFT);
} else {
/* CLR BIT IDLE */
MET_REG_BCLR(ADDR_EMI+EMI_BMEN, BUS_MON_IDLE_SHIFT);
/* SET BIT EN */
MET_REG_BSET(ADDR_EMI+EMI_BMEN, BUS_MON_EN_SHIFT);
}
value_check = emi_readl(IOMEM(ADDR_EMI+EMI_BMEN));
if (enable == 0) {
/* EN == 0, IDLE == 0 when EMI RESET*/
if (!test_bit(BUS_MON_EN_SHIFT, &value_check)
&& !test_bit(BUS_MON_IDLE_SHIFT, &value_check)) {
break;
}
} else {
/* EN == 1, IDLE == 0 when EMI START*/
if (test_bit(BUS_MON_EN_SHIFT, &value_check)
&& !test_bit(BUS_MON_IDLE_SHIFT, &value_check)) {
break;
}
}
i++;
}
for (i = 0; i < MX_DRAMC_CHAN_NR; i++) {
if (enable == 0)
/* Disable Dramc Bus Monitor */
MET_DRAMC_BMEnable(i, 0);
else
/* Enable Dramc Bus Monitor */
MET_DRAMC_BMEnable(i, 1);
}
/*MET_TRACE("[MET_BM_ENABLE] value_check: %lx, enable = %d\n", value_check, enable);*/
}
void MET_BM_Pause(void)
{
int i = 0;
const unsigned int value = emi_readl(IOMEM(ADDR_EMI+EMI_BMEN));
emi_reg_sync_writel(value | (1<<BUS_MON_PAUSE_SHIFT), ADDR_EMI+EMI_BMEN);
for (i = 0; i < MX_DRAMC_CHAN_NR; i++) {
/* Pause Dramc Bus Monitor */
MET_DRAMC_BMPause(i, 1);
}
}
void MET_BM_Continue(void)
{
int i = 0;
const unsigned int value = emi_readl(IOMEM(ADDR_EMI+EMI_BMEN));
emi_reg_sync_writel(value & (~(1<<BUS_MON_PAUSE_SHIFT)), ADDR_EMI+EMI_BMEN);
for (i = 0; i < MX_DRAMC_CHAN_NR; i++) {
/* Enable Dramc Bus Monitor */
MET_DRAMC_BMPause(i, 0);
}
}
unsigned int MET_BM_IsOverrun(void)
{
/*
* return 0 if EMI_BCNT(bus cycle counts) or
* EMI_WACT(total word counts) is overrun,
* otherwise return an !0 value
*/
const unsigned int value = emi_readl(IOMEM(ADDR_EMI+EMI_BMEN));
return (value & (1<<BC_OVERRUN_SHIFT));
}
unsigned int MET_BM_GetReadWriteType(void)
{
const unsigned int value = emi_readl(IOMEM(ADDR_EMI+EMI_BMEN));
return ((value & 0xFFFFFFCF) >> 4);
}
void MET_BM_SetReadWriteType(const unsigned int ReadWriteType)
{
const unsigned int value = emi_readl(IOMEM(ADDR_EMI+EMI_BMEN));
/*
* ReadWriteType: 00/11 --> both R/W
* 01 --> only R
* 10 --> only W
*/
emi_reg_sync_writel((value & 0xFFFFFFCF) | (ReadWriteType << 4), ADDR_EMI+EMI_BMEN);
}
int MET_BM_GetBusCycCount(void)
{
return MET_BM_IsOverrun() ? BM_ERR_OVERRUN : emi_readl(IOMEM(ADDR_EMI+EMI_BCNT));/*Bus cycle counter*/
}
unsigned int MET_BM_GetTransAllCount(void)
{
return emi_readl(IOMEM(ADDR_EMI+EMI_TACT));
}
int MET_BM_GetTransCount(const unsigned int counter_num)
{
unsigned int iCount;
switch (counter_num) {
case 1:
iCount = emi_readl(IOMEM(ADDR_EMI+EMI_TSCT));
break;
case 2:
iCount = emi_readl(IOMEM(ADDR_EMI+EMI_TSCT2));
break;
case 3:
iCount = emi_readl(IOMEM(ADDR_EMI+EMI_TSCT3));
break;
default:
return BM_ERR_WRONG_REQ;
}
return iCount;
}
int MET_BM_GetWordAllCount(void)
{
return MET_BM_IsOverrun() ? BM_ERR_OVERRUN : emi_readl(IOMEM(ADDR_EMI+EMI_WACT));
}
int MET_BM_GetWordCount(const unsigned int counter_num)
{
unsigned int iCount;
switch (counter_num) {
case 1:
iCount = emi_readl(IOMEM(ADDR_EMI+EMI_WSCT));
break;
case 2:
iCount = emi_readl(IOMEM(ADDR_EMI+EMI_WSCT2));
break;
case 3:
iCount = emi_readl(IOMEM(ADDR_EMI+EMI_WSCT3));
break;
case 4:
iCount = emi_readl(IOMEM(ADDR_EMI+EMI_WSCT4));
break;
default:
return BM_ERR_WRONG_REQ;
}
return iCount;
}
unsigned int MET_BM_GetBandwidthWordCount(void)
{
return emi_readl(IOMEM(ADDR_EMI+EMI_BACT));/*Bandwidth counter for access*/
}
unsigned int MET_BM_GetOverheadWordCount(void)
{
return emi_readl(IOMEM(ADDR_EMI+EMI_BSCT));/*Overhead counter*/
}
int MET_BM_GetTransTypeCount(const unsigned int counter_num)
{
return (counter_num < 1 || counter_num > BM_COUNTER_MAX)
? BM_ERR_WRONG_REQ : emi_readl(IOMEM(ADDR_EMI+EMI_TTYPE1 + (counter_num - 1) * 8));
}
int MET_BM_GetMDCT(void)
{
return emi_readl(IOMEM(ADDR_EMI+EMI_MDCT));
}
int MET_BM_GetMDCT_2(void)
{
return emi_readl(IOMEM(ADDR_EMI+EMI_MDCT_2ND));
}
int MET_BM_SetMDCT_MDMCU(unsigned int mdmcu_rd_buf)
{
volatile unsigned int value_origin;
value_origin = emi_readl(IOMEM(ADDR_EMI+EMI_MDCT_2ND));
MET_TRACE("[MET_BM_SetMDCT_MDMCU] value_origin: %x\n", value_origin);
value_origin = value_origin & ~(0x7);
value_origin = value_origin | ((mdmcu_rd_buf)&0x7);
emi_reg_sync_writel(value_origin, ADDR_EMI+EMI_MDCT_2ND);
return BM_REQ_OK;
}
int MET_BM_GetMonitorCounter(const unsigned int counter_num,
unsigned int *master,
unsigned int *trans_type)
{
unsigned int value, addr;
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));
*master = (value>>16) & MASK_MASTER;
*trans_type = (value>>24) & MASK_TRANS_TYPE;
} else {
addr = (counter_num <= 3) ?
EMI_MSEL : (EMI_MSEL2 + (counter_num / 2 - 2) * 8);
value = emi_readl(IOMEM(ADDR_EMI+addr)) >> ((counter_num % 2) * 16);
*master = value & MASK_MASTER;
*trans_type = (value>>8) & MASK_TRANS_TYPE;
}
return BM_REQ_OK;
}
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);
/* clear master and transaction type fields */
value = emi_readl(IOMEM(ADDR_EMI+addr)) & ~(iMask << ((counter_num % 2) * 16));
/* set master and transaction type fields */
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)
{
volatile 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_SetMaster(const unsigned int counter_num, const unsigned int master)
{
unsigned int value, addr;
const unsigned int iMask = 0x7F;
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)) | ((master & iMask) << 16);
} else {
addr = (counter_num <= 3) ? EMI_MSEL : (EMI_MSEL2 + (counter_num / 2 - 2) * 8);
/* clear master and transaction type fields */
value = emi_readl(IOMEM(ADDR_EMI+addr)) & ~(iMask << ((counter_num % 2) * 16));
/* set master and transaction type fields */
value |= ((master & iMask) << ((counter_num % 2) * 16));
}
emi_reg_sync_writel(value, ADDR_EMI+addr);
return BM_REQ_OK;
}
int MET_BM_SetIDSelect(const unsigned int counter_num,
const unsigned int id,
const unsigned int enable)
{
unsigned int value, addr, shift_num;
if (enable == 0) {
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;
}
if ((counter_num < 1 || counter_num > BM_COUNTER_MAX) || (id > EMI_BMID_MASK) || (enable > 1))
return BM_ERR_WRONG_REQ;
addr = EMI_BMID0 + (counter_num - 1) / 2 * 4;
/* field's offset in the target EMI_BMIDx register */
shift_num = ((counter_num - 1) % 2) * 16;
/* clear SELx_ID field */
value = emi_readl(IOMEM(ADDR_EMI+addr)) & ~(EMI_BMID_MASK << shift_num);
/* set SELx_ID field */
value |= id << shift_num;
emi_reg_sync_writel(value, ADDR_EMI+addr);
value = (emi_readl(IOMEM(ADDR_EMI+EMI_BMEN2))
& ~(1 << (counter_num - 1)))
| (enable << (counter_num - 1));
emi_reg_sync_writel(value, ADDR_EMI+EMI_BMEN2);
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);
/*
* emi_ttype1 -- emi_ttype8 change as total latencies
* for m0 -- m7,
* and emi_ttype9 -- emi_ttype16 change as total transaction counts
* for m0 -- m7
*/
if (enable == 1)
value |= (0x2 << 24);
emi_reg_sync_writel(value, ADDR_EMI+EMI_BMEN2);
return BM_REQ_OK;
}
int MET_BM_GetLatencyCycle(const unsigned int counter_num)
{
unsigned int cycle_count;
switch (counter_num) {
case 1:
cycle_count = emi_readl(IOMEM(ADDR_EMI+EMI_TTYPE1));
break;
case 2:
cycle_count = emi_readl(IOMEM(ADDR_EMI+EMI_TTYPE2));
break;
case 3:
cycle_count = emi_readl(IOMEM(ADDR_EMI+EMI_TTYPE3));
break;
case 4:
cycle_count = emi_readl(IOMEM(ADDR_EMI+EMI_TTYPE4));
break;
case 5:
cycle_count = emi_readl(IOMEM(ADDR_EMI+EMI_TTYPE5));
break;
case 6:
cycle_count = emi_readl(IOMEM(ADDR_EMI+EMI_TTYPE6));
break;
case 7:
cycle_count = emi_readl(IOMEM(ADDR_EMI+EMI_TTYPE7));
break;
case 8:
cycle_count = emi_readl(IOMEM(ADDR_EMI+EMI_TTYPE8));
break;
case 9:
cycle_count = emi_readl(IOMEM(ADDR_EMI+EMI_TTYPE9));
break;
case 10:
cycle_count = emi_readl(IOMEM(ADDR_EMI+EMI_TTYPE10));
break;
case 11:
cycle_count = emi_readl(IOMEM(ADDR_EMI+EMI_TTYPE11));
break;
case 12:
cycle_count = emi_readl(IOMEM(ADDR_EMI+EMI_TTYPE12));
break;
case 13:
cycle_count = emi_readl(IOMEM(ADDR_EMI+EMI_TTYPE13));
break;
case 14:
cycle_count = emi_readl(IOMEM(ADDR_EMI+EMI_TTYPE14));
break;
case 15:
cycle_count = emi_readl(IOMEM(ADDR_EMI+EMI_TTYPE15));
break;
case 16:
cycle_count = emi_readl(IOMEM(ADDR_EMI+EMI_TTYPE16));
break;
case 17:
cycle_count = emi_readl(IOMEM(ADDR_EMI+EMI_TTYPE17));
break;
case 18:
cycle_count = emi_readl(IOMEM(ADDR_EMI+EMI_TTYPE18));
break;
case 19:
cycle_count = emi_readl(IOMEM(ADDR_EMI+EMI_TTYPE19));
break;
case 20:
cycle_count = emi_readl(IOMEM(ADDR_EMI+EMI_TTYPE20));
break;
case 21:
cycle_count = emi_readl(IOMEM(ADDR_EMI+EMI_TTYPE21));
break;
default:
return BM_ERR_WRONG_REQ;
}
return cycle_count;
}
unsigned int MET_BM_GetEmiDcm(void)
{
return (emi_readl(IOMEM(ADDR_EMI+EMI_CONM))>>24);
}
int MET_BM_SetEmiDcm(const unsigned int setting)
{
unsigned int value;
value = emi_readl(IOMEM(ADDR_EMI+EMI_CONM));
emi_reg_sync_writel((value & 0x00FFFFFF) | (setting << 24), ADDR_EMI+EMI_CONM);
return BM_REQ_OK;
}
/* DRAMC */
unsigned int MET_DRAMC_GetPageHitCount(DRAMC_Cnt_Type CountType, int chann)
{
unsigned int iCount;
unsigned long addr_base = ADDR_DRAMC0;
if (chann == 0)
addr_base = ADDR_DRAMC0;
else if (chann == 1)
addr_base = ADDR_DRAMC1;
else if (chann == 2)
addr_base = ADDR_DRAMC2;
else if (chann == 3)
addr_base = ADDR_DRAMC3;
else
return BM_ERR_WRONG_REQ;
switch (CountType) {
case DRAMC_R2R:
iCount = emi_readl(IOMEM(addr_base+DRAMC_R2R_PAGE_HIT));
break;
case DRAMC_R2W:
iCount = emi_readl(IOMEM(addr_base+DRAMC_R2W_PAGE_HIT));
break;
case DRAMC_W2R:
iCount = emi_readl(IOMEM(addr_base+DRAMC_W2R_PAGE_HIT));
break;
case DRAMC_W2W:
iCount = emi_readl(IOMEM(addr_base+DRAMC_W2W_PAGE_HIT));
break;
case DRAMC_ALL:
iCount = emi_readl(IOMEM(addr_base+DRAMC_R2R_PAGE_HIT)) +
emi_readl(IOMEM(addr_base+DRAMC_R2W_PAGE_HIT)) +
emi_readl(IOMEM(addr_base+DRAMC_W2R_PAGE_HIT)) +
emi_readl(IOMEM(addr_base+DRAMC_W2W_PAGE_HIT));
break;
default:
return BM_ERR_WRONG_REQ;
}
return iCount;
}
unsigned int MET_DRAMC_GetPageMissCount(DRAMC_Cnt_Type CountType, int chann)
{
unsigned int iCount;
unsigned long addr_base = ADDR_DRAMC0;
if (chann == 0)
addr_base = ADDR_DRAMC0;
else if (chann == 1)
addr_base = ADDR_DRAMC1;
else if (chann == 2)
addr_base = ADDR_DRAMC2;
else if (chann == 3)
addr_base = ADDR_DRAMC3;
else
return BM_ERR_WRONG_REQ;
switch (CountType) {
case DRAMC_R2R:
iCount = emi_readl(IOMEM(addr_base+DRAMC_R2R_PAGE_MISS));
break;
case DRAMC_R2W:
iCount = emi_readl(IOMEM(addr_base+DRAMC_R2W_PAGE_MISS));
break;
case DRAMC_W2R:
iCount = emi_readl(IOMEM(addr_base+DRAMC_W2R_PAGE_MISS));
break;
case DRAMC_W2W:
iCount = emi_readl(IOMEM(addr_base+DRAMC_W2W_PAGE_MISS));
break;
case DRAMC_ALL:
iCount = emi_readl(IOMEM(addr_base+DRAMC_R2R_PAGE_MISS)) +
emi_readl(IOMEM(addr_base+DRAMC_R2W_PAGE_MISS)) +
emi_readl(IOMEM(addr_base+DRAMC_W2R_PAGE_MISS)) +
emi_readl(IOMEM(addr_base+DRAMC_W2W_PAGE_MISS));
break;
default:
return BM_ERR_WRONG_REQ;
}
return iCount;
}
unsigned int MET_DRAMC_GetInterbankCount(DRAMC_Cnt_Type CountType, int chann)
{
unsigned int iCount;
unsigned long addr_base = ADDR_DRAMC0;
if (chann == 0)
addr_base = ADDR_DRAMC0;
else if (chann == 1)
addr_base = ADDR_DRAMC1;
else if (chann == 2)
addr_base = ADDR_DRAMC2;
else if (chann == 3)
addr_base = ADDR_DRAMC3;
else
return BM_ERR_WRONG_REQ;
switch (CountType) {
case DRAMC_R2R:
iCount = emi_readl(IOMEM(addr_base+DRAMC_R2R_INTERBANK));
break;
case DRAMC_R2W:
iCount = emi_readl(IOMEM(addr_base+DRAMC_R2W_INTERBANK));
break;
case DRAMC_W2R:
iCount = emi_readl(IOMEM(addr_base+DRAMC_W2R_INTERBANK));
break;
case DRAMC_W2W:
iCount = emi_readl(IOMEM(addr_base+DRAMC_W2W_INTERBANK));
break;
case DRAMC_ALL:
iCount = emi_readl(IOMEM(addr_base+DRAMC_R2R_INTERBANK)) +
emi_readl(IOMEM(addr_base+DRAMC_R2W_INTERBANK)) +
emi_readl(IOMEM(addr_base+DRAMC_W2R_INTERBANK)) +
emi_readl(IOMEM(addr_base+DRAMC_W2W_INTERBANK));
break;
default:
return BM_ERR_WRONG_REQ;
}
return iCount;
}
unsigned int MET_DRAMC_GetIdleCount(int chann)
{
unsigned long addr_base = ADDR_DRAMC0;
if (chann == 0)
addr_base = ADDR_DRAMC0;
else if (chann == 1)
addr_base = ADDR_DRAMC1;
else if (chann == 2)
addr_base = ADDR_DRAMC2;
else if (chann == 3)
addr_base = ADDR_DRAMC3;
else
return BM_ERR_WRONG_REQ;
return emi_readl(IOMEM(addr_base+DRAMC_IDLE_COUNT));
}
unsigned int MET_DRAMC_Misc_Status(int chann)
{
unsigned long addr_base = ADDR_DRAMC0;
if (chann == 0)
addr_base = ADDR_DRAMC0;
else if (chann == 1)
addr_base = ADDR_DRAMC1;
else if (chann == 2)
addr_base = ADDR_DRAMC2;
else if (chann == 3)
addr_base = ADDR_DRAMC3;
else
return BM_ERR_WRONG_REQ;
return emi_readl(IOMEM(addr_base+DRAMC_MISC_STATUSA));
}
int MET_DRAMC_BMPause(int chann, int set)
{
unsigned long addr_base = ADDR_DRAMC0;
unsigned int value;
if (chann == 0)
addr_base = ADDR_DRAMC0;
else if (chann == 1)
addr_base = ADDR_DRAMC1;
else if (chann == 2)
addr_base = ADDR_DRAMC2;
else if (chann == 3)
addr_base = ADDR_DRAMC3;
else
return BM_ERR_WRONG_REQ;
value = emi_readl(IOMEM(addr_base+DRAMC_DMMONITOR));
if (set == 0) {
/* Continue DRAMC Monitor*/
value = (value & 0xFFFFFFFB);
}
else if (set == 1) {
/* Pause DRAMC Monitor*/
value = (value | 0x00000004);
}
else
return BM_ERR_WRONG_REQ;
emi_reg_sync_writel(value, addr_base+DRAMC_DMMONITOR);
return BM_REQ_OK;
}
int MET_DRAMC_BMEnable(int chann, int set)
{
unsigned long addr_base = ADDR_DRAMC0;
unsigned int value;
if (chann == 0)
addr_base = ADDR_DRAMC0;
else if (chann == 1)
addr_base = ADDR_DRAMC1;
else if (chann == 2)
addr_base = ADDR_DRAMC2;
else if (chann == 3)
addr_base = ADDR_DRAMC3;
else
return BM_ERR_WRONG_REQ;
value = emi_readl(IOMEM(addr_base+DRAMC_DMMONITOR));
if (set == 0) {
/* Disable DRAMC Monitor*/
value = (value & 0xFFFFFFF7);
}
else if (set == 1) {
/* Enable DRAMC Monitor*/
value = (value | 0x00000008);
}
else
return BM_ERR_WRONG_REQ;
emi_reg_sync_writel(value, addr_base+DRAMC_DMMONITOR);
return BM_REQ_OK;
}
unsigned int MET_DRAMC_RefPop(int chann)
{
unsigned long addr_base = ADDR_DRAMC0;
if (chann == 0)
addr_base = ADDR_DRAMC0;
else if (chann == 1)
addr_base = ADDR_DRAMC1;
else if (chann == 2)
addr_base = ADDR_DRAMC2;
else if (chann == 3)
addr_base = ADDR_DRAMC3;
else
return BM_ERR_WRONG_REQ;
return emi_readl(IOMEM(addr_base+DRAMC_REFRESH_POP));
}
unsigned int MET_DRAMC_Free26M(int chann)
{
unsigned long addr_base = ADDR_DRAMC0;
if (chann == 0)
addr_base = ADDR_DRAMC0;
else if (chann == 1)
addr_base = ADDR_DRAMC1;
else if (chann == 2)
addr_base = ADDR_DRAMC2;
else if (chann == 3)
addr_base = ADDR_DRAMC3;
else
return BM_ERR_WRONG_REQ;
return emi_readl(IOMEM(addr_base+DRAMC_FREERUN_26M));
}
unsigned int MET_DRAMC_RByte(int chann)
{
unsigned long addr_base = ADDR_DRAMC0;
if (chann == 0)
addr_base = ADDR_DRAMC0;
else if (chann == 1)
addr_base = ADDR_DRAMC1;
else if (chann == 2)
addr_base = ADDR_DRAMC2;
else if (chann == 3)
addr_base = ADDR_DRAMC3;
else
return BM_ERR_WRONG_REQ;
return emi_readl(IOMEM(addr_base+DRAMC_READ_BYTES));
}
unsigned int MET_DRAMC_WByte(int chann)
{
unsigned long addr_base = ADDR_DRAMC0;
if (chann == 0)
addr_base = ADDR_DRAMC0;
else if (chann == 1)
addr_base = ADDR_DRAMC1;
else if (chann == 2)
addr_base = ADDR_DRAMC2;
else if (chann == 3)
addr_base = ADDR_DRAMC3;
else
return BM_ERR_WRONG_REQ;
return emi_readl(IOMEM(addr_base+DRAMC_WRITE_BYTES));
}
unsigned int MET_EMI_GetMDCT(void)
{
return emi_readl(IOMEM(ADDR_EMI+EMI_MDCT));
}
unsigned int MET_EMI_GetMDCT_2ND(void)
{
return emi_readl(IOMEM(ADDR_EMI+EMI_MDCT_2ND));
}
unsigned int MET_EMI_GetARBA(void)
{
/* EMI_ARBA EMI Bandwidth Filter Control M0/1 */
return emi_readl(IOMEM(ADDR_EMI+EMI_ARBA));
}
unsigned int MET_EMI_GetARBB(void)
{
/* return emi_readl(IOMEM(ADDR_EMI+EMI_ARBB)); */
/* Note: Olympus Coda doesn't has this regiester, So we return 0 */
return 0;
}
unsigned int MET_EMI_GetARBC(void)
{
return emi_readl(IOMEM(ADDR_EMI+EMI_ARBC));
}
unsigned int MET_EMI_GetARBD(void)
{
return emi_readl(IOMEM(ADDR_EMI+EMI_ARBD));
}
unsigned int MET_EMI_GetARBE(void)
{
return emi_readl(IOMEM(ADDR_EMI+EMI_ARBE));
}
unsigned int MET_EMI_GetARBF(void)
{
return emi_readl(IOMEM(ADDR_EMI+EMI_ARBF));
}
unsigned int MET_EMI_GetARBG(void)
{
return emi_readl(IOMEM(ADDR_EMI+EMI_ARBG));
}
unsigned int MET_EMI_GetARBH(void)
{
return emi_readl(IOMEM(ADDR_EMI+EMI_ARBH));
}
/* Total BW status*/
unsigned int MET_EMI_GetBWCT0(void)
{
return emi_readl(IOMEM(ADDR_EMI+EMI_BWCT0));
}
/* Total BW status*/
unsigned int MET_EMI_GetBWCT1(void)
{
return emi_readl(IOMEM(ADDR_EMI+EMI_BWCT1));
}
/* Total BW status*/
unsigned int MET_EMI_GetBWCT2(void)
{
return emi_readl(IOMEM(ADDR_EMI+EMI_BWCT2));
}
/* Total BW status*/
unsigned int MET_EMI_GetBWCT3(void)
{
return emi_readl(IOMEM(ADDR_EMI+EMI_BWCT3));
}
/* Total BW status*/
unsigned int MET_EMI_GetBWCT4(void)
{
return emi_readl(IOMEM(ADDR_EMI+EMI_BWCT4));
}
/* Total BW status*/
unsigned int MET_EMI_GetBWST0(void)
{
return emi_readl(IOMEM(ADDR_EMI+EMI_BWST0));
}
/* Total BW status*/
unsigned int MET_EMI_GetBWST1(void)
{
return emi_readl(IOMEM(ADDR_EMI+EMI_BWST1));
}
/* C+G BW status*/
unsigned int MET_EMI_GetBWCT0_2ND(void)
{
return emi_readl(IOMEM(ADDR_EMI+EMI_BWCT0_2ND));
}
/* C+G BW status*/
unsigned int MET_EMI_GetBWCT1_2ND(void)
{
return emi_readl(IOMEM(ADDR_EMI+EMI_BWCT1_2ND));
}
/* C+G BW status*/
unsigned int MET_EMI_GetBWST_2ND(void)
{
return emi_readl(IOMEM(ADDR_EMI+EMI_BWST_2ND));
}
unsigned int MET_EMI_GetBMRW0(void)
{
return readl(IOMEM(ADDR_EMI+EMI_BMRW0));
}
void emi_dump_reg(void)
{
int i;
MET_TRACE("[emi_regdump]\n");
for (i = 0x400; i < 0x500; i = i+16)
MET_TRACE("%4x__ %8x %8x %8x %8x\n", i, readl(IOMEM(ADDR_EMI+i)),
readl(IOMEM(ADDR_EMI+i+4)), readl(IOMEM(ADDR_EMI+i+8)), readl(IOMEM(ADDR_EMI+i+12)));
}
unsigned int MET_EMI_GetDramChannNum(void)
{
int num = -1;
if (BaseAddrEMI) {
num = emi_readl(IOMEM(ADDR_EMI+EMI_CONA));
num = ((num >> 8) & 0x0000003);
} else {
return 1;
}
if (num == M0_DOUBLE_HALF_BW_1CH)
return 1;
else if (num == M0_DOUBLE_HALF_BW_2CH)
return 2;
else if (num == M0_DOUBLE_HALF_BW_4CH)
return 4;
else /* default return single channel */
return 1;
}
void MET_DRAMC_GetDebugCounter(int *value, int chann)
{
int i;
unsigned long addr_base = ADDR_DRAMC0;
for (i = 0; i < chann; i++) {
if (i == 0)
addr_base = ADDR_DRAMC0;
else if (i == 1)
addr_base = ADDR_DRAMC1;
else if (i == 2)
addr_base = ADDR_DRAMC2;
else if (i == 3)
addr_base = ADDR_DRAMC3;
else
return;
value[DRAMC_Debug_MAX_CNT*i + BM_RK0_PRE_STANDBY] =
emi_readl(IOMEM(addr_base + DRAMC_RK0_PRE_STANDBY));
value[DRAMC_Debug_MAX_CNT*i + BM_RK0_PRE_POWERDOWN] =
emi_readl(IOMEM(addr_base + DRAMC_RK0_PRE_POWERDOWN));
value[DRAMC_Debug_MAX_CNT*i + BM_RK0_ACT_STANDBY] =
emi_readl(IOMEM(addr_base + DRAMC_RK0_ACT_STANDBY));
value[DRAMC_Debug_MAX_CNT*i + BM_RK0_ACT_POWERDOWN] =
emi_readl(IOMEM(addr_base + DRAMC_RK0_ACT_POWERDOWN));
value[DRAMC_Debug_MAX_CNT*i + BM_RK1_PRE_STANDBY] =
emi_readl(IOMEM(addr_base + DRAMC_RK1_PRE_STANDBY));
value[DRAMC_Debug_MAX_CNT*i + BM_RK1_PRE_POWERDOWN] =
emi_readl(IOMEM(addr_base + DRAMC_RK1_PRE_POWERDOWN));
value[DRAMC_Debug_MAX_CNT*i + BM_RK1_ACT_STANDBY] =
emi_readl(IOMEM(addr_base + DRAMC_RK1_ACT_STANDBY));
value[DRAMC_Debug_MAX_CNT*i + BM_RK1_ACT_POWERDOWN] =
emi_readl(IOMEM(addr_base + DRAMC_RK1_ACT_POWERDOWN));
value[DRAMC_Debug_MAX_CNT*i + BM_RK2_PRE_STANDBY] =
emi_readl(IOMEM(addr_base + DRAMC_RK2_PRE_STANDBY));
value[DRAMC_Debug_MAX_CNT*i + BM_RK2_PRE_POWERDOWN] =
emi_readl(IOMEM(addr_base + DRAMC_RK2_PRE_POWERDOWN));
value[DRAMC_Debug_MAX_CNT*i + BM_RK2_ACT_STANDBY] =
emi_readl(IOMEM(addr_base + DRAMC_RK2_ACT_STANDBY));
value[DRAMC_Debug_MAX_CNT*i + BM_RK2_ACT_POWERDOWN] =
emi_readl(IOMEM(addr_base + DRAMC_RK2_ACT_POWERDOWN));
}
}
#if 1
static inline unsigned int dramc_reg_read(unsigned long addr)
{
#if 0
#ifdef CONFIG_64BIT
unsigned int value = 0;
value = HAL_READ32((void*)addr);
#else
unsigned int value = readl((void*)addr);
#endif
#endif
unsigned int value = readl((void*)addr);
mb();
return value;
}
#if 0
u32 DRAMC_GetDramcFreq(void)
{
unsigned long tcm_dramc_flags = 0;
tcm_dramc_flags = dramc_reg_read(TCM_DRAM_FLAGS_ADDR);
return TCMGET_DDR_CLK(tcm_dramc_flags);
}
unsigned int get_dram_data_rate(void)
{
return DRAMC_GetDramcFreq()/1000000;
}
#else
#define DRAM_DATARATE_REG 0x10100D9C
u32 DRAMC_GetDramcFreq(void)
{
unsigned long reg_val;
unsigned long dram_datarate = 0;
reg_val = dramc_reg_read((unsigned long)(AddrDramDatarate + 0xD9C));
// pr_err("dram datarate reg val = 0x%lx, reg_val[9-16] = %lu\n", reg_val, (reg_val >> 9) & 0xff);
dram_datarate = (((dramc_reg_read((unsigned long)(AddrDramDatarate + 0xD9C))) >> 16) & 0x1ffff) * 26 / 256;
return dram_datarate;
}
unsigned int get_dram_data_rate(void)
{
return DRAMC_GetDramcFreq();
}
#endif
#else
#define DRAMC_AO_CHA_BASE_ADDR (DRAM_BASE)
#define PDEF_DRAMC0_CHA_REG_0E4 IOMEM((DRAMC_AO_CHA_BASE_ADDR + 0x00e4))
#define PDEF_DRAMC0_CHA_REG_010 IOMEM((DRAMC_AO_CHA_BASE_ADDR + 0x0010))
#define DDRPHY_CHA_BASE_ADDR (DRAM_DDRPHY_CHA_BANK)
unsigned int DRAM_TYPE = 0;
enum DDRTYPE {
TYPE_LPDDR3 = 1,
TYPE_LPDDR4,
TYPE_LPDDR4X
};
static unsigned int get_shuffle_status(void)
{
/* HPM = 0, LPM = 1, ULPM = 2; */
return (emi_readl(PDEF_DRAMC0_CHA_REG_0E4) & 0x6) >> 1;
}
unsigned int get_dram_data_rate(void)
{
return DRAMC_GetDramcFreq();
unsigned long addr_base = DDRPHY_CHA_BASE_ADDR;
unsigned int u4ShuLevel, u4SDM_PCW, u4PREDIV, u4POSDIV, u4CKDIV4, u4VCOFreq, u4DataRate = 0;
if (DRAM_TYPE == 0)
DRAM_TYPE = (emi_readl(PDEF_DRAMC0_CHA_REG_010) & 0x1C00) >> 10;
u4ShuLevel = get_shuffle_status();
u4SDM_PCW = emi_readl(IOMEM(addr_base + 0xd94 + 0x500 * u4ShuLevel)) >> 16;
u4PREDIV = (emi_readl(IOMEM(addr_base + 0xda0 + 0x500 * u4ShuLevel)) & 0x000c0000) >> 18;
u4POSDIV = emi_readl(IOMEM(addr_base + 0xda0 + 0x500 * u4ShuLevel)) & 0x00000007;
u4CKDIV4 = (emi_readl(IOMEM(addr_base + 0xd18 + 0x500 * u4ShuLevel)) & 0x08000000) >> 27;
u4VCOFreq = ((52>>u4PREDIV)*(u4SDM_PCW>>8))>>u4POSDIV;
u4DataRate = u4VCOFreq>>u4CKDIV4;
/* pr_err("[DRAMC Driver] u4ShuLevel=%d, PCW=0x%X, u4PREDIV=%d, u4POSDIV=%d, CKDIV4=%d, DataRate=%d\n",
* u4ShuLevel, u4SDM_PCW, u4PREDIV, u4POSDIV, u4CKDIV4, u4DataRate);
*/
// if (DRAM_TYPE == TYPE_LPDDR4X) {
if (u4DataRate == 3198)
u4DataRate = 3200;
else if (u4DataRate == 2652)
u4DataRate = 2667;
else if (u4DataRate == 1599)
u4DataRate = 1600;
else if (u4DataRate == 799)
u4DataRate = 800;
else
u4DataRate = 0;
// } else
// u4DataRate = 0;
return u4DataRate;
}
#endif