/* 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 #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); }