Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6ce9e531 authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "soc: qcom: dcc_v2: support multiple link lists"

parents bd6e2552 e208a816
Loading
Loading
Loading
Loading
+69 −43
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
 */

#include <linux/module.h>
@@ -75,7 +75,7 @@
#define DCC_AHB_IND			0x00
#define DCC_APB_IND			BIT(29)

#define DCC_MAX_LINK_LIST		5
#define DCC_MAX_LINK_LIST		8
#define DCC_INVALID_LINK_LIST		0xFF

enum dcc_func_type {
@@ -131,7 +131,7 @@ struct dcc_drvdata {
	void __iomem		*ram_base;
	uint32_t		ram_size;
	uint32_t		ram_offset;
	enum dcc_data_sink	data_sink;
	enum dcc_data_sink	data_sink[DCC_MAX_LINK_LIST];
	enum dcc_func_type	func_type[DCC_MAX_LINK_LIST];
	uint32_t		ram_cfg;
	uint32_t		ram_start;
@@ -459,7 +459,7 @@ static int __dcc_ll_cfg(struct dcc_drvdata *drvdata, int curr_list)
	sram_offset += 4;

	/* Update ram_cfg and check if the data will overstep */
	if (drvdata->data_sink == DCC_DATA_SINK_SRAM &&
	if (drvdata->data_sink[curr_list] == DCC_DATA_SINK_SRAM &&
	    drvdata->func_type[curr_list] == DCC_FUNC_TYPE_CAPTURE) {
		drvdata->ram_cfg = (sram_offset + total_len) / 4;

@@ -561,12 +561,7 @@ static int dcc_enable(struct dcc_drvdata *drvdata)
				drvdata->ram_offset/4, DCC_FD_BASE(list));
		dcc_writel(drvdata, 0xFFF, DCC_LL_TIMEOUT(list));

		/* 4. Configure data sink and function type */
		dcc_writel(drvdata, ((drvdata->cti_trig << 8) |
			   (drvdata->data_sink << 4) |
			   (drvdata->func_type[list])), DCC_LL_CFG(list));

		/* 5. Clears interrupt status register */
		/* 4. Clears interrupt status register */
		dcc_writel(drvdata, 0, DCC_LL_INT_ENABLE(list));
		dcc_writel(drvdata, (BIT(0) | BIT(1) | BIT(2)),
			   DCC_LL_INT_STATUS(list));
@@ -586,9 +581,9 @@ static int dcc_enable(struct dcc_drvdata *drvdata)
					   DCC_LL_INT_ENABLE(list));
		}

		/* 6. Configure trigger */
		/* 5. Configure trigger */
		dcc_writel(drvdata, BIT(9) | ((drvdata->cti_trig << 8) |
			   (drvdata->data_sink << 4) |
			   (drvdata->data_sink[list] << 4) |
			   (drvdata->func_type[list])), DCC_LL_CFG(list));
	}

@@ -712,9 +707,14 @@ static ssize_t data_sink_show(struct device *dev,
				  struct device_attribute *attr, char *buf)
{
	struct dcc_drvdata *drvdata = dev_get_drvdata(dev);
	ssize_t len = 0;
	unsigned int i;

	return scnprintf(buf, PAGE_SIZE, "%s\n",
			 str_dcc_data_sink[drvdata->data_sink]);
	for (i = 0; i < DCC_MAX_LINK_LIST; i++)
		len += scnprintf(buf + len, PAGE_SIZE - len, "%u :%s\n",
				 i, str_dcc_data_sink[drvdata->data_sink[i]]);

	return len;
}

static ssize_t data_sink_store(struct device *dev,
@@ -731,15 +731,22 @@ static ssize_t data_sink_store(struct device *dev,
		return -EINVAL;

	mutex_lock(&drvdata->mutex);
	if (drvdata->curr_list >= DCC_MAX_LINK_LIST) {
		dev_err(dev,
			"Select link list to program using curr_list\n");
		ret = -EINVAL;
		goto out;
	}

	if (drvdata->enable[drvdata->curr_list]) {
		ret = -EBUSY;
		goto out;
	}

	if (!strcmp(str, str_dcc_data_sink[DCC_DATA_SINK_SRAM]))
		drvdata->data_sink = DCC_DATA_SINK_SRAM;
		drvdata->data_sink[drvdata->curr_list] = DCC_DATA_SINK_SRAM;
	else if (!strcmp(str, str_dcc_data_sink[DCC_DATA_SINK_ATB]))
		drvdata->data_sink = DCC_DATA_SINK_ATB;
		drvdata->data_sink[drvdata->curr_list] = DCC_DATA_SINK_ATB;
	else {
		ret = -EINVAL;
		goto out;
@@ -1485,25 +1492,41 @@ static void dcc_sram_dev_exit(struct dcc_drvdata *drvdata)
	dcc_sram_dev_deregister(drvdata);
}

static void dcc_configure_list(struct dcc_drvdata *drvdata,
			       struct device_node *np)
static int dcc_dt_parse(struct dcc_drvdata *drvdata, struct device_node *np)
{
	int ret, i;
	int i, ret = -1;
	const __be32 *prop;
	uint32_t len, entry, val1, val2, apb_bus;
	uint32_t curr_link_list;
	const char *data_sink;

	ret = of_property_read_u32(np, "qcom,curr-link-list",
				&curr_link_list);
	if (ret)
		return;
		return ret;

	if (curr_link_list >= DCC_MAX_LINK_LIST) {
		dev_err(drvdata->dev, "List configuration failed.\n");
		return;
		return ret;
	}
	drvdata->curr_list = curr_link_list;

	drvdata->data_sink[curr_link_list] = DCC_DATA_SINK_SRAM;
	ret = of_property_read_string(np, "qcom,data-sink",
					&data_sink);
	if (!ret) {
		for (i = 0; i < ARRAY_SIZE(str_dcc_data_sink); i++)
			if (!strcmp(data_sink, str_dcc_data_sink[i])) {
				drvdata->data_sink[curr_link_list] = i;
				break;
			}

		if (i == ARRAY_SIZE(str_dcc_data_sink)) {
			dev_err(drvdata->dev, "Unknown sink type for DCC Using '%s' as data sink\n",
			str_dcc_data_sink[drvdata->data_sink[curr_link_list]]);
		}
	}

	prop = of_get_property(np, "qcom,link-list", &len);
	if (prop) {
		len /= sizeof(__be32);
@@ -1537,11 +1560,31 @@ static void dcc_configure_list(struct dcc_drvdata *drvdata,
				break;
			}
		}
	}
	return ret;
}

static void dcc_configure_list(struct dcc_drvdata *drvdata,
			       struct device_node *np)
{
	int ret = -1;
	struct device_node *link_node = NULL;

	for_each_available_child_of_node(np, link_node) {
		ret = dcc_dt_parse(drvdata, link_node);
		if (ret) {
			dev_err(drvdata->dev,
				"DCC link list config failed err:%d\n", ret);
			break;
		}
	}

	if (ret == -1)
		ret = dcc_dt_parse(drvdata, np);

	if (!ret)
		dcc_enable(drvdata);
}
}

static int dcc_probe(struct platform_device *pdev)
{
@@ -1549,7 +1592,6 @@ static int dcc_probe(struct platform_device *pdev)
	struct device *dev = &pdev->dev;
	struct dcc_drvdata *drvdata;
	struct resource *res;
	const char *data_sink;

	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
	if (!drvdata)
@@ -1591,22 +1633,6 @@ static int dcc_probe(struct platform_device *pdev)

	memset_io(drvdata->ram_base, 0, drvdata->ram_size);

	drvdata->data_sink = DCC_DATA_SINK_SRAM;
	ret = of_property_read_string(pdev->dev.of_node, "qcom,data-sink",
				      &data_sink);
	if (!ret) {
		for (i = 0; i < ARRAY_SIZE(str_dcc_data_sink); i++)
			if (!strcmp(data_sink, str_dcc_data_sink[i])) {
				drvdata->data_sink = i;
				break;
			}

		if (i == ARRAY_SIZE(str_dcc_data_sink)) {
			dev_err(dev, "Unknown sink type for DCC Using '%s' as data sink\n",
				str_dcc_data_sink[drvdata->data_sink]);
		}
	}

	drvdata->curr_list = DCC_INVALID_LINK_LIST;

	ret = dcc_sram_dev_init(drvdata);