iommu/iommu-debug: Add debugfs file to enable config clocks

It's fairly common while debugging to need to enable the config clocks
for an SMMU so that you can poke around at the registers.  Add a debugfs
file to do this.

CRs-Fixed: 997751
Change-Id: I31b90d64c2facb0a681f9da586e2c90803776819
Signed-off-by: Mitchel Humpherys <mitchelh@codeaurora.org>
Signed-off-by: Patrick Daly <pdaly@codeaurora.org>
diff --git a/drivers/iommu/iommu-debug.c b/drivers/iommu/iommu-debug.c
index e828469..7f4e3ef 100644
--- a/drivers/iommu/iommu-debug.c
+++ b/drivers/iommu/iommu-debug.c
@@ -1785,6 +1785,53 @@
 	.write	= iommu_debug_unmap_write,
 };
 
+static ssize_t iommu_debug_config_clocks_write(struct file *file,
+					       const char __user *ubuf,
+					       size_t count, loff_t *offset)
+{
+	char buf;
+	struct iommu_debug_device *ddev = file->private_data;
+	struct device *dev = ddev->dev;
+
+	/* we're expecting a single character plus (optionally) a newline */
+	if (count > 2) {
+		dev_err(dev, "Invalid value\n");
+		return -EINVAL;
+	}
+
+	if (!ddev->domain) {
+		dev_err(dev, "No domain. Did you already attach?\n");
+		return -EINVAL;
+	}
+
+	if (copy_from_user(&buf, ubuf, 1)) {
+		dev_err(dev, "Couldn't copy from user\n");
+		return -EFAULT;
+	}
+
+	switch (buf) {
+	case '0':
+		dev_err(dev, "Disabling config clocks\n");
+		iommu_disable_config_clocks(ddev->domain);
+		break;
+	case '1':
+		dev_err(dev, "Enabling config clocks\n");
+		if (iommu_enable_config_clocks(ddev->domain))
+			dev_err(dev, "Failed!\n");
+		break;
+	default:
+		dev_err(dev, "Invalid value. Should be 0 or 1.\n");
+		return -EINVAL;
+	}
+
+	return count;
+}
+
+static const struct file_operations iommu_debug_config_clocks_fops = {
+	.open	= simple_open,
+	.write	= iommu_debug_config_clocks_write,
+};
+
 /*
  * The following will only work for drivers that implement the generic
  * device tree bindings described in
@@ -1893,6 +1940,13 @@
 		goto err_rmdir;
 	}
 
+	if (!debugfs_create_file("config_clocks", S_IWUSR, dir, ddev,
+				 &iommu_debug_config_clocks_fops)) {
+		pr_err("Couldn't create iommu/devices/%s/config_clocks debugfs file\n",
+		       dev_name(dev));
+		goto err_rmdir;
+	}
+
 	list_add(&ddev->list, &iommu_debug_devices);
 	return 0;