Linux Audio

Check our new training course

Loading...
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Ampere Computing SoC's SMpro Error Monitoring Driver
  4 *
  5 * Copyright (c) 2022, Ampere Computing LLC
  6 *
  7 */
  8
  9#include <linux/mod_devicetable.h>
 10#include <linux/module.h>
 11#include <linux/platform_device.h>
 12#include <linux/regmap.h>
 13
 14/* GPI RAS Error Registers */
 15#define GPI_RAS_ERR		0x7E
 16
 17/* Core and L2C Error Registers */
 18#define CORE_CE_ERR_CNT		0x80
 19#define CORE_CE_ERR_LEN		0x81
 20#define CORE_CE_ERR_DATA	0x82
 21#define CORE_UE_ERR_CNT		0x83
 22#define CORE_UE_ERR_LEN		0x84
 23#define CORE_UE_ERR_DATA	0x85
 24
 25/* Memory Error Registers */
 26#define MEM_CE_ERR_CNT		0x90
 27#define MEM_CE_ERR_LEN		0x91
 28#define MEM_CE_ERR_DATA		0x92
 29#define MEM_UE_ERR_CNT		0x93
 30#define MEM_UE_ERR_LEN		0x94
 31#define MEM_UE_ERR_DATA		0x95
 32
 33/* RAS Error/Warning Registers */
 34#define ERR_SMPRO_TYPE		0xA0
 35#define ERR_PMPRO_TYPE		0xA1
 36#define ERR_SMPRO_INFO_LO	0xA2
 37#define ERR_SMPRO_INFO_HI	0xA3
 38#define ERR_SMPRO_DATA_LO	0xA4
 39#define ERR_SMPRO_DATA_HI	0xA5
 40#define WARN_SMPRO_INFO_LO	0xAA
 41#define WARN_SMPRO_INFO_HI	0xAB
 42#define ERR_PMPRO_INFO_LO	0xA6
 43#define ERR_PMPRO_INFO_HI	0xA7
 44#define ERR_PMPRO_DATA_LO	0xA8
 45#define ERR_PMPRO_DATA_HI	0xA9
 46#define WARN_PMPRO_INFO_LO	0xAC
 47#define WARN_PMPRO_INFO_HI	0xAD
 48
 49/* Boot Stage Register */
 50#define BOOTSTAGE		0xB0
 51#define DIMM_SYNDROME_SEL	0xB4
 52#define DIMM_SYNDROME_ERR	0xB5
 53#define DIMM_SYNDROME_STAGE	4
 54
 55/* PCIE Error Registers */
 56#define PCIE_CE_ERR_CNT		0xC0
 57#define PCIE_CE_ERR_LEN		0xC1
 58#define PCIE_CE_ERR_DATA	0xC2
 59#define PCIE_UE_ERR_CNT		0xC3
 60#define PCIE_UE_ERR_LEN		0xC4
 61#define PCIE_UE_ERR_DATA	0xC5
 62
 63/* Other Error Registers */
 64#define OTHER_CE_ERR_CNT	0xD0
 65#define OTHER_CE_ERR_LEN	0xD1
 66#define OTHER_CE_ERR_DATA	0xD2
 67#define OTHER_UE_ERR_CNT	0xD8
 68#define OTHER_UE_ERR_LEN	0xD9
 69#define OTHER_UE_ERR_DATA	0xDA
 70
 71/* Event Data Registers */
 72#define VRD_WARN_FAULT_EVENT_DATA	0x78
 73#define VRD_HOT_EVENT_DATA		0x79
 74#define DIMM_HOT_EVENT_DATA		0x7A
 75#define DIMM_2X_REFRESH_EVENT_DATA	0x96
 76
 77#define MAX_READ_BLOCK_LENGTH	48
 78
 79#define RAS_SMPRO_ERR		0
 80#define RAS_PMPRO_ERR		1
 81
 82enum RAS_48BYTES_ERR_TYPES {
 83	CORE_CE_ERR,
 84	CORE_UE_ERR,
 85	MEM_CE_ERR,
 86	MEM_UE_ERR,
 87	PCIE_CE_ERR,
 88	PCIE_UE_ERR,
 89	OTHER_CE_ERR,
 90	OTHER_UE_ERR,
 91	NUM_48BYTES_ERR_TYPE,
 92};
 93
 94struct smpro_error_hdr {
 95	u8 count;	/* Number of the RAS errors */
 96	u8 len;		/* Number of data bytes */
 97	u8 data;	/* Start of 48-byte data */
 98	u8 max_cnt;	/* Max num of errors */
 99};
100
101/*
102 * Included Address of registers to get Count, Length of data and Data
103 * of the 48 bytes error data
104 */
105static struct smpro_error_hdr smpro_error_table[] = {
106	[CORE_CE_ERR] = {
107		.count = CORE_CE_ERR_CNT,
108		.len = CORE_CE_ERR_LEN,
109		.data = CORE_CE_ERR_DATA,
110		.max_cnt = 32
111	},
112	[CORE_UE_ERR] = {
113		.count = CORE_UE_ERR_CNT,
114		.len = CORE_UE_ERR_LEN,
115		.data = CORE_UE_ERR_DATA,
116		.max_cnt = 32
117	},
118	[MEM_CE_ERR] = {
119		.count = MEM_CE_ERR_CNT,
120		.len = MEM_CE_ERR_LEN,
121		.data = MEM_CE_ERR_DATA,
122		.max_cnt = 16
123	},
124	[MEM_UE_ERR] = {
125		.count = MEM_UE_ERR_CNT,
126		.len = MEM_UE_ERR_LEN,
127		.data = MEM_UE_ERR_DATA,
128		.max_cnt = 16
129	},
130	[PCIE_CE_ERR] = {
131		.count = PCIE_CE_ERR_CNT,
132		.len = PCIE_CE_ERR_LEN,
133		.data = PCIE_CE_ERR_DATA,
134		.max_cnt = 96
135	},
136	[PCIE_UE_ERR] = {
137		.count = PCIE_UE_ERR_CNT,
138		.len = PCIE_UE_ERR_LEN,
139		.data = PCIE_UE_ERR_DATA,
140		.max_cnt = 96
141	},
142	[OTHER_CE_ERR] = {
143		.count = OTHER_CE_ERR_CNT,
144		.len = OTHER_CE_ERR_LEN,
145		.data = OTHER_CE_ERR_DATA,
146		.max_cnt = 8
147	},
148	[OTHER_UE_ERR] = {
149		.count = OTHER_UE_ERR_CNT,
150		.len = OTHER_UE_ERR_LEN,
151		.data = OTHER_UE_ERR_DATA,
152		.max_cnt = 8
153	},
154};
155
156/*
157 * List of SCP registers which are used to get
158 * one type of RAS Internal errors.
159 */
160struct smpro_int_error_hdr {
161	u8 type;
162	u8 info_l;
163	u8 info_h;
164	u8 data_l;
165	u8 data_h;
166	u8 warn_l;
167	u8 warn_h;
168};
169
170static struct smpro_int_error_hdr list_smpro_int_error_hdr[] = {
171	[RAS_SMPRO_ERR] = {
172		.type = ERR_SMPRO_TYPE,
173		.info_l = ERR_SMPRO_INFO_LO,
174		.info_h = ERR_SMPRO_INFO_HI,
175		.data_l = ERR_SMPRO_DATA_LO,
176		.data_h = ERR_SMPRO_DATA_HI,
177		.warn_l = WARN_SMPRO_INFO_LO,
178		.warn_h = WARN_SMPRO_INFO_HI,
179	},
180	[RAS_PMPRO_ERR] = {
181		.type = ERR_PMPRO_TYPE,
182		.info_l = ERR_PMPRO_INFO_LO,
183		.info_h = ERR_PMPRO_INFO_HI,
184		.data_l = ERR_PMPRO_DATA_LO,
185		.data_h = ERR_PMPRO_DATA_HI,
186		.warn_l = WARN_PMPRO_INFO_LO,
187		.warn_h = WARN_PMPRO_INFO_HI,
188	},
189};
190
191struct smpro_errmon {
192	struct regmap *regmap;
193};
194
195enum EVENT_TYPES {
196	VRD_WARN_FAULT_EVENT,
197	VRD_HOT_EVENT,
198	DIMM_HOT_EVENT,
199	DIMM_2X_REFRESH_EVENT,
200	NUM_EVENTS_TYPE,
201};
202
203/* Included Address of event source and data registers */
204static u8 smpro_event_table[NUM_EVENTS_TYPE] = {
205	VRD_WARN_FAULT_EVENT_DATA,
206	VRD_HOT_EVENT_DATA,
207	DIMM_HOT_EVENT_DATA,
208	DIMM_2X_REFRESH_EVENT_DATA,
209};
210
211static ssize_t smpro_event_data_read(struct device *dev,
212				     struct device_attribute *da, char *buf,
213				     int channel)
214{
215	struct smpro_errmon *errmon = dev_get_drvdata(dev);
216	s32 event_data;
217	int ret;
218
219	ret = regmap_read(errmon->regmap, smpro_event_table[channel], &event_data);
220	if (ret)
221		return ret;
222	/* Clear event after read */
223	if (event_data != 0)
224		regmap_write(errmon->regmap, smpro_event_table[channel], event_data);
225
226	return sysfs_emit(buf, "%04x\n", event_data);
227}
228
229static ssize_t smpro_overflow_data_read(struct device *dev, struct device_attribute *da,
230					char *buf, int channel)
231{
232	struct smpro_errmon *errmon = dev_get_drvdata(dev);
233	struct smpro_error_hdr *err_info;
234	s32 err_count;
235	int ret;
236
237	err_info = &smpro_error_table[channel];
238
239	ret = regmap_read(errmon->regmap, err_info->count, &err_count);
240	if (ret)
241		return ret;
242
243	/* Bit 8 indicates the overflow status */
244	return sysfs_emit(buf, "%d\n", (err_count & BIT(8)) ? 1 : 0);
245}
246
247static ssize_t smpro_error_data_read(struct device *dev, struct device_attribute *da,
248				     char *buf, int channel)
249{
250	struct smpro_errmon *errmon = dev_get_drvdata(dev);
251	unsigned char err_data[MAX_READ_BLOCK_LENGTH];
252	struct smpro_error_hdr *err_info;
253	s32 err_count, err_length;
254	int ret;
255
256	err_info = &smpro_error_table[channel];
257
258	ret = regmap_read(errmon->regmap, err_info->count, &err_count);
259	/* Error count is the low byte */
260	err_count &= 0xff;
261	if (ret || !err_count || err_count > err_info->max_cnt)
262		return ret;
263
264	ret = regmap_read(errmon->regmap, err_info->len, &err_length);
265	if (ret || err_length <= 0)
266		return ret;
267
268	if (err_length > MAX_READ_BLOCK_LENGTH)
269		err_length = MAX_READ_BLOCK_LENGTH;
270
271	memset(err_data, 0x00, MAX_READ_BLOCK_LENGTH);
272	ret = regmap_noinc_read(errmon->regmap, err_info->data, err_data, err_length);
273	if (ret < 0)
274		return ret;
275
276	/* clear the error */
277	ret = regmap_write(errmon->regmap, err_info->count, 0x100);
278	if (ret)
279		return ret;
280	/*
281	 * The output of Core/Memory/PCIe/Others UE/CE errors follows the format
282	 * specified in section 5.8.1 CE/UE Error Data record in
283	 * Altra SOC BMC Interface specification.
284	 */
285	return sysfs_emit(buf, "%*phN\n", MAX_READ_BLOCK_LENGTH, err_data);
286}
287
288/*
289 * Output format:
290 * <4-byte hex value of error info><4-byte hex value of error extensive data>
291 * Where:
292 *   + error info : The error information
293 *   + error data : Extensive data (32 bits)
294 * Reference to section 5.10 RAS Internal Error Register Definition in
295 * Altra SOC BMC Interface specification
296 */
297static ssize_t smpro_internal_err_read(struct device *dev, struct device_attribute *da,
298				       char *buf, int channel)
299{
300	struct smpro_errmon *errmon = dev_get_drvdata(dev);
301	struct smpro_int_error_hdr *err_info;
302	unsigned int err[4] = { 0 };
303	unsigned int err_type;
304	unsigned int val;
305	int ret;
306
307	/* read error status */
308	ret = regmap_read(errmon->regmap, GPI_RAS_ERR, &val);
309	if (ret)
310		return ret;
311
312	if ((channel == RAS_SMPRO_ERR && !(val & BIT(0))) ||
313	    (channel == RAS_PMPRO_ERR && !(val & BIT(1))))
314		return 0;
315
316	err_info = &list_smpro_int_error_hdr[channel];
317	ret = regmap_read(errmon->regmap, err_info->type, &val);
318	if (ret)
319		return ret;
320
321	err_type = (val & BIT(1)) ? BIT(1) :
322		   (val & BIT(2)) ? BIT(2) : 0;
323
324	if (!err_type)
325		return 0;
326
327	ret = regmap_read(errmon->regmap, err_info->info_l, err + 1);
328	if (ret)
329		return ret;
330
331	ret = regmap_read(errmon->regmap, err_info->info_h, err);
332	if (ret)
333		return ret;
334
335	if (err_type & BIT(2)) {
336		/* Error with data type */
337		ret = regmap_read(errmon->regmap, err_info->data_l, err + 3);
338		if (ret)
339			return ret;
340
341		ret = regmap_read(errmon->regmap, err_info->data_h, err + 2);
342		if (ret)
343			return ret;
344	}
345
346	/* clear the read errors */
347	ret = regmap_write(errmon->regmap, err_info->type, err_type);
348	if (ret)
349		return ret;
350
351	return sysfs_emit(buf, "%*phN\n", (int)sizeof(err), err);
352}
353
354/*
355 * Output format:
356 * <4-byte hex value of warining info>
357 * Reference to section 5.10 RAS Internal Error Register Definition in
358 * Altra SOC BMC Interface specification
359 */
360static ssize_t smpro_internal_warn_read(struct device *dev, struct device_attribute *da,
361					char *buf, int channel)
362{
363	struct smpro_errmon *errmon = dev_get_drvdata(dev);
364	struct smpro_int_error_hdr *err_info;
365	unsigned int warn[2] = { 0 };
366	unsigned int val;
367	int ret;
368
369	/* read error status */
370	ret = regmap_read(errmon->regmap, GPI_RAS_ERR, &val);
371	if (ret)
372		return ret;
373
374	if ((channel == RAS_SMPRO_ERR && !(val & BIT(0))) ||
375	    (channel == RAS_PMPRO_ERR && !(val & BIT(1))))
376		return 0;
377
378	err_info = &list_smpro_int_error_hdr[channel];
379	ret = regmap_read(errmon->regmap, err_info->type, &val);
380	if (ret)
381		return ret;
382
383	if (!(val & BIT(0)))
384		return 0;
385
386	ret = regmap_read(errmon->regmap, err_info->warn_l, warn + 1);
387	if (ret)
388		return ret;
389
390	ret = regmap_read(errmon->regmap, err_info->warn_h, warn);
391	if (ret)
392		return ret;
393
394	/* clear the warning */
395	ret = regmap_write(errmon->regmap, err_info->type, BIT(0));
396	if (ret)
397		return ret;
398
399	return sysfs_emit(buf, "%*phN\n", (int)sizeof(warn), warn);
400}
401
402#define ERROR_OVERFLOW_RO(_error, _index) \
403	static ssize_t overflow_##_error##_show(struct device *dev,            \
404						struct device_attribute *da,   \
405						char *buf)                     \
406	{                                                                      \
407		return smpro_overflow_data_read(dev, da, buf, _index);         \
408	}                                                                      \
409	static DEVICE_ATTR_RO(overflow_##_error)
410
411ERROR_OVERFLOW_RO(core_ce, CORE_CE_ERR);
412ERROR_OVERFLOW_RO(core_ue, CORE_UE_ERR);
413ERROR_OVERFLOW_RO(mem_ce, MEM_CE_ERR);
414ERROR_OVERFLOW_RO(mem_ue, MEM_UE_ERR);
415ERROR_OVERFLOW_RO(pcie_ce, PCIE_CE_ERR);
416ERROR_OVERFLOW_RO(pcie_ue, PCIE_UE_ERR);
417ERROR_OVERFLOW_RO(other_ce, OTHER_CE_ERR);
418ERROR_OVERFLOW_RO(other_ue, OTHER_UE_ERR);
419
420#define ERROR_RO(_error, _index) \
421	static ssize_t error_##_error##_show(struct device *dev,            \
422					     struct device_attribute *da,   \
423					     char *buf)                     \
424	{                                                                   \
425		return smpro_error_data_read(dev, da, buf, _index);         \
426	}                                                                   \
427	static DEVICE_ATTR_RO(error_##_error)
428
429ERROR_RO(core_ce, CORE_CE_ERR);
430ERROR_RO(core_ue, CORE_UE_ERR);
431ERROR_RO(mem_ce, MEM_CE_ERR);
432ERROR_RO(mem_ue, MEM_UE_ERR);
433ERROR_RO(pcie_ce, PCIE_CE_ERR);
434ERROR_RO(pcie_ue, PCIE_UE_ERR);
435ERROR_RO(other_ce, OTHER_CE_ERR);
436ERROR_RO(other_ue, OTHER_UE_ERR);
437
438static ssize_t error_smpro_show(struct device *dev, struct device_attribute *da, char *buf)
439{
440	return smpro_internal_err_read(dev, da, buf, RAS_SMPRO_ERR);
441}
442static DEVICE_ATTR_RO(error_smpro);
443
444static ssize_t error_pmpro_show(struct device *dev, struct device_attribute *da, char *buf)
445{
446	return smpro_internal_err_read(dev, da, buf, RAS_PMPRO_ERR);
447}
448static DEVICE_ATTR_RO(error_pmpro);
449
450static ssize_t warn_smpro_show(struct device *dev, struct device_attribute *da, char *buf)
451{
452	return smpro_internal_warn_read(dev, da, buf, RAS_SMPRO_ERR);
453}
454static DEVICE_ATTR_RO(warn_smpro);
455
456static ssize_t warn_pmpro_show(struct device *dev, struct device_attribute *da, char *buf)
457{
458	return smpro_internal_warn_read(dev, da, buf, RAS_PMPRO_ERR);
459}
460static DEVICE_ATTR_RO(warn_pmpro);
461
462#define EVENT_RO(_event, _index) \
463	static ssize_t event_##_event##_show(struct device *dev,            \
464					     struct device_attribute *da,   \
465					     char *buf)                     \
466	{                                                                   \
467		return smpro_event_data_read(dev, da, buf, _index);         \
468	}                                                                   \
469	static DEVICE_ATTR_RO(event_##_event)
470
471EVENT_RO(vrd_warn_fault, VRD_WARN_FAULT_EVENT);
472EVENT_RO(vrd_hot, VRD_HOT_EVENT);
473EVENT_RO(dimm_hot, DIMM_HOT_EVENT);
474EVENT_RO(dimm_2x_refresh, DIMM_2X_REFRESH_EVENT);
475
476static ssize_t smpro_dimm_syndrome_read(struct device *dev, struct device_attribute *da,
477					char *buf, unsigned int slot)
478{
479	struct smpro_errmon *errmon = dev_get_drvdata(dev);
480	unsigned int data;
481	int ret;
482
483	ret = regmap_read(errmon->regmap, BOOTSTAGE, &data);
484	if (ret)
485		return ret;
486
487	/* check for valid stage */
488	data = (data >> 8) & 0xff;
489	if (data != DIMM_SYNDROME_STAGE)
490		return ret;
491
492	/* Write the slot ID to retrieve Error Syndrome */
493	ret = regmap_write(errmon->regmap, DIMM_SYNDROME_SEL, slot);
494	if (ret)
495		return ret;
496
497	/* Read the Syndrome error */
498	ret = regmap_read(errmon->regmap, DIMM_SYNDROME_ERR, &data);
499	if (ret || !data)
500		return ret;
501
502	return sysfs_emit(buf, "%04x\n", data);
503}
504
505#define EVENT_DIMM_SYNDROME(_slot) \
506	static ssize_t event_dimm##_slot##_syndrome_show(struct device *dev,          \
507							 struct device_attribute *da, \
508							 char *buf)                   \
509	{                                                                             \
510		return smpro_dimm_syndrome_read(dev, da, buf, _slot);                 \
511	}                                                                             \
512	static DEVICE_ATTR_RO(event_dimm##_slot##_syndrome)
513
514EVENT_DIMM_SYNDROME(0);
515EVENT_DIMM_SYNDROME(1);
516EVENT_DIMM_SYNDROME(2);
517EVENT_DIMM_SYNDROME(3);
518EVENT_DIMM_SYNDROME(4);
519EVENT_DIMM_SYNDROME(5);
520EVENT_DIMM_SYNDROME(6);
521EVENT_DIMM_SYNDROME(7);
522EVENT_DIMM_SYNDROME(8);
523EVENT_DIMM_SYNDROME(9);
524EVENT_DIMM_SYNDROME(10);
525EVENT_DIMM_SYNDROME(11);
526EVENT_DIMM_SYNDROME(12);
527EVENT_DIMM_SYNDROME(13);
528EVENT_DIMM_SYNDROME(14);
529EVENT_DIMM_SYNDROME(15);
530
531static struct attribute *smpro_errmon_attrs[] = {
532	&dev_attr_overflow_core_ce.attr,
533	&dev_attr_overflow_core_ue.attr,
534	&dev_attr_overflow_mem_ce.attr,
535	&dev_attr_overflow_mem_ue.attr,
536	&dev_attr_overflow_pcie_ce.attr,
537	&dev_attr_overflow_pcie_ue.attr,
538	&dev_attr_overflow_other_ce.attr,
539	&dev_attr_overflow_other_ue.attr,
540	&dev_attr_error_core_ce.attr,
541	&dev_attr_error_core_ue.attr,
542	&dev_attr_error_mem_ce.attr,
543	&dev_attr_error_mem_ue.attr,
544	&dev_attr_error_pcie_ce.attr,
545	&dev_attr_error_pcie_ue.attr,
546	&dev_attr_error_other_ce.attr,
547	&dev_attr_error_other_ue.attr,
548	&dev_attr_error_smpro.attr,
549	&dev_attr_error_pmpro.attr,
550	&dev_attr_warn_smpro.attr,
551	&dev_attr_warn_pmpro.attr,
552	&dev_attr_event_vrd_warn_fault.attr,
553	&dev_attr_event_vrd_hot.attr,
554	&dev_attr_event_dimm_hot.attr,
555	&dev_attr_event_dimm_2x_refresh.attr,
556	&dev_attr_event_dimm0_syndrome.attr,
557	&dev_attr_event_dimm1_syndrome.attr,
558	&dev_attr_event_dimm2_syndrome.attr,
559	&dev_attr_event_dimm3_syndrome.attr,
560	&dev_attr_event_dimm4_syndrome.attr,
561	&dev_attr_event_dimm5_syndrome.attr,
562	&dev_attr_event_dimm6_syndrome.attr,
563	&dev_attr_event_dimm7_syndrome.attr,
564	&dev_attr_event_dimm8_syndrome.attr,
565	&dev_attr_event_dimm9_syndrome.attr,
566	&dev_attr_event_dimm10_syndrome.attr,
567	&dev_attr_event_dimm11_syndrome.attr,
568	&dev_attr_event_dimm12_syndrome.attr,
569	&dev_attr_event_dimm13_syndrome.attr,
570	&dev_attr_event_dimm14_syndrome.attr,
571	&dev_attr_event_dimm15_syndrome.attr,
572	NULL
573};
574
575ATTRIBUTE_GROUPS(smpro_errmon);
576
577static int smpro_errmon_probe(struct platform_device *pdev)
578{
579	struct smpro_errmon *errmon;
580
581	errmon = devm_kzalloc(&pdev->dev, sizeof(struct smpro_errmon), GFP_KERNEL);
582	if (!errmon)
583		return -ENOMEM;
584
585	platform_set_drvdata(pdev, errmon);
586
587	errmon->regmap = dev_get_regmap(pdev->dev.parent, NULL);
588	if (!errmon->regmap)
589		return -ENODEV;
590
591	return 0;
592}
593
594static struct platform_driver smpro_errmon_driver = {
595	.probe          = smpro_errmon_probe,
596	.driver = {
597		.name   = "smpro-errmon",
598		.dev_groups = smpro_errmon_groups,
599	},
600};
601
602module_platform_driver(smpro_errmon_driver);
603
604MODULE_AUTHOR("Tung Nguyen <tung.nguyen@amperecomputing.com>");
605MODULE_AUTHOR("Thinh Pham <thinh.pham@amperecomputing.com>");
606MODULE_AUTHOR("Hoang Nguyen <hnguyen@amperecomputing.com>");
607MODULE_AUTHOR("Thu Nguyen <thu@os.amperecomputing.com>");
608MODULE_AUTHOR("Quan Nguyen <quan@os.amperecomputing.com>");
609MODULE_DESCRIPTION("Ampere Altra SMpro driver");
610MODULE_LICENSE("GPL");
v6.8
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Ampere Computing SoC's SMpro Error Monitoring Driver
  4 *
  5 * Copyright (c) 2022, Ampere Computing LLC
  6 *
  7 */
  8
  9#include <linux/mod_devicetable.h>
 10#include <linux/module.h>
 11#include <linux/platform_device.h>
 12#include <linux/regmap.h>
 13
 14/* GPI RAS Error Registers */
 15#define GPI_RAS_ERR		0x7E
 16
 17/* Core and L2C Error Registers */
 18#define CORE_CE_ERR_CNT		0x80
 19#define CORE_CE_ERR_LEN		0x81
 20#define CORE_CE_ERR_DATA	0x82
 21#define CORE_UE_ERR_CNT		0x83
 22#define CORE_UE_ERR_LEN		0x84
 23#define CORE_UE_ERR_DATA	0x85
 24
 25/* Memory Error Registers */
 26#define MEM_CE_ERR_CNT		0x90
 27#define MEM_CE_ERR_LEN		0x91
 28#define MEM_CE_ERR_DATA		0x92
 29#define MEM_UE_ERR_CNT		0x93
 30#define MEM_UE_ERR_LEN		0x94
 31#define MEM_UE_ERR_DATA		0x95
 32
 33/* RAS Error/Warning Registers */
 34#define ERR_SMPRO_TYPE		0xA0
 35#define ERR_PMPRO_TYPE		0xA1
 36#define ERR_SMPRO_INFO_LO	0xA2
 37#define ERR_SMPRO_INFO_HI	0xA3
 38#define ERR_SMPRO_DATA_LO	0xA4
 39#define ERR_SMPRO_DATA_HI	0xA5
 40#define WARN_SMPRO_INFO_LO	0xAA
 41#define WARN_SMPRO_INFO_HI	0xAB
 42#define ERR_PMPRO_INFO_LO	0xA6
 43#define ERR_PMPRO_INFO_HI	0xA7
 44#define ERR_PMPRO_DATA_LO	0xA8
 45#define ERR_PMPRO_DATA_HI	0xA9
 46#define WARN_PMPRO_INFO_LO	0xAC
 47#define WARN_PMPRO_INFO_HI	0xAD
 48
 49/* Boot Stage Register */
 50#define BOOTSTAGE		0xB0
 51#define DIMM_SYNDROME_SEL	0xB4
 52#define DIMM_SYNDROME_ERR	0xB5
 53#define DIMM_SYNDROME_STAGE	4
 54
 55/* PCIE Error Registers */
 56#define PCIE_CE_ERR_CNT		0xC0
 57#define PCIE_CE_ERR_LEN		0xC1
 58#define PCIE_CE_ERR_DATA	0xC2
 59#define PCIE_UE_ERR_CNT		0xC3
 60#define PCIE_UE_ERR_LEN		0xC4
 61#define PCIE_UE_ERR_DATA	0xC5
 62
 63/* Other Error Registers */
 64#define OTHER_CE_ERR_CNT	0xD0
 65#define OTHER_CE_ERR_LEN	0xD1
 66#define OTHER_CE_ERR_DATA	0xD2
 67#define OTHER_UE_ERR_CNT	0xD8
 68#define OTHER_UE_ERR_LEN	0xD9
 69#define OTHER_UE_ERR_DATA	0xDA
 70
 71/* Event Data Registers */
 72#define VRD_WARN_FAULT_EVENT_DATA	0x78
 73#define VRD_HOT_EVENT_DATA		0x79
 74#define DIMM_HOT_EVENT_DATA		0x7A
 75#define DIMM_2X_REFRESH_EVENT_DATA	0x96
 76
 77#define MAX_READ_BLOCK_LENGTH	48
 78
 79#define RAS_SMPRO_ERR		0
 80#define RAS_PMPRO_ERR		1
 81
 82enum RAS_48BYTES_ERR_TYPES {
 83	CORE_CE_ERR,
 84	CORE_UE_ERR,
 85	MEM_CE_ERR,
 86	MEM_UE_ERR,
 87	PCIE_CE_ERR,
 88	PCIE_UE_ERR,
 89	OTHER_CE_ERR,
 90	OTHER_UE_ERR,
 91	NUM_48BYTES_ERR_TYPE,
 92};
 93
 94struct smpro_error_hdr {
 95	u8 count;	/* Number of the RAS errors */
 96	u8 len;		/* Number of data bytes */
 97	u8 data;	/* Start of 48-byte data */
 98	u8 max_cnt;	/* Max num of errors */
 99};
100
101/*
102 * Included Address of registers to get Count, Length of data and Data
103 * of the 48 bytes error data
104 */
105static struct smpro_error_hdr smpro_error_table[] = {
106	[CORE_CE_ERR] = {
107		.count = CORE_CE_ERR_CNT,
108		.len = CORE_CE_ERR_LEN,
109		.data = CORE_CE_ERR_DATA,
110		.max_cnt = 32
111	},
112	[CORE_UE_ERR] = {
113		.count = CORE_UE_ERR_CNT,
114		.len = CORE_UE_ERR_LEN,
115		.data = CORE_UE_ERR_DATA,
116		.max_cnt = 32
117	},
118	[MEM_CE_ERR] = {
119		.count = MEM_CE_ERR_CNT,
120		.len = MEM_CE_ERR_LEN,
121		.data = MEM_CE_ERR_DATA,
122		.max_cnt = 16
123	},
124	[MEM_UE_ERR] = {
125		.count = MEM_UE_ERR_CNT,
126		.len = MEM_UE_ERR_LEN,
127		.data = MEM_UE_ERR_DATA,
128		.max_cnt = 16
129	},
130	[PCIE_CE_ERR] = {
131		.count = PCIE_CE_ERR_CNT,
132		.len = PCIE_CE_ERR_LEN,
133		.data = PCIE_CE_ERR_DATA,
134		.max_cnt = 96
135	},
136	[PCIE_UE_ERR] = {
137		.count = PCIE_UE_ERR_CNT,
138		.len = PCIE_UE_ERR_LEN,
139		.data = PCIE_UE_ERR_DATA,
140		.max_cnt = 96
141	},
142	[OTHER_CE_ERR] = {
143		.count = OTHER_CE_ERR_CNT,
144		.len = OTHER_CE_ERR_LEN,
145		.data = OTHER_CE_ERR_DATA,
146		.max_cnt = 8
147	},
148	[OTHER_UE_ERR] = {
149		.count = OTHER_UE_ERR_CNT,
150		.len = OTHER_UE_ERR_LEN,
151		.data = OTHER_UE_ERR_DATA,
152		.max_cnt = 8
153	},
154};
155
156/*
157 * List of SCP registers which are used to get
158 * one type of RAS Internal errors.
159 */
160struct smpro_int_error_hdr {
161	u8 type;
162	u8 info_l;
163	u8 info_h;
164	u8 data_l;
165	u8 data_h;
166	u8 warn_l;
167	u8 warn_h;
168};
169
170static struct smpro_int_error_hdr list_smpro_int_error_hdr[] = {
171	[RAS_SMPRO_ERR] = {
172		.type = ERR_SMPRO_TYPE,
173		.info_l = ERR_SMPRO_INFO_LO,
174		.info_h = ERR_SMPRO_INFO_HI,
175		.data_l = ERR_SMPRO_DATA_LO,
176		.data_h = ERR_SMPRO_DATA_HI,
177		.warn_l = WARN_SMPRO_INFO_LO,
178		.warn_h = WARN_SMPRO_INFO_HI,
179	},
180	[RAS_PMPRO_ERR] = {
181		.type = ERR_PMPRO_TYPE,
182		.info_l = ERR_PMPRO_INFO_LO,
183		.info_h = ERR_PMPRO_INFO_HI,
184		.data_l = ERR_PMPRO_DATA_LO,
185		.data_h = ERR_PMPRO_DATA_HI,
186		.warn_l = WARN_PMPRO_INFO_LO,
187		.warn_h = WARN_PMPRO_INFO_HI,
188	},
189};
190
191struct smpro_errmon {
192	struct regmap *regmap;
193};
194
195enum EVENT_TYPES {
196	VRD_WARN_FAULT_EVENT,
197	VRD_HOT_EVENT,
198	DIMM_HOT_EVENT,
199	DIMM_2X_REFRESH_EVENT,
200	NUM_EVENTS_TYPE,
201};
202
203/* Included Address of event source and data registers */
204static u8 smpro_event_table[NUM_EVENTS_TYPE] = {
205	VRD_WARN_FAULT_EVENT_DATA,
206	VRD_HOT_EVENT_DATA,
207	DIMM_HOT_EVENT_DATA,
208	DIMM_2X_REFRESH_EVENT_DATA,
209};
210
211static ssize_t smpro_event_data_read(struct device *dev,
212				     struct device_attribute *da, char *buf,
213				     int channel)
214{
215	struct smpro_errmon *errmon = dev_get_drvdata(dev);
216	s32 event_data;
217	int ret;
218
219	ret = regmap_read(errmon->regmap, smpro_event_table[channel], &event_data);
220	if (ret)
221		return ret;
222	/* Clear event after read */
223	if (event_data != 0)
224		regmap_write(errmon->regmap, smpro_event_table[channel], event_data);
225
226	return sysfs_emit(buf, "%04x\n", event_data);
227}
228
229static ssize_t smpro_overflow_data_read(struct device *dev, struct device_attribute *da,
230					char *buf, int channel)
231{
232	struct smpro_errmon *errmon = dev_get_drvdata(dev);
233	struct smpro_error_hdr *err_info;
234	s32 err_count;
235	int ret;
236
237	err_info = &smpro_error_table[channel];
238
239	ret = regmap_read(errmon->regmap, err_info->count, &err_count);
240	if (ret)
241		return ret;
242
243	/* Bit 8 indicates the overflow status */
244	return sysfs_emit(buf, "%d\n", (err_count & BIT(8)) ? 1 : 0);
245}
246
247static ssize_t smpro_error_data_read(struct device *dev, struct device_attribute *da,
248				     char *buf, int channel)
249{
250	struct smpro_errmon *errmon = dev_get_drvdata(dev);
251	unsigned char err_data[MAX_READ_BLOCK_LENGTH];
252	struct smpro_error_hdr *err_info;
253	s32 err_count, err_length;
254	int ret;
255
256	err_info = &smpro_error_table[channel];
257
258	ret = regmap_read(errmon->regmap, err_info->count, &err_count);
259	/* Error count is the low byte */
260	err_count &= 0xff;
261	if (ret || !err_count || err_count > err_info->max_cnt)
262		return ret;
263
264	ret = regmap_read(errmon->regmap, err_info->len, &err_length);
265	if (ret || err_length <= 0)
266		return ret;
267
268	if (err_length > MAX_READ_BLOCK_LENGTH)
269		err_length = MAX_READ_BLOCK_LENGTH;
270
271	memset(err_data, 0x00, MAX_READ_BLOCK_LENGTH);
272	ret = regmap_noinc_read(errmon->regmap, err_info->data, err_data, err_length);
273	if (ret < 0)
274		return ret;
275
276	/* clear the error */
277	ret = regmap_write(errmon->regmap, err_info->count, 0x100);
278	if (ret)
279		return ret;
280	/*
281	 * The output of Core/Memory/PCIe/Others UE/CE errors follows the format
282	 * specified in section 5.8.1 CE/UE Error Data record in
283	 * Altra SOC BMC Interface specification.
284	 */
285	return sysfs_emit(buf, "%*phN\n", MAX_READ_BLOCK_LENGTH, err_data);
286}
287
288/*
289 * Output format:
290 * <4-byte hex value of error info><4-byte hex value of error extensive data>
291 * Where:
292 *   + error info : The error information
293 *   + error data : Extensive data (32 bits)
294 * Reference to section 5.10 RAS Internal Error Register Definition in
295 * Altra SOC BMC Interface specification
296 */
297static ssize_t smpro_internal_err_read(struct device *dev, struct device_attribute *da,
298				       char *buf, int channel)
299{
300	struct smpro_errmon *errmon = dev_get_drvdata(dev);
301	struct smpro_int_error_hdr *err_info;
302	unsigned int err[4] = { 0 };
303	unsigned int err_type;
304	unsigned int val;
305	int ret;
306
307	/* read error status */
308	ret = regmap_read(errmon->regmap, GPI_RAS_ERR, &val);
309	if (ret)
310		return ret;
311
312	if ((channel == RAS_SMPRO_ERR && !(val & BIT(0))) ||
313	    (channel == RAS_PMPRO_ERR && !(val & BIT(1))))
314		return 0;
315
316	err_info = &list_smpro_int_error_hdr[channel];
317	ret = regmap_read(errmon->regmap, err_info->type, &val);
318	if (ret)
319		return ret;
320
321	err_type = (val & BIT(1)) ? BIT(1) :
322		   (val & BIT(2)) ? BIT(2) : 0;
323
324	if (!err_type)
325		return 0;
326
327	ret = regmap_read(errmon->regmap, err_info->info_l, err + 1);
328	if (ret)
329		return ret;
330
331	ret = regmap_read(errmon->regmap, err_info->info_h, err);
332	if (ret)
333		return ret;
334
335	if (err_type & BIT(2)) {
336		/* Error with data type */
337		ret = regmap_read(errmon->regmap, err_info->data_l, err + 3);
338		if (ret)
339			return ret;
340
341		ret = regmap_read(errmon->regmap, err_info->data_h, err + 2);
342		if (ret)
343			return ret;
344	}
345
346	/* clear the read errors */
347	ret = regmap_write(errmon->regmap, err_info->type, err_type);
348	if (ret)
349		return ret;
350
351	return sysfs_emit(buf, "%*phN\n", (int)sizeof(err), err);
352}
353
354/*
355 * Output format:
356 * <4-byte hex value of warining info>
357 * Reference to section 5.10 RAS Internal Error Register Definition in
358 * Altra SOC BMC Interface specification
359 */
360static ssize_t smpro_internal_warn_read(struct device *dev, struct device_attribute *da,
361					char *buf, int channel)
362{
363	struct smpro_errmon *errmon = dev_get_drvdata(dev);
364	struct smpro_int_error_hdr *err_info;
365	unsigned int warn[2] = { 0 };
366	unsigned int val;
367	int ret;
368
369	/* read error status */
370	ret = regmap_read(errmon->regmap, GPI_RAS_ERR, &val);
371	if (ret)
372		return ret;
373
374	if ((channel == RAS_SMPRO_ERR && !(val & BIT(0))) ||
375	    (channel == RAS_PMPRO_ERR && !(val & BIT(1))))
376		return 0;
377
378	err_info = &list_smpro_int_error_hdr[channel];
379	ret = regmap_read(errmon->regmap, err_info->type, &val);
380	if (ret)
381		return ret;
382
383	if (!(val & BIT(0)))
384		return 0;
385
386	ret = regmap_read(errmon->regmap, err_info->warn_l, warn + 1);
387	if (ret)
388		return ret;
389
390	ret = regmap_read(errmon->regmap, err_info->warn_h, warn);
391	if (ret)
392		return ret;
393
394	/* clear the warning */
395	ret = regmap_write(errmon->regmap, err_info->type, BIT(0));
396	if (ret)
397		return ret;
398
399	return sysfs_emit(buf, "%*phN\n", (int)sizeof(warn), warn);
400}
401
402#define ERROR_OVERFLOW_RO(_error, _index) \
403	static ssize_t overflow_##_error##_show(struct device *dev,            \
404						struct device_attribute *da,   \
405						char *buf)                     \
406	{                                                                      \
407		return smpro_overflow_data_read(dev, da, buf, _index);         \
408	}                                                                      \
409	static DEVICE_ATTR_RO(overflow_##_error)
410
411ERROR_OVERFLOW_RO(core_ce, CORE_CE_ERR);
412ERROR_OVERFLOW_RO(core_ue, CORE_UE_ERR);
413ERROR_OVERFLOW_RO(mem_ce, MEM_CE_ERR);
414ERROR_OVERFLOW_RO(mem_ue, MEM_UE_ERR);
415ERROR_OVERFLOW_RO(pcie_ce, PCIE_CE_ERR);
416ERROR_OVERFLOW_RO(pcie_ue, PCIE_UE_ERR);
417ERROR_OVERFLOW_RO(other_ce, OTHER_CE_ERR);
418ERROR_OVERFLOW_RO(other_ue, OTHER_UE_ERR);
419
420#define ERROR_RO(_error, _index) \
421	static ssize_t error_##_error##_show(struct device *dev,            \
422					     struct device_attribute *da,   \
423					     char *buf)                     \
424	{                                                                   \
425		return smpro_error_data_read(dev, da, buf, _index);         \
426	}                                                                   \
427	static DEVICE_ATTR_RO(error_##_error)
428
429ERROR_RO(core_ce, CORE_CE_ERR);
430ERROR_RO(core_ue, CORE_UE_ERR);
431ERROR_RO(mem_ce, MEM_CE_ERR);
432ERROR_RO(mem_ue, MEM_UE_ERR);
433ERROR_RO(pcie_ce, PCIE_CE_ERR);
434ERROR_RO(pcie_ue, PCIE_UE_ERR);
435ERROR_RO(other_ce, OTHER_CE_ERR);
436ERROR_RO(other_ue, OTHER_UE_ERR);
437
438static ssize_t error_smpro_show(struct device *dev, struct device_attribute *da, char *buf)
439{
440	return smpro_internal_err_read(dev, da, buf, RAS_SMPRO_ERR);
441}
442static DEVICE_ATTR_RO(error_smpro);
443
444static ssize_t error_pmpro_show(struct device *dev, struct device_attribute *da, char *buf)
445{
446	return smpro_internal_err_read(dev, da, buf, RAS_PMPRO_ERR);
447}
448static DEVICE_ATTR_RO(error_pmpro);
449
450static ssize_t warn_smpro_show(struct device *dev, struct device_attribute *da, char *buf)
451{
452	return smpro_internal_warn_read(dev, da, buf, RAS_SMPRO_ERR);
453}
454static DEVICE_ATTR_RO(warn_smpro);
455
456static ssize_t warn_pmpro_show(struct device *dev, struct device_attribute *da, char *buf)
457{
458	return smpro_internal_warn_read(dev, da, buf, RAS_PMPRO_ERR);
459}
460static DEVICE_ATTR_RO(warn_pmpro);
461
462#define EVENT_RO(_event, _index) \
463	static ssize_t event_##_event##_show(struct device *dev,            \
464					     struct device_attribute *da,   \
465					     char *buf)                     \
466	{                                                                   \
467		return smpro_event_data_read(dev, da, buf, _index);         \
468	}                                                                   \
469	static DEVICE_ATTR_RO(event_##_event)
470
471EVENT_RO(vrd_warn_fault, VRD_WARN_FAULT_EVENT);
472EVENT_RO(vrd_hot, VRD_HOT_EVENT);
473EVENT_RO(dimm_hot, DIMM_HOT_EVENT);
474EVENT_RO(dimm_2x_refresh, DIMM_2X_REFRESH_EVENT);
475
476static ssize_t smpro_dimm_syndrome_read(struct device *dev, struct device_attribute *da,
477					char *buf, unsigned int slot)
478{
479	struct smpro_errmon *errmon = dev_get_drvdata(dev);
480	unsigned int data;
481	int ret;
482
483	ret = regmap_read(errmon->regmap, BOOTSTAGE, &data);
484	if (ret)
485		return ret;
486
487	/* check for valid stage */
488	data = (data >> 8) & 0xff;
489	if (data != DIMM_SYNDROME_STAGE)
490		return ret;
491
492	/* Write the slot ID to retrieve Error Syndrome */
493	ret = regmap_write(errmon->regmap, DIMM_SYNDROME_SEL, slot);
494	if (ret)
495		return ret;
496
497	/* Read the Syndrome error */
498	ret = regmap_read(errmon->regmap, DIMM_SYNDROME_ERR, &data);
499	if (ret || !data)
500		return ret;
501
502	return sysfs_emit(buf, "%04x\n", data);
503}
504
505#define EVENT_DIMM_SYNDROME(_slot) \
506	static ssize_t event_dimm##_slot##_syndrome_show(struct device *dev,          \
507							 struct device_attribute *da, \
508							 char *buf)                   \
509	{                                                                             \
510		return smpro_dimm_syndrome_read(dev, da, buf, _slot);                 \
511	}                                                                             \
512	static DEVICE_ATTR_RO(event_dimm##_slot##_syndrome)
513
514EVENT_DIMM_SYNDROME(0);
515EVENT_DIMM_SYNDROME(1);
516EVENT_DIMM_SYNDROME(2);
517EVENT_DIMM_SYNDROME(3);
518EVENT_DIMM_SYNDROME(4);
519EVENT_DIMM_SYNDROME(5);
520EVENT_DIMM_SYNDROME(6);
521EVENT_DIMM_SYNDROME(7);
522EVENT_DIMM_SYNDROME(8);
523EVENT_DIMM_SYNDROME(9);
524EVENT_DIMM_SYNDROME(10);
525EVENT_DIMM_SYNDROME(11);
526EVENT_DIMM_SYNDROME(12);
527EVENT_DIMM_SYNDROME(13);
528EVENT_DIMM_SYNDROME(14);
529EVENT_DIMM_SYNDROME(15);
530
531static struct attribute *smpro_errmon_attrs[] = {
532	&dev_attr_overflow_core_ce.attr,
533	&dev_attr_overflow_core_ue.attr,
534	&dev_attr_overflow_mem_ce.attr,
535	&dev_attr_overflow_mem_ue.attr,
536	&dev_attr_overflow_pcie_ce.attr,
537	&dev_attr_overflow_pcie_ue.attr,
538	&dev_attr_overflow_other_ce.attr,
539	&dev_attr_overflow_other_ue.attr,
540	&dev_attr_error_core_ce.attr,
541	&dev_attr_error_core_ue.attr,
542	&dev_attr_error_mem_ce.attr,
543	&dev_attr_error_mem_ue.attr,
544	&dev_attr_error_pcie_ce.attr,
545	&dev_attr_error_pcie_ue.attr,
546	&dev_attr_error_other_ce.attr,
547	&dev_attr_error_other_ue.attr,
548	&dev_attr_error_smpro.attr,
549	&dev_attr_error_pmpro.attr,
550	&dev_attr_warn_smpro.attr,
551	&dev_attr_warn_pmpro.attr,
552	&dev_attr_event_vrd_warn_fault.attr,
553	&dev_attr_event_vrd_hot.attr,
554	&dev_attr_event_dimm_hot.attr,
555	&dev_attr_event_dimm_2x_refresh.attr,
556	&dev_attr_event_dimm0_syndrome.attr,
557	&dev_attr_event_dimm1_syndrome.attr,
558	&dev_attr_event_dimm2_syndrome.attr,
559	&dev_attr_event_dimm3_syndrome.attr,
560	&dev_attr_event_dimm4_syndrome.attr,
561	&dev_attr_event_dimm5_syndrome.attr,
562	&dev_attr_event_dimm6_syndrome.attr,
563	&dev_attr_event_dimm7_syndrome.attr,
564	&dev_attr_event_dimm8_syndrome.attr,
565	&dev_attr_event_dimm9_syndrome.attr,
566	&dev_attr_event_dimm10_syndrome.attr,
567	&dev_attr_event_dimm11_syndrome.attr,
568	&dev_attr_event_dimm12_syndrome.attr,
569	&dev_attr_event_dimm13_syndrome.attr,
570	&dev_attr_event_dimm14_syndrome.attr,
571	&dev_attr_event_dimm15_syndrome.attr,
572	NULL
573};
574
575ATTRIBUTE_GROUPS(smpro_errmon);
576
577static int smpro_errmon_probe(struct platform_device *pdev)
578{
579	struct smpro_errmon *errmon;
580
581	errmon = devm_kzalloc(&pdev->dev, sizeof(struct smpro_errmon), GFP_KERNEL);
582	if (!errmon)
583		return -ENOMEM;
584
585	platform_set_drvdata(pdev, errmon);
586
587	errmon->regmap = dev_get_regmap(pdev->dev.parent, NULL);
588	if (!errmon->regmap)
589		return -ENODEV;
590
591	return 0;
592}
593
594static struct platform_driver smpro_errmon_driver = {
595	.probe          = smpro_errmon_probe,
596	.driver = {
597		.name   = "smpro-errmon",
598		.dev_groups = smpro_errmon_groups,
599	},
600};
601
602module_platform_driver(smpro_errmon_driver);
603
604MODULE_AUTHOR("Tung Nguyen <tung.nguyen@amperecomputing.com>");
605MODULE_AUTHOR("Thinh Pham <thinh.pham@amperecomputing.com>");
606MODULE_AUTHOR("Hoang Nguyen <hnguyen@amperecomputing.com>");
607MODULE_AUTHOR("Thu Nguyen <thu@os.amperecomputing.com>");
608MODULE_AUTHOR("Quan Nguyen <quan@os.amperecomputing.com>");
609MODULE_DESCRIPTION("Ampere Altra SMpro driver");
610MODULE_LICENSE("GPL");