xref: /linux/drivers/gpu/drm/xe/xe_vram_freq.c (revision 4ae3aeab32d7f37cde4724524f5525703e5a9b54)
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