brintos

brintos / linux-shallow public Read only

0
0
Text · 16.2 KiB · c12035a Raw
611 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Ampere Computing SoC's SMpro Error Monitoring Driver4 *5 * Copyright (c) 2022, Ampere Computing LLC6 *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		0x7E16 17/* Core and L2C Error Registers */18#define CORE_CE_ERR_CNT		0x8019#define CORE_CE_ERR_LEN		0x8120#define CORE_CE_ERR_DATA	0x8221#define CORE_UE_ERR_CNT		0x8322#define CORE_UE_ERR_LEN		0x8423#define CORE_UE_ERR_DATA	0x8524 25/* Memory Error Registers */26#define MEM_CE_ERR_CNT		0x9027#define MEM_CE_ERR_LEN		0x9128#define MEM_CE_ERR_DATA		0x9229#define MEM_UE_ERR_CNT		0x9330#define MEM_UE_ERR_LEN		0x9431#define MEM_UE_ERR_DATA		0x9532 33/* RAS Error/Warning Registers */34#define ERR_SMPRO_TYPE		0xA035#define ERR_PMPRO_TYPE		0xA136#define ERR_SMPRO_INFO_LO	0xA237#define ERR_SMPRO_INFO_HI	0xA338#define ERR_SMPRO_DATA_LO	0xA439#define ERR_SMPRO_DATA_HI	0xA540#define WARN_SMPRO_INFO_LO	0xAA41#define WARN_SMPRO_INFO_HI	0xAB42#define ERR_PMPRO_INFO_LO	0xA643#define ERR_PMPRO_INFO_HI	0xA744#define ERR_PMPRO_DATA_LO	0xA845#define ERR_PMPRO_DATA_HI	0xA946#define WARN_PMPRO_INFO_LO	0xAC47#define WARN_PMPRO_INFO_HI	0xAD48 49/* Boot Stage Register */50#define BOOTSTAGE		0xB051#define DIMM_SYNDROME_SEL	0xB452#define DIMM_SYNDROME_ERR	0xB553#define DIMM_SYNDROME_STAGE	454 55/* PCIE Error Registers */56#define PCIE_CE_ERR_CNT		0xC057#define PCIE_CE_ERR_LEN		0xC158#define PCIE_CE_ERR_DATA	0xC259#define PCIE_UE_ERR_CNT		0xC360#define PCIE_UE_ERR_LEN		0xC461#define PCIE_UE_ERR_DATA	0xC562 63/* Other Error Registers */64#define OTHER_CE_ERR_CNT	0xD065#define OTHER_CE_ERR_LEN	0xD166#define OTHER_CE_ERR_DATA	0xD267#define OTHER_UE_ERR_CNT	0xD868#define OTHER_UE_ERR_LEN	0xD969#define OTHER_UE_ERR_DATA	0xDA70 71/* Event Data Registers */72#define VRD_WARN_FAULT_EVENT_DATA	0x7873#define VRD_HOT_EVENT_DATA		0x7974#define DIMM_HOT_EVENT_DATA		0x7A75#define DIMM_2X_REFRESH_EVENT_DATA	0x9676 77#define MAX_READ_BLOCK_LENGTH	4878 79#define RAS_SMPRO_ERR		080#define RAS_PMPRO_ERR		181 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 Data103 * of the 48 bytes error data104 */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 = 32111	},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 = 32117	},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 = 16123	},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 = 16129	},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 = 96135	},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 = 96141	},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 = 8147	},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 = 8153	},154};155 156/*157 * List of SCP registers which are used to get158 * 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 format282	 * specified in section 5.8.1 CE/UE Error Data record in283	 * 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 information293 *   + error data : Extensive data (32 bits)294 * Reference to section 5.10 RAS Internal Error Register Definition in295 * Altra SOC BMC Interface specification296 */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 in358 * Altra SOC BMC Interface specification359 */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	NULL573};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");611