1eb3ae0aaSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2*ac36fdb1SLee Jones /*
3b2a65138SFrank Haverkamp * IBM Accelerator Family 'GenWQE'
4b2a65138SFrank Haverkamp *
5b2a65138SFrank Haverkamp * (C) Copyright IBM Corp. 2013
6b2a65138SFrank Haverkamp *
7b2a65138SFrank Haverkamp * Author: Frank Haverkamp <haver@linux.vnet.ibm.com>
8b2a65138SFrank Haverkamp * Author: Joerg-Stephan Vogt <jsvogt@de.ibm.com>
926d8f6f1SFrank Haverkamp * Author: Michael Jung <mijung@gmx.net>
10b2a65138SFrank Haverkamp * Author: Michael Ruettger <michael@ibmra.de>
11b2a65138SFrank Haverkamp */
12b2a65138SFrank Haverkamp
13b2a65138SFrank Haverkamp /*
14b2a65138SFrank Haverkamp * Sysfs interfaces for the GenWQE card. There are attributes to query
15b2a65138SFrank Haverkamp * the version of the bitstream as well as some for the driver. For
16b2a65138SFrank Haverkamp * debugging, please also see the debugfs interfaces of this driver.
17b2a65138SFrank Haverkamp */
18b2a65138SFrank Haverkamp
19b2a65138SFrank Haverkamp #include <linux/kernel.h>
20b2a65138SFrank Haverkamp #include <linux/types.h>
21b2a65138SFrank Haverkamp #include <linux/module.h>
22b2a65138SFrank Haverkamp #include <linux/pci.h>
23b2a65138SFrank Haverkamp #include <linux/string.h>
24b2a65138SFrank Haverkamp #include <linux/fs.h>
25b2a65138SFrank Haverkamp #include <linux/sysfs.h>
26b2a65138SFrank Haverkamp #include <linux/ctype.h>
27b2a65138SFrank Haverkamp #include <linux/device.h>
28b2a65138SFrank Haverkamp
29b2a65138SFrank Haverkamp #include "card_base.h"
30b2a65138SFrank Haverkamp #include "card_ddcb.h"
31b2a65138SFrank Haverkamp
32b2a65138SFrank Haverkamp static const char * const genwqe_types[] = {
33b2a65138SFrank Haverkamp [GENWQE_TYPE_ALTERA_230] = "GenWQE4-230",
34b2a65138SFrank Haverkamp [GENWQE_TYPE_ALTERA_530] = "GenWQE4-530",
35b2a65138SFrank Haverkamp [GENWQE_TYPE_ALTERA_A4] = "GenWQE5-A4",
36b2a65138SFrank Haverkamp [GENWQE_TYPE_ALTERA_A7] = "GenWQE5-A7",
37b2a65138SFrank Haverkamp };
38b2a65138SFrank Haverkamp
status_show(struct device * dev,struct device_attribute * attr,char * buf)39b2a65138SFrank Haverkamp static ssize_t status_show(struct device *dev, struct device_attribute *attr,
40b2a65138SFrank Haverkamp char *buf)
41b2a65138SFrank Haverkamp {
42b2a65138SFrank Haverkamp struct genwqe_dev *cd = dev_get_drvdata(dev);
43b2a65138SFrank Haverkamp const char *cs[GENWQE_CARD_STATE_MAX] = { "unused", "used", "error" };
44b2a65138SFrank Haverkamp
45b2a65138SFrank Haverkamp return sprintf(buf, "%s\n", cs[cd->card_state]);
46b2a65138SFrank Haverkamp }
47b2a65138SFrank Haverkamp static DEVICE_ATTR_RO(status);
48b2a65138SFrank Haverkamp
appid_show(struct device * dev,struct device_attribute * attr,char * buf)49b2a65138SFrank Haverkamp static ssize_t appid_show(struct device *dev, struct device_attribute *attr,
50b2a65138SFrank Haverkamp char *buf)
51b2a65138SFrank Haverkamp {
52b2a65138SFrank Haverkamp char app_name[5];
53b2a65138SFrank Haverkamp struct genwqe_dev *cd = dev_get_drvdata(dev);
54b2a65138SFrank Haverkamp
55b2a65138SFrank Haverkamp genwqe_read_app_id(cd, app_name, sizeof(app_name));
56b2a65138SFrank Haverkamp return sprintf(buf, "%s\n", app_name);
57b2a65138SFrank Haverkamp }
58b2a65138SFrank Haverkamp static DEVICE_ATTR_RO(appid);
59b2a65138SFrank Haverkamp
version_show(struct device * dev,struct device_attribute * attr,char * buf)60b2a65138SFrank Haverkamp static ssize_t version_show(struct device *dev, struct device_attribute *attr,
61b2a65138SFrank Haverkamp char *buf)
62b2a65138SFrank Haverkamp {
63b2a65138SFrank Haverkamp u64 slu_id, app_id;
64b2a65138SFrank Haverkamp struct genwqe_dev *cd = dev_get_drvdata(dev);
65b2a65138SFrank Haverkamp
66b2a65138SFrank Haverkamp slu_id = __genwqe_readq(cd, IO_SLU_UNITCFG);
67b2a65138SFrank Haverkamp app_id = __genwqe_readq(cd, IO_APP_UNITCFG);
68b2a65138SFrank Haverkamp
69b2a65138SFrank Haverkamp return sprintf(buf, "%016llx.%016llx\n", slu_id, app_id);
70b2a65138SFrank Haverkamp }
71b2a65138SFrank Haverkamp static DEVICE_ATTR_RO(version);
72b2a65138SFrank Haverkamp
type_show(struct device * dev,struct device_attribute * attr,char * buf)73b2a65138SFrank Haverkamp static ssize_t type_show(struct device *dev, struct device_attribute *attr,
74b2a65138SFrank Haverkamp char *buf)
75b2a65138SFrank Haverkamp {
76b2a65138SFrank Haverkamp u8 card_type;
77b2a65138SFrank Haverkamp struct genwqe_dev *cd = dev_get_drvdata(dev);
78b2a65138SFrank Haverkamp
79b2a65138SFrank Haverkamp card_type = genwqe_card_type(cd);
80b2a65138SFrank Haverkamp return sprintf(buf, "%s\n", (card_type >= ARRAY_SIZE(genwqe_types)) ?
81b2a65138SFrank Haverkamp "invalid" : genwqe_types[card_type]);
82b2a65138SFrank Haverkamp }
83b2a65138SFrank Haverkamp static DEVICE_ATTR_RO(type);
84b2a65138SFrank Haverkamp
tempsens_show(struct device * dev,struct device_attribute * attr,char * buf)85b2a65138SFrank Haverkamp static ssize_t tempsens_show(struct device *dev, struct device_attribute *attr,
86b2a65138SFrank Haverkamp char *buf)
87b2a65138SFrank Haverkamp {
88b2a65138SFrank Haverkamp u64 tempsens;
89b2a65138SFrank Haverkamp struct genwqe_dev *cd = dev_get_drvdata(dev);
90b2a65138SFrank Haverkamp
91b2a65138SFrank Haverkamp tempsens = __genwqe_readq(cd, IO_SLU_TEMPERATURE_SENSOR);
92b2a65138SFrank Haverkamp return sprintf(buf, "%016llx\n", tempsens);
93b2a65138SFrank Haverkamp }
94b2a65138SFrank Haverkamp static DEVICE_ATTR_RO(tempsens);
95b2a65138SFrank Haverkamp
freerunning_timer_show(struct device * dev,struct device_attribute * attr,char * buf)96b2a65138SFrank Haverkamp static ssize_t freerunning_timer_show(struct device *dev,
97b2a65138SFrank Haverkamp struct device_attribute *attr,
98b2a65138SFrank Haverkamp char *buf)
99b2a65138SFrank Haverkamp {
100b2a65138SFrank Haverkamp u64 t;
101b2a65138SFrank Haverkamp struct genwqe_dev *cd = dev_get_drvdata(dev);
102b2a65138SFrank Haverkamp
103b2a65138SFrank Haverkamp t = __genwqe_readq(cd, IO_SLC_FREE_RUNNING_TIMER);
104b2a65138SFrank Haverkamp return sprintf(buf, "%016llx\n", t);
105b2a65138SFrank Haverkamp }
106b2a65138SFrank Haverkamp static DEVICE_ATTR_RO(freerunning_timer);
107b2a65138SFrank Haverkamp
queue_working_time_show(struct device * dev,struct device_attribute * attr,char * buf)108b2a65138SFrank Haverkamp static ssize_t queue_working_time_show(struct device *dev,
109b2a65138SFrank Haverkamp struct device_attribute *attr,
110b2a65138SFrank Haverkamp char *buf)
111b2a65138SFrank Haverkamp {
112b2a65138SFrank Haverkamp u64 t;
113b2a65138SFrank Haverkamp struct genwqe_dev *cd = dev_get_drvdata(dev);
114b2a65138SFrank Haverkamp
115b2a65138SFrank Haverkamp t = __genwqe_readq(cd, IO_SLC_QUEUE_WTIME);
116b2a65138SFrank Haverkamp return sprintf(buf, "%016llx\n", t);
117b2a65138SFrank Haverkamp }
118b2a65138SFrank Haverkamp static DEVICE_ATTR_RO(queue_working_time);
119b2a65138SFrank Haverkamp
base_clock_show(struct device * dev,struct device_attribute * attr,char * buf)120b2a65138SFrank Haverkamp static ssize_t base_clock_show(struct device *dev,
121b2a65138SFrank Haverkamp struct device_attribute *attr,
122b2a65138SFrank Haverkamp char *buf)
123b2a65138SFrank Haverkamp {
124b2a65138SFrank Haverkamp u64 base_clock;
125b2a65138SFrank Haverkamp struct genwqe_dev *cd = dev_get_drvdata(dev);
126b2a65138SFrank Haverkamp
127b2a65138SFrank Haverkamp base_clock = genwqe_base_clock_frequency(cd);
128b2a65138SFrank Haverkamp return sprintf(buf, "%lld\n", base_clock);
129b2a65138SFrank Haverkamp }
130b2a65138SFrank Haverkamp static DEVICE_ATTR_RO(base_clock);
131b2a65138SFrank Haverkamp
132*ac36fdb1SLee Jones /*
133b2a65138SFrank Haverkamp * curr_bitstream_show() - Show the current bitstream id
134b2a65138SFrank Haverkamp *
135b2a65138SFrank Haverkamp * There is a bug in some old versions of the CPLD which selects the
136b2a65138SFrank Haverkamp * bitstream, which causes the IO_SLU_BITSTREAM register to report
137b2a65138SFrank Haverkamp * unreliable data in very rare cases. This makes this sysfs
138b2a65138SFrank Haverkamp * unreliable up to the point were a new CPLD version is being used.
139b2a65138SFrank Haverkamp *
140b2a65138SFrank Haverkamp * Unfortunately there is no automatic way yet to query the CPLD
141b2a65138SFrank Haverkamp * version, such that you need to manually ensure via programming
142b2a65138SFrank Haverkamp * tools that you have a recent version of the CPLD software.
143b2a65138SFrank Haverkamp *
144b2a65138SFrank Haverkamp * The proposed circumvention is to use a special recovery bitstream
145b2a65138SFrank Haverkamp * on the backup partition (0) to identify problems while loading the
146b2a65138SFrank Haverkamp * image.
147b2a65138SFrank Haverkamp */
curr_bitstream_show(struct device * dev,struct device_attribute * attr,char * buf)148b2a65138SFrank Haverkamp static ssize_t curr_bitstream_show(struct device *dev,
149b2a65138SFrank Haverkamp struct device_attribute *attr, char *buf)
150b2a65138SFrank Haverkamp {
151b2a65138SFrank Haverkamp int curr_bitstream;
152b2a65138SFrank Haverkamp struct genwqe_dev *cd = dev_get_drvdata(dev);
153b2a65138SFrank Haverkamp
154b2a65138SFrank Haverkamp curr_bitstream = __genwqe_readq(cd, IO_SLU_BITSTREAM) & 0x1;
155b2a65138SFrank Haverkamp return sprintf(buf, "%d\n", curr_bitstream);
156b2a65138SFrank Haverkamp }
157b2a65138SFrank Haverkamp static DEVICE_ATTR_RO(curr_bitstream);
158b2a65138SFrank Haverkamp
159*ac36fdb1SLee Jones /*
160b2a65138SFrank Haverkamp * next_bitstream_show() - Show the next activated bitstream
161b2a65138SFrank Haverkamp *
162b2a65138SFrank Haverkamp * IO_SLC_CFGREG_SOFTRESET: This register can only be accessed by the PF.
163b2a65138SFrank Haverkamp */
next_bitstream_show(struct device * dev,struct device_attribute * attr,char * buf)164b2a65138SFrank Haverkamp static ssize_t next_bitstream_show(struct device *dev,
165b2a65138SFrank Haverkamp struct device_attribute *attr, char *buf)
166b2a65138SFrank Haverkamp {
167b2a65138SFrank Haverkamp int next_bitstream;
168b2a65138SFrank Haverkamp struct genwqe_dev *cd = dev_get_drvdata(dev);
169b2a65138SFrank Haverkamp
170b2a65138SFrank Haverkamp switch ((cd->softreset & 0xc) >> 2) {
171b2a65138SFrank Haverkamp case 0x2:
172b2a65138SFrank Haverkamp next_bitstream = 0;
173b2a65138SFrank Haverkamp break;
174b2a65138SFrank Haverkamp case 0x3:
175b2a65138SFrank Haverkamp next_bitstream = 1;
176b2a65138SFrank Haverkamp break;
177b2a65138SFrank Haverkamp default:
178b2a65138SFrank Haverkamp next_bitstream = -1;
179b2a65138SFrank Haverkamp break; /* error */
180b2a65138SFrank Haverkamp }
181b2a65138SFrank Haverkamp return sprintf(buf, "%d\n", next_bitstream);
182b2a65138SFrank Haverkamp }
183b2a65138SFrank Haverkamp
next_bitstream_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)184b2a65138SFrank Haverkamp static ssize_t next_bitstream_store(struct device *dev,
185b2a65138SFrank Haverkamp struct device_attribute *attr,
186b2a65138SFrank Haverkamp const char *buf, size_t count)
187b2a65138SFrank Haverkamp {
188b2a65138SFrank Haverkamp int partition;
189b2a65138SFrank Haverkamp struct genwqe_dev *cd = dev_get_drvdata(dev);
190b2a65138SFrank Haverkamp
191b2a65138SFrank Haverkamp if (kstrtoint(buf, 0, &partition) < 0)
192b2a65138SFrank Haverkamp return -EINVAL;
193b2a65138SFrank Haverkamp
194b2a65138SFrank Haverkamp switch (partition) {
195b2a65138SFrank Haverkamp case 0x0:
196b2a65138SFrank Haverkamp cd->softreset = 0x78;
197b2a65138SFrank Haverkamp break;
198b2a65138SFrank Haverkamp case 0x1:
199b2a65138SFrank Haverkamp cd->softreset = 0x7c;
200b2a65138SFrank Haverkamp break;
201b2a65138SFrank Haverkamp default:
202b2a65138SFrank Haverkamp return -EINVAL;
203b2a65138SFrank Haverkamp }
204b2a65138SFrank Haverkamp
205b2a65138SFrank Haverkamp __genwqe_writeq(cd, IO_SLC_CFGREG_SOFTRESET, cd->softreset);
206b2a65138SFrank Haverkamp return count;
207b2a65138SFrank Haverkamp }
208b2a65138SFrank Haverkamp static DEVICE_ATTR_RW(next_bitstream);
209b2a65138SFrank Haverkamp
reload_bitstream_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)210c1f732adSKleber Sacilotto de Souza static ssize_t reload_bitstream_store(struct device *dev,
211c1f732adSKleber Sacilotto de Souza struct device_attribute *attr,
212c1f732adSKleber Sacilotto de Souza const char *buf, size_t count)
213c1f732adSKleber Sacilotto de Souza {
214c1f732adSKleber Sacilotto de Souza int reload;
215c1f732adSKleber Sacilotto de Souza struct genwqe_dev *cd = dev_get_drvdata(dev);
216c1f732adSKleber Sacilotto de Souza
217c1f732adSKleber Sacilotto de Souza if (kstrtoint(buf, 0, &reload) < 0)
218c1f732adSKleber Sacilotto de Souza return -EINVAL;
219c1f732adSKleber Sacilotto de Souza
220c1f732adSKleber Sacilotto de Souza if (reload == 0x1) {
221c1f732adSKleber Sacilotto de Souza if (cd->card_state == GENWQE_CARD_UNUSED ||
222c1f732adSKleber Sacilotto de Souza cd->card_state == GENWQE_CARD_USED)
223c1f732adSKleber Sacilotto de Souza cd->card_state = GENWQE_CARD_RELOAD_BITSTREAM;
224c1f732adSKleber Sacilotto de Souza else
225c1f732adSKleber Sacilotto de Souza return -EIO;
226c1f732adSKleber Sacilotto de Souza } else {
227c1f732adSKleber Sacilotto de Souza return -EINVAL;
228c1f732adSKleber Sacilotto de Souza }
229c1f732adSKleber Sacilotto de Souza
230c1f732adSKleber Sacilotto de Souza return count;
231c1f732adSKleber Sacilotto de Souza }
232c1f732adSKleber Sacilotto de Souza static DEVICE_ATTR_WO(reload_bitstream);
233c1f732adSKleber Sacilotto de Souza
234b2a65138SFrank Haverkamp /*
235b2a65138SFrank Haverkamp * Create device_attribute structures / params: name, mode, show, store
236b2a65138SFrank Haverkamp * additional flag if valid in VF
237b2a65138SFrank Haverkamp */
238b2a65138SFrank Haverkamp static struct attribute *genwqe_attributes[] = {
239b2a65138SFrank Haverkamp &dev_attr_tempsens.attr,
240b2a65138SFrank Haverkamp &dev_attr_next_bitstream.attr,
241b2a65138SFrank Haverkamp &dev_attr_curr_bitstream.attr,
242b2a65138SFrank Haverkamp &dev_attr_base_clock.attr,
243b2a65138SFrank Haverkamp &dev_attr_type.attr,
244b2a65138SFrank Haverkamp &dev_attr_version.attr,
245b2a65138SFrank Haverkamp &dev_attr_appid.attr,
246b2a65138SFrank Haverkamp &dev_attr_status.attr,
247b2a65138SFrank Haverkamp &dev_attr_freerunning_timer.attr,
248b2a65138SFrank Haverkamp &dev_attr_queue_working_time.attr,
249c1f732adSKleber Sacilotto de Souza &dev_attr_reload_bitstream.attr,
250b2a65138SFrank Haverkamp NULL,
251b2a65138SFrank Haverkamp };
252b2a65138SFrank Haverkamp
253b2a65138SFrank Haverkamp static struct attribute *genwqe_normal_attributes[] = {
254b2a65138SFrank Haverkamp &dev_attr_type.attr,
255b2a65138SFrank Haverkamp &dev_attr_version.attr,
256b2a65138SFrank Haverkamp &dev_attr_appid.attr,
257b2a65138SFrank Haverkamp &dev_attr_status.attr,
258b2a65138SFrank Haverkamp &dev_attr_freerunning_timer.attr,
259b2a65138SFrank Haverkamp &dev_attr_queue_working_time.attr,
260b2a65138SFrank Haverkamp NULL,
261b2a65138SFrank Haverkamp };
262b2a65138SFrank Haverkamp
263*ac36fdb1SLee Jones /*
264b2a65138SFrank Haverkamp * genwqe_is_visible() - Determine if sysfs attribute should be visible or not
265b2a65138SFrank Haverkamp *
266b2a65138SFrank Haverkamp * VFs have restricted mmio capabilities, so not all sysfs entries
267b2a65138SFrank Haverkamp * are allowed in VFs.
268b2a65138SFrank Haverkamp */
genwqe_is_visible(struct kobject * kobj,struct attribute * attr,int n)269b2a65138SFrank Haverkamp static umode_t genwqe_is_visible(struct kobject *kobj,
270b2a65138SFrank Haverkamp struct attribute *attr, int n)
271b2a65138SFrank Haverkamp {
272b2a65138SFrank Haverkamp unsigned int j;
2736908b45eSGeliang Tang struct device *dev = kobj_to_dev(kobj);
274b2a65138SFrank Haverkamp struct genwqe_dev *cd = dev_get_drvdata(dev);
275b2a65138SFrank Haverkamp umode_t mode = attr->mode;
276b2a65138SFrank Haverkamp
277b2a65138SFrank Haverkamp if (genwqe_is_privileged(cd))
278b2a65138SFrank Haverkamp return mode;
279b2a65138SFrank Haverkamp
280b2a65138SFrank Haverkamp for (j = 0; genwqe_normal_attributes[j] != NULL; j++)
281b2a65138SFrank Haverkamp if (genwqe_normal_attributes[j] == attr)
282b2a65138SFrank Haverkamp return mode;
283b2a65138SFrank Haverkamp
284b2a65138SFrank Haverkamp return 0;
285b2a65138SFrank Haverkamp }
286b2a65138SFrank Haverkamp
287b2a65138SFrank Haverkamp static struct attribute_group genwqe_attribute_group = {
288b2a65138SFrank Haverkamp .is_visible = genwqe_is_visible,
289b2a65138SFrank Haverkamp .attrs = genwqe_attributes,
290b2a65138SFrank Haverkamp };
291b2a65138SFrank Haverkamp
292b2a65138SFrank Haverkamp const struct attribute_group *genwqe_attribute_groups[] = {
293b2a65138SFrank Haverkamp &genwqe_attribute_group,
294b2a65138SFrank Haverkamp NULL,
295b2a65138SFrank Haverkamp };
296