Skip to content

Commit 1c01ff9

Browse files
author
Russ Weight
committed
mfd: intel-m10-bmc: Create BMC log sub-driver
The PMCI MAX10 BMC contains high and low timestamp registers that are to be periodically written by the host driver to facilitate BMC error logs. Add a kernel worker thread at BMC initialization time to update the BMC timestamp registers at a frequency of once per minute. Signed-off-by: Russ Weight <russell.h.weight@intel.com>
1 parent 116ec2e commit 1c01ff9

5 files changed

Lines changed: 102 additions & 1 deletion

File tree

drivers/mfd/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2192,5 +2192,14 @@ config MFD_INTEL_M10_BMC_PMCI
21922192
additional drivers must be enabled in order to use the functionality
21932193
of the device.
21942194

2195+
config MFD_INTEL_M10_BMC_LOG
2196+
tristate "Intel MAX 10 Board Management Controller Log Driver"
2197+
depends on MFD_INTEL_M10_BMC_CORE
2198+
help
2199+
Support for the Intel MAX 10 board management controller log
2200+
2201+
This driver provides timestamp synchronization with the MAX10
2202+
BMC log.
2203+
21952204
endmenu
21962205
endif

drivers/mfd/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ intel-m10-bmc-objs := intel-m10-bmc-core.o
272272
obj-$(CONFIG_MFD_INTEL_M10_BMC_CORE) += intel-m10-bmc.o
273273
obj-$(CONFIG_MFD_INTEL_M10_BMC_SPI) += intel-m10-bmc-spi.o
274274
obj-$(CONFIG_MFD_INTEL_M10_BMC_PMCI) += intel-m10-bmc-pmci.o
275+
obj-$(CONFIG_MFD_INTEL_M10_BMC_LOG) += intel-m10-bmc-log.o
275276

276277
obj-$(CONFIG_MFD_ATC260X) += atc260x-core.o
277278
obj-$(CONFIG_MFD_ATC260X_I2C) += atc260x-i2c.o

drivers/mfd/intel-m10-bmc-core.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ static const struct m10bmc_csr m10bmc_spi_csr = {
3333

3434
static struct mfd_cell m10bmc_n6010_bmc_subdevs[] = {
3535
{ .name = "n6010bmc-hwmon" },
36-
{ .name = "n6010bmc-secure" }
36+
{ .name = "n6010bmc-secure" },
37+
{ .name = "n6010bmc-log" }
3738
};
3839

3940
static const struct regmap_range n6010_fw_handshake_regs[] = {

drivers/mfd/intel-m10-bmc-log.c

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Intel Max10 Board Management Controller Secure Update Driver
4+
*
5+
* Copyright (C) 2021 Intel Corporation. All rights reserved.
6+
*
7+
*/
8+
9+
#include <linux/bitfield.h>
10+
#include <linux/mfd/intel-m10-bmc.h>
11+
#include <linux/module.h>
12+
#include <linux/platform_device.h>
13+
14+
struct m10bmc_log {
15+
struct device *dev;
16+
struct intel_m10bmc *m10bmc;
17+
unsigned int freq_s; /* update frequency in seconds */
18+
struct delayed_work dwork;
19+
};
20+
21+
#define M10BMC_TIMESTAMP_FREQ 60 /* 60 seconds between updates */
22+
#define TIME_LOW GENMASK(31, 0)
23+
#define TIME_HIGH GENMASK(63, 32)
24+
static void m10bmc_log_time_sync(struct work_struct *work)
25+
{
26+
struct delayed_work *dwork;
27+
u32 time_high, time_low;
28+
struct m10bmc_log *log;
29+
s64 time_ns;
30+
int ret;
31+
32+
dwork = to_delayed_work(work);
33+
log = container_of(dwork, struct m10bmc_log, dwork);
34+
35+
time_ns = ktime_to_ns(ktime_get_real());
36+
time_low = (u32)FIELD_GET(TIME_LOW, time_ns);
37+
time_high = (u32)FIELD_GET(TIME_LOW, time_ns);
38+
ret = regmap_write(log->m10bmc->regmap, m10bmc_base(log->m10bmc) +
39+
M10BMC_PMCI_TIME_HIGH, time_high);
40+
if (!ret)
41+
ret = regmap_write(log->m10bmc->regmap,
42+
m10bmc_base(log->m10bmc) +
43+
M10BMC_PMCI_TIME_LOW, time_low);
44+
if (ret)
45+
dev_err_once(log->dev,
46+
"Failed to update BMC timestamp: %d\n", ret);
47+
48+
schedule_delayed_work(&log->dwork, log->freq_s * HZ);
49+
}
50+
51+
static int m10bmc_log_probe(struct platform_device *pdev)
52+
{
53+
struct m10bmc_log *ddata;
54+
55+
ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
56+
if (!ddata)
57+
return -ENOMEM;
58+
59+
ddata->dev = &pdev->dev;
60+
ddata->m10bmc = dev_get_drvdata(pdev->dev.parent);
61+
ddata->freq_s = M10BMC_TIMESTAMP_FREQ;
62+
INIT_DELAYED_WORK(&ddata->dwork, m10bmc_log_time_sync);
63+
dev_set_drvdata(&pdev->dev, ddata);
64+
65+
m10bmc_log_time_sync(&ddata->dwork.work);
66+
67+
return 0;
68+
}
69+
70+
static int m10bmc_log_remove(struct platform_device *pdev)
71+
{
72+
struct m10bmc_log *ddata = dev_get_drvdata(&pdev->dev);
73+
74+
cancel_delayed_work_sync(&ddata->dwork);
75+
return 0;
76+
}
77+
78+
static struct platform_driver intel_m10bmc_log_driver = {
79+
.probe = m10bmc_log_probe,
80+
.remove = m10bmc_log_remove,
81+
};
82+
module_platform_driver(intel_m10bmc_log_driver);
83+
84+
MODULE_AUTHOR("Intel Corporation");
85+
MODULE_DESCRIPTION("Intel MAX10 BMC Log");
86+
MODULE_LICENSE("GPL v2");
87+
MODULE_ALIAS("platform:intel-m10bmc-log");

include/linux/mfd/intel-m10-bmc.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,9 @@ enum m10bmc_type {
181181
#define M10BMC_PMCI_MAC_LOW 0x20
182182
#define M10BMC_PMCI_MAC_HIGH 0x24
183183

184+
#define M10BMC_PMCI_TIME_LOW 0x60
185+
#define M10BMC_PMCI_TIME_HIGH 0x60
186+
184187
#define M10BMC_PMCI_FLASH_CTRL 0x1d0
185188
#define FLASH_MUX_SELECTION GENMASK(2, 0)
186189
#define FLASH_MUX_IDLE 0

0 commit comments

Comments
 (0)