diff --git a/drivers/soc/qcom/dcc_v2.c b/drivers/soc/qcom/dcc_v2.c index a15b2d0581c5..440dcb246390 100644 --- a/drivers/soc/qcom/dcc_v2.c +++ b/drivers/soc/qcom/dcc_v2.c @@ -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; }