1*0136db58SBen Widawsky /* 2*0136db58SBen Widawsky * Copyright © 2012 Intel Corporation 3*0136db58SBen Widawsky * 4*0136db58SBen Widawsky * Permission is hereby granted, free of charge, to any person obtaining a 5*0136db58SBen Widawsky * copy of this software and associated documentation files (the "Software"), 6*0136db58SBen Widawsky * to deal in the Software without restriction, including without limitation 7*0136db58SBen Widawsky * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8*0136db58SBen Widawsky * and/or sell copies of the Software, and to permit persons to whom the 9*0136db58SBen Widawsky * Software is furnished to do so, subject to the following conditions: 10*0136db58SBen Widawsky * 11*0136db58SBen Widawsky * The above copyright notice and this permission notice (including the next 12*0136db58SBen Widawsky * paragraph) shall be included in all copies or substantial portions of the 13*0136db58SBen Widawsky * Software. 14*0136db58SBen Widawsky * 15*0136db58SBen Widawsky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16*0136db58SBen Widawsky * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17*0136db58SBen Widawsky * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18*0136db58SBen Widawsky * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19*0136db58SBen Widawsky * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20*0136db58SBen Widawsky * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21*0136db58SBen Widawsky * IN THE SOFTWARE. 22*0136db58SBen Widawsky * 23*0136db58SBen Widawsky * Authors: 24*0136db58SBen Widawsky * Ben Widawsky <ben@bwidawsk.net> 25*0136db58SBen Widawsky * 26*0136db58SBen Widawsky */ 27*0136db58SBen Widawsky 28*0136db58SBen Widawsky #include <linux/device.h> 29*0136db58SBen Widawsky #include <linux/module.h> 30*0136db58SBen Widawsky #include <linux/stat.h> 31*0136db58SBen Widawsky #include <linux/sysfs.h> 32*0136db58SBen Widawsky #include "i915_drv.h" 33*0136db58SBen Widawsky 34*0136db58SBen Widawsky static u32 calc_residency(struct drm_device *dev, const u32 reg) 35*0136db58SBen Widawsky { 36*0136db58SBen Widawsky struct drm_i915_private *dev_priv = dev->dev_private; 37*0136db58SBen Widawsky u64 raw_time; /* 32b value may overflow during fixed point math */ 38*0136db58SBen Widawsky 39*0136db58SBen Widawsky if (!intel_enable_rc6(dev)) 40*0136db58SBen Widawsky return 0; 41*0136db58SBen Widawsky 42*0136db58SBen Widawsky raw_time = I915_READ(reg) * 128ULL + 500; 43*0136db58SBen Widawsky return do_div(raw_time, 100000); 44*0136db58SBen Widawsky } 45*0136db58SBen Widawsky 46*0136db58SBen Widawsky static ssize_t 47*0136db58SBen Widawsky show_rc6_mask(struct device *dev, struct device_attribute *attr, char *buf) 48*0136db58SBen Widawsky { 49*0136db58SBen Widawsky struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev); 50*0136db58SBen Widawsky return snprintf(buf, PAGE_SIZE, "%x", intel_enable_rc6(dminor->dev)); 51*0136db58SBen Widawsky } 52*0136db58SBen Widawsky 53*0136db58SBen Widawsky static ssize_t 54*0136db58SBen Widawsky show_rc6_ms(struct device *dev, struct device_attribute *attr, char *buf) 55*0136db58SBen Widawsky { 56*0136db58SBen Widawsky struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev); 57*0136db58SBen Widawsky u32 rc6_residency = calc_residency(dminor->dev, GEN6_GT_GFX_RC6); 58*0136db58SBen Widawsky return snprintf(buf, PAGE_SIZE, "%u", rc6_residency); 59*0136db58SBen Widawsky } 60*0136db58SBen Widawsky 61*0136db58SBen Widawsky static ssize_t 62*0136db58SBen Widawsky show_rc6p_ms(struct device *dev, struct device_attribute *attr, char *buf) 63*0136db58SBen Widawsky { 64*0136db58SBen Widawsky struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev); 65*0136db58SBen Widawsky u32 rc6p_residency = calc_residency(dminor->dev, GEN6_GT_GFX_RC6p); 66*0136db58SBen Widawsky return snprintf(buf, PAGE_SIZE, "%u", rc6p_residency); 67*0136db58SBen Widawsky } 68*0136db58SBen Widawsky 69*0136db58SBen Widawsky static ssize_t 70*0136db58SBen Widawsky show_rc6pp_ms(struct device *dev, struct device_attribute *attr, char *buf) 71*0136db58SBen Widawsky { 72*0136db58SBen Widawsky struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev); 73*0136db58SBen Widawsky u32 rc6pp_residency = calc_residency(dminor->dev, GEN6_GT_GFX_RC6pp); 74*0136db58SBen Widawsky return snprintf(buf, PAGE_SIZE, "%u", rc6pp_residency); 75*0136db58SBen Widawsky } 76*0136db58SBen Widawsky 77*0136db58SBen Widawsky static DEVICE_ATTR(rc6_enable, S_IRUGO, show_rc6_mask, NULL); 78*0136db58SBen Widawsky static DEVICE_ATTR(rc6_residency_ms, S_IRUGO, show_rc6_ms, NULL); 79*0136db58SBen Widawsky static DEVICE_ATTR(rc6p_residency_ms, S_IRUGO, show_rc6p_ms, NULL); 80*0136db58SBen Widawsky static DEVICE_ATTR(rc6pp_residency_ms, S_IRUGO, show_rc6pp_ms, NULL); 81*0136db58SBen Widawsky 82*0136db58SBen Widawsky static struct attribute *rc6_attrs[] = { 83*0136db58SBen Widawsky &dev_attr_rc6_enable.attr, 84*0136db58SBen Widawsky &dev_attr_rc6_residency_ms.attr, 85*0136db58SBen Widawsky &dev_attr_rc6p_residency_ms.attr, 86*0136db58SBen Widawsky &dev_attr_rc6pp_residency_ms.attr, 87*0136db58SBen Widawsky NULL 88*0136db58SBen Widawsky }; 89*0136db58SBen Widawsky 90*0136db58SBen Widawsky static struct attribute_group rc6_attr_group = { 91*0136db58SBen Widawsky .name = power_group_name, 92*0136db58SBen Widawsky .attrs = rc6_attrs 93*0136db58SBen Widawsky }; 94*0136db58SBen Widawsky 95*0136db58SBen Widawsky void i915_setup_sysfs(struct drm_device *dev) 96*0136db58SBen Widawsky { 97*0136db58SBen Widawsky int ret; 98*0136db58SBen Widawsky 99*0136db58SBen Widawsky /* ILK doesn't have any residency information */ 100*0136db58SBen Widawsky if (INTEL_INFO(dev)->gen < 6) 101*0136db58SBen Widawsky return; 102*0136db58SBen Widawsky 103*0136db58SBen Widawsky ret = sysfs_merge_group(&dev->primary->kdev.kobj, &rc6_attr_group); 104*0136db58SBen Widawsky if (ret) 105*0136db58SBen Widawsky DRM_ERROR("sysfs setup failed\n"); 106*0136db58SBen Widawsky } 107*0136db58SBen Widawsky 108*0136db58SBen Widawsky void i915_teardown_sysfs(struct drm_device *dev) 109*0136db58SBen Widawsky { 110*0136db58SBen Widawsky sysfs_unmerge_group(&dev->primary->kdev.kobj, &rc6_attr_group); 111*0136db58SBen Widawsky } 112