blob: a7aa93927a6cb2bbcece727a6c56675805031266 [file] [log] [blame]
Harshdeep Dhatte2c71372018-01-03 11:45:41 -07001/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
Shrenuj Bansala419c792016-10-20 14:05:11 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/sysfs.h>
14#include <linux/device.h>
15
16#include "kgsl_device.h"
17#include "adreno.h"
18
19struct adreno_sysfs_attribute {
20 struct device_attribute attr;
21 unsigned int (*show)(struct adreno_device *adreno_dev);
22 int (*store)(struct adreno_device *adreno_dev, unsigned int val);
23};
24
25#define _ADRENO_SYSFS_ATTR(_name, __show, __store) \
26struct adreno_sysfs_attribute adreno_attr_##_name = { \
27 .attr = __ATTR(_name, 0644, __show, __store), \
28 .show = _ ## _name ## _show, \
29 .store = _ ## _name ## _store, \
30}
31
Harshdeep Dhatt4ab35b12017-11-16 08:34:39 -070032#define _ADRENO_SYSFS_ATTR_RO(_name, __show) \
33struct adreno_sysfs_attribute adreno_attr_##_name = { \
Harshdeep Dhatte2c71372018-01-03 11:45:41 -070034 .attr = __ATTR(_name, 0444, __show, NULL), \
Harshdeep Dhatt4ab35b12017-11-16 08:34:39 -070035 .show = _ ## _name ## _show, \
36 .store = NULL, \
37}
38
Shrenuj Bansala419c792016-10-20 14:05:11 -070039#define ADRENO_SYSFS_ATTR(_a) \
40 container_of((_a), struct adreno_sysfs_attribute, attr)
41
42static struct adreno_device *_get_adreno_dev(struct device *dev)
43{
44 struct kgsl_device *device = kgsl_device_from_dev(dev);
45
46 return device ? ADRENO_DEVICE(device) : NULL;
47}
48
49static int _ft_policy_store(struct adreno_device *adreno_dev,
50 unsigned int val)
51{
52 adreno_dev->ft_policy = val & KGSL_FT_POLICY_MASK;
53 return 0;
54}
55
56static unsigned int _ft_policy_show(struct adreno_device *adreno_dev)
57{
58 return adreno_dev->ft_policy;
59}
60
Harshdeep Dhatt26c54f22017-08-30 17:37:39 -060061static int _preempt_level_store(struct adreno_device *adreno_dev,
62 unsigned int val)
63{
Harshdeep Dhatta8ec51c2017-09-21 17:24:08 -060064 struct adreno_preemption *preempt = &adreno_dev->preempt;
65
Harshdeep Dhatt26c54f22017-08-30 17:37:39 -060066 if (val <= 2)
Harshdeep Dhatta8ec51c2017-09-21 17:24:08 -060067 preempt->preempt_level = val;
Harshdeep Dhatt26c54f22017-08-30 17:37:39 -060068 return 0;
69}
70
71static unsigned int _preempt_level_show(struct adreno_device *adreno_dev)
72{
Harshdeep Dhatta8ec51c2017-09-21 17:24:08 -060073 struct adreno_preemption *preempt = &adreno_dev->preempt;
74
75 return preempt->preempt_level;
Harshdeep Dhatt26c54f22017-08-30 17:37:39 -060076}
77
78static int _usesgmem_store(struct adreno_device *adreno_dev,
79 unsigned int val)
80{
Harshdeep Dhatta8ec51c2017-09-21 17:24:08 -060081 struct adreno_preemption *preempt = &adreno_dev->preempt;
82
83 preempt->usesgmem = val ? 1 : 0;
Harshdeep Dhatt26c54f22017-08-30 17:37:39 -060084 return 0;
85}
86
87static unsigned int _usesgmem_show(struct adreno_device *adreno_dev)
88{
Harshdeep Dhatta8ec51c2017-09-21 17:24:08 -060089 struct adreno_preemption *preempt = &adreno_dev->preempt;
90
91 return preempt->usesgmem;
Harshdeep Dhatt26c54f22017-08-30 17:37:39 -060092}
93
94static int _skipsaverestore_store(struct adreno_device *adreno_dev,
95 unsigned int val)
96{
Harshdeep Dhatta8ec51c2017-09-21 17:24:08 -060097 struct adreno_preemption *preempt = &adreno_dev->preempt;
98
99 preempt->skipsaverestore = val ? 1 : 0;
Harshdeep Dhatt26c54f22017-08-30 17:37:39 -0600100 return 0;
101}
102
103static unsigned int _skipsaverestore_show(struct adreno_device *adreno_dev)
104{
Harshdeep Dhatta8ec51c2017-09-21 17:24:08 -0600105 struct adreno_preemption *preempt = &adreno_dev->preempt;
106
107 return preempt->skipsaverestore;
Harshdeep Dhatt26c54f22017-08-30 17:37:39 -0600108}
109
Shrenuj Bansala419c792016-10-20 14:05:11 -0700110static int _ft_pagefault_policy_store(struct adreno_device *adreno_dev,
111 unsigned int val)
112{
113 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
114 int ret = 0;
115
116 mutex_lock(&device->mutex);
117 val &= KGSL_FT_PAGEFAULT_MASK;
118
119 if (test_bit(ADRENO_DEVICE_STARTED, &adreno_dev->priv))
120 ret = kgsl_mmu_set_pagefault_policy(&device->mmu,
121 (unsigned long) val);
122
123 if (ret == 0)
124 adreno_dev->ft_pf_policy = val;
125
126 mutex_unlock(&device->mutex);
127
128 return 0;
129}
130
131static unsigned int _ft_pagefault_policy_show(struct adreno_device *adreno_dev)
132{
133 return adreno_dev->ft_pf_policy;
134}
135
Sushmita Susheelendrab1976682016-11-07 14:21:11 -0700136static int _gpu_llc_slice_enable_store(struct adreno_device *adreno_dev,
137 unsigned int val)
138{
139 adreno_dev->gpu_llc_slice_enable = val ? true : false;
140 return 0;
141}
142
143static unsigned int _gpu_llc_slice_enable_show(struct adreno_device *adreno_dev)
144{
145 return adreno_dev->gpu_llc_slice_enable;
146}
147
Sushmita Susheelendrad3756c02017-01-11 15:05:40 -0700148static int _gpuhtw_llc_slice_enable_store(struct adreno_device *adreno_dev,
149 unsigned int val)
150{
151 adreno_dev->gpuhtw_llc_slice_enable = val ? true : false;
152 return 0;
153}
154
155static unsigned int
156_gpuhtw_llc_slice_enable_show(struct adreno_device *adreno_dev)
157{
158 return adreno_dev->gpuhtw_llc_slice_enable;
159}
160
Shrenuj Bansala419c792016-10-20 14:05:11 -0700161static int _ft_long_ib_detect_store(struct adreno_device *adreno_dev,
162 unsigned int val)
163{
164 adreno_dev->long_ib_detect = val;
165 return 0;
166}
167
168static unsigned int _ft_long_ib_detect_show(struct adreno_device *adreno_dev)
169{
170 return adreno_dev->long_ib_detect;
171}
172
173static int _ft_hang_intr_status_store(struct adreno_device *adreno_dev,
174 unsigned int val)
175{
176 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
177 int ret = 0;
178
179 if (val == test_bit(ADRENO_DEVICE_HANG_INTR, &adreno_dev->priv))
180 return 0;
181
182 mutex_lock(&device->mutex);
183 change_bit(ADRENO_DEVICE_HANG_INTR, &adreno_dev->priv);
184
185 if (test_bit(ADRENO_DEVICE_STARTED, &adreno_dev->priv)) {
186 kgsl_pwrctrl_change_state(device, KGSL_STATE_ACTIVE);
Shrenuj Bansala419c792016-10-20 14:05:11 -0700187 } else if (device->state == KGSL_STATE_INIT) {
188 ret = -EACCES;
189 change_bit(ADRENO_DEVICE_HANG_INTR, &adreno_dev->priv);
190 }
191
192 mutex_unlock(&device->mutex);
193 return ret;
194}
195
196static unsigned int _ft_hang_intr_status_show(struct adreno_device *adreno_dev)
197{
198 return test_bit(ADRENO_DEVICE_HANG_INTR, &adreno_dev->priv);
199}
200
201static int _pwrctrl_store(struct adreno_device *adreno_dev,
202 unsigned int val, unsigned int flag)
203{
204 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
205
206 if (val == test_bit(flag, &adreno_dev->pwrctrl_flag))
207 return 0;
208
209 mutex_lock(&device->mutex);
210
211 /* Power down the GPU before changing the state */
212 kgsl_pwrctrl_change_state(device, KGSL_STATE_SUSPEND);
213 change_bit(flag, &adreno_dev->pwrctrl_flag);
214 kgsl_pwrctrl_change_state(device, KGSL_STATE_SLUMBER);
215
216 mutex_unlock(&device->mutex);
217
218 return 0;
219}
220
221static int _preemption_store(struct adreno_device *adreno_dev,
222 unsigned int val)
223{
224 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
225
Shrenuj Bansala419c792016-10-20 14:05:11 -0700226 mutex_lock(&device->mutex);
227
Harshdeep Dhatt6f568de2017-12-12 15:08:08 -0700228 if (!(ADRENO_FEATURE(adreno_dev, ADRENO_PREEMPTION)) ||
Harshdeep Dhatt7ee8a862017-11-20 17:51:54 -0700229 (test_bit(ADRENO_DEVICE_PREEMPTION,
Harshdeep Dhatt6f568de2017-12-12 15:08:08 -0700230 &adreno_dev->priv) == val)) {
231 mutex_unlock(&device->mutex);
232 return 0;
233 }
234
Shrenuj Bansala419c792016-10-20 14:05:11 -0700235 kgsl_pwrctrl_change_state(device, KGSL_STATE_SUSPEND);
Harshdeep Dhatt7ee8a862017-11-20 17:51:54 -0700236 change_bit(ADRENO_DEVICE_PREEMPTION, &adreno_dev->priv);
Shrenuj Bansala419c792016-10-20 14:05:11 -0700237 adreno_dev->cur_rb = &(adreno_dev->ringbuffers[0]);
238 kgsl_pwrctrl_change_state(device, KGSL_STATE_SLUMBER);
239
240 mutex_unlock(&device->mutex);
241
242 return 0;
243}
244
Kyle Piefer970398f2017-09-27 13:23:40 -0700245static int _gmu_idle_level_store(struct adreno_device *adreno_dev,
246 unsigned int val)
247{
248 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
249 struct gmu_device *gmu = &device->gmu;
250
251 mutex_lock(&device->mutex);
252
253 /* Power down the GPU before changing the idle level */
254 kgsl_pwrctrl_change_state(device, KGSL_STATE_SUSPEND);
255 gmu->idle_level = val;
256 kgsl_pwrctrl_change_state(device, KGSL_STATE_SLUMBER);
257
258 mutex_unlock(&device->mutex);
259 return 0;
260}
261
Shrenuj Bansala419c792016-10-20 14:05:11 -0700262static unsigned int _preemption_show(struct adreno_device *adreno_dev)
263{
Harshdeep Dhatt7ee8a862017-11-20 17:51:54 -0700264 return adreno_is_preemption_enabled(adreno_dev);
Shrenuj Bansala419c792016-10-20 14:05:11 -0700265}
266
267static int _hwcg_store(struct adreno_device *adreno_dev,
268 unsigned int val)
269{
270 return _pwrctrl_store(adreno_dev, val, ADRENO_HWCG_CTRL);
271}
272
273static unsigned int _hwcg_show(struct adreno_device *adreno_dev)
274{
275 return test_bit(ADRENO_HWCG_CTRL, &adreno_dev->pwrctrl_flag);
276}
277
278static int _throttling_store(struct adreno_device *adreno_dev,
279 unsigned int val)
280{
281 return _pwrctrl_store(adreno_dev, val, ADRENO_THROTTLING_CTRL);
282}
283
284static unsigned int _throttling_show(struct adreno_device *adreno_dev)
285{
286 return test_bit(ADRENO_THROTTLING_CTRL, &adreno_dev->pwrctrl_flag);
287}
288
289static int _sptp_pc_store(struct adreno_device *adreno_dev,
290 unsigned int val)
291{
292 return _pwrctrl_store(adreno_dev, val, ADRENO_SPTP_PC_CTRL);
293}
294
295static unsigned int _sptp_pc_show(struct adreno_device *adreno_dev)
296{
297 return test_bit(ADRENO_SPTP_PC_CTRL, &adreno_dev->pwrctrl_flag);
298}
299
300static int _lm_store(struct adreno_device *adreno_dev, unsigned int val)
301{
302 return _pwrctrl_store(adreno_dev, val, ADRENO_LM_CTRL);
303}
304
305static unsigned int _lm_show(struct adreno_device *adreno_dev)
306{
307 return test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag);
308}
309
Kyle Piefer970398f2017-09-27 13:23:40 -0700310static int _ifpc_store(struct adreno_device *adreno_dev, unsigned int val)
311{
312 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
313 struct gmu_device *gmu = &device->gmu;
314 unsigned int requested_idle_level;
315
316 if (!kgsl_gmu_isenabled(device) ||
317 !ADRENO_FEATURE(adreno_dev, ADRENO_IFPC))
318 return -EINVAL;
319
320 if ((val && gmu->idle_level >= GPU_HW_IFPC) ||
321 (!val && gmu->idle_level < GPU_HW_IFPC))
322 return 0;
323
324 if (val)
325 requested_idle_level = GPU_HW_IFPC;
326 else {
327 if (ADRENO_FEATURE(adreno_dev, ADRENO_SPTP_PC))
328 requested_idle_level = GPU_HW_SPTP_PC;
329 else
330 requested_idle_level = GPU_HW_ACTIVE;
331 }
332
333 return _gmu_idle_level_store(adreno_dev, requested_idle_level);
334}
335
336static unsigned int _ifpc_show(struct adreno_device *adreno_dev)
337{
338 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
339 struct gmu_device *gmu = &device->gmu;
340
341 return kgsl_gmu_isenabled(device) && gmu->idle_level >= GPU_HW_IFPC;
342}
343
Kyle Pieferd0d8a842018-04-11 11:22:14 -0700344static unsigned int _ifpc_count_show(struct adreno_device *adreno_dev)
345{
346 return adreno_dev->ifpc_count;
347}
348
Harshdeep Dhatt4ab35b12017-11-16 08:34:39 -0700349static unsigned int _preempt_count_show(struct adreno_device *adreno_dev)
350{
351 struct adreno_preemption *preempt = &adreno_dev->preempt;
352
353 return preempt->count;
354}
355
Shrenuj Bansala419c792016-10-20 14:05:11 -0700356static ssize_t _sysfs_store_u32(struct device *dev,
357 struct device_attribute *attr,
358 const char *buf, size_t count)
359{
360 struct adreno_device *adreno_dev = _get_adreno_dev(dev);
361 struct adreno_sysfs_attribute *_attr = ADRENO_SYSFS_ATTR(attr);
362 unsigned int val = 0;
363 int ret;
364
365 if (adreno_dev == NULL)
366 return 0;
367
368 ret = kgsl_sysfs_store(buf, &val);
369
370 if (!ret && _attr->store)
371 ret = _attr->store(adreno_dev, val);
372
373 return (ssize_t) ret < 0 ? ret : count;
374}
375
376static ssize_t _sysfs_show_u32(struct device *dev,
377 struct device_attribute *attr,
378 char *buf)
379{
380 struct adreno_device *adreno_dev = _get_adreno_dev(dev);
381 struct adreno_sysfs_attribute *_attr = ADRENO_SYSFS_ATTR(attr);
382 unsigned int val = 0;
383
384 if (adreno_dev == NULL)
385 return 0;
386
387 if (_attr->show)
388 val = _attr->show(adreno_dev);
389
390 return snprintf(buf, PAGE_SIZE, "0x%X\n", val);
391}
392
393static ssize_t _sysfs_store_bool(struct device *dev,
394 struct device_attribute *attr,
395 const char *buf, size_t count)
396{
397 struct adreno_device *adreno_dev = _get_adreno_dev(dev);
398 struct adreno_sysfs_attribute *_attr = ADRENO_SYSFS_ATTR(attr);
399 unsigned int val = 0;
400 int ret;
401
402 if (adreno_dev == NULL)
403 return 0;
404
405 ret = kgsl_sysfs_store(buf, &val);
406
407 if (!ret && _attr->store)
408 ret = _attr->store(adreno_dev, val ? 1 : 0);
409
410 return (ssize_t) ret < 0 ? ret : count;
411}
412
413static ssize_t _sysfs_show_bool(struct device *dev,
414 struct device_attribute *attr,
415 char *buf)
416{
417 struct adreno_device *adreno_dev = _get_adreno_dev(dev);
418 struct adreno_sysfs_attribute *_attr = ADRENO_SYSFS_ATTR(attr);
419 unsigned int val = 0;
420
421 if (adreno_dev == NULL)
422 return 0;
423
424 if (_attr->show)
425 val = _attr->show(adreno_dev);
426
427 return snprintf(buf, PAGE_SIZE, "%d\n", val);
428}
429
430#define ADRENO_SYSFS_BOOL(_name) \
431 _ADRENO_SYSFS_ATTR(_name, _sysfs_show_bool, _sysfs_store_bool)
432
433#define ADRENO_SYSFS_U32(_name) \
434 _ADRENO_SYSFS_ATTR(_name, _sysfs_show_u32, _sysfs_store_u32)
435
Harshdeep Dhatt4ab35b12017-11-16 08:34:39 -0700436#define ADRENO_SYSFS_RO_U32(_name) \
437 _ADRENO_SYSFS_ATTR_RO(_name, _sysfs_show_u32)
438
Shrenuj Bansala419c792016-10-20 14:05:11 -0700439static ADRENO_SYSFS_U32(ft_policy);
440static ADRENO_SYSFS_U32(ft_pagefault_policy);
Harshdeep Dhatt26c54f22017-08-30 17:37:39 -0600441static ADRENO_SYSFS_U32(preempt_level);
Harshdeep Dhatt4ab35b12017-11-16 08:34:39 -0700442static ADRENO_SYSFS_RO_U32(preempt_count);
Harshdeep Dhatt26c54f22017-08-30 17:37:39 -0600443static ADRENO_SYSFS_BOOL(usesgmem);
444static ADRENO_SYSFS_BOOL(skipsaverestore);
Shrenuj Bansala419c792016-10-20 14:05:11 -0700445static ADRENO_SYSFS_BOOL(ft_long_ib_detect);
446static ADRENO_SYSFS_BOOL(ft_hang_intr_status);
Sushmita Susheelendrab1976682016-11-07 14:21:11 -0700447static ADRENO_SYSFS_BOOL(gpu_llc_slice_enable);
Sushmita Susheelendrad3756c02017-01-11 15:05:40 -0700448static ADRENO_SYSFS_BOOL(gpuhtw_llc_slice_enable);
Shrenuj Bansala419c792016-10-20 14:05:11 -0700449
450static DEVICE_INT_ATTR(wake_nice, 0644, adreno_wake_nice);
451static DEVICE_INT_ATTR(wake_timeout, 0644, adreno_wake_timeout);
452
453static ADRENO_SYSFS_BOOL(sptp_pc);
454static ADRENO_SYSFS_BOOL(lm);
455static ADRENO_SYSFS_BOOL(preemption);
456static ADRENO_SYSFS_BOOL(hwcg);
457static ADRENO_SYSFS_BOOL(throttling);
Kyle Piefer970398f2017-09-27 13:23:40 -0700458static ADRENO_SYSFS_BOOL(ifpc);
Kyle Pieferd0d8a842018-04-11 11:22:14 -0700459static ADRENO_SYSFS_RO_U32(ifpc_count);
Shrenuj Bansala419c792016-10-20 14:05:11 -0700460
461
462
463static const struct device_attribute *_attr_list[] = {
464 &adreno_attr_ft_policy.attr,
465 &adreno_attr_ft_pagefault_policy.attr,
Shrenuj Bansala419c792016-10-20 14:05:11 -0700466 &adreno_attr_ft_long_ib_detect.attr,
467 &adreno_attr_ft_hang_intr_status.attr,
468 &dev_attr_wake_nice.attr,
469 &dev_attr_wake_timeout.attr,
470 &adreno_attr_sptp_pc.attr,
471 &adreno_attr_lm.attr,
472 &adreno_attr_preemption.attr,
473 &adreno_attr_hwcg.attr,
474 &adreno_attr_throttling.attr,
Sushmita Susheelendrab1976682016-11-07 14:21:11 -0700475 &adreno_attr_gpu_llc_slice_enable.attr,
Sushmita Susheelendrad3756c02017-01-11 15:05:40 -0700476 &adreno_attr_gpuhtw_llc_slice_enable.attr,
Harshdeep Dhatt26c54f22017-08-30 17:37:39 -0600477 &adreno_attr_preempt_level.attr,
478 &adreno_attr_usesgmem.attr,
479 &adreno_attr_skipsaverestore.attr,
Kyle Piefer970398f2017-09-27 13:23:40 -0700480 &adreno_attr_ifpc.attr,
Kyle Pieferd0d8a842018-04-11 11:22:14 -0700481 &adreno_attr_ifpc_count.attr,
Harshdeep Dhatt4ab35b12017-11-16 08:34:39 -0700482 &adreno_attr_preempt_count.attr,
Shrenuj Bansala419c792016-10-20 14:05:11 -0700483 NULL,
484};
485
486/* Add a ppd directory for controlling different knobs from sysfs */
487struct adreno_ppd_attribute {
488 struct attribute attr;
489 ssize_t (*show)(struct kgsl_device *device, char *buf);
490 ssize_t (*store)(struct kgsl_device *device, const char *buf,
491 size_t count);
492};
493
494#define PPD_ATTR(_name, _mode, _show, _store) \
495struct adreno_ppd_attribute attr_##_name = { \
496 .attr = { .name = __stringify(_name), .mode = _mode }, \
497 .show = _show, \
498 .store = _store, \
499}
500
501#define to_ppd_attr(a) \
502container_of((a), struct adreno_ppd_attribute, attr)
503
504#define kobj_to_device(a) \
505container_of((a), struct kgsl_device, ppd_kobj)
506
507static ssize_t ppd_enable_store(struct kgsl_device *device,
508 const char *buf, size_t count)
509{
510 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
511 unsigned int ppd_on = 0;
512 int ret;
513
514 if (!adreno_is_a430v2(adreno_dev) ||
515 !ADRENO_FEATURE(adreno_dev, ADRENO_PPD))
516 return count;
517
518 ret = kgsl_sysfs_store(buf, &ppd_on);
519 if (ret < 0)
520 return ret;
521
522 ppd_on = (ppd_on) ? 1 : 0;
523
524 if (ppd_on == test_bit(ADRENO_PPD_CTRL, &adreno_dev->pwrctrl_flag))
525 return count;
526
527 mutex_lock(&device->mutex);
528
529 kgsl_pwrctrl_change_state(device, KGSL_STATE_SUSPEND);
530 change_bit(ADRENO_PPD_CTRL, &adreno_dev->pwrctrl_flag);
531 kgsl_pwrctrl_change_state(device, KGSL_STATE_SLUMBER);
532
533 mutex_unlock(&device->mutex);
534 return count;
535}
536
537static ssize_t ppd_enable_show(struct kgsl_device *device,
538 char *buf)
539{
540 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
541
542 return snprintf(buf, PAGE_SIZE, "%u\n",
543 test_bit(ADRENO_PPD_CTRL, &adreno_dev->pwrctrl_flag));
544}
545/* Add individual ppd attributes here */
546static PPD_ATTR(enable, 0644, ppd_enable_show, ppd_enable_store);
547
548static ssize_t ppd_sysfs_show(struct kobject *kobj,
549 struct attribute *attr, char *buf)
550{
551 struct adreno_ppd_attribute *pattr = to_ppd_attr(attr);
552 struct kgsl_device *device = kobj_to_device(kobj);
553 ssize_t ret = -EIO;
554
555 if (device != NULL && pattr->show != NULL)
556 ret = pattr->show(device, buf);
557
558 return ret;
559}
560
561static ssize_t ppd_sysfs_store(struct kobject *kobj,
562 struct attribute *attr, const char *buf, size_t count)
563{
564 struct adreno_ppd_attribute *pattr = to_ppd_attr(attr);
565 struct kgsl_device *device = kobj_to_device(kobj);
566 ssize_t ret = -EIO;
567
568 if (device != NULL && pattr->store != NULL)
569 ret = pattr->store(device, buf, count);
570
571 return ret;
572}
573
574static const struct sysfs_ops ppd_sysfs_ops = {
575 .show = ppd_sysfs_show,
576 .store = ppd_sysfs_store,
577};
578
579static struct kobj_type ktype_ppd = {
580 .sysfs_ops = &ppd_sysfs_ops,
581};
582
583static void ppd_sysfs_close(struct adreno_device *adreno_dev)
584{
585 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
586
587 if (!ADRENO_FEATURE(adreno_dev, ADRENO_PPD))
588 return;
589
590 sysfs_remove_file(&device->ppd_kobj, &attr_enable.attr);
591 kobject_put(&device->ppd_kobj);
592}
593
594static int ppd_sysfs_init(struct adreno_device *adreno_dev)
595{
596 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
597 int ret;
598
599 if (!ADRENO_FEATURE(adreno_dev, ADRENO_PPD))
600 return -ENODEV;
601
602 ret = kobject_init_and_add(&device->ppd_kobj, &ktype_ppd,
603 &device->dev->kobj, "ppd");
604
605 if (ret == 0)
606 ret = sysfs_create_file(&device->ppd_kobj, &attr_enable.attr);
607
608 return ret;
609}
610
611/**
612 * adreno_sysfs_close() - Take down the adreno sysfs files
613 * @adreno_dev: Pointer to the adreno device
614 *
615 * Take down the sysfs files on when the device goes away
616 */
617void adreno_sysfs_close(struct adreno_device *adreno_dev)
618{
619 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
620
621 ppd_sysfs_close(adreno_dev);
622 kgsl_remove_device_sysfs_files(device->dev, _attr_list);
623}
624
625/**
626 * adreno_sysfs_init() - Initialize adreno sysfs files
627 * @adreno_dev: Pointer to the adreno device
628 *
629 * Initialize many of the adreno specific sysfs files especially for fault
630 * tolerance and power control
631 */
632int adreno_sysfs_init(struct adreno_device *adreno_dev)
633{
634 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
635 int ret;
636
637 ret = kgsl_create_device_sysfs_files(device->dev, _attr_list);
638
639 /* Add the PPD directory and files */
640 if (ret == 0)
641 ppd_sysfs_init(adreno_dev);
642
643 return 0;
644}
645