summaryrefslogtreecommitdiff
path: root/drivers/soc
diff options
context:
space:
mode:
authorShashank Mittal <mittals@codeaurora.org>2015-05-11 14:57:24 -0700
committerJeevan Shriram <jshriram@codeaurora.org>2016-05-16 20:10:36 -0700
commitc5d78d4e6e6eb40903ecdf799470715a2813ee51 (patch)
treebb3e4eabfc7ae53711908ddd02bb04d64a40a54d /drivers/soc
parentd3d5065b82d5ca7502f4c11f4794938aed4bd4e1 (diff)
soc: qcom: dcc: add support for CRC mode
In CRC mode DCC can perform CRC on configuration data or system memory after receiving SW or HW trigger. Change-Id: Iab0a6ffa92ef6e311054756cfe85d1b2b91743c9 Signed-off-by: Shashank Mittal <mittals@codeaurora.org>
Diffstat (limited to 'drivers/soc')
-rw-r--r--drivers/soc/qcom/dcc.c60
1 files changed, 59 insertions, 1 deletions
diff --git a/drivers/soc/qcom/dcc.c b/drivers/soc/qcom/dcc.c
index e02cf7dc77d2..b4a3536361a3 100644
--- a/drivers/soc/qcom/dcc.c
+++ b/drivers/soc/qcom/dcc.c
@@ -97,6 +97,7 @@ struct dcc_drvdata {
enum dcc_func_type func_type;
uint32_t ram_cfg;
bool enable;
+ bool interrupt_disable;
char *sram_node;
struct cdev sram_dev;
struct class *sram_class;
@@ -281,6 +282,25 @@ static void __dcc_reg_dump(struct dcc_drvdata *drvdata)
drvdata->reg_data.magic = DCC_REG_DUMP_MAGIC_V2;
}
+static void __dcc_first_crc(struct dcc_drvdata *drvdata)
+{
+ int i;
+
+ /*
+ * Need to send 2 triggers to DCC. First trigger sets CRC error status
+ * bit. So need second trigger to reset this bit.
+ */
+ for (i = 0; i < 2; i++) {
+ if (!dcc_ready(drvdata))
+ dev_err(drvdata->dev, "DCC is not ready!\n");
+
+ dcc_writel(drvdata, 1, DCC_SW_CTL);
+ }
+
+ /* Clear CRC error interrupt */
+ dcc_writel(drvdata, BIT(0), DCC_INT_STATUS);
+}
+
static int dcc_enable(struct dcc_drvdata *drvdata)
{
int ret = 0;
@@ -314,7 +334,8 @@ static int dcc_enable(struct dcc_drvdata *drvdata)
DCC_CFG);
/* 5. Clears interrupt status register */
- dcc_writel(drvdata, 0, DCC_INT_STATUS);
+ dcc_writel(drvdata, 0, DCC_INT_ENABLE);
+ dcc_writel(drvdata, (BIT(4) | BIT(0)), DCC_INT_STATUS);
/* Make sure all config is written in sram */
mb();
@@ -323,6 +344,14 @@ static int dcc_enable(struct dcc_drvdata *drvdata)
dcc_writel(drvdata, 1, DCC_LL);
drvdata->enable = 1;
+ if (drvdata->func_type == DCC_FUNC_TYPE_CRC) {
+ __dcc_first_crc(drvdata);
+
+ /* Enable CRC error interrupt */
+ if (!drvdata->interrupt_disable)
+ dcc_writel(drvdata, BIT(0), DCC_INT_ENABLE);
+ }
+
/* Save DCC registers */
if (drvdata->save_reg)
__dcc_reg_dump(drvdata);
@@ -670,6 +699,34 @@ err:
}
static DEVICE_ATTR(ready, S_IRUGO, dcc_show_ready, NULL);
+static ssize_t dcc_show_interrupt_disable(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct dcc_drvdata *drvdata = dev_get_drvdata(dev);
+
+ return scnprintf(buf, PAGE_SIZE, "%u\n",
+ (unsigned)drvdata->interrupt_disable);
+}
+
+static ssize_t dcc_store_interrupt_disable(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned long val;
+ struct dcc_drvdata *drvdata = dev_get_drvdata(dev);
+
+ if (kstrtoul(buf, 16, &val))
+ return -EINVAL;
+
+ mutex_lock(&drvdata->mutex);
+ drvdata->interrupt_disable = (val ? 1:0);
+ mutex_unlock(&drvdata->mutex);
+ return size;
+}
+static DEVICE_ATTR(interrupt_disable, S_IRUGO | S_IWUSR,
+ dcc_show_interrupt_disable, dcc_store_interrupt_disable);
+
static const struct device_attribute *dcc_attrs[] = {
&dev_attr_func_type,
&dev_attr_data_sink,
@@ -679,6 +736,7 @@ static const struct device_attribute *dcc_attrs[] = {
&dev_attr_config_reset,
&dev_attr_ready,
&dev_attr_crc_error,
+ &dev_attr_interrupt_disable,
NULL,
};