1 /* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
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.
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.
13 #define pr_fmt(fmt) "%s:%s " fmt, KBUILD_MODNAME, __func__
15 #include <linux/module.h>
16 #include <linux/device.h>
17 #include <linux/interrupt.h>
18 #include <linux/kernel.h>
20 #include <linux/err.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>
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
43 struct lmh_mon_threshold {
48 struct lmh_device_data {
49 char device_name[LMH_NAME_MAX];
50 struct lmh_device_ops *device_ops;
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;
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;
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;
90 LMH_DEBUG_CONFIG_TYPE,
94 static struct lmh_mon_driver_data *lmh_mon_data;
95 static struct class lmh_class_info = {
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);
104 #define LMH_CREATE_DEBUGFS_FILE(_node, _name, _mode, _parent, _data, _ops, \
106 _node = debugfs_create_file(_name, _mode, _parent, \
108 if ((IS_ENABLED(CONFIG_DEBUG_FS))) \
110 if (IS_ERR(_node)) { \
111 _ret = PTR_ERR(_node); \
112 pr_err("Error creating debugfs file:%s. err:%d\n", \
117 #define LMH_CREATE_DEBUGFS_DIR(_node, _name, _parent, _ret) \
119 _node = debugfs_create_dir(_name, _parent); \
120 if ((IS_ENABLED(CONFIG_DEBUG_FS))) \
122 if (IS_ERR(_node)) { \
123 _ret = PTR_ERR(_node); \
124 pr_err("Error creating debugfs dir:%s. err:%d\n", \
129 #define LMH_HW_LOG_FS(_name) \
130 static int _name##_get(void *data, u64 *val) \
132 *val = lmh_mon_data->_name; \
135 static int _name##_set(void *data, u64 val) \
137 struct lmh_mon_sensor_data *lmh_sensor = data; \
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); \
145 ret = lmh_sensor->sensor_ops->disable_hw_log(); \
148 DEFINE_SIMPLE_ATTRIBUTE(_name##_fops, _name##_get, _name##_set, \
151 #define LMH_DEV_GET(_name) \
152 static ssize_t _name##_get(struct device *dev, \
153 struct device_attribute *attr, char *buf) \
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); \
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);
165 int lmh_get_poll_interval(void)
167 return lmh_poll_interval;
170 static ssize_t curr_level_set(struct device *dev,
171 struct device_attribute *attr, const char *buf, size_t count)
173 struct lmh_device_data *lmh_dev = container_of(dev,
174 struct lmh_device_data, dev);
175 int val = 0, ret = 0;
177 ret = kstrtouint(buf, 0, &val);
179 pr_err("Invalid input [%s]. err:%d\n", buf, ret);
182 return lmh_set_dev_level(lmh_dev->device_name, val);
185 static ssize_t avail_level_get(struct device *dev,
186 struct device_attribute *attr, char *buf)
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;
194 if (!lmh_dev || !lmh_dev->levels || !lmh_dev->max_level) {
195 pr_err("Invalid input\n");
198 type_list = lmh_dev->levels;
199 lvl_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
201 pr_err("Error allocating memory\n");
204 for (idx = 0; (idx < lmh_dev->max_level) && (lvl_buf_count < PAGE_SIZE)
206 count = snprintf(lvl_buf + lvl_buf_count,
207 PAGE_SIZE - lvl_buf_count, "%d ",
209 if (count + lvl_buf_count >= PAGE_SIZE) {
210 pr_err("overflow.\n");
212 } else if (count < 0) {
213 pr_err("Error writing to buffer. err:%d\n", count);
217 lvl_buf_count += count;
219 count = snprintf(lvl_buf + lvl_buf_count, PAGE_SIZE - lvl_buf_count,
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;
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");
235 return (ret) ? ret : count;
238 static int lmh_create_dev_sysfs(struct lmh_device_data *lmh_dev)
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);
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);
249 pr_err("Error registering profile device. err:%d\n", ret);
252 ret = device_create_file(&lmh_dev->dev, &dev_attr_level);
254 pr_err("Error creating profile level sysfs node. err:%d\n",
258 ret = device_create_file(&lmh_dev->dev, &dev_attr_total_levels);
260 pr_err("Error creating total level sysfs node. err:%d\n",
264 ret = device_create_file(&lmh_dev->dev, &dev_attr_available_levels);
266 pr_err("Error creating available level sysfs node. err:%d\n",
273 device_unregister(&lmh_dev->dev);
277 static int lmh_create_debugfs_nodes(struct lmh_mon_sensor_data *lmh_sensor)
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);
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);
292 goto create_debugfs_exit;
296 debugfs_remove_recursive(lmh_mon_data->debugfs_parent);
300 static struct lmh_mon_sensor_data *lmh_match_sensor_ops(
301 struct lmh_sensor_ops *ops)
303 struct lmh_mon_sensor_data *lmh_sensor = NULL;
305 list_for_each_entry(lmh_sensor, &lmh_sensor_list, list_ptr) {
306 if (lmh_sensor->sensor_ops == ops)
313 static struct lmh_mon_sensor_data *lmh_match_sensor_name(char *sensor_name)
315 struct lmh_mon_sensor_data *lmh_sensor = NULL;
317 list_for_each_entry(lmh_sensor, &lmh_sensor_list, list_ptr) {
318 if (!strncasecmp(lmh_sensor->sensor_name, sensor_name,
326 static void lmh_evaluate_and_notify(struct lmh_mon_sensor_data *lmh_sensor,
329 int idx = 0, trip = 0;
332 for (idx = 0; idx < LMH_TRIP_MAX; idx++) {
333 if (!lmh_sensor->trip[idx].active)
335 if (idx == LMH_HIGH_TRIP) {
336 trip = THERMAL_TRIP_CONFIGURABLE_HI;
337 cond = (val >= lmh_sensor->trip[idx].value);
339 trip = THERMAL_TRIP_CONFIGURABLE_LOW;
340 cond = (val <= lmh_sensor->trip[idx].value);
343 lmh_sensor->trip[idx].active = false;
344 thermal_sensor_trip(lmh_sensor->tzdev, trip, val);
349 void lmh_update_reading(struct lmh_sensor_ops *ops, int trip_val)
351 struct lmh_mon_sensor_data *lmh_sensor = NULL;
354 pr_err("Invalid input\n");
358 down_read(&lmh_mon_access_lock);
359 lmh_sensor = lmh_match_sensor_ops(ops);
361 pr_err("Invalid ops\n");
364 down_write(&lmh_sensor->lock);
365 pr_debug("Sensor:[%s] intensity:%d\n", lmh_sensor->sensor_name,
367 lmh_evaluate_and_notify(lmh_sensor, trip_val);
370 up_write(&lmh_sensor->lock);
371 up_read(&lmh_mon_access_lock);
375 static int lmh_sensor_read(struct thermal_zone_device *dev, int *val)
378 struct lmh_mon_sensor_data *lmh_sensor;
380 if (!val || !dev || !dev->devdata) {
381 pr_err("Invalid input\n");
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);
389 pr_err("Error reading sensor:%s. err:%d\n",
390 lmh_sensor->sensor_name, ret);
391 goto unlock_and_exit;
394 up_read(&lmh_sensor->lock);
395 up_read(&lmh_mon_access_lock);
400 static int lmh_get_mode(struct thermal_zone_device *dev,
401 enum thermal_device_mode *mode)
403 struct lmh_mon_sensor_data *lmh_sensor;
405 if (!dev || !dev->devdata || !mode) {
406 pr_err("Invalid input\n");
409 lmh_sensor = dev->devdata;
410 *mode = lmh_sensor->mode;
415 static int lmh_get_trip_type(struct thermal_zone_device *dev,
416 int trip, enum thermal_trip_type *type)
418 if (!type || !dev || !dev->devdata || trip < 0
419 || trip >= LMH_TRIP_MAX) {
420 pr_err("Invalid input\n");
426 *type = THERMAL_TRIP_CONFIGURABLE_HI;
429 *type = THERMAL_TRIP_CONFIGURABLE_LOW;
438 static int lmh_activate_trip(struct thermal_zone_device *dev,
439 int trip, enum thermal_trip_activation_mode mode)
441 struct lmh_mon_sensor_data *lmh_sensor;
443 if (!dev || !dev->devdata || trip < 0 || trip >= LMH_TRIP_MAX) {
444 pr_err("Invalid input\n");
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);
459 static int lmh_get_trip_value(struct thermal_zone_device *dev,
460 int trip, int *value)
462 struct lmh_mon_sensor_data *lmh_sensor;
464 if (!dev || !dev->devdata || trip < 0 || trip >= LMH_TRIP_MAX
466 pr_err("Invalid input\n");
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);
480 static int lmh_set_trip_value(struct thermal_zone_device *dev,
483 struct lmh_mon_sensor_data *lmh_sensor;
485 if (!dev || !dev->devdata || trip < 0 || trip >= LMH_TRIP_MAX) {
486 pr_err("Invalid input\n");
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);
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,
509 static int lmh_register_sensor(struct lmh_mon_sensor_data *lmh_sensor)
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,
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);
527 static int lmh_sensor_init(struct lmh_mon_sensor_data *lmh_sensor,
528 char *sensor_name, struct lmh_sensor_ops *ops)
530 int idx = 0, ret = 0;
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;
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);
548 int lmh_sensor_register(char *sensor_name, struct lmh_sensor_ops *ops)
551 struct lmh_mon_sensor_data *lmh_sensor = NULL;
553 if (!sensor_name || !ops) {
554 pr_err("Invalid input\n");
558 if (!ops->read || !ops->enable_hw_log || !ops->disable_hw_log) {
559 pr_err("Invalid ops input for sensor:%s\n", sensor_name);
562 down_write(&lmh_mon_access_lock);
563 if (lmh_match_sensor_name(sensor_name)
564 || lmh_match_sensor_ops(ops)) {
566 pr_err("Sensor[%s] exists\n", sensor_name);
569 lmh_sensor = kzalloc(sizeof(struct lmh_mon_sensor_data), GFP_KERNEL);
571 pr_err("kzalloc failed\n");
575 ret = lmh_sensor_init(lmh_sensor, sensor_name, ops);
577 pr_err("Error registering sensor:%s. err:%d\n", sensor_name,
583 pr_debug("Registered Sensor:[%s]\n", sensor_name);
586 up_write(&lmh_mon_access_lock);
589 ret = lmh_register_sensor(lmh_sensor);
591 pr_err("Thermal Zone register failed for Sensor:[%s]\n"
595 pr_debug("Registered Sensor:[%s]\n", sensor_name);
599 static void lmh_sensor_remove(struct lmh_sensor_ops *ops)
601 struct lmh_mon_sensor_data *lmh_sensor = NULL;
603 lmh_sensor = lmh_match_sensor_ops(ops);
605 pr_err("No match for the sensor\n");
606 goto deregister_exit;
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);
619 void lmh_sensor_deregister(struct lmh_sensor_ops *ops)
622 pr_err("Invalid input\n");
626 down_write(&lmh_mon_access_lock);
627 lmh_sensor_remove(ops);
628 up_write(&lmh_mon_access_lock);
633 static struct lmh_device_data *lmh_match_device_name(char *device_name)
635 struct lmh_device_data *lmh_device = NULL;
637 list_for_each_entry(lmh_device, &lmh_device_list, list_ptr) {
638 if (!strncasecmp(lmh_device->device_name, device_name,
646 static struct lmh_device_data *lmh_match_device_ops(struct lmh_device_ops *ops)
648 struct lmh_device_data *lmh_device = NULL;
650 list_for_each_entry(lmh_device, &lmh_device_list, list_ptr) {
651 if (lmh_device->device_ops == ops)
658 static int lmh_device_init(struct lmh_device_data *lmh_device,
659 char *device_name, struct lmh_device_ops *ops)
663 ret = ops->get_curr_level(ops, &lmh_device->curr_level);
665 pr_err("Error getting curr level for Device:[%s]. err:%d\n",
669 ret = ops->get_available_levels(ops, NULL);
671 pr_err("Error getting max level for Device:[%s]. err:%d\n",
673 ret = (!ret) ? -EINVAL : ret;
676 lmh_device->max_level = ret;
677 lmh_device->levels = kzalloc(lmh_device->max_level * sizeof(int),
679 if (!lmh_device->levels) {
680 pr_err("No memory\n");
684 ret = ops->get_available_levels(ops, lmh_device->levels);
686 pr_err("Error getting device:[%s] levels. err:%d\n",
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);
698 kfree(lmh_device->levels);
702 int lmh_get_all_dev_levels(char *device_name, int *val)
705 struct lmh_device_data *lmh_device = NULL;
708 pr_err("Invalid input\n");
711 down_read(&lmh_dev_access_lock);
712 lmh_device = lmh_match_device_name(device_name);
714 pr_err("Invalid device:%s\n", device_name);
716 goto get_all_lvl_exit;
718 down_read(&lmh_device->lock);
720 ret = lmh_device->max_level;
721 goto get_all_lvl_exit;
723 memcpy(val, lmh_device->levels,
724 sizeof(int) * lmh_device->max_level);
728 up_read(&lmh_device->lock);
729 up_read(&lmh_dev_access_lock);
733 int lmh_set_dev_level(char *device_name, int curr_lvl)
736 struct lmh_device_data *lmh_device = NULL;
739 pr_err("Invalid input\n");
742 down_read(&lmh_dev_access_lock);
743 lmh_device = lmh_match_device_name(device_name);
745 pr_err("Invalid device:%s\n", device_name);
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)
754 ret = lmh_device->device_ops->set_level(lmh_device->device_ops,
757 pr_err("Error setting current level%d for device[%s]. err:%d\n",
758 curr_lvl, device_name, ret);
761 pr_debug("Device:[%s] configured to level %d\n", device_name, curr_lvl);
762 lmh_device->curr_level = curr_lvl;
766 up_write(&lmh_device->lock);
767 up_read(&lmh_dev_access_lock);
771 int lmh_get_curr_level(char *device_name, int *val)
774 struct lmh_device_data *lmh_device = NULL;
776 if (!device_name || !val) {
777 pr_err("Invalid input\n");
780 down_read(&lmh_dev_access_lock);
781 lmh_device = lmh_match_device_name(device_name);
783 pr_err("Invalid device:%s\n", device_name);
787 down_read(&lmh_device->lock);
788 ret = lmh_device->device_ops->get_curr_level(lmh_device->device_ops,
789 &lmh_device->curr_level);
791 pr_err("Error getting device[%s] current level. err:%d\n",
795 *val = lmh_device->curr_level;
796 pr_debug("Device:%s current level:%d\n", device_name, *val);
800 up_read(&lmh_device->lock);
801 up_read(&lmh_dev_access_lock);
805 int lmh_device_register(char *device_name, struct lmh_device_ops *ops)
808 struct lmh_device_data *lmh_device = NULL;
810 if (!device_name || !ops) {
811 pr_err("Invalid input\n");
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);
821 down_write(&lmh_dev_access_lock);
822 if (lmh_match_device_name(device_name)
823 || lmh_match_device_ops(ops)) {
825 pr_err("Device[%s] allready exists\n", device_name);
828 lmh_device = kzalloc(sizeof(struct lmh_device_data), GFP_KERNEL);
830 pr_err("kzalloc failed\n");
834 ret = lmh_device_init(lmh_device, device_name, ops);
836 pr_err("Error registering device:%s. err:%d\n", device_name,
842 pr_debug("Registered Device:[%s] with %d levels\n", device_name,
843 lmh_device->max_level);
846 up_write(&lmh_dev_access_lock);
850 static void lmh_device_remove(struct lmh_device_ops *ops)
852 struct lmh_device_data *lmh_device = NULL;
854 lmh_device = lmh_match_device_ops(ops);
856 pr_err("No match for the device\n");
857 goto deregister_exit;
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);
870 void lmh_device_deregister(struct lmh_device_ops *ops)
873 pr_err("Invalid input\n");
877 down_write(&lmh_dev_access_lock);
878 lmh_device_remove(ops);
879 up_write(&lmh_dev_access_lock);
883 static int lmh_parse_and_extract(const char __user *user_buf, size_t count,
884 enum lmh_read_type type)
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;
891 /* Allocate two extra space to add ';' character and NULL terminate */
892 local_buf = kzalloc(count + 2, GFP_KERNEL);
895 goto dfs_cfg_write_exit;
897 if (copy_from_user(local_buf, user_buf, count)) {
898 pr_err("user buf error\n");
900 goto dfs_cfg_write_exit;
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, ';'))
910 curr_ptr = next_line;
911 next_line = token1 + 1;
912 for (token = (char *)curr_ptr; token &&
913 ((token = strnchr(token, next_line - token, ' '))
917 pr_err("Invalid format string:[%s]\n", curr_ptr);
919 goto dfs_cfg_write_exit;
921 config_buf = kzalloc((++data_ct) * sizeof(uint32_t),
925 goto dfs_cfg_write_exit;
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);
930 token = strnchr(token, next_line - token, ' ');
933 ret = kstrtouint(curr_ptr, 0, &config_buf[i]);
935 pr_err("Data[%s] scan error. err:%d\n",
938 goto dfs_cfg_write_exit;
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);
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);
958 pr_err("Config error. type:%d err:%d\n", type, ret);
959 goto dfs_cfg_write_exit;
968 static ssize_t lmh_dbgfs_config_write(struct file *file,
969 const char __user *user_buf, size_t count, loff_t *ppos)
971 lmh_parse_and_extract(user_buf, count, LMH_DEBUG_CONFIG_TYPE);
975 static int lmh_dbgfs_data_read(struct seq_file *seq_fp, void *data)
977 static uint32_t *read_buf;
978 static int read_buf_size;
979 int idx = 0, ret = 0;
981 if (!read_buf_size) {
982 ret = lmh_mon_data->debug_ops->debug_read(
983 lmh_mon_data->debug_ops, &read_buf);
986 if (!read_buf || ret < sizeof(uint32_t)) {
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);
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);
1008 } while (idx < (read_buf_size / sizeof(uint32_t)));
1016 static ssize_t lmh_dbgfs_data_write(struct file *file,
1017 const char __user *user_buf, size_t count, loff_t *ppos)
1019 lmh_parse_and_extract(user_buf, count, LMH_DEBUG_READ_TYPE);
1023 static int lmh_dbgfs_data_open(struct inode *inode, struct file *file)
1025 return single_open(file, lmh_dbgfs_data_read, inode->i_private);
1028 static int lmh_get_types(struct seq_file *seq_fp, enum lmh_read_type type)
1030 int ret = 0, idx = 0, size = 0;
1031 uint32_t *type_list = NULL;
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);
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);
1045 if (ret <= 0 || !type_list) {
1046 pr_err("No device information. err:%d\n", ret);
1050 for (idx = 0; idx < size; idx++)
1051 seq_printf(seq_fp, "0x%x ", type_list[idx]);
1052 seq_puts(seq_fp, "\n");
1057 static int lmh_dbgfs_read_type(struct seq_file *seq_fp, void *data)
1059 return lmh_get_types(seq_fp, LMH_DEBUG_READ_TYPE);
1062 static int lmh_dbgfs_read_type_open(struct inode *inode, struct file *file)
1064 return single_open(file, lmh_dbgfs_read_type, inode->i_private);
1067 static int lmh_dbgfs_config_type(struct seq_file *seq_fp, void *data)
1069 return lmh_get_types(seq_fp, LMH_DEBUG_CONFIG_TYPE);
1072 static int lmh_dbgfs_config_type_open(struct inode *inode, struct file *file)
1074 return single_open(file, lmh_dbgfs_config_type, inode->i_private);
1077 static const struct file_operations lmh_dbgfs_config_fops = {
1078 .write = lmh_dbgfs_config_write,
1080 static const struct file_operations lmh_dbgfs_read_fops = {
1081 .open = lmh_dbgfs_data_open,
1083 .write = lmh_dbgfs_data_write,
1084 .llseek = seq_lseek,
1085 .release = single_release,
1087 static const struct file_operations lmh_dbgfs_read_type_fops = {
1088 .open = lmh_dbgfs_read_type_open,
1090 .llseek = seq_lseek,
1091 .release = single_release,
1093 static const struct file_operations lmh_dbgfs_config_type_fops = {
1094 .open = lmh_dbgfs_config_type_open,
1096 .llseek = seq_lseek,
1097 .release = single_release,
1100 int lmh_debug_register(struct lmh_debug_ops *ops)
1104 if (!ops || !ops->debug_read || !ops->debug_config_read
1105 || !ops->debug_get_types) {
1106 pr_err("Invalid input");
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);
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");
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");
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");
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");
1151 /*Clean up all the dbg nodes*/
1152 debugfs_remove_recursive(lmh_mon_data->debug_dir);
1153 lmh_mon_data->debug_ops = NULL;
1159 static int lmh_mon_init_driver(void)
1163 lmh_mon_data = kzalloc(sizeof(struct lmh_mon_driver_data),
1165 if (!lmh_mon_data) {
1166 pr_err("No memory\n");
1170 LMH_CREATE_DEBUGFS_DIR(lmh_mon_data->debugfs_parent, LMH_MON_NAME,
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));
1186 static int __init lmh_mon_init_call(void)
1190 ret = lmh_mon_init_driver();
1192 pr_err("Error initializing the debugfs. err:%d\n", ret);
1195 ret = class_register(&lmh_class_info);
1201 class_unregister(&lmh_class_info);
1205 static void lmh_mon_cleanup(void)
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);
1212 up_write(&lmh_mon_access_lock);
1213 debugfs_remove_recursive(lmh_mon_data->debugfs_parent);
1214 kfree(lmh_mon_data);
1217 static void lmh_device_cleanup(void)
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);
1224 up_write(&lmh_dev_access_lock);
1227 static void lmh_debug_cleanup(void)
1229 if (lmh_mon_data->debug_ops) {
1230 debugfs_remove_recursive(lmh_mon_data->debug_dir);
1231 lmh_mon_data->debug_ops = NULL;
1235 static void __exit lmh_mon_exit(void)
1238 lmh_device_cleanup();
1239 lmh_debug_cleanup();
1240 class_unregister(&lmh_class_info);
1243 module_init(lmh_mon_init_call);
1244 module_exit(lmh_mon_exit);
1246 MODULE_LICENSE("GPL v2");
1247 MODULE_DESCRIPTION("LMH monitor driver");
1248 MODULE_ALIAS("platform:" LMH_MON_NAME);