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