1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * processor thermal device for Workload type hints 4 * update from user space 5 * 6 * Copyright (c) 2020-2023, Intel Corporation. 7 */ 8 9#include <linux/pci.h> 10#include "processor_thermal_device.h" 11 12/* List of workload types */ 13static const char * const workload_types[] = { 14 "none", 15 "idle", 16 "semi_active", 17 "bursty", 18 "sustained", 19 "battery_life", 20 NULL 21}; 22 23static ssize_t workload_available_types_show(struct device *dev, 24 struct device_attribute *attr, 25 char *buf) 26{ 27 int i = 0; 28 int ret = 0; 29 30 while (workload_types[i] != NULL) 31 ret += sprintf(&buf[ret], "%s ", workload_types[i++]); 32 33 ret += sprintf(&buf[ret], "\n"); 34 35 return ret; 36} 37 38static DEVICE_ATTR_RO(workload_available_types); 39 40static ssize_t workload_type_store(struct device *dev, 41 struct device_attribute *attr, 42 const char *buf, size_t count) 43{ 44 struct pci_dev *pdev = to_pci_dev(dev); 45 char str_preference[15]; 46 u32 data = 0; 47 ssize_t ret; 48 49 ret = sscanf(buf, "%14s", str_preference); 50 if (ret != 1) 51 return -EINVAL; 52 53 ret = match_string(workload_types, -1, str_preference); 54 if (ret < 0) 55 return ret; 56 57 ret &= 0xff; 58 59 if (ret) 60 data = BIT(MBOX_DATA_BIT_VALID) | BIT(MBOX_DATA_BIT_AC_DC); 61 62 data |= ret; 63 64 ret = processor_thermal_send_mbox_write_cmd(pdev, MBOX_CMD_WORKLOAD_TYPE_WRITE, data); 65 if (ret) 66 return false; 67 68 return count; 69} 70 71static ssize_t workload_type_show(struct device *dev, 72 struct device_attribute *attr, 73 char *buf) 74{ 75 struct pci_dev *pdev = to_pci_dev(dev); 76 u64 cmd_resp; 77 int ret; 78 79 ret = processor_thermal_send_mbox_read_cmd(pdev, MBOX_CMD_WORKLOAD_TYPE_READ, &cmd_resp); 80 if (ret) 81 return false; 82 83 cmd_resp &= 0xff; 84 85 if (cmd_resp > ARRAY_SIZE(workload_types) - 1) 86 return -EINVAL; 87 88 return sprintf(buf, "%s\n", workload_types[cmd_resp]); 89} 90 91static DEVICE_ATTR_RW(workload_type); 92 93static struct attribute *workload_req_attrs[] = { 94 &dev_attr_workload_available_types.attr, 95 &dev_attr_workload_type.attr, 96 NULL 97}; 98 99static const struct attribute_group workload_req_attribute_group = { 100 .attrs = workload_req_attrs, 101 .name = "workload_request" 102}; 103 104static bool workload_req_created; 105 106int proc_thermal_wt_req_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv) 107{ 108 u64 cmd_resp; 109 int ret; 110 111 /* Check if there is a mailbox support, if fails return success */ 112 ret = processor_thermal_send_mbox_read_cmd(pdev, MBOX_CMD_WORKLOAD_TYPE_READ, &cmd_resp); 113 if (ret) 114 return 0; 115 116 ret = sysfs_create_group(&pdev->dev.kobj, &workload_req_attribute_group); 117 if (ret) 118 return ret; 119 120 workload_req_created = true; 121 122 return 0; 123} 124EXPORT_SYMBOL_GPL(proc_thermal_wt_req_add); 125 126void proc_thermal_wt_req_remove(struct pci_dev *pdev) 127{ 128 if (workload_req_created) 129 sysfs_remove_group(&pdev->dev.kobj, &workload_req_attribute_group); 130 131 workload_req_created = false; 132} 133EXPORT_SYMBOL_GPL(proc_thermal_wt_req_remove); 134 135MODULE_IMPORT_NS(INT340X_THERMAL); 136MODULE_LICENSE("GPL"); 137