1 // SPDX-License-Identifier: GPL-2.0
3 * Intel MAX 10 Board Management Controller chip - common code
5 * Copyright (C) 2018-2020 Intel Corporation. All rights reserved.
8 #include <linux/bitfield.h>
9 #include <linux/device.h>
10 #include <linux/dev_printk.h>
11 #include <linux/mfd/core.h>
12 #include <linux/mfd/intel-m10-bmc.h>
13 #include <linux/module.h>
15 void m10bmc_fw_state_set(struct intel_m10bmc
*m10bmc
, enum m10bmc_fw_state new_state
)
17 /* bmcfw_state is only needed if handshake_sys_reg_nranges > 0 */
18 if (!m10bmc
->info
->handshake_sys_reg_nranges
)
21 down_write(&m10bmc
->bmcfw_lock
);
22 m10bmc
->bmcfw_state
= new_state
;
23 up_write(&m10bmc
->bmcfw_lock
);
25 EXPORT_SYMBOL_NS_GPL(m10bmc_fw_state_set
, "INTEL_M10_BMC_CORE");
28 * For some Intel FPGA devices, the BMC firmware is not available to service
29 * handshake registers during a secure update.
31 static bool m10bmc_reg_always_available(struct intel_m10bmc
*m10bmc
, unsigned int offset
)
33 if (!m10bmc
->info
->handshake_sys_reg_nranges
)
36 return !regmap_reg_in_ranges(offset
, m10bmc
->info
->handshake_sys_reg_ranges
,
37 m10bmc
->info
->handshake_sys_reg_nranges
);
41 * m10bmc_handshake_reg_unavailable - Checks if reg access collides with secure update state
42 * @m10bmc: M10 BMC structure
44 * For some Intel FPGA devices, the BMC firmware is not available to service
45 * handshake registers during a secure update erase and write phases.
47 * Context: @m10bmc->bmcfw_lock must be held.
49 static bool m10bmc_handshake_reg_unavailable(struct intel_m10bmc
*m10bmc
)
51 return m10bmc
->bmcfw_state
== M10BMC_FW_STATE_SEC_UPDATE_PREPARE
||
52 m10bmc
->bmcfw_state
== M10BMC_FW_STATE_SEC_UPDATE_WRITE
;
56 * This function helps to simplify the accessing of the system registers.
58 * The base of the system registers is configured through the struct
61 int m10bmc_sys_read(struct intel_m10bmc
*m10bmc
, unsigned int offset
, unsigned int *val
)
63 const struct m10bmc_csr_map
*csr_map
= m10bmc
->info
->csr_map
;
66 if (m10bmc_reg_always_available(m10bmc
, offset
))
67 return m10bmc_raw_read(m10bmc
, csr_map
->base
+ offset
, val
);
69 down_read(&m10bmc
->bmcfw_lock
);
70 if (m10bmc_handshake_reg_unavailable(m10bmc
))
71 ret
= -EBUSY
; /* Reg not available during secure update */
73 ret
= m10bmc_raw_read(m10bmc
, csr_map
->base
+ offset
, val
);
74 up_read(&m10bmc
->bmcfw_lock
);
78 EXPORT_SYMBOL_NS_GPL(m10bmc_sys_read
, "INTEL_M10_BMC_CORE");
80 int m10bmc_sys_update_bits(struct intel_m10bmc
*m10bmc
, unsigned int offset
,
81 unsigned int msk
, unsigned int val
)
83 const struct m10bmc_csr_map
*csr_map
= m10bmc
->info
->csr_map
;
86 if (m10bmc_reg_always_available(m10bmc
, offset
))
87 return regmap_update_bits(m10bmc
->regmap
, csr_map
->base
+ offset
, msk
, val
);
89 down_read(&m10bmc
->bmcfw_lock
);
90 if (m10bmc_handshake_reg_unavailable(m10bmc
))
91 ret
= -EBUSY
; /* Reg not available during secure update */
93 ret
= regmap_update_bits(m10bmc
->regmap
, csr_map
->base
+ offset
, msk
, val
);
94 up_read(&m10bmc
->bmcfw_lock
);
98 EXPORT_SYMBOL_NS_GPL(m10bmc_sys_update_bits
, "INTEL_M10_BMC_CORE");
100 static ssize_t
bmc_version_show(struct device
*dev
,
101 struct device_attribute
*attr
, char *buf
)
103 struct intel_m10bmc
*ddata
= dev_get_drvdata(dev
);
107 ret
= m10bmc_sys_read(ddata
, ddata
->info
->csr_map
->build_version
, &val
);
111 return sprintf(buf
, "0x%x\n", val
);
113 static DEVICE_ATTR_RO(bmc_version
);
115 static ssize_t
bmcfw_version_show(struct device
*dev
,
116 struct device_attribute
*attr
, char *buf
)
118 struct intel_m10bmc
*ddata
= dev_get_drvdata(dev
);
122 ret
= m10bmc_sys_read(ddata
, ddata
->info
->csr_map
->fw_version
, &val
);
126 return sprintf(buf
, "0x%x\n", val
);
128 static DEVICE_ATTR_RO(bmcfw_version
);
130 static ssize_t
mac_address_show(struct device
*dev
,
131 struct device_attribute
*attr
, char *buf
)
133 struct intel_m10bmc
*ddata
= dev_get_drvdata(dev
);
134 unsigned int macaddr_low
, macaddr_high
;
137 ret
= m10bmc_sys_read(ddata
, ddata
->info
->csr_map
->mac_low
, &macaddr_low
);
141 ret
= m10bmc_sys_read(ddata
, ddata
->info
->csr_map
->mac_high
, &macaddr_high
);
145 return sysfs_emit(buf
, "%02x:%02x:%02x:%02x:%02x:%02x\n",
146 (u8
)FIELD_GET(M10BMC_N3000_MAC_BYTE1
, macaddr_low
),
147 (u8
)FIELD_GET(M10BMC_N3000_MAC_BYTE2
, macaddr_low
),
148 (u8
)FIELD_GET(M10BMC_N3000_MAC_BYTE3
, macaddr_low
),
149 (u8
)FIELD_GET(M10BMC_N3000_MAC_BYTE4
, macaddr_low
),
150 (u8
)FIELD_GET(M10BMC_N3000_MAC_BYTE5
, macaddr_high
),
151 (u8
)FIELD_GET(M10BMC_N3000_MAC_BYTE6
, macaddr_high
));
153 static DEVICE_ATTR_RO(mac_address
);
155 static ssize_t
mac_count_show(struct device
*dev
,
156 struct device_attribute
*attr
, char *buf
)
158 struct intel_m10bmc
*ddata
= dev_get_drvdata(dev
);
159 unsigned int macaddr_high
;
162 ret
= m10bmc_sys_read(ddata
, ddata
->info
->csr_map
->mac_high
, &macaddr_high
);
166 return sysfs_emit(buf
, "%u\n", (u8
)FIELD_GET(M10BMC_N3000_MAC_COUNT
, macaddr_high
));
168 static DEVICE_ATTR_RO(mac_count
);
170 static struct attribute
*m10bmc_attrs
[] = {
171 &dev_attr_bmc_version
.attr
,
172 &dev_attr_bmcfw_version
.attr
,
173 &dev_attr_mac_address
.attr
,
174 &dev_attr_mac_count
.attr
,
178 static const struct attribute_group m10bmc_group
= {
179 .attrs
= m10bmc_attrs
,
182 const struct attribute_group
*m10bmc_dev_groups
[] = {
186 EXPORT_SYMBOL_NS_GPL(m10bmc_dev_groups
, "INTEL_M10_BMC_CORE");
188 int m10bmc_dev_init(struct intel_m10bmc
*m10bmc
, const struct intel_m10bmc_platform_info
*info
)
193 dev_set_drvdata(m10bmc
->dev
, m10bmc
);
194 init_rwsem(&m10bmc
->bmcfw_lock
);
196 ret
= devm_mfd_add_devices(m10bmc
->dev
, PLATFORM_DEVID_AUTO
,
197 info
->cells
, info
->n_cells
,
200 dev_err(m10bmc
->dev
, "Failed to register sub-devices: %d\n", ret
);
204 EXPORT_SYMBOL_NS_GPL(m10bmc_dev_init
, "INTEL_M10_BMC_CORE");
206 MODULE_DESCRIPTION("Intel MAX 10 BMC core driver");
207 MODULE_AUTHOR("Intel Corporation");
208 MODULE_LICENSE("GPL v2");