]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
video: tegra: host: Support forcing engines on
authorArto Merilainen <amerilainen@nvidia.com>
Wed, 15 Oct 2014 14:39:15 +0000 (17:39 +0300)
committerArto Merilainen <amerilainen@nvidia.com>
Wed, 22 Oct 2014 04:56:12 +0000 (21:56 -0700)
This patch adds an interface to force devices into powered and
clocked state. The interface can be used to bypass power features
to debug the driver or hardware.

Bug 200043887

Change-Id: I18957ba56cec217df1c0574a4ad7e687d2757da0
Signed-off-by: Arto Merilainen <amerilainen@nvidia.com>
Reviewed-on: http://git-master/r/557978
Reviewed-by: Shridhar Rasal <srasal@nvidia.com>
GVS: Gerrit_Virtual_Submit

drivers/video/tegra/host/nvhost_acm.c
include/linux/nvhost.h

index 922d5f9ef2c327c23e7e85b7f8f85e7bcfaa3f93..807ab1e43ee7867bf502338010bb46d06f774c81 100644 (file)
@@ -434,6 +434,48 @@ void nvhost_module_remove_client(struct platform_device *dev, void *priv)
        mutex_unlock(&client_list_lock);
 }
 
+static ssize_t force_on_store(struct kobject *kobj,
+       struct kobj_attribute *attr, const char *buf, size_t count)
+{
+       int force_on = 0, ret = 0;
+       struct nvhost_device_power_attr *power_attribute =
+               container_of(attr, struct nvhost_device_power_attr,
+                            power_attr[NVHOST_POWER_SYSFS_ATTRIB_FORCE_ON]);
+       struct platform_device *dev = power_attribute->ndev;
+       struct nvhost_device_data *pdata = platform_get_drvdata(dev);
+
+       ret = sscanf(buf, "%d", &force_on);
+       if (ret != 1)
+               return -EINVAL;
+
+       /* should we force the power on or off? */
+       if (force_on && !pdata->forced_on) {
+               /* force on */
+               ret = nvhost_module_busy(dev);
+               if (!ret)
+                       pdata->forced_on = true;
+       } else if (!force_on && pdata->forced_on) {
+               /* force off */
+               nvhost_module_idle(dev);
+               pdata->forced_on = false;
+       }
+
+       return count;
+}
+
+static ssize_t force_on_show(struct kobject *kobj,
+       struct kobj_attribute *attr, char *buf)
+{
+       struct nvhost_device_power_attr *power_attribute =
+               container_of(attr, struct nvhost_device_power_attr,
+                            power_attr[NVHOST_POWER_SYSFS_ATTRIB_FORCE_ON]);
+       struct platform_device *dev = power_attribute->ndev;
+       struct nvhost_device_data *pdata = platform_get_drvdata(dev);
+
+       return sprintf(buf, "%d\n", pdata->forced_on);
+
+}
+
 static ssize_t powergate_delay_store(struct kobject *kobj,
        struct kobj_attribute *attr, const char *buf, size_t count)
 {
@@ -705,8 +747,24 @@ int nvhost_module_init(struct platform_device *dev)
                goto fail_powergatedelay;
        }
 
+       attr = &pdata->power_attrib->power_attr[NVHOST_POWER_SYSFS_ATTRIB_FORCE_ON];
+       attr->attr.name = "force_on";
+       attr->attr.mode = S_IWUSR | S_IRUGO;
+       attr->show = force_on_show;
+       attr->store = force_on_store;
+       sysfs_attr_init(&attr->attr);
+       if (sysfs_create_file(pdata->power_kobj, &attr->attr)) {
+               dev_err(&dev->dev, "Could not create sysfs attribute force_on\n");
+               err = -EIO;
+               goto fail_forceon;
+       }
+
        return 0;
 
+fail_forceon:
+       attr = &pdata->power_attrib->power_attr[NVHOST_POWER_SYSFS_ATTRIB_POWERGATE_DELAY];
+       sysfs_remove_file(pdata->power_kobj, &attr->attr);
+
 fail_powergatedelay:
        attr = &pdata->power_attrib->power_attr[NVHOST_POWER_SYSFS_ATTRIB_CLOCKGATE_DELAY];
        sysfs_remove_file(pdata->power_kobj, &attr->attr);
index 4a53dcf9e16e035b9326f1588c5613fd1a219c61..67ddd0a45cda6f796cd1c896c7e30a10c950d74a 100644 (file)
@@ -85,6 +85,7 @@ struct sync_pt;
 enum nvhost_power_sysfs_attributes {
        NVHOST_POWER_SYSFS_ATTRIB_CLOCKGATE_DELAY = 0,
        NVHOST_POWER_SYSFS_ATTRIB_POWERGATE_DELAY,
+       NVHOST_POWER_SYSFS_ATTRIB_FORCE_ON,
        NVHOST_POWER_SYSFS_ATTRIB_MAX
 };
 
@@ -301,6 +302,9 @@ struct nvhost_device_data {
 
        /* Actmon IRQ from hintstatus_r */
        unsigned int actmon_irq;
+
+       /* Is the device already forced on? */
+       bool forced_on;
 };