OSDN Git Service

Merge tag 'LA.UM.8.4.r1-04700-8x98.0' of https://source.codeaurora.org/quic/la/kernel...
[sagit-ice-cold/kernel_xiaomi_msm8998.git] / drivers / thermal / lmh_interface.c
1 /* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
2  *
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 #define pr_fmt(fmt) "%s:%s " fmt, KBUILD_MODNAME, __func__
14
15 #include <linux/module.h>
16 #include <linux/device.h>
17 #include <linux/interrupt.h>
18 #include <linux/kernel.h>
19 #include <linux/io.h>
20 #include <linux/err.h>
21 #include <linux/of.h>
22 #include <linux/sysfs.h>
23 #include <linux/rwsem.h>
24 #include <linux/debugfs.h>
25 #include <linux/thermal.h>
26 #include <linux/slab.h>
27 #include "lmh_interface.h"
28 #include <linux/string.h>
29 #include <linux/uaccess.h>
30
31 #define LMH_MON_NAME                    "lmh_monitor"
32 #define LMH_ISR_POLL_DELAY              "interrupt_poll_delay_msec"
33 #define LMH_TRACE_ENABLE                "hw_trace_enable"
34 #define LMH_TRACE_INTERVAL              "hw_trace_interval"
35 #define LMH_DBGFS_DIR                   "debug"
36 #define LMH_DBGFS_READ                  "data"
37 #define LMH_DBGFS_CONFIG_READ           "config"
38 #define LMH_DBGFS_READ_TYPES            "data_types"
39 #define LMH_DBGFS_CONFIG_TYPES          "config_types"
40 #define LMH_TRACE_INTERVAL_XO_TICKS     250
41 #define LMH_POLLING_MSEC                30
42
43 struct lmh_mon_threshold {
44         int                             value;
45         bool                            active;
46 };
47
48 struct lmh_device_data {
49         char                            device_name[LMH_NAME_MAX];
50         struct lmh_device_ops           *device_ops;
51         uint32_t                        max_level;
52         int                             curr_level;
53         int                             *levels;
54         struct dentry                   *dev_parent;
55         struct dentry                   *max_lvl_fs;
56         struct dentry                   *curr_lvl_fs;
57         struct dentry                   *avail_lvl_fs;
58         struct list_head                list_ptr;
59         struct rw_semaphore             lock;
60         struct device                   dev;
61 };
62
63 struct lmh_mon_sensor_data {
64         struct list_head                list_ptr;
65         char                            sensor_name[LMH_NAME_MAX];
66         struct lmh_sensor_ops           *sensor_ops;
67         struct rw_semaphore             lock;
68         struct lmh_mon_threshold        trip[LMH_TRIP_MAX];
69         struct thermal_zone_device      *tzdev;
70         enum thermal_device_mode        mode;
71 };
72
73 struct lmh_mon_driver_data {
74         struct dentry                   *debugfs_parent;
75         struct dentry                   *poll_fs;
76         struct dentry                   *enable_hw_log;
77         struct dentry                   *hw_log_delay;
78         uint32_t                        hw_log_enable;
79         uint64_t                        hw_log_interval;
80         struct dentry                   *debug_dir;
81         struct dentry                   *debug_read;
82         struct dentry                   *debug_config;
83         struct dentry                   *debug_read_type;
84         struct dentry                   *debug_config_type;
85         struct lmh_debug_ops            *debug_ops;
86 };
87
88 enum lmh_read_type {
89         LMH_DEBUG_READ_TYPE,
90         LMH_DEBUG_CONFIG_TYPE,
91         LMH_PROFILES,
92 };
93
94 static struct lmh_mon_driver_data       *lmh_mon_data;
95 static struct class                     lmh_class_info = {
96         .name = "msm_limits",
97 };
98 static int lmh_poll_interval = LMH_POLLING_MSEC;
99 static DECLARE_RWSEM(lmh_mon_access_lock);
100 static LIST_HEAD(lmh_sensor_list);
101 static DECLARE_RWSEM(lmh_dev_access_lock);
102 static LIST_HEAD(lmh_device_list);
103
104 #define LMH_CREATE_DEBUGFS_FILE(_node, _name, _mode, _parent, _data, _ops, \
105         _ret) do { \
106                 _node = debugfs_create_file(_name, _mode, _parent, \
107                                 _data, _ops); \
108                 if ((IS_ENABLED(CONFIG_DEBUG_FS))) \
109                         break; \
110                 if (IS_ERR(_node)) { \
111                         _ret = PTR_ERR(_node); \
112                         pr_err("Error creating debugfs file:%s. err:%d\n", \
113                                         _name, _ret); \
114                 } \
115         } while (0)
116
117 #define LMH_CREATE_DEBUGFS_DIR(_node, _name, _parent, _ret) \
118         do { \
119                 _node = debugfs_create_dir(_name, _parent); \
120                 if ((IS_ENABLED(CONFIG_DEBUG_FS))) \
121                         break; \
122                 if (IS_ERR(_node)) { \
123                         _ret = PTR_ERR(_node); \
124                         pr_err("Error creating debugfs dir:%s. err:%d\n", \
125                                         _name, _ret); \
126                 } \
127         } while (0)
128
129 #define LMH_HW_LOG_FS(_name) \
130 static int _name##_get(void *data, u64 *val) \
131 { \
132         *val = lmh_mon_data->_name; \
133         return 0; \
134 } \
135 static int _name##_set(void *data, u64 val) \
136 { \
137         struct lmh_mon_sensor_data *lmh_sensor = data; \
138         int ret = 0; \
139         lmh_mon_data->_name = val; \
140         if (lmh_mon_data->hw_log_enable) \
141                 ret = lmh_sensor->sensor_ops->enable_hw_log( \
142                         lmh_mon_data->hw_log_interval \
143                                 , lmh_mon_data->hw_log_enable); \
144         else \
145                 ret = lmh_sensor->sensor_ops->disable_hw_log(); \
146         return ret; \
147 } \
148 DEFINE_SIMPLE_ATTRIBUTE(_name##_fops, _name##_get, _name##_set, \
149         "%llu\n");
150
151 #define LMH_DEV_GET(_name) \
152 static ssize_t _name##_get(struct device *dev, \
153         struct device_attribute *attr, char *buf) \
154 { \
155         struct lmh_device_data *lmh_dev = container_of(dev, \
156                         struct lmh_device_data, dev); \
157         return snprintf(buf, LMH_NAME_MAX, "%d", lmh_dev->_name); \
158 } \
159
160 LMH_HW_LOG_FS(hw_log_enable);
161 LMH_HW_LOG_FS(hw_log_interval);
162 LMH_DEV_GET(max_level);
163 LMH_DEV_GET(curr_level);
164
165 int lmh_get_poll_interval(void)
166 {
167         return lmh_poll_interval;
168 }
169
170 static ssize_t curr_level_set(struct device *dev,
171         struct device_attribute *attr, const char *buf, size_t count)
172 {
173         struct lmh_device_data *lmh_dev = container_of(dev,
174                 struct lmh_device_data, dev);
175         int val = 0, ret = 0;
176
177         ret = kstrtouint(buf, 0, &val);
178         if (ret < 0) {
179                 pr_err("Invalid input [%s]. err:%d\n", buf, ret);
180                 return ret;
181         }
182         return lmh_set_dev_level(lmh_dev->device_name, val);
183 }
184
185 static ssize_t avail_level_get(struct device *dev,
186         struct device_attribute *attr, char *buf)
187 {
188         struct lmh_device_data *lmh_dev = container_of(dev,
189                 struct lmh_device_data, dev);
190         uint32_t *type_list = NULL;
191         int ret = 0, count = 0, lvl_buf_count = 0, idx = 0;
192         char *lvl_buf = NULL;
193
194         if (!lmh_dev || !lmh_dev->levels || !lmh_dev->max_level) {
195                 pr_err("Invalid input\n");
196                 return -EINVAL;
197         }
198         type_list = lmh_dev->levels;
199         lvl_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
200         if (!lvl_buf) {
201                 pr_err("Error allocating memory\n");
202                 return -ENOMEM;
203         }
204         for (idx = 0; (idx < lmh_dev->max_level) && (lvl_buf_count < PAGE_SIZE)
205                 ; idx++) {
206                 count = snprintf(lvl_buf + lvl_buf_count,
207                                 PAGE_SIZE - lvl_buf_count, "%d ",
208                                 type_list[idx]);
209                 if (count + lvl_buf_count >= PAGE_SIZE) {
210                         pr_err("overflow.\n");
211                         break;
212                 } else if (count < 0) {
213                         pr_err("Error writing to buffer. err:%d\n", count);
214                         ret = count;
215                         goto lvl_get_exit;
216                 }
217                 lvl_buf_count += count;
218         }
219         count = snprintf(lvl_buf + lvl_buf_count, PAGE_SIZE - lvl_buf_count,
220                         "\n");
221         if (count < 0)
222                 pr_err("Error writing new line to buffer. err:%d\n", count);
223         else if (count + lvl_buf_count < PAGE_SIZE)
224                 lvl_buf_count += count;
225
226         count = snprintf(buf, lvl_buf_count + 1, lvl_buf);
227         if (count > PAGE_SIZE || count < 0) {
228                 pr_err("copy to user buffer failed\n");
229                 ret = -EFAULT;
230                 goto lvl_get_exit;
231         }
232
233 lvl_get_exit:
234         kfree(lvl_buf);
235         return (ret) ? ret : count;
236 }
237
238 static int lmh_create_dev_sysfs(struct lmh_device_data *lmh_dev)
239 {
240         int ret = 0;
241         static DEVICE_ATTR(level, 0600, curr_level_get, curr_level_set);
242         static DEVICE_ATTR(available_levels, 0400, avail_level_get, NULL);
243         static DEVICE_ATTR(total_levels, 0400, max_level_get, NULL);
244
245         lmh_dev->dev.class = &lmh_class_info;
246         dev_set_name(&lmh_dev->dev, "%s", lmh_dev->device_name);
247         ret = device_register(&lmh_dev->dev);
248         if (ret) {
249                 pr_err("Error registering profile device. err:%d\n", ret);
250                 return ret;
251         }
252         ret = device_create_file(&lmh_dev->dev, &dev_attr_level);
253         if (ret) {
254                 pr_err("Error creating profile level sysfs node. err:%d\n",
255                         ret);
256                 goto dev_sysfs_exit;
257         }
258         ret = device_create_file(&lmh_dev->dev, &dev_attr_total_levels);
259         if (ret) {
260                 pr_err("Error creating total level sysfs node. err:%d\n",
261                         ret);
262                 goto dev_sysfs_exit;
263         }
264         ret = device_create_file(&lmh_dev->dev, &dev_attr_available_levels);
265         if (ret) {
266                 pr_err("Error creating available level sysfs node. err:%d\n",
267                         ret);
268                 goto dev_sysfs_exit;
269         }
270
271 dev_sysfs_exit:
272         if (ret)
273                 device_unregister(&lmh_dev->dev);
274         return ret;
275 }
276
277 static int lmh_create_debugfs_nodes(struct lmh_mon_sensor_data *lmh_sensor)
278 {
279         int ret = 0;
280
281         lmh_mon_data->hw_log_enable = 0;
282         lmh_mon_data->hw_log_interval = LMH_TRACE_INTERVAL_XO_TICKS;
283         LMH_CREATE_DEBUGFS_FILE(lmh_mon_data->enable_hw_log, LMH_TRACE_ENABLE,
284                 0600, lmh_mon_data->debugfs_parent, (void *)lmh_sensor,
285                 &hw_log_enable_fops, ret);
286         if (ret)
287                 goto create_debugfs_exit;
288         LMH_CREATE_DEBUGFS_FILE(lmh_mon_data->hw_log_delay, LMH_TRACE_INTERVAL,
289                 0600, lmh_mon_data->debugfs_parent, (void *)lmh_sensor,
290                 &hw_log_interval_fops, ret);
291         if (ret)
292                 goto create_debugfs_exit;
293
294 create_debugfs_exit:
295         if (ret)
296                 debugfs_remove_recursive(lmh_mon_data->debugfs_parent);
297         return ret;
298 }
299
300 static struct lmh_mon_sensor_data *lmh_match_sensor_ops(
301                 struct lmh_sensor_ops *ops)
302 {
303         struct lmh_mon_sensor_data *lmh_sensor = NULL;
304
305         list_for_each_entry(lmh_sensor, &lmh_sensor_list, list_ptr) {
306                 if (lmh_sensor->sensor_ops == ops)
307                         return lmh_sensor;
308         }
309
310         return NULL;
311 }
312
313 static struct lmh_mon_sensor_data *lmh_match_sensor_name(char *sensor_name)
314 {
315         struct lmh_mon_sensor_data *lmh_sensor = NULL;
316
317         list_for_each_entry(lmh_sensor, &lmh_sensor_list, list_ptr) {
318                 if (!strncasecmp(lmh_sensor->sensor_name, sensor_name,
319                         LMH_NAME_MAX))
320                         return lmh_sensor;
321         }
322
323         return NULL;
324 }
325
326 static void lmh_evaluate_and_notify(struct lmh_mon_sensor_data *lmh_sensor,
327                int val)
328 {
329         int idx = 0, trip = 0;
330         bool cond = false;
331
332         for (idx = 0; idx < LMH_TRIP_MAX; idx++) {
333                 if (!lmh_sensor->trip[idx].active)
334                         continue;
335                 if (idx == LMH_HIGH_TRIP) {
336                         trip = THERMAL_TRIP_CONFIGURABLE_HI;
337                         cond = (val >= lmh_sensor->trip[idx].value);
338                 } else {
339                         trip = THERMAL_TRIP_CONFIGURABLE_LOW;
340                         cond = (val <= lmh_sensor->trip[idx].value);
341                 }
342                 if (cond) {
343                         lmh_sensor->trip[idx].active = false;
344                         thermal_sensor_trip(lmh_sensor->tzdev, trip, val);
345                 }
346         }
347 }
348
349 void lmh_update_reading(struct lmh_sensor_ops *ops, int trip_val)
350 {
351         struct lmh_mon_sensor_data *lmh_sensor = NULL;
352
353         if (!ops) {
354                 pr_err("Invalid input\n");
355                 return;
356         }
357
358         down_read(&lmh_mon_access_lock);
359         lmh_sensor = lmh_match_sensor_ops(ops);
360         if (!lmh_sensor) {
361                 pr_err("Invalid ops\n");
362                 goto interrupt_exit;
363         }
364         down_write(&lmh_sensor->lock);
365         pr_debug("Sensor:[%s] intensity:%d\n", lmh_sensor->sensor_name,
366                 trip_val);
367         lmh_evaluate_and_notify(lmh_sensor, trip_val);
368 interrupt_exit:
369         if (lmh_sensor)
370                 up_write(&lmh_sensor->lock);
371         up_read(&lmh_mon_access_lock);
372         return;
373 }
374
375 static int lmh_sensor_read(struct thermal_zone_device *dev, int *val)
376 {
377         int ret = 0;
378         struct lmh_mon_sensor_data *lmh_sensor;
379
380         if (!val || !dev || !dev->devdata) {
381                 pr_err("Invalid input\n");
382                 return -EINVAL;
383         }
384         lmh_sensor = dev->devdata;
385         down_read(&lmh_mon_access_lock);
386         down_read(&lmh_sensor->lock);
387         ret = lmh_sensor->sensor_ops->read(lmh_sensor->sensor_ops, val);
388         if (ret) {
389                 pr_err("Error reading sensor:%s. err:%d\n",
390                                 lmh_sensor->sensor_name, ret);
391                 goto unlock_and_exit;
392         }
393 unlock_and_exit:
394         up_read(&lmh_sensor->lock);
395         up_read(&lmh_mon_access_lock);
396
397         return ret;
398 }
399
400 static int lmh_get_mode(struct thermal_zone_device *dev,
401                 enum thermal_device_mode *mode)
402 {
403         struct lmh_mon_sensor_data *lmh_sensor;
404
405         if (!dev || !dev->devdata || !mode) {
406                 pr_err("Invalid input\n");
407                 return -EINVAL;
408         }
409         lmh_sensor = dev->devdata;
410         *mode = lmh_sensor->mode;
411
412         return 0;
413 }
414
415 static int lmh_get_trip_type(struct thermal_zone_device *dev,
416                 int trip, enum thermal_trip_type *type)
417 {
418         if (!type || !dev || !dev->devdata || trip < 0
419                 || trip >= LMH_TRIP_MAX) {
420                 pr_err("Invalid input\n");
421                 return -EINVAL;
422         }
423
424         switch (trip) {
425         case LMH_HIGH_TRIP:
426                 *type = THERMAL_TRIP_CONFIGURABLE_HI;
427                 break;
428         case LMH_LOW_TRIP:
429                 *type = THERMAL_TRIP_CONFIGURABLE_LOW;
430                 break;
431         default:
432                 return -EINVAL;
433         }
434
435         return 0;
436 }
437
438 static int lmh_activate_trip(struct thermal_zone_device *dev,
439                 int trip, enum thermal_trip_activation_mode mode)
440 {
441         struct lmh_mon_sensor_data *lmh_sensor;
442
443         if (!dev || !dev->devdata || trip < 0 || trip >= LMH_TRIP_MAX) {
444                 pr_err("Invalid input\n");
445                 return -EINVAL;
446         }
447
448         lmh_sensor = dev->devdata;
449         down_read(&lmh_mon_access_lock);
450         down_write(&lmh_sensor->lock);
451         lmh_sensor->trip[trip].active = (mode ==
452                                         THERMAL_TRIP_ACTIVATION_ENABLED);
453         up_write(&lmh_sensor->lock);
454         up_read(&lmh_mon_access_lock);
455
456         return 0;
457 }
458
459 static int lmh_get_trip_value(struct thermal_zone_device *dev,
460                 int trip, int *value)
461 {
462         struct lmh_mon_sensor_data *lmh_sensor;
463
464         if (!dev || !dev->devdata || trip < 0 || trip >= LMH_TRIP_MAX
465                 || !value) {
466                 pr_err("Invalid input\n");
467                 return -EINVAL;
468         }
469
470         lmh_sensor = dev->devdata;
471         down_read(&lmh_mon_access_lock);
472         down_read(&lmh_sensor->lock);
473         *value = lmh_sensor->trip[trip].value;
474         up_read(&lmh_sensor->lock);
475         up_read(&lmh_mon_access_lock);
476
477         return 0;
478 }
479
480 static int lmh_set_trip_value(struct thermal_zone_device *dev,
481                 int trip, int value)
482 {
483         struct lmh_mon_sensor_data *lmh_sensor;
484
485         if (!dev || !dev->devdata || trip < 0 || trip >= LMH_TRIP_MAX) {
486                 pr_err("Invalid input\n");
487                 return -EINVAL;
488         }
489
490         lmh_sensor = dev->devdata;
491         down_read(&lmh_mon_access_lock);
492         down_write(&lmh_sensor->lock);
493         lmh_sensor->trip[trip].value = value;
494         up_write(&lmh_sensor->lock);
495         up_read(&lmh_mon_access_lock);
496
497         return 0;
498 }
499
500 static struct thermal_zone_device_ops lmh_sens_ops = {
501         .get_temp = lmh_sensor_read,
502         .get_mode = lmh_get_mode,
503         .get_trip_type = lmh_get_trip_type,
504         .activate_trip_type = lmh_activate_trip,
505         .get_trip_temp = lmh_get_trip_value,
506         .set_trip_temp = lmh_set_trip_value,
507 };
508
509 static int lmh_register_sensor(struct lmh_mon_sensor_data *lmh_sensor)
510 {
511         int ret = 0;
512
513         lmh_sensor->tzdev = thermal_zone_device_register(
514                         lmh_sensor->sensor_name, LMH_TRIP_MAX,
515                         (1 << LMH_TRIP_MAX) - 1, lmh_sensor, &lmh_sens_ops,
516                         NULL, 0 , 0);
517         if (IS_ERR_OR_NULL(lmh_sensor->tzdev)) {
518                 ret = PTR_ERR(lmh_sensor->tzdev);
519                 pr_err("Error registering sensor:[%s] with thermal. err:%d\n",
520                         lmh_sensor->sensor_name, ret);
521                 return ret;
522         }
523
524         return ret;
525 }
526
527 static int lmh_sensor_init(struct lmh_mon_sensor_data *lmh_sensor,
528                char *sensor_name, struct lmh_sensor_ops *ops)
529 {
530         int idx = 0, ret = 0;
531
532         strlcpy(lmh_sensor->sensor_name, sensor_name, LMH_NAME_MAX);
533         lmh_sensor->sensor_ops = ops;
534         ops->new_value_notify = lmh_update_reading;
535         for (idx = 0; idx < LMH_TRIP_MAX; idx++) {
536                 lmh_sensor->trip[idx].value = 0;
537                 lmh_sensor->trip[idx].active = false;
538         }
539         init_rwsem(&lmh_sensor->lock);
540         if (list_empty(&lmh_sensor_list)
541                 && !lmh_mon_data->enable_hw_log)
542                 lmh_create_debugfs_nodes(lmh_sensor);
543         list_add_tail(&lmh_sensor->list_ptr, &lmh_sensor_list);
544
545         return ret;
546 }
547
548 int lmh_sensor_register(char *sensor_name, struct lmh_sensor_ops *ops)
549 {
550         int ret = 0;
551         struct lmh_mon_sensor_data *lmh_sensor = NULL;
552
553         if (!sensor_name || !ops) {
554                 pr_err("Invalid input\n");
555                 return -EINVAL;
556         }
557
558         if (!ops->read || !ops->enable_hw_log || !ops->disable_hw_log) {
559                 pr_err("Invalid ops input for sensor:%s\n", sensor_name);
560                 return -EINVAL;
561         }
562         down_write(&lmh_mon_access_lock);
563         if (lmh_match_sensor_name(sensor_name)
564                 || lmh_match_sensor_ops(ops)) {
565                 ret = -EEXIST;
566                 pr_err("Sensor[%s] exists\n", sensor_name);
567                 goto register_exit;
568         }
569         lmh_sensor = kzalloc(sizeof(struct lmh_mon_sensor_data), GFP_KERNEL);
570         if (!lmh_sensor) {
571                 pr_err("kzalloc failed\n");
572                 ret = -ENOMEM;
573                 goto register_exit;
574         }
575         ret = lmh_sensor_init(lmh_sensor, sensor_name, ops);
576         if (ret) {
577                 pr_err("Error registering sensor:%s. err:%d\n", sensor_name,
578                         ret);
579                 kfree(lmh_sensor);
580                 goto register_exit;
581         }
582
583         pr_debug("Registered Sensor:[%s]\n", sensor_name);
584
585 register_exit:
586         up_write(&lmh_mon_access_lock);
587         if (ret)
588                 return ret;
589         ret = lmh_register_sensor(lmh_sensor);
590         if (ret) {
591                 pr_err("Thermal Zone register failed for Sensor:[%s]\n"
592                         , sensor_name);
593                 return ret;
594         }
595         pr_debug("Registered Sensor:[%s]\n", sensor_name);
596         return ret;
597 }
598
599 static void lmh_sensor_remove(struct lmh_sensor_ops *ops)
600 {
601         struct lmh_mon_sensor_data *lmh_sensor = NULL;
602
603         lmh_sensor = lmh_match_sensor_ops(ops);
604         if (!lmh_sensor) {
605                 pr_err("No match for the sensor\n");
606                 goto deregister_exit;
607         }
608         down_write(&lmh_sensor->lock);
609         thermal_zone_device_unregister(lmh_sensor->tzdev);
610         list_del(&lmh_sensor->list_ptr);
611         up_write(&lmh_sensor->lock);
612         pr_debug("Deregistered sensor:[%s]\n", lmh_sensor->sensor_name);
613         kfree(lmh_sensor);
614
615 deregister_exit:
616         return;
617 }
618
619 void lmh_sensor_deregister(struct lmh_sensor_ops *ops)
620 {
621         if (!ops) {
622                 pr_err("Invalid input\n");
623                 return;
624         }
625
626         down_write(&lmh_mon_access_lock);
627         lmh_sensor_remove(ops);
628         up_write(&lmh_mon_access_lock);
629
630         return;
631 }
632
633 static struct lmh_device_data *lmh_match_device_name(char *device_name)
634 {
635         struct lmh_device_data *lmh_device = NULL;
636
637         list_for_each_entry(lmh_device, &lmh_device_list, list_ptr) {
638                 if (!strncasecmp(lmh_device->device_name, device_name,
639                         LMH_NAME_MAX))
640                         return lmh_device;
641         }
642
643         return NULL;
644 }
645
646 static struct lmh_device_data *lmh_match_device_ops(struct lmh_device_ops *ops)
647 {
648         struct lmh_device_data *lmh_device = NULL;
649
650         list_for_each_entry(lmh_device, &lmh_device_list, list_ptr) {
651                 if (lmh_device->device_ops == ops)
652                         return lmh_device;
653         }
654
655         return NULL;
656 }
657
658 static int lmh_device_init(struct lmh_device_data *lmh_device,
659                 char *device_name, struct lmh_device_ops *ops)
660 {
661         int ret = 0;
662
663         ret = ops->get_curr_level(ops, &lmh_device->curr_level);
664         if (ret) {
665                 pr_err("Error getting curr level for Device:[%s]. err:%d\n",
666                         device_name, ret);
667                 goto dev_init_exit;
668         }
669         ret = ops->get_available_levels(ops, NULL);
670         if (ret <= 0) {
671                 pr_err("Error getting max level for Device:[%s]. err:%d\n",
672                         device_name, ret);
673                 ret = (!ret) ? -EINVAL : ret;
674                 goto dev_init_exit;
675         }
676         lmh_device->max_level = ret;
677         lmh_device->levels = kzalloc(lmh_device->max_level * sizeof(int),
678                                 GFP_KERNEL);
679         if (!lmh_device->levels) {
680                 pr_err("No memory\n");
681                 ret = -ENOMEM;
682                 goto dev_init_exit;
683         }
684         ret = ops->get_available_levels(ops, lmh_device->levels);
685         if (ret) {
686                 pr_err("Error getting device:[%s] levels. err:%d\n",
687                         device_name, ret);
688                 goto dev_init_exit;
689         }
690         init_rwsem(&lmh_device->lock);
691         lmh_device->device_ops = ops;
692         strlcpy(lmh_device->device_name, device_name, LMH_NAME_MAX);
693         list_add_tail(&lmh_device->list_ptr, &lmh_device_list);
694         lmh_create_dev_sysfs(lmh_device);
695
696 dev_init_exit:
697         if (ret)
698                 kfree(lmh_device->levels);
699         return ret;
700 }
701
702 int lmh_get_all_dev_levels(char *device_name, int *val)
703 {
704         int ret = 0;
705         struct lmh_device_data *lmh_device = NULL;
706
707         if (!device_name) {
708                 pr_err("Invalid input\n");
709                 return -EINVAL;
710         }
711         down_read(&lmh_dev_access_lock);
712         lmh_device = lmh_match_device_name(device_name);
713         if (!lmh_device) {
714                 pr_err("Invalid device:%s\n", device_name);
715                 ret = -EINVAL;
716                 goto get_all_lvl_exit;
717         }
718         down_read(&lmh_device->lock);
719         if (!val) {
720                 ret = lmh_device->max_level;
721                 goto get_all_lvl_exit;
722         }
723         memcpy(val, lmh_device->levels,
724                 sizeof(int) * lmh_device->max_level);
725
726 get_all_lvl_exit:
727         if (lmh_device)
728                 up_read(&lmh_device->lock);
729         up_read(&lmh_dev_access_lock);
730         return ret;
731 }
732
733 int lmh_set_dev_level(char *device_name, int curr_lvl)
734 {
735         int ret = 0;
736         struct lmh_device_data *lmh_device = NULL;
737
738         if (!device_name) {
739                 pr_err("Invalid input\n");
740                 return -EINVAL;
741         }
742         down_read(&lmh_dev_access_lock);
743         lmh_device = lmh_match_device_name(device_name);
744         if (!lmh_device) {
745                 pr_err("Invalid device:%s\n", device_name);
746                 ret = -EINVAL;
747                 goto set_dev_exit;
748         }
749         down_write(&lmh_device->lock);
750         curr_lvl = min(curr_lvl, lmh_device->levels[lmh_device->max_level - 1]);
751         curr_lvl = max(curr_lvl, lmh_device->levels[0]);
752         if (curr_lvl == lmh_device->curr_level)
753                 goto set_dev_exit;
754         ret = lmh_device->device_ops->set_level(lmh_device->device_ops,
755                         curr_lvl);
756         if (ret) {
757                 pr_err("Error setting current level%d for device[%s]. err:%d\n",
758                         curr_lvl, device_name, ret);
759                 goto set_dev_exit;
760         }
761         pr_debug("Device:[%s] configured to level %d\n", device_name, curr_lvl);
762         lmh_device->curr_level = curr_lvl;
763
764 set_dev_exit:
765         if (lmh_device)
766                 up_write(&lmh_device->lock);
767         up_read(&lmh_dev_access_lock);
768         return ret;
769 }
770
771 int lmh_get_curr_level(char *device_name, int *val)
772 {
773         int ret = 0;
774         struct lmh_device_data *lmh_device = NULL;
775
776         if (!device_name || !val) {
777                 pr_err("Invalid input\n");
778                 return -EINVAL;
779         }
780         down_read(&lmh_dev_access_lock);
781         lmh_device = lmh_match_device_name(device_name);
782         if (!lmh_device) {
783                 pr_err("Invalid device:%s\n", device_name);
784                 ret = -EINVAL;
785                 goto get_curr_level;
786         }
787         down_read(&lmh_device->lock);
788         ret = lmh_device->device_ops->get_curr_level(lmh_device->device_ops,
789                         &lmh_device->curr_level);
790         if (ret) {
791                 pr_err("Error getting device[%s] current level. err:%d\n",
792                         device_name, ret);
793                 goto get_curr_level;
794         }
795         *val = lmh_device->curr_level;
796         pr_debug("Device:%s current level:%d\n", device_name, *val);
797
798 get_curr_level:
799         if (lmh_device)
800                 up_read(&lmh_device->lock);
801         up_read(&lmh_dev_access_lock);
802         return ret;
803 }
804
805 int lmh_device_register(char *device_name, struct lmh_device_ops *ops)
806 {
807         int ret = 0;
808         struct lmh_device_data *lmh_device = NULL;
809
810         if (!device_name || !ops) {
811                 pr_err("Invalid input\n");
812                 return -EINVAL;
813         }
814
815         if (!ops->get_available_levels || !ops->get_curr_level
816                 || !ops->set_level) {
817                 pr_err("Invalid ops input for device:%s\n", device_name);
818                 return -EINVAL;
819         }
820
821         down_write(&lmh_dev_access_lock);
822         if (lmh_match_device_name(device_name)
823                 || lmh_match_device_ops(ops)) {
824                 ret = -EEXIST;
825                 pr_err("Device[%s] allready exists\n", device_name);
826                 goto register_exit;
827         }
828         lmh_device = kzalloc(sizeof(struct lmh_device_data), GFP_KERNEL);
829         if (!lmh_device) {
830                 pr_err("kzalloc failed\n");
831                 ret = -ENOMEM;
832                 goto register_exit;
833         }
834         ret = lmh_device_init(lmh_device, device_name, ops);
835         if (ret) {
836                 pr_err("Error registering device:%s. err:%d\n", device_name,
837                         ret);
838                 kfree(lmh_device);
839                 goto register_exit;
840         }
841
842         pr_debug("Registered Device:[%s] with %d levels\n", device_name,
843                         lmh_device->max_level);
844
845 register_exit:
846         up_write(&lmh_dev_access_lock);
847         return ret;
848 }
849
850 static void lmh_device_remove(struct lmh_device_ops *ops)
851 {
852         struct lmh_device_data *lmh_device = NULL;
853
854         lmh_device = lmh_match_device_ops(ops);
855         if (!lmh_device) {
856                 pr_err("No match for the device\n");
857                 goto deregister_exit;
858         }
859         down_write(&lmh_device->lock);
860         list_del(&lmh_device->list_ptr);
861         pr_debug("Deregistered device:[%s]\n", lmh_device->device_name);
862         kfree(lmh_device->levels);
863         up_write(&lmh_device->lock);
864         kfree(lmh_device);
865
866 deregister_exit:
867         return;
868 }
869
870 void lmh_device_deregister(struct lmh_device_ops *ops)
871 {
872         if (!ops) {
873                 pr_err("Invalid input\n");
874                 return;
875         }
876
877         down_write(&lmh_dev_access_lock);
878         lmh_device_remove(ops);
879         up_write(&lmh_dev_access_lock);
880         return;
881 }
882
883 static int lmh_parse_and_extract(const char __user *user_buf, size_t count,
884         enum lmh_read_type type)
885 {
886         char *local_buf = NULL, *token = NULL, *curr_ptr = NULL, *token1 = NULL;
887         char *next_line = NULL;
888         int ret = 0, data_ct = 0, i = 0, size = 0;
889         uint32_t *config_buf = NULL;
890
891         /* Allocate two extra space to add ';' character and NULL terminate */
892         local_buf = kzalloc(count + 2, GFP_KERNEL);
893         if (!local_buf) {
894                 ret = -ENOMEM;
895                 goto dfs_cfg_write_exit;
896         }
897         if (copy_from_user(local_buf, user_buf, count)) {
898                 pr_err("user buf error\n");
899                 ret = -EFAULT;
900                 goto dfs_cfg_write_exit;
901         }
902         size = count + (strnchr(local_buf, count, '\n') ? 1 :  2);
903         local_buf[size - 2] = ';';
904         local_buf[size - 1] = '\0';
905         curr_ptr = next_line = local_buf;
906         while ((token1 = strnchr(next_line, local_buf + size - next_line, ';'))
907                 != NULL) {
908                 data_ct = 0;
909                 *token1 = '\0';
910                 curr_ptr = next_line;
911                 next_line = token1 + 1;
912                 for (token = (char *)curr_ptr; token &&
913                         ((token = strnchr(token, next_line - token, ' '))
914                          != NULL); token++)
915                         data_ct++;
916                 if (data_ct < 2) {
917                         pr_err("Invalid format string:[%s]\n", curr_ptr);
918                         ret = -EINVAL;
919                         goto dfs_cfg_write_exit;
920                 }
921                 config_buf = kzalloc((++data_ct) * sizeof(uint32_t),
922                                 GFP_KERNEL);
923                 if (!config_buf) {
924                         ret = -ENOMEM;
925                         goto dfs_cfg_write_exit;
926                 }
927                 pr_debug("Input:%s data_ct:%d\n", curr_ptr, data_ct);
928                 for (i = 0, token = (char *)curr_ptr; token && (i < data_ct);
929                         i++) {
930                         token = strnchr(token, next_line - token, ' ');
931                         if (token)
932                                 *token = '\0';
933                         ret = kstrtouint(curr_ptr, 0, &config_buf[i]);
934                         if (ret < 0) {
935                                 pr_err("Data[%s] scan error. err:%d\n",
936                                         curr_ptr, ret);
937                                 kfree(config_buf);
938                                 goto dfs_cfg_write_exit;
939                         }
940                         if (token)
941                                 curr_ptr = ++token;
942                 }
943                 switch (type) {
944                 case LMH_DEBUG_READ_TYPE:
945                         ret = lmh_mon_data->debug_ops->debug_config_read(
946                                 lmh_mon_data->debug_ops, config_buf, data_ct);
947                         break;
948                 case LMH_DEBUG_CONFIG_TYPE:
949                         ret = lmh_mon_data->debug_ops->debug_config_lmh(
950                                 lmh_mon_data->debug_ops, config_buf, data_ct);
951                         break;
952                 default:
953                         ret = -EINVAL;
954                         break;
955                 }
956                 kfree(config_buf);
957                 if (ret) {
958                         pr_err("Config error. type:%d err:%d\n", type, ret);
959                         goto dfs_cfg_write_exit;
960                 }
961         }
962
963 dfs_cfg_write_exit:
964         kfree(local_buf);
965         return ret;
966 }
967
968 static ssize_t lmh_dbgfs_config_write(struct file *file,
969         const char __user *user_buf, size_t count, loff_t *ppos)
970 {
971         lmh_parse_and_extract(user_buf, count, LMH_DEBUG_CONFIG_TYPE);
972         return count;
973 }
974
975 static int lmh_dbgfs_data_read(struct seq_file *seq_fp, void *data)
976 {
977         static uint32_t *read_buf;
978         static int read_buf_size;
979         int idx = 0, ret = 0;
980
981         if (!read_buf_size) {
982                 ret = lmh_mon_data->debug_ops->debug_read(
983                         lmh_mon_data->debug_ops, &read_buf);
984                 if (ret <= 0)
985                         goto dfs_read_exit;
986                 if (!read_buf || ret < sizeof(uint32_t)) {
987                         ret = -EINVAL;
988                         goto dfs_read_exit;
989                }
990                 read_buf_size = ret;
991                 ret = 0;
992         }
993
994         do {
995                 seq_printf(seq_fp, "0x%x ", read_buf[idx]);
996                 if (seq_has_overflowed(seq_fp)) {
997                         pr_err("Seq overflow. idx:%d\n", idx);
998                         goto dfs_read_exit;
999                 }
1000                 idx++;
1001                 if ((idx % LMH_READ_LINE_LENGTH) == 0) {
1002                         seq_puts(seq_fp, "\n");
1003                         if (seq_has_overflowed(seq_fp)) {
1004                                 pr_err("Seq overflow. idx:%d\n", idx);
1005                                 goto dfs_read_exit;
1006                         }
1007                 }
1008         } while (idx < (read_buf_size / sizeof(uint32_t)));
1009         read_buf_size = 0;
1010         read_buf = NULL;
1011
1012 dfs_read_exit:
1013         return ret;
1014 }
1015
1016 static ssize_t lmh_dbgfs_data_write(struct file *file,
1017         const char __user *user_buf, size_t count, loff_t *ppos)
1018 {
1019         lmh_parse_and_extract(user_buf, count, LMH_DEBUG_READ_TYPE);
1020         return count;
1021 }
1022
1023 static int lmh_dbgfs_data_open(struct inode *inode, struct file *file)
1024 {
1025         return single_open(file, lmh_dbgfs_data_read, inode->i_private);
1026 }
1027
1028 static int lmh_get_types(struct seq_file *seq_fp, enum lmh_read_type type)
1029 {
1030         int ret = 0, idx = 0, size = 0;
1031         uint32_t *type_list = NULL;
1032
1033         switch (type) {
1034         case LMH_DEBUG_READ_TYPE:
1035                 ret = lmh_mon_data->debug_ops->debug_get_types(
1036                         lmh_mon_data->debug_ops, true, &type_list);
1037                 break;
1038         case LMH_DEBUG_CONFIG_TYPE:
1039                 ret = lmh_mon_data->debug_ops->debug_get_types(
1040                         lmh_mon_data->debug_ops, false, &type_list);
1041                 break;
1042         default:
1043                 return -EINVAL;
1044         }
1045         if (ret <= 0 || !type_list) {
1046                 pr_err("No device information. err:%d\n", ret);
1047                 return -ENODEV;
1048         }
1049         size = ret;
1050         for (idx = 0; idx < size; idx++)
1051                 seq_printf(seq_fp, "0x%x ", type_list[idx]);
1052         seq_puts(seq_fp, "\n");
1053
1054         return 0;
1055 }
1056
1057 static int lmh_dbgfs_read_type(struct seq_file *seq_fp, void *data)
1058 {
1059         return lmh_get_types(seq_fp, LMH_DEBUG_READ_TYPE);
1060 }
1061
1062 static int lmh_dbgfs_read_type_open(struct inode *inode, struct file *file)
1063 {
1064         return single_open(file, lmh_dbgfs_read_type, inode->i_private);
1065 }
1066
1067 static int lmh_dbgfs_config_type(struct seq_file *seq_fp, void *data)
1068 {
1069         return lmh_get_types(seq_fp, LMH_DEBUG_CONFIG_TYPE);
1070 }
1071
1072 static int lmh_dbgfs_config_type_open(struct inode *inode, struct file *file)
1073 {
1074         return single_open(file, lmh_dbgfs_config_type, inode->i_private);
1075 }
1076
1077 static const struct file_operations lmh_dbgfs_config_fops = {
1078         .write          = lmh_dbgfs_config_write,
1079 };
1080 static const struct file_operations lmh_dbgfs_read_fops = {
1081         .open           = lmh_dbgfs_data_open,
1082         .read           = seq_read,
1083         .write          = lmh_dbgfs_data_write,
1084         .llseek         = seq_lseek,
1085         .release        = single_release,
1086 };
1087 static const struct file_operations lmh_dbgfs_read_type_fops = {
1088         .open           = lmh_dbgfs_read_type_open,
1089         .read           = seq_read,
1090         .llseek         = seq_lseek,
1091         .release        = single_release,
1092 };
1093 static const struct file_operations lmh_dbgfs_config_type_fops = {
1094         .open           = lmh_dbgfs_config_type_open,
1095         .read           = seq_read,
1096         .llseek         = seq_lseek,
1097         .release        = single_release,
1098 };
1099
1100 int lmh_debug_register(struct lmh_debug_ops *ops)
1101 {
1102         int ret = 0;
1103
1104         if (!ops || !ops->debug_read || !ops->debug_config_read
1105                        || !ops->debug_get_types) {
1106                 pr_err("Invalid input");
1107                 ret = -EINVAL;
1108                 goto dbg_reg_exit;
1109         }
1110
1111         lmh_mon_data->debug_ops = ops;
1112         LMH_CREATE_DEBUGFS_DIR(lmh_mon_data->debug_dir, LMH_DBGFS_DIR,
1113                         lmh_mon_data->debugfs_parent, ret);
1114         if (ret)
1115                 goto dbg_reg_exit;
1116
1117         LMH_CREATE_DEBUGFS_FILE(lmh_mon_data->debug_read, LMH_DBGFS_READ, 0600,
1118                 lmh_mon_data->debug_dir, NULL, &lmh_dbgfs_read_fops, ret);
1119         if (!lmh_mon_data->debug_read) {
1120                 pr_err("Error creating" LMH_DBGFS_READ "entry.\n");
1121                 ret = -ENODEV;
1122                 goto dbg_reg_exit;
1123         }
1124         LMH_CREATE_DEBUGFS_FILE(lmh_mon_data->debug_config,
1125                 LMH_DBGFS_CONFIG_READ, 0200, lmh_mon_data->debug_dir, NULL,
1126                 &lmh_dbgfs_config_fops, ret);
1127         if (!lmh_mon_data->debug_config) {
1128                 pr_err("Error creating" LMH_DBGFS_CONFIG_READ "entry\n");
1129                 ret = -ENODEV;
1130                 goto dbg_reg_exit;
1131         }
1132         LMH_CREATE_DEBUGFS_FILE(lmh_mon_data->debug_read_type,
1133                 LMH_DBGFS_READ_TYPES, 0400, lmh_mon_data->debug_dir, NULL,
1134                 &lmh_dbgfs_read_type_fops, ret);
1135         if (!lmh_mon_data->debug_read_type) {
1136                 pr_err("Error creating" LMH_DBGFS_READ_TYPES "entry\n");
1137                 ret = -ENODEV;
1138                 goto dbg_reg_exit;
1139         }
1140         LMH_CREATE_DEBUGFS_FILE(lmh_mon_data->debug_config_type,
1141                 LMH_DBGFS_CONFIG_TYPES, 0400, lmh_mon_data->debug_dir, NULL,
1142                 &lmh_dbgfs_config_type_fops, ret);
1143         if (!lmh_mon_data->debug_config_type) {
1144                 pr_err("Error creating" LMH_DBGFS_CONFIG_TYPES "entry\n");
1145                 ret = -ENODEV;
1146                 goto dbg_reg_exit;
1147         }
1148
1149 dbg_reg_exit:
1150         if (ret) {
1151                 /*Clean up all the dbg nodes*/
1152                 debugfs_remove_recursive(lmh_mon_data->debug_dir);
1153                 lmh_mon_data->debug_ops = NULL;
1154         }
1155
1156         return ret;
1157 }
1158
1159 static int lmh_mon_init_driver(void)
1160 {
1161         int ret = 0;
1162
1163         lmh_mon_data = kzalloc(sizeof(struct lmh_mon_driver_data),
1164                                 GFP_KERNEL);
1165         if (!lmh_mon_data) {
1166                 pr_err("No memory\n");
1167                 return -ENOMEM;
1168         }
1169
1170         LMH_CREATE_DEBUGFS_DIR(lmh_mon_data->debugfs_parent, LMH_MON_NAME,
1171                                 NULL, ret);
1172         if (ret)
1173                 goto init_exit;
1174         lmh_mon_data->poll_fs = debugfs_create_u32(LMH_ISR_POLL_DELAY, 0600,
1175                         lmh_mon_data->debugfs_parent, &lmh_poll_interval);
1176         if (IS_ERR(lmh_mon_data->poll_fs))
1177                 pr_err("Error creating debugfs:[%s]. err:%ld\n",
1178                         LMH_ISR_POLL_DELAY, PTR_ERR(lmh_mon_data->poll_fs));
1179
1180 init_exit:
1181         if (ret == -ENODEV)
1182                 ret = 0;
1183         return ret;
1184 }
1185
1186 static int __init lmh_mon_init_call(void)
1187 {
1188         int ret = 0;
1189
1190         ret = lmh_mon_init_driver();
1191         if (ret) {
1192                 pr_err("Error initializing the debugfs. err:%d\n", ret);
1193                 goto lmh_init_exit;
1194         }
1195         ret = class_register(&lmh_class_info);
1196         if (ret)
1197                 goto lmh_init_exit;
1198
1199 lmh_init_exit:
1200         if (ret)
1201                 class_unregister(&lmh_class_info);
1202         return ret;
1203 }
1204
1205 static void lmh_mon_cleanup(void)
1206 {
1207         down_write(&lmh_mon_access_lock);
1208         while (!list_empty(&lmh_sensor_list)) {
1209                 lmh_sensor_remove(list_first_entry(&lmh_sensor_list,
1210                         struct lmh_mon_sensor_data, list_ptr)->sensor_ops);
1211         }
1212         up_write(&lmh_mon_access_lock);
1213         debugfs_remove_recursive(lmh_mon_data->debugfs_parent);
1214         kfree(lmh_mon_data);
1215 }
1216
1217 static void lmh_device_cleanup(void)
1218 {
1219         down_write(&lmh_dev_access_lock);
1220         while (!list_empty(&lmh_device_list)) {
1221                 lmh_device_remove(list_first_entry(&lmh_device_list,
1222                         struct lmh_device_data, list_ptr)->device_ops);
1223         }
1224         up_write(&lmh_dev_access_lock);
1225 }
1226
1227 static void lmh_debug_cleanup(void)
1228 {
1229         if (lmh_mon_data->debug_ops) {
1230                 debugfs_remove_recursive(lmh_mon_data->debug_dir);
1231                 lmh_mon_data->debug_ops = NULL;
1232         }
1233 }
1234
1235 static void __exit lmh_mon_exit(void)
1236 {
1237         lmh_mon_cleanup();
1238         lmh_device_cleanup();
1239         lmh_debug_cleanup();
1240         class_unregister(&lmh_class_info);
1241 }
1242
1243 module_init(lmh_mon_init_call);
1244 module_exit(lmh_mon_exit);
1245
1246 MODULE_LICENSE("GPL v2");
1247 MODULE_DESCRIPTION("LMH monitor driver");
1248 MODULE_ALIAS("platform:" LMH_MON_NAME);