Skip to content

Commit dacbf71

Browse files
author
Russ Weight
committed
mfd: intel-m10-bmc: Synchronize timestamp with BMC
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 ccc3008 commit dacbf71

5 files changed

Lines changed: 101 additions & 1 deletion

File tree

drivers/mfd/Kconfig

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

2177+
config MFD_INTEL_M10_BMC_LOG
2178+
tristate "Intel MAX 10 Board Management Controller Log Driver"
2179+
depends on MFD_INTEL_M10_BMC
2180+
help
2181+
Support for the Intel MAX 10 board management controller log
2182+
2183+
This driver provides timestamp synchronization with the MAX10
2184+
BMC log.
2185+
21772186
endmenu
21782187
endif

drivers/mfd/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,3 +273,4 @@ intel-m10-bmc-objs := intel-m10-bmc-core.o
273273
obj-$(CONFIG_MFD_INTEL_M10_BMC_CORE) += intel-m10-bmc.o
274274
obj-$(CONFIG_MFD_INTEL_M10_BMC_SPI) += intel-m10-bmc-spi.o
275275
obj-$(CONFIG_MFD_INTEL_M10_BMC_PMCI) += intel-m10-bmc-pmci.o
276+
obj-$(CONFIG_MFD_INTEL_M10_BMC_LOG) += intel-m10-bmc-log.o

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313

1414
static struct mfd_cell pmci_bmc_subdevs[] = {
1515
{ .name = "intel-pmci-hwmon" },
16-
{ .name = "intel-pmci-secure" }
16+
{ .name = "intel-pmci-secure" },
17+
{ .name = "intel-pmci-log" }
1718
};
1819

1920
static const struct regmap_range pmci_fw_handshake_regs[] = {

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

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
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+
13+
struct m10bmc_log {
14+
struct device *dev;
15+
struct intel_m10bmc *m10bmc;
16+
unsigned int freq_s; /* update frequency in seconds */
17+
struct delayed_work dwork;
18+
};
19+
20+
#define M10BMC_TIMESTAMP_FREQ 60 /* 60 seconds between updates */
21+
#define TIME_LOW GENMASK(31, 0)
22+
#define TIME_HIGH GENMASK(63, 32)
23+
static void m10bmc_log_time_sync(struct work_struct *work)
24+
{
25+
struct delayed_work *dwork;
26+
u32 time_high, time_low;
27+
struct m10bmc_log *log;
28+
s64 time_ns;
29+
int ret;
30+
31+
dwork = to_delayed_work(work);
32+
log = container_of(dwork, struct m10bmc_log, dwork);
33+
34+
time_ns = ktime_to_ns(ktime_get_real());
35+
time_low = (u32)FIELD_GET(TIME_LOW, time_ns);
36+
time_high = (u32)FIELD_GET(TIME_LOW, time_ns);
37+
ret = regmap_write(log->m10bmc->regmap, m10bmc_base(log->m10bmc) +
38+
PMCI_M10BMC_TIME_HIGH, time_high);
39+
if (!ret)
40+
ret = regmap_write(log->m10bmc->regmap,
41+
m10bmc_base(log->m10bmc) +
42+
PMCI_M10BMC_TIME_LOW, time_low);
43+
if (ret)
44+
dev_err_once(log->dev,
45+
"Failed to update BMC timestamp: %d\n", ret);
46+
47+
schedule_delayed_work(&log->dwork, log->freq_s * HZ);
48+
}
49+
50+
static int m10bmc_log_probe(struct platform_device *pdev)
51+
{
52+
struct m10bmc_log *ddata;
53+
54+
ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
55+
if (!ddata)
56+
return -ENOMEM;
57+
58+
ddata->dev = &pdev->dev;
59+
ddata->m10bmc = dev_get_drvdata(pdev->dev.parent);
60+
ddata->freq_s = M10BMC_TIMESTAMP_FREQ;
61+
INIT_DELAYED_WORK(&ddata->dwork, m10bmc_log_time_sync);
62+
dev_set_drvdata(&pdev->dev, ddata);
63+
64+
m10bmc_log_time_sync(&ddata->dwork.work);
65+
66+
return 0;
67+
}
68+
69+
int m10bmc_log_remove(struct platform_device *pdev)
70+
{
71+
struct m10bmc_log *ddata = dev_get_drvdata(&pdev->dev);
72+
73+
cancel_delayed_work_sync(&ddata->dwork);
74+
return 0;
75+
}
76+
77+
static struct platform_driver intel_m10bmc_log_driver = {
78+
.probe = m10bmc_log_probe,
79+
.remove = m10bmc_log_remove,
80+
};
81+
module_platform_driver(intel_m10bmc_log_driver);
82+
83+
MODULE_AUTHOR("Intel Corporation");
84+
MODULE_DESCRIPTION("Intel MAX10 BMC Log");
85+
MODULE_LICENSE("GPL v2");
86+
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
@@ -178,6 +178,9 @@ enum m10bmc_type {
178178
#define PMCI_M10BMC_MAC_LOW 0x20
179179
#define PMCI_M10BMC_MAC_HIGH 0x24
180180

181+
#define PMCI_M10BMC_TIME_LOW 0x60
182+
#define PMCI_M10BMC_TIME_HIGH 0x60
183+
181184
#define PMCI_M10BMC_FLASH_CTRL 0x1d0
182185
#define FLASH_MUX_SELECTION GENMASK(2, 0)
183186
#define FLASH_MUX_IDLE 0

0 commit comments

Comments
 (0)