linux/drivers/misc/habanalabs/common/sysfs.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2
   3/*
   4 * Copyright 2016-2019 HabanaLabs, Ltd.
   5 * All Rights Reserved.
   6 */
   7
   8#include "habanalabs.h"
   9
  10#include <linux/pci.h>
  11
  12long hl_get_frequency(struct hl_device *hdev, u32 pll_index, bool curr)
  13{
  14        struct cpucp_packet pkt;
  15        u32 used_pll_idx;
  16        u64 result;
  17        int rc;
  18
  19        rc = get_used_pll_index(hdev, pll_index, &used_pll_idx);
  20        if (rc)
  21                return rc;
  22
  23        memset(&pkt, 0, sizeof(pkt));
  24
  25        if (curr)
  26                pkt.ctl = cpu_to_le32(CPUCP_PACKET_FREQUENCY_CURR_GET <<
  27                                                CPUCP_PKT_CTL_OPCODE_SHIFT);
  28        else
  29                pkt.ctl = cpu_to_le32(CPUCP_PACKET_FREQUENCY_GET <<
  30                                                CPUCP_PKT_CTL_OPCODE_SHIFT);
  31        pkt.pll_index = cpu_to_le32((u32)used_pll_idx);
  32
  33        rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
  34                                                0, &result);
  35
  36        if (rc) {
  37                dev_err(hdev->dev,
  38                        "Failed to get frequency of PLL %d, error %d\n",
  39                        used_pll_idx, rc);
  40                return rc;
  41        }
  42
  43        return (long) result;
  44}
  45
  46void hl_set_frequency(struct hl_device *hdev, u32 pll_index, u64 freq)
  47{
  48        struct cpucp_packet pkt;
  49        u32 used_pll_idx;
  50        int rc;
  51
  52        rc = get_used_pll_index(hdev, pll_index, &used_pll_idx);
  53        if (rc)
  54                return;
  55
  56        memset(&pkt, 0, sizeof(pkt));
  57
  58        pkt.ctl = cpu_to_le32(CPUCP_PACKET_FREQUENCY_SET <<
  59                                        CPUCP_PKT_CTL_OPCODE_SHIFT);
  60        pkt.pll_index = cpu_to_le32((u32)used_pll_idx);
  61        pkt.value = cpu_to_le64(freq);
  62
  63        rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
  64                                                0, NULL);
  65
  66        if (rc)
  67                dev_err(hdev->dev,
  68                        "Failed to set frequency to PLL %d, error %d\n",
  69                        used_pll_idx, rc);
  70}
  71
  72u64 hl_get_max_power(struct hl_device *hdev)
  73{
  74        struct cpucp_packet pkt;
  75        u64 result;
  76        int rc;
  77
  78        memset(&pkt, 0, sizeof(pkt));
  79
  80        pkt.ctl = cpu_to_le32(CPUCP_PACKET_MAX_POWER_GET <<
  81                                CPUCP_PKT_CTL_OPCODE_SHIFT);
  82
  83        rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
  84                                                0, &result);
  85
  86        if (rc) {
  87                dev_err(hdev->dev, "Failed to get max power, error %d\n", rc);
  88                return (u64) rc;
  89        }
  90
  91        return result;
  92}
  93
  94void hl_set_max_power(struct hl_device *hdev)
  95{
  96        struct cpucp_packet pkt;
  97        int rc;
  98
  99        memset(&pkt, 0, sizeof(pkt));
 100
 101        pkt.ctl = cpu_to_le32(CPUCP_PACKET_MAX_POWER_SET <<
 102                                CPUCP_PKT_CTL_OPCODE_SHIFT);
 103        pkt.value = cpu_to_le64(hdev->max_power);
 104
 105        rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
 106                                                0, NULL);
 107
 108        if (rc)
 109                dev_err(hdev->dev, "Failed to set max power, error %d\n", rc);
 110}
 111
 112static ssize_t uboot_ver_show(struct device *dev, struct device_attribute *attr,
 113                                char *buf)
 114{
 115        struct hl_device *hdev = dev_get_drvdata(dev);
 116
 117        return sprintf(buf, "%s\n", hdev->asic_prop.uboot_ver);
 118}
 119
 120static ssize_t armcp_kernel_ver_show(struct device *dev,
 121                                struct device_attribute *attr, char *buf)
 122{
 123        struct hl_device *hdev = dev_get_drvdata(dev);
 124
 125        return sprintf(buf, "%s", hdev->asic_prop.cpucp_info.kernel_version);
 126}
 127
 128static ssize_t armcp_ver_show(struct device *dev, struct device_attribute *attr,
 129                                char *buf)
 130{
 131        struct hl_device *hdev = dev_get_drvdata(dev);
 132
 133        return sprintf(buf, "%s\n", hdev->asic_prop.cpucp_info.cpucp_version);
 134}
 135
 136static ssize_t cpld_ver_show(struct device *dev, struct device_attribute *attr,
 137                                char *buf)
 138{
 139        struct hl_device *hdev = dev_get_drvdata(dev);
 140
 141        return sprintf(buf, "0x%08x\n",
 142                        hdev->asic_prop.cpucp_info.cpld_version);
 143}
 144
 145static ssize_t cpucp_kernel_ver_show(struct device *dev,
 146                                struct device_attribute *attr, char *buf)
 147{
 148        struct hl_device *hdev = dev_get_drvdata(dev);
 149
 150        return sprintf(buf, "%s", hdev->asic_prop.cpucp_info.kernel_version);
 151}
 152
 153static ssize_t cpucp_ver_show(struct device *dev, struct device_attribute *attr,
 154                                char *buf)
 155{
 156        struct hl_device *hdev = dev_get_drvdata(dev);
 157
 158        return sprintf(buf, "%s\n", hdev->asic_prop.cpucp_info.cpucp_version);
 159}
 160
 161static ssize_t infineon_ver_show(struct device *dev,
 162                                struct device_attribute *attr, char *buf)
 163{
 164        struct hl_device *hdev = dev_get_drvdata(dev);
 165
 166        return sprintf(buf, "0x%04x\n",
 167                        hdev->asic_prop.cpucp_info.infineon_version);
 168}
 169
 170static ssize_t fuse_ver_show(struct device *dev, struct device_attribute *attr,
 171                                char *buf)
 172{
 173        struct hl_device *hdev = dev_get_drvdata(dev);
 174
 175        return sprintf(buf, "%s\n", hdev->asic_prop.cpucp_info.fuse_version);
 176}
 177
 178static ssize_t thermal_ver_show(struct device *dev,
 179                                struct device_attribute *attr, char *buf)
 180{
 181        struct hl_device *hdev = dev_get_drvdata(dev);
 182
 183        return sprintf(buf, "%s", hdev->asic_prop.cpucp_info.thermal_version);
 184}
 185
 186static ssize_t preboot_btl_ver_show(struct device *dev,
 187                                struct device_attribute *attr, char *buf)
 188{
 189        struct hl_device *hdev = dev_get_drvdata(dev);
 190
 191        return sprintf(buf, "%s\n", hdev->asic_prop.preboot_ver);
 192}
 193
 194static ssize_t soft_reset_store(struct device *dev,
 195                                struct device_attribute *attr, const char *buf,
 196                                size_t count)
 197{
 198        struct hl_device *hdev = dev_get_drvdata(dev);
 199        long value;
 200        int rc;
 201
 202        rc = kstrtoul(buf, 0, &value);
 203
 204        if (rc) {
 205                count = -EINVAL;
 206                goto out;
 207        }
 208
 209        if (!hdev->allow_external_soft_reset) {
 210                dev_err(hdev->dev, "Device does not support soft-reset\n");
 211                goto out;
 212        }
 213
 214        dev_warn(hdev->dev, "Soft-Reset requested through sysfs\n");
 215
 216        hl_device_reset(hdev, 0);
 217
 218out:
 219        return count;
 220}
 221
 222static ssize_t hard_reset_store(struct device *dev,
 223                                struct device_attribute *attr,
 224                                const char *buf, size_t count)
 225{
 226        struct hl_device *hdev = dev_get_drvdata(dev);
 227        long value;
 228        int rc;
 229
 230        rc = kstrtoul(buf, 0, &value);
 231
 232        if (rc) {
 233                count = -EINVAL;
 234                goto out;
 235        }
 236
 237        dev_warn(hdev->dev, "Hard-Reset requested through sysfs\n");
 238
 239        hl_device_reset(hdev, HL_RESET_HARD);
 240
 241out:
 242        return count;
 243}
 244
 245static ssize_t device_type_show(struct device *dev,
 246                struct device_attribute *attr, char *buf)
 247{
 248        struct hl_device *hdev = dev_get_drvdata(dev);
 249        char *str;
 250
 251        switch (hdev->asic_type) {
 252        case ASIC_GOYA:
 253                str = "GOYA";
 254                break;
 255        case ASIC_GAUDI:
 256                str = "GAUDI";
 257                break;
 258        case ASIC_GAUDI_SEC:
 259                str = "GAUDI SEC";
 260                break;
 261        default:
 262                dev_err(hdev->dev, "Unrecognized ASIC type %d\n",
 263                                hdev->asic_type);
 264                return -EINVAL;
 265        }
 266
 267        return sprintf(buf, "%s\n", str);
 268}
 269
 270static ssize_t pci_addr_show(struct device *dev, struct device_attribute *attr,
 271                                char *buf)
 272{
 273        struct hl_device *hdev = dev_get_drvdata(dev);
 274
 275        return sprintf(buf, "%04x:%02x:%02x.%x\n",
 276                        pci_domain_nr(hdev->pdev->bus),
 277                        hdev->pdev->bus->number,
 278                        PCI_SLOT(hdev->pdev->devfn),
 279                        PCI_FUNC(hdev->pdev->devfn));
 280}
 281
 282static ssize_t status_show(struct device *dev, struct device_attribute *attr,
 283                                char *buf)
 284{
 285        struct hl_device *hdev = dev_get_drvdata(dev);
 286        char str[HL_STR_MAX];
 287
 288        strscpy(str, hdev->status[hl_device_status(hdev)], HL_STR_MAX);
 289
 290        /* use uppercase for backward compatibility */
 291        str[0] = 'A' + (str[0] - 'a');
 292
 293        return sprintf(buf, "%s\n", str);
 294}
 295
 296static ssize_t soft_reset_cnt_show(struct device *dev,
 297                struct device_attribute *attr, char *buf)
 298{
 299        struct hl_device *hdev = dev_get_drvdata(dev);
 300
 301        return sprintf(buf, "%d\n", hdev->soft_reset_cnt);
 302}
 303
 304static ssize_t hard_reset_cnt_show(struct device *dev,
 305                struct device_attribute *attr, char *buf)
 306{
 307        struct hl_device *hdev = dev_get_drvdata(dev);
 308
 309        return sprintf(buf, "%d\n", hdev->hard_reset_cnt);
 310}
 311
 312static ssize_t max_power_show(struct device *dev, struct device_attribute *attr,
 313                                char *buf)
 314{
 315        struct hl_device *hdev = dev_get_drvdata(dev);
 316        long val;
 317
 318        if (!hl_device_operational(hdev, NULL))
 319                return -ENODEV;
 320
 321        val = hl_get_max_power(hdev);
 322
 323        return sprintf(buf, "%lu\n", val);
 324}
 325
 326static ssize_t max_power_store(struct device *dev,
 327                struct device_attribute *attr, const char *buf, size_t count)
 328{
 329        struct hl_device *hdev = dev_get_drvdata(dev);
 330        unsigned long value;
 331        int rc;
 332
 333        if (!hl_device_operational(hdev, NULL)) {
 334                count = -ENODEV;
 335                goto out;
 336        }
 337
 338        rc = kstrtoul(buf, 0, &value);
 339
 340        if (rc) {
 341                count = -EINVAL;
 342                goto out;
 343        }
 344
 345        hdev->max_power = value;
 346        hl_set_max_power(hdev);
 347
 348out:
 349        return count;
 350}
 351
 352static ssize_t eeprom_read_handler(struct file *filp, struct kobject *kobj,
 353                        struct bin_attribute *attr, char *buf, loff_t offset,
 354                        size_t max_size)
 355{
 356        struct device *dev = kobj_to_dev(kobj);
 357        struct hl_device *hdev = dev_get_drvdata(dev);
 358        char *data;
 359        int rc;
 360
 361        if (!hl_device_operational(hdev, NULL))
 362                return -ENODEV;
 363
 364        if (!max_size)
 365                return -EINVAL;
 366
 367        data = kzalloc(max_size, GFP_KERNEL);
 368        if (!data)
 369                return -ENOMEM;
 370
 371        rc = hdev->asic_funcs->get_eeprom_data(hdev, data, max_size);
 372        if (rc)
 373                goto out;
 374
 375        memcpy(buf, data, max_size);
 376
 377out:
 378        kfree(data);
 379
 380        return max_size;
 381}
 382
 383static DEVICE_ATTR_RO(armcp_kernel_ver);
 384static DEVICE_ATTR_RO(armcp_ver);
 385static DEVICE_ATTR_RO(cpld_ver);
 386static DEVICE_ATTR_RO(cpucp_kernel_ver);
 387static DEVICE_ATTR_RO(cpucp_ver);
 388static DEVICE_ATTR_RO(device_type);
 389static DEVICE_ATTR_RO(fuse_ver);
 390static DEVICE_ATTR_WO(hard_reset);
 391static DEVICE_ATTR_RO(hard_reset_cnt);
 392static DEVICE_ATTR_RO(infineon_ver);
 393static DEVICE_ATTR_RW(max_power);
 394static DEVICE_ATTR_RO(pci_addr);
 395static DEVICE_ATTR_RO(preboot_btl_ver);
 396static DEVICE_ATTR_WO(soft_reset);
 397static DEVICE_ATTR_RO(soft_reset_cnt);
 398static DEVICE_ATTR_RO(status);
 399static DEVICE_ATTR_RO(thermal_ver);
 400static DEVICE_ATTR_RO(uboot_ver);
 401
 402static struct bin_attribute bin_attr_eeprom = {
 403        .attr = {.name = "eeprom", .mode = (0444)},
 404        .size = PAGE_SIZE,
 405        .read = eeprom_read_handler
 406};
 407
 408static struct attribute *hl_dev_attrs[] = {
 409        &dev_attr_armcp_kernel_ver.attr,
 410        &dev_attr_armcp_ver.attr,
 411        &dev_attr_cpld_ver.attr,
 412        &dev_attr_cpucp_kernel_ver.attr,
 413        &dev_attr_cpucp_ver.attr,
 414        &dev_attr_device_type.attr,
 415        &dev_attr_fuse_ver.attr,
 416        &dev_attr_hard_reset.attr,
 417        &dev_attr_hard_reset_cnt.attr,
 418        &dev_attr_infineon_ver.attr,
 419        &dev_attr_max_power.attr,
 420        &dev_attr_pci_addr.attr,
 421        &dev_attr_preboot_btl_ver.attr,
 422        &dev_attr_soft_reset.attr,
 423        &dev_attr_soft_reset_cnt.attr,
 424        &dev_attr_status.attr,
 425        &dev_attr_thermal_ver.attr,
 426        &dev_attr_uboot_ver.attr,
 427        NULL,
 428};
 429
 430static struct bin_attribute *hl_dev_bin_attrs[] = {
 431        &bin_attr_eeprom,
 432        NULL
 433};
 434
 435static struct attribute_group hl_dev_attr_group = {
 436        .attrs = hl_dev_attrs,
 437        .bin_attrs = hl_dev_bin_attrs,
 438};
 439
 440static struct attribute_group hl_dev_clks_attr_group;
 441
 442static const struct attribute_group *hl_dev_attr_groups[] = {
 443        &hl_dev_attr_group,
 444        &hl_dev_clks_attr_group,
 445        NULL,
 446};
 447
 448int hl_sysfs_init(struct hl_device *hdev)
 449{
 450        int rc;
 451
 452        if (hdev->asic_type == ASIC_GOYA)
 453                hdev->pm_mng_profile = PM_AUTO;
 454        else
 455                hdev->pm_mng_profile = PM_MANUAL;
 456
 457        hdev->max_power = hdev->asic_prop.max_power_default;
 458
 459        hdev->asic_funcs->add_device_attr(hdev, &hl_dev_clks_attr_group);
 460
 461        rc = device_add_groups(hdev->dev, hl_dev_attr_groups);
 462        if (rc) {
 463                dev_err(hdev->dev,
 464                        "Failed to add groups to device, error %d\n", rc);
 465                return rc;
 466        }
 467
 468        return 0;
 469}
 470
 471void hl_sysfs_fini(struct hl_device *hdev)
 472{
 473        device_remove_groups(hdev->dev, hl_dev_attr_groups);
 474}
 475