soc: qcom: dcc: Support new DCC HW feature

Add support to new register memory map, fix loop offset and
dynamic number of link list.

Change-Id: Ibadfa723842dae80cdd50bf08018d86c2ef30b94
Signed-off-by: Tingwei Zhang <tingwei@codeaurora.org>
This commit is contained in:
Tingwei Zhang 2019-09-02 15:08:03 +08:00
commit 777bece578

View file

@ -25,9 +25,9 @@
#define BVAL(val, n) ((val & BIT(n)) >> n)
#define dcc_writel(drvdata, val, off) \
__raw_writel((val), drvdata->base + off)
__raw_writel((val), drvdata->base + dcc_offset_conv(drvdata, off))
#define dcc_readl(drvdata, off) \
__raw_readl(drvdata->base + off)
__raw_readl(drvdata->base + dcc_offset_conv(drvdata, off))
#define dcc_sram_readl(drvdata, off) \
__raw_readl(drvdata->ram_base + off)
@ -37,23 +37,35 @@
/* DCC registers */
#define DCC_HW_VERSION (0x00)
#define DCC_HW_INFO (0x04)
#define DCC_EXEC_CTRL (0x08)
#define DCC_STATUS (0x0C)
#define DCC_CFG (0x10)
#define DCC_FDA_CURR (0x14)
#define DCC_LLA_CURR (0x18)
#define DCC_LL_LOCK(m) (0x1C + 0x80 * (m + HLOS_LIST_START))
#define DCC_LL_CFG(m) (0x20 + 0x80 * (m + HLOS_LIST_START))
#define DCC_LL_BASE(m) (0x24 + 0x80 * (m + HLOS_LIST_START))
#define DCC_FD_BASE(m) (0x28 + 0x80 * (m + HLOS_LIST_START))
#define DCC_LL_TIMEOUT(m) (0x2c + 0x80 * (m + HLOS_LIST_START))
#define DCC_LL_INT_ENABLE(m) (0x30 + 0x80 * (m + HLOS_LIST_START))
#define DCC_LL_INT_STATUS(m) (0x34 + 0x80 * (m + HLOS_LIST_START))
#define DCC_FDA_CAPTURED(m) (0x38 + 0x80 * (m + HLOS_LIST_START))
#define DCC_LLA_CAPTURED(m) (0x3C + 0x80 * (m + HLOS_LIST_START))
#define DCC_LL_CRC_CAPTURED(m) (0x40 + 0x80 * (m + HLOS_LIST_START))
#define DCC_LL_SW_TRIGGER(m) (0x44 + 0x80 * (m + HLOS_LIST_START))
#define DCC_LL_BUS_ACCESS_STATUS(m) (0x48 + 0x80 * (m + HLOS_LIST_START))
#define DCC_SRAM_SIZE_INFO (0x08)
#define DCC_APU_INFO (0x0C)
#define DCC_LL_NUM_INFO (0x10)
#define DCC_TIMEOUT_SIGNATURE (0x14)
#define DCC_EXEC_CTRL (0x18)
#define DCC_STATUS (0x1C)
#define DCC_CFG (0x20)
#define DCC_FDA_CURR (0x24)
#define DCC_LLA_CURR (0x28)
#define DCC_LL_LOCK(m) (0x2C + 0x80 * (m + HLOS_LIST_START))
#define DCC_LL_CFG(m) (0x30 + 0x80 * (m + HLOS_LIST_START))
#define DCC_LL_BASE(m) (0x34 + 0x80 * (m + HLOS_LIST_START))
#define DCC_FD_BASE(m) (0x38 + 0x80 * (m + HLOS_LIST_START))
#define DCC_LL_TIMEOUT(m) (0x3c + 0x80 * (m + HLOS_LIST_START))
#define DCC_TRANS_TIMEOUT(m) (0x40 + 0x80 * (m + HLOS_LIST_START))
#define DCC_LL_INT_ENABLE(m) (0x44 + 0x80 * (m + HLOS_LIST_START))
#define DCC_LL_INT_STATUS(m) (0x48 + 0x80 * (m + HLOS_LIST_START))
#define DCC_FDA_CAPTURED(m) (0x4C + 0x80 * (m + HLOS_LIST_START))
#define DCC_LLA_CAPTURED(m) (0x50 + 0x80 * (m + HLOS_LIST_START))
#define DCC_LL_CRC_CAPTURED(m) (0x54 + 0x80 * (m + HLOS_LIST_START))
#define DCC_LL_SW_TRIGGER(m) (0x58 + 0x80 * (m + HLOS_LIST_START))
#define DCC_LL_BUS_ACCESS_STATUS(m) (0x5C + 0x80 * (m + HLOS_LIST_START))
#define DCC_MAP2_LEVEL1 (0x18)
#define DCC_MAP2_OFFSET1 (0x10)
#define DCC_MAP2_LEVEL2 (0x44)
#define DCC_MAP2_OFFSET2 (0x14)
#define DCC_FIX_LOOP_OFFSET (16)
#define DCC_REG_DUMP_MAGIC_V2 (0x42445953)
#define DCC_REG_DUMP_VER (1)
@ -129,23 +141,36 @@ struct dcc_drvdata {
void __iomem *ram_base;
uint32_t ram_size;
uint32_t ram_offset;
enum dcc_data_sink data_sink[DCC_MAX_LINK_LIST];
enum dcc_func_type func_type[DCC_MAX_LINK_LIST];
enum dcc_data_sink *data_sink;
enum dcc_func_type *func_type;
uint32_t ram_cfg;
uint32_t ram_start;
bool enable[DCC_MAX_LINK_LIST];
bool configured[DCC_MAX_LINK_LIST];
bool *enable;
bool *configured;
bool interrupt_disable;
bool memory_map2;
char *sram_node;
struct cdev sram_dev;
struct class *sram_class;
struct list_head cfg_head[DCC_MAX_LINK_LIST];
uint32_t nr_config[DCC_MAX_LINK_LIST];
struct list_head *cfg_head;
uint32_t *nr_config;
uint32_t nr_link_list;
uint8_t curr_list;
uint8_t cti_trig;
uint8_t loopoff;
};
static uint32_t dcc_offset_conv(struct dcc_drvdata *drvdata, uint32_t off)
{
if (!drvdata->memory_map2) {
if ((off & 0x7F) > DCC_MAP2_LEVEL2)
return (off - DCC_MAP2_OFFSET2);
else if ((off & 0x7F) > DCC_MAP2_LEVEL1)
return (off - DCC_MAP2_OFFSET1);
}
return (off);
}
static int dcc_sram_writel(struct dcc_drvdata *drvdata,
uint32_t val, uint32_t off)
{
@ -176,7 +201,7 @@ static int dcc_read_status(struct dcc_drvdata *drvdata)
uint32_t ll_cfg = 0;
uint32_t tmp_ll_cfg = 0;
for (curr_list = 0; curr_list < DCC_MAX_LINK_LIST; curr_list++) {
for (curr_list = 0; curr_list < drvdata->nr_link_list; curr_list++) {
if (!drvdata->enable[curr_list])
continue;
@ -211,7 +236,7 @@ static int dcc_sw_trigger(struct dcc_drvdata *drvdata)
mutex_lock(&drvdata->mutex);
for (curr_list = 0; curr_list < DCC_MAX_LINK_LIST; curr_list++) {
for (curr_list = 0; curr_list < drvdata->nr_link_list; curr_list++) {
if (!drvdata->enable[curr_list])
continue;
ll_cfg = dcc_readl(drvdata, DCC_LL_CFG(curr_list));
@ -588,7 +613,7 @@ static int dcc_enable(struct dcc_drvdata *drvdata)
memset_io(drvdata->ram_base, 0xDE, drvdata->ram_size);
for (list = 0; list < DCC_MAX_LINK_LIST; list++) {
for (list = 0; list < drvdata->nr_link_list; list++) {
if (dcc_valid_list(drvdata, list))
continue;
@ -652,7 +677,7 @@ static void dcc_disable(struct dcc_drvdata *drvdata)
if (!dcc_ready(drvdata))
dev_err(drvdata->dev, "DCC is not ready Disabling DCC...\n");
for (curr_list = 0; curr_list < DCC_MAX_LINK_LIST; curr_list++) {
for (curr_list = 0; curr_list < drvdata->nr_link_list; curr_list++) {
if (!drvdata->enable[curr_list])
continue;
dcc_writel(drvdata, 0, DCC_LL_CFG(curr_list));
@ -672,7 +697,7 @@ static bool is_dcc_enabled(struct dcc_drvdata *drvdata)
bool dcc_enable = false;
int list;
for (list = 0; list < DCC_MAX_LINK_LIST; list++) {
for (list = 0; list < drvdata->nr_link_list; list++) {
if (drvdata->enable[list]) {
dcc_enable = true;
break;
@ -713,7 +738,7 @@ static ssize_t curr_list_store(struct device *dev,
if (kstrtoul(buf, 16, &val))
return -EINVAL;
if (val >= DCC_MAX_LINK_LIST)
if (val >= drvdata->nr_link_list)
return -EINVAL;
mutex_lock(&drvdata->mutex);
@ -745,7 +770,7 @@ static ssize_t func_type_show(struct device *dev,
ssize_t len = 0;
unsigned int i;
for (i = 0; i < DCC_MAX_LINK_LIST; i++)
for (i = 0; i < drvdata->nr_link_list; i++)
len += scnprintf(buf + len, PAGE_SIZE - len, "%u :%s\n",
i, str_dcc_func_type[drvdata->func_type[i]]);
@ -766,7 +791,7 @@ static ssize_t func_type_store(struct device *dev,
return -EINVAL;
mutex_lock(&drvdata->mutex);
if (drvdata->curr_list >= DCC_MAX_LINK_LIST) {
if (drvdata->curr_list >= drvdata->nr_link_list) {
dev_err(dev,
"Select link list to program using curr_list\n");
ret = -EINVAL;
@ -803,7 +828,7 @@ static ssize_t data_sink_show(struct device *dev,
ssize_t len = 0;
unsigned int i;
for (i = 0; i < DCC_MAX_LINK_LIST; i++)
for (i = 0; i < drvdata->nr_link_list; i++)
len += scnprintf(buf + len, PAGE_SIZE - len, "%u :%s\n",
i, str_dcc_data_sink[drvdata->data_sink[i]]);
@ -824,7 +849,7 @@ static ssize_t data_sink_store(struct device *dev,
return -EINVAL;
mutex_lock(&drvdata->mutex);
if (drvdata->curr_list >= DCC_MAX_LINK_LIST) {
if (drvdata->curr_list >= drvdata->nr_link_list) {
dev_err(dev,
"Select link list to program using curr_list\n");
ret = -EINVAL;
@ -881,7 +906,7 @@ static ssize_t enable_show(struct device *dev,
struct dcc_drvdata *drvdata = dev_get_drvdata(dev);
mutex_lock(&drvdata->mutex);
if (drvdata->curr_list >= DCC_MAX_LINK_LIST) {
if (drvdata->curr_list >= drvdata->nr_link_list) {
dev_err(dev, "Select link list to program using curr_list\n");
ret = -EINVAL;
goto err;
@ -931,7 +956,7 @@ static ssize_t config_show(struct device *dev,
buf[0] = '\0';
mutex_lock(&drvdata->mutex);
if (drvdata->curr_list >= DCC_MAX_LINK_LIST) {
if (drvdata->curr_list >= drvdata->nr_link_list) {
dev_err(dev, "Select link list to program using curr_list\n");
count = -EINVAL;
goto err;
@ -987,7 +1012,7 @@ static int dcc_config_add(struct dcc_drvdata *drvdata, unsigned int addr,
mutex_lock(&drvdata->mutex);
if (drvdata->curr_list >= DCC_MAX_LINK_LIST) {
if (drvdata->curr_list >= drvdata->nr_link_list) {
dev_err(drvdata->dev, "Select link list to program using curr_list\n");
ret = -EINVAL;
goto err;
@ -1112,7 +1137,7 @@ static void dcc_config_reset(struct dcc_drvdata *drvdata)
mutex_lock(&drvdata->mutex);
for (curr_list = 0; curr_list < DCC_MAX_LINK_LIST; curr_list++) {
for (curr_list = 0; curr_list < drvdata->nr_link_list; curr_list++) {
list_for_each_entry_safe(entry, temp,
&drvdata->cfg_head[curr_list], list) {
@ -1150,7 +1175,7 @@ static ssize_t crc_error_show(struct device *dev,
struct dcc_drvdata *drvdata = dev_get_drvdata(dev);
mutex_lock(&drvdata->mutex);
if (drvdata->curr_list >= DCC_MAX_LINK_LIST) {
if (drvdata->curr_list >= drvdata->nr_link_list) {
dev_err(dev, "Select link list to program using curr_list\n");
ret = -EINVAL;
goto err;
@ -1178,7 +1203,7 @@ static ssize_t ready_show(struct device *dev,
mutex_lock(&drvdata->mutex);
if (drvdata->curr_list >= DCC_MAX_LINK_LIST) {
if (drvdata->curr_list >= drvdata->nr_link_list) {
dev_err(dev, "Select link list to program using curr_list\n");
ret = -EINVAL;
goto err;
@ -1256,7 +1281,7 @@ static ssize_t loop_store(struct device *dev,
goto err;
}
if (drvdata->curr_list >= DCC_MAX_LINK_LIST) {
if (drvdata->curr_list >= drvdata->nr_link_list) {
dev_err(dev, "Select link list to program using curr_list\n");
ret = -EINVAL;
goto err;
@ -1282,7 +1307,7 @@ static int dcc_rd_mod_wr_add(struct dcc_drvdata *drvdata, unsigned int mask,
mutex_lock(&drvdata->mutex);
if (drvdata->curr_list >= DCC_MAX_LINK_LIST) {
if (drvdata->curr_list >= drvdata->nr_link_list) {
dev_err(drvdata->dev, "Select link list to program using curr_list\n");
ret = -EINVAL;
goto err;
@ -1375,7 +1400,7 @@ static ssize_t config_write_store(struct device *dev,
goto err;
}
if (drvdata->curr_list >= DCC_MAX_LINK_LIST) {
if (drvdata->curr_list >= drvdata->nr_link_list) {
dev_err(dev, "Select link list to program using curr_list\n");
ret = -EINVAL;
goto err;
@ -1417,7 +1442,7 @@ static ssize_t cti_trig_store(struct device *dev,
mutex_lock(&drvdata->mutex);
if (drvdata->curr_list >= DCC_MAX_LINK_LIST) {
if (drvdata->curr_list >= drvdata->nr_link_list) {
dev_err(dev, "Select link list to program using curr_list\n");
ret = -EINVAL;
goto out;
@ -1612,7 +1637,7 @@ static int dcc_dt_parse(struct dcc_drvdata *drvdata, struct device_node *np)
if (ret)
return ret;
if (curr_link_list >= DCC_MAX_LINK_LIST) {
if (curr_link_list >= drvdata->nr_link_list) {
dev_err(drvdata->dev, "List configuration failed.\n");
return ret;
}
@ -1735,11 +1760,48 @@ static int dcc_probe(struct platform_device *pdev)
if (ret)
return -EINVAL;
drvdata->loopoff = get_bitmask_order((drvdata->ram_size +
if ((dcc_readl(drvdata, DCC_HW_INFO) & 0x3F) == 0x3F) {
drvdata->memory_map2 = true;
drvdata->nr_link_list = dcc_readl(drvdata, DCC_LL_NUM_INFO);
if (drvdata->nr_link_list == 0)
return -EINVAL;
} else {
drvdata->memory_map2 = false;
drvdata->nr_link_list = DCC_MAX_LINK_LIST;
}
if ((dcc_readl(drvdata, DCC_HW_INFO) & BIT(6)) == BIT(6))
drvdata->loopoff = DCC_FIX_LOOP_OFFSET;
else
drvdata->loopoff = get_bitmask_order((drvdata->ram_size +
drvdata->ram_offset) / 4 - 1);
mutex_init(&drvdata->mutex);
drvdata->data_sink = devm_kzalloc(dev, drvdata->nr_link_list *
sizeof(enum dcc_data_sink), GFP_KERNEL);
if (!drvdata->data_sink)
return -ENOMEM;
drvdata->func_type = devm_kzalloc(dev, drvdata->nr_link_list *
sizeof(enum dcc_func_type), GFP_KERNEL);
if (!drvdata->func_type)
return -ENOMEM;
drvdata->enable = devm_kzalloc(dev, drvdata->nr_link_list *
sizeof(bool), GFP_KERNEL);
if (!drvdata->enable)
return -ENOMEM;
drvdata->configured = devm_kzalloc(dev, drvdata->nr_link_list *
sizeof(bool), GFP_KERNEL);
if (!drvdata->configured)
return -ENOMEM;
drvdata->nr_config = devm_kzalloc(dev, drvdata->nr_link_list *
sizeof(uint32_t), GFP_KERNEL);
if (!drvdata->nr_config)
return -ENOMEM;
drvdata->cfg_head = devm_kzalloc(dev, drvdata->nr_link_list *
sizeof(struct list_head), GFP_KERNEL);
if (!drvdata->cfg_head)
return -ENOMEM;
for (i = 0; i < DCC_MAX_LINK_LIST; i++) {
for (i = 0; i < drvdata->nr_link_list; i++) {
INIT_LIST_HEAD(&drvdata->cfg_head[i]);
drvdata->nr_config[i] = 0;
}