144 lines
3.9 KiB
C
144 lines
3.9 KiB
C
|
/* Copyright (c) 2016 Samsung Electronics Co., Ltd.
|
||
|
* http://www.samsung.com/
|
||
|
*
|
||
|
* EXYNOS - BTS CAL code.
|
||
|
*
|
||
|
* 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 "cal_bts9610.h"
|
||
|
#include <linux/soc/samsung/exynos-soc.h>
|
||
|
|
||
|
#define LOG(x, ...) \
|
||
|
({ \
|
||
|
seq_printf(buf, x, ##__VA_ARGS__); \
|
||
|
})
|
||
|
|
||
|
#define TREX_CON 0x000
|
||
|
#define TREX_TIMEOUT 0x010
|
||
|
#define TREX_RCON 0x020
|
||
|
#define TREX_WCON 0x040
|
||
|
#define TREX_RBLOCK_UPPER 0x024
|
||
|
#define TREX_WBLOCK_UPPER 0x044
|
||
|
#define TREX_RBLOCK_UPPER_NORMAL 0x028
|
||
|
#define TREX_WBLOCK_UPPER_NORMAL 0x048
|
||
|
#define TREX_RBLOCK_UPPER_FULL 0x02C
|
||
|
#define TREX_WBLOCK_UPPER_FULL 0x04C
|
||
|
#define TREX_RBLOCK_UPPER_BUSY 0x030
|
||
|
#define TREX_WBLOCK_UPPER_BUSY 0x050
|
||
|
#define TREX_RBLOCK_UPPER_MAX 0x034
|
||
|
#define TREX_WBLOCK_UPPER_MAX 0x054
|
||
|
|
||
|
#define QMAX_THRESHOLD_R 0x050
|
||
|
#define QMAX_THRESHOLD_W 0x054
|
||
|
|
||
|
static unsigned int set_mo(unsigned int mo)
|
||
|
{
|
||
|
if (mo > BTS_MAX_MO || !mo)
|
||
|
mo = BTS_MAX_MO;
|
||
|
return mo;
|
||
|
}
|
||
|
|
||
|
static unsigned int set_threshold(unsigned int threshold)
|
||
|
{
|
||
|
if (threshold > BTS_QMAX_MAX_THRESHOLD || !threshold)
|
||
|
threshold = BTS_QMAX_MAX_THRESHOLD;
|
||
|
return threshold;
|
||
|
}
|
||
|
|
||
|
void bts_setqos(void __iomem *base, struct bts_status *stat)
|
||
|
{
|
||
|
unsigned int tmp_reg = 0;
|
||
|
bool block_en = false;
|
||
|
|
||
|
if (!base)
|
||
|
return;
|
||
|
|
||
|
if (stat->disable) {
|
||
|
__raw_writel(0x4000, base + TREX_RCON);
|
||
|
__raw_writel(0x4000, base + TREX_WCON);
|
||
|
__raw_writel(0x0, base + TREX_CON);
|
||
|
return;
|
||
|
}
|
||
|
__raw_writel(set_mo(stat->rmo), base + TREX_RBLOCK_UPPER);
|
||
|
__raw_writel(set_mo(stat->wmo), base + TREX_WBLOCK_UPPER);
|
||
|
if (stat->max_rmo || stat->max_wmo || stat->full_rmo || stat->full_wmo)
|
||
|
block_en = true;
|
||
|
|
||
|
__raw_writel(set_mo(stat->max_rmo), base + TREX_RBLOCK_UPPER_MAX);
|
||
|
__raw_writel(set_mo(stat->max_wmo), base + TREX_WBLOCK_UPPER_MAX);
|
||
|
__raw_writel(set_mo(stat->full_rmo), base + TREX_RBLOCK_UPPER_FULL);
|
||
|
__raw_writel(set_mo(stat->full_wmo), base + TREX_WBLOCK_UPPER_FULL);
|
||
|
|
||
|
if (stat->timeout_en) {
|
||
|
if (stat->timeout_r > 0xff)
|
||
|
stat->timeout_r = 0xff;
|
||
|
if (stat->timeout_w > 0xff)
|
||
|
stat->timeout_w = 0xff;
|
||
|
__raw_writel(stat->timeout_r | (stat->timeout_w << 16),
|
||
|
base + TREX_TIMEOUT);
|
||
|
} else {
|
||
|
__raw_writel(0xff | (0xff << 16), base + TREX_TIMEOUT);
|
||
|
}
|
||
|
|
||
|
/* override QoS value */
|
||
|
tmp_reg |= (1 & !stat->bypass_en) << 8;
|
||
|
tmp_reg |= (stat->priority & 0xf) << 12;
|
||
|
|
||
|
/* enable Blocking logic */
|
||
|
tmp_reg |= (1 & block_en) << 0;
|
||
|
__raw_writel(tmp_reg, base + TREX_RCON);
|
||
|
__raw_writel(tmp_reg, base + TREX_WCON);
|
||
|
|
||
|
__raw_writel(((1 & stat->timeout_en) << 20) | 0x1, base + TREX_CON);
|
||
|
}
|
||
|
|
||
|
void bts_showqos(void __iomem *base, struct seq_file *buf)
|
||
|
{
|
||
|
if (!base)
|
||
|
return;
|
||
|
|
||
|
LOG("CON0x%08X qos(%d,%d)0x%Xr%Xw, wmo: %d, rmo: %d\n",
|
||
|
__raw_readl(base + TREX_CON),
|
||
|
(__raw_readl(base + TREX_RCON) >> 8) & 0x1,
|
||
|
(__raw_readl(base + TREX_WCON) >> 8) & 0x1,
|
||
|
(__raw_readl(base + TREX_RCON) >> 12) & 0xf,
|
||
|
(__raw_readl(base + TREX_WCON) >> 12) & 0xf,
|
||
|
(__raw_readl(base + TREX_WBLOCK_UPPER)),
|
||
|
(__raw_readl(base + TREX_RBLOCK_UPPER))
|
||
|
);
|
||
|
}
|
||
|
|
||
|
void bts_set_qmax(void __iomem *base, unsigned int r_thsd0,
|
||
|
unsigned int r_thsd1, unsigned int w_thsd0,
|
||
|
unsigned int w_thsd1)
|
||
|
{
|
||
|
unsigned int tmp_reg = 0;
|
||
|
|
||
|
if (!base)
|
||
|
return;
|
||
|
|
||
|
tmp_reg |= set_threshold(r_thsd0);
|
||
|
tmp_reg |= set_threshold(r_thsd1) << 16;
|
||
|
__raw_writel(tmp_reg, base + QMAX_THRESHOLD_R);
|
||
|
|
||
|
tmp_reg = 0;
|
||
|
tmp_reg |= set_threshold(w_thsd0);
|
||
|
tmp_reg |= set_threshold(w_thsd1) << 16;
|
||
|
__raw_writel(tmp_reg, base + QMAX_THRESHOLD_W);
|
||
|
}
|
||
|
|
||
|
void bts_show_qmax(void __iomem *base, struct seq_file *buf)
|
||
|
{
|
||
|
if (!base)
|
||
|
return;
|
||
|
|
||
|
LOG("threshold_r(0x%04x,0x%04x), threshold_w(0x%04x,0x%04x)\n",
|
||
|
__raw_readl(base + QMAX_THRESHOLD_R) & 0xffff,
|
||
|
(__raw_readl(base + QMAX_THRESHOLD_R) >> 16) & 0xffff,
|
||
|
__raw_readl(base + QMAX_THRESHOLD_W) & 0xffff,
|
||
|
(__raw_readl(base + QMAX_THRESHOLD_W) >> 16) & 0xffff);
|
||
|
}
|