1*4ae3aeabSSujaritha Sundaresan // SPDX-License-Identifier: MIT 2*4ae3aeabSSujaritha Sundaresan /* 3*4ae3aeabSSujaritha Sundaresan * Copyright © 2024 Intel Corporation 4*4ae3aeabSSujaritha Sundaresan */ 5*4ae3aeabSSujaritha Sundaresan #include <linux/sysfs.h> 6*4ae3aeabSSujaritha Sundaresan #include <drm/drm_managed.h> 7*4ae3aeabSSujaritha Sundaresan 8*4ae3aeabSSujaritha Sundaresan #include "xe_gt_types.h" 9*4ae3aeabSSujaritha Sundaresan #include "xe_pcode.h" 10*4ae3aeabSSujaritha Sundaresan #include "xe_pcode_api.h" 11*4ae3aeabSSujaritha Sundaresan #include "xe_tile.h" 12*4ae3aeabSSujaritha Sundaresan #include "xe_tile_sysfs.h" 13*4ae3aeabSSujaritha Sundaresan #include "xe_vram_freq.h" 14*4ae3aeabSSujaritha Sundaresan 15*4ae3aeabSSujaritha Sundaresan /** 16*4ae3aeabSSujaritha Sundaresan * DOC: Xe VRAM freq 17*4ae3aeabSSujaritha Sundaresan * 18*4ae3aeabSSujaritha Sundaresan * Provides sysfs entries for vram frequency in tile 19*4ae3aeabSSujaritha Sundaresan * 20*4ae3aeabSSujaritha Sundaresan * device/tile#/memory/freq0/max_freq - This is maximum frequency. This value is read-only as it 21*4ae3aeabSSujaritha Sundaresan * is the fixed fuse point P0. It is not the system 22*4ae3aeabSSujaritha Sundaresan * configuration. 23*4ae3aeabSSujaritha Sundaresan * device/tile#/memory/freq0/min_freq - This is minimum frequency. This value is read-only as it 24*4ae3aeabSSujaritha Sundaresan * is the fixed fuse point PN. It is not the system 25*4ae3aeabSSujaritha Sundaresan * configuration. 26*4ae3aeabSSujaritha Sundaresan */ 27*4ae3aeabSSujaritha Sundaresan 28*4ae3aeabSSujaritha Sundaresan static struct xe_tile *dev_to_tile(struct device *dev) 29*4ae3aeabSSujaritha Sundaresan { 30*4ae3aeabSSujaritha Sundaresan return kobj_to_tile(dev->kobj.parent); 31*4ae3aeabSSujaritha Sundaresan } 32*4ae3aeabSSujaritha Sundaresan 33*4ae3aeabSSujaritha Sundaresan static ssize_t max_freq_show(struct device *dev, struct device_attribute *attr, 34*4ae3aeabSSujaritha Sundaresan char *buf) 35*4ae3aeabSSujaritha Sundaresan { 36*4ae3aeabSSujaritha Sundaresan struct xe_tile *tile = dev_to_tile(dev); 37*4ae3aeabSSujaritha Sundaresan struct xe_gt *gt = tile->primary_gt; 38*4ae3aeabSSujaritha Sundaresan u32 val, mbox; 39*4ae3aeabSSujaritha Sundaresan int err; 40*4ae3aeabSSujaritha Sundaresan 41*4ae3aeabSSujaritha Sundaresan mbox = REG_FIELD_PREP(PCODE_MB_COMMAND, PCODE_FREQUENCY_CONFIG) 42*4ae3aeabSSujaritha Sundaresan | REG_FIELD_PREP(PCODE_MB_PARAM1, PCODE_MBOX_FC_SC_READ_FUSED_P0) 43*4ae3aeabSSujaritha Sundaresan | REG_FIELD_PREP(PCODE_MB_PARAM2, PCODE_MBOX_DOMAIN_HBM); 44*4ae3aeabSSujaritha Sundaresan 45*4ae3aeabSSujaritha Sundaresan err = xe_pcode_read(gt, mbox, &val, NULL); 46*4ae3aeabSSujaritha Sundaresan if (err) 47*4ae3aeabSSujaritha Sundaresan return err; 48*4ae3aeabSSujaritha Sundaresan 49*4ae3aeabSSujaritha Sundaresan /* data_out - Fused P0 for domain ID in units of 50 MHz */ 50*4ae3aeabSSujaritha Sundaresan val *= 50; 51*4ae3aeabSSujaritha Sundaresan 52*4ae3aeabSSujaritha Sundaresan return sysfs_emit(buf, "%u\n", val); 53*4ae3aeabSSujaritha Sundaresan } 54*4ae3aeabSSujaritha Sundaresan static DEVICE_ATTR_RO(max_freq); 55*4ae3aeabSSujaritha Sundaresan 56*4ae3aeabSSujaritha Sundaresan static ssize_t min_freq_show(struct device *dev, struct device_attribute *attr, 57*4ae3aeabSSujaritha Sundaresan char *buf) 58*4ae3aeabSSujaritha Sundaresan { 59*4ae3aeabSSujaritha Sundaresan struct xe_tile *tile = dev_to_tile(dev); 60*4ae3aeabSSujaritha Sundaresan struct xe_gt *gt = tile->primary_gt; 61*4ae3aeabSSujaritha Sundaresan u32 val, mbox; 62*4ae3aeabSSujaritha Sundaresan int err; 63*4ae3aeabSSujaritha Sundaresan 64*4ae3aeabSSujaritha Sundaresan mbox = REG_FIELD_PREP(PCODE_MB_COMMAND, PCODE_FREQUENCY_CONFIG) 65*4ae3aeabSSujaritha Sundaresan | REG_FIELD_PREP(PCODE_MB_PARAM1, PCODE_MBOX_FC_SC_READ_FUSED_PN) 66*4ae3aeabSSujaritha Sundaresan | REG_FIELD_PREP(PCODE_MB_PARAM2, PCODE_MBOX_DOMAIN_HBM); 67*4ae3aeabSSujaritha Sundaresan 68*4ae3aeabSSujaritha Sundaresan err = xe_pcode_read(gt, mbox, &val, NULL); 69*4ae3aeabSSujaritha Sundaresan if (err) 70*4ae3aeabSSujaritha Sundaresan return err; 71*4ae3aeabSSujaritha Sundaresan 72*4ae3aeabSSujaritha Sundaresan /* data_out - Fused Pn for domain ID in units of 50 MHz */ 73*4ae3aeabSSujaritha Sundaresan val *= 50; 74*4ae3aeabSSujaritha Sundaresan 75*4ae3aeabSSujaritha Sundaresan return sysfs_emit(buf, "%u\n", val); 76*4ae3aeabSSujaritha Sundaresan } 77*4ae3aeabSSujaritha Sundaresan static DEVICE_ATTR_RO(min_freq); 78*4ae3aeabSSujaritha Sundaresan 79*4ae3aeabSSujaritha Sundaresan static struct attribute *freq_attrs[] = { 80*4ae3aeabSSujaritha Sundaresan &dev_attr_max_freq.attr, 81*4ae3aeabSSujaritha Sundaresan &dev_attr_min_freq.attr, 82*4ae3aeabSSujaritha Sundaresan NULL 83*4ae3aeabSSujaritha Sundaresan }; 84*4ae3aeabSSujaritha Sundaresan 85*4ae3aeabSSujaritha Sundaresan static const struct attribute_group freq_group_attrs = { 86*4ae3aeabSSujaritha Sundaresan .name = "freq0", 87*4ae3aeabSSujaritha Sundaresan .attrs = freq_attrs, 88*4ae3aeabSSujaritha Sundaresan }; 89*4ae3aeabSSujaritha Sundaresan 90*4ae3aeabSSujaritha Sundaresan static void vram_freq_sysfs_fini(struct drm_device *drm, void *arg) 91*4ae3aeabSSujaritha Sundaresan { 92*4ae3aeabSSujaritha Sundaresan struct kobject *kobj = arg; 93*4ae3aeabSSujaritha Sundaresan 94*4ae3aeabSSujaritha Sundaresan sysfs_remove_group(kobj, &freq_group_attrs); 95*4ae3aeabSSujaritha Sundaresan kobject_put(kobj); 96*4ae3aeabSSujaritha Sundaresan } 97*4ae3aeabSSujaritha Sundaresan 98*4ae3aeabSSujaritha Sundaresan /* 99*4ae3aeabSSujaritha Sundaresan * xe_vram_freq_init - Initialize vram frequency component 100*4ae3aeabSSujaritha Sundaresan * @tile: Xe Tile object 101*4ae3aeabSSujaritha Sundaresan * 102*4ae3aeabSSujaritha Sundaresan * It needs to be initialized after the main tile component is ready 103*4ae3aeabSSujaritha Sundaresan */ 104*4ae3aeabSSujaritha Sundaresan 105*4ae3aeabSSujaritha Sundaresan void xe_vram_freq_sysfs_init(struct xe_tile *tile) 106*4ae3aeabSSujaritha Sundaresan { 107*4ae3aeabSSujaritha Sundaresan struct xe_device *xe = tile_to_xe(tile); 108*4ae3aeabSSujaritha Sundaresan struct kobject *kobj; 109*4ae3aeabSSujaritha Sundaresan int err; 110*4ae3aeabSSujaritha Sundaresan 111*4ae3aeabSSujaritha Sundaresan if (xe->info.platform != XE_PVC) 112*4ae3aeabSSujaritha Sundaresan return; 113*4ae3aeabSSujaritha Sundaresan 114*4ae3aeabSSujaritha Sundaresan kobj = kobject_create_and_add("memory", tile->sysfs); 115*4ae3aeabSSujaritha Sundaresan if (!kobj) 116*4ae3aeabSSujaritha Sundaresan drm_warn(&xe->drm, "failed to add memory directory, err: %d\n", -ENOMEM); 117*4ae3aeabSSujaritha Sundaresan 118*4ae3aeabSSujaritha Sundaresan err = sysfs_create_group(kobj, &freq_group_attrs); 119*4ae3aeabSSujaritha Sundaresan if (err) { 120*4ae3aeabSSujaritha Sundaresan kobject_put(kobj); 121*4ae3aeabSSujaritha Sundaresan drm_warn(&xe->drm, "failed to register vram freq sysfs, err: %d\n", err); 122*4ae3aeabSSujaritha Sundaresan return; 123*4ae3aeabSSujaritha Sundaresan } 124*4ae3aeabSSujaritha Sundaresan 125*4ae3aeabSSujaritha Sundaresan err = drmm_add_action_or_reset(&xe->drm, vram_freq_sysfs_fini, kobj); 126*4ae3aeabSSujaritha Sundaresan if (err) 127*4ae3aeabSSujaritha Sundaresan drm_warn(&xe->drm, "%s: drmm_add_action_or_reset failed, err: %d\n", 128*4ae3aeabSSujaritha Sundaresan __func__, err); 129*4ae3aeabSSujaritha Sundaresan } 130