1*603aed8fSIlpo Järvinen // SPDX-License-Identifier: GPL-2.0
2*603aed8fSIlpo Järvinen /*
3*603aed8fSIlpo Järvinen  * Intel MAX 10 Board Management Controller chip - common code
4*603aed8fSIlpo Järvinen  *
5*603aed8fSIlpo Järvinen  * Copyright (C) 2018-2020 Intel Corporation. All rights reserved.
6*603aed8fSIlpo Järvinen  */
7*603aed8fSIlpo Järvinen 
8*603aed8fSIlpo Järvinen #include <linux/bitfield.h>
9*603aed8fSIlpo Järvinen #include <linux/device.h>
10*603aed8fSIlpo Järvinen #include <linux/dev_printk.h>
11*603aed8fSIlpo Järvinen #include <linux/mfd/core.h>
12*603aed8fSIlpo Järvinen #include <linux/mfd/intel-m10-bmc.h>
13*603aed8fSIlpo Järvinen #include <linux/module.h>
14*603aed8fSIlpo Järvinen 
15*603aed8fSIlpo Järvinen static ssize_t bmc_version_show(struct device *dev,
16*603aed8fSIlpo Järvinen 				struct device_attribute *attr, char *buf)
17*603aed8fSIlpo Järvinen {
18*603aed8fSIlpo Järvinen 	struct intel_m10bmc *ddata = dev_get_drvdata(dev);
19*603aed8fSIlpo Järvinen 	unsigned int val;
20*603aed8fSIlpo Järvinen 	int ret;
21*603aed8fSIlpo Järvinen 
22*603aed8fSIlpo Järvinen 	ret = m10bmc_sys_read(ddata, M10BMC_BUILD_VER, &val);
23*603aed8fSIlpo Järvinen 	if (ret)
24*603aed8fSIlpo Järvinen 		return ret;
25*603aed8fSIlpo Järvinen 
26*603aed8fSIlpo Järvinen 	return sprintf(buf, "0x%x\n", val);
27*603aed8fSIlpo Järvinen }
28*603aed8fSIlpo Järvinen static DEVICE_ATTR_RO(bmc_version);
29*603aed8fSIlpo Järvinen 
30*603aed8fSIlpo Järvinen static ssize_t bmcfw_version_show(struct device *dev,
31*603aed8fSIlpo Järvinen 				  struct device_attribute *attr, char *buf)
32*603aed8fSIlpo Järvinen {
33*603aed8fSIlpo Järvinen 	struct intel_m10bmc *ddata = dev_get_drvdata(dev);
34*603aed8fSIlpo Järvinen 	unsigned int val;
35*603aed8fSIlpo Järvinen 	int ret;
36*603aed8fSIlpo Järvinen 
37*603aed8fSIlpo Järvinen 	ret = m10bmc_sys_read(ddata, NIOS2_FW_VERSION, &val);
38*603aed8fSIlpo Järvinen 	if (ret)
39*603aed8fSIlpo Järvinen 		return ret;
40*603aed8fSIlpo Järvinen 
41*603aed8fSIlpo Järvinen 	return sprintf(buf, "0x%x\n", val);
42*603aed8fSIlpo Järvinen }
43*603aed8fSIlpo Järvinen static DEVICE_ATTR_RO(bmcfw_version);
44*603aed8fSIlpo Järvinen 
45*603aed8fSIlpo Järvinen static ssize_t mac_address_show(struct device *dev,
46*603aed8fSIlpo Järvinen 				struct device_attribute *attr, char *buf)
47*603aed8fSIlpo Järvinen {
48*603aed8fSIlpo Järvinen 	struct intel_m10bmc *ddata = dev_get_drvdata(dev);
49*603aed8fSIlpo Järvinen 	unsigned int macaddr_low, macaddr_high;
50*603aed8fSIlpo Järvinen 	int ret;
51*603aed8fSIlpo Järvinen 
52*603aed8fSIlpo Järvinen 	ret = m10bmc_sys_read(ddata, M10BMC_MAC_LOW, &macaddr_low);
53*603aed8fSIlpo Järvinen 	if (ret)
54*603aed8fSIlpo Järvinen 		return ret;
55*603aed8fSIlpo Järvinen 
56*603aed8fSIlpo Järvinen 	ret = m10bmc_sys_read(ddata, M10BMC_MAC_HIGH, &macaddr_high);
57*603aed8fSIlpo Järvinen 	if (ret)
58*603aed8fSIlpo Järvinen 		return ret;
59*603aed8fSIlpo Järvinen 
60*603aed8fSIlpo Järvinen 	return sysfs_emit(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n",
61*603aed8fSIlpo Järvinen 			  (u8)FIELD_GET(M10BMC_MAC_BYTE1, macaddr_low),
62*603aed8fSIlpo Järvinen 			  (u8)FIELD_GET(M10BMC_MAC_BYTE2, macaddr_low),
63*603aed8fSIlpo Järvinen 			  (u8)FIELD_GET(M10BMC_MAC_BYTE3, macaddr_low),
64*603aed8fSIlpo Järvinen 			  (u8)FIELD_GET(M10BMC_MAC_BYTE4, macaddr_low),
65*603aed8fSIlpo Järvinen 			  (u8)FIELD_GET(M10BMC_MAC_BYTE5, macaddr_high),
66*603aed8fSIlpo Järvinen 			  (u8)FIELD_GET(M10BMC_MAC_BYTE6, macaddr_high));
67*603aed8fSIlpo Järvinen }
68*603aed8fSIlpo Järvinen static DEVICE_ATTR_RO(mac_address);
69*603aed8fSIlpo Järvinen 
70*603aed8fSIlpo Järvinen static ssize_t mac_count_show(struct device *dev,
71*603aed8fSIlpo Järvinen 			      struct device_attribute *attr, char *buf)
72*603aed8fSIlpo Järvinen {
73*603aed8fSIlpo Järvinen 	struct intel_m10bmc *ddata = dev_get_drvdata(dev);
74*603aed8fSIlpo Järvinen 	unsigned int macaddr_high;
75*603aed8fSIlpo Järvinen 	int ret;
76*603aed8fSIlpo Järvinen 
77*603aed8fSIlpo Järvinen 	ret = m10bmc_sys_read(ddata, M10BMC_MAC_HIGH, &macaddr_high);
78*603aed8fSIlpo Järvinen 	if (ret)
79*603aed8fSIlpo Järvinen 		return ret;
80*603aed8fSIlpo Järvinen 
81*603aed8fSIlpo Järvinen 	return sysfs_emit(buf, "%u\n", (u8)FIELD_GET(M10BMC_MAC_COUNT, macaddr_high));
82*603aed8fSIlpo Järvinen }
83*603aed8fSIlpo Järvinen static DEVICE_ATTR_RO(mac_count);
84*603aed8fSIlpo Järvinen 
85*603aed8fSIlpo Järvinen static struct attribute *m10bmc_attrs[] = {
86*603aed8fSIlpo Järvinen 	&dev_attr_bmc_version.attr,
87*603aed8fSIlpo Järvinen 	&dev_attr_bmcfw_version.attr,
88*603aed8fSIlpo Järvinen 	&dev_attr_mac_address.attr,
89*603aed8fSIlpo Järvinen 	&dev_attr_mac_count.attr,
90*603aed8fSIlpo Järvinen 	NULL,
91*603aed8fSIlpo Järvinen };
92*603aed8fSIlpo Järvinen 
93*603aed8fSIlpo Järvinen static const struct attribute_group m10bmc_group = {
94*603aed8fSIlpo Järvinen 	.attrs = m10bmc_attrs,
95*603aed8fSIlpo Järvinen };
96*603aed8fSIlpo Järvinen 
97*603aed8fSIlpo Järvinen const struct attribute_group *m10bmc_dev_groups[] = {
98*603aed8fSIlpo Järvinen 	&m10bmc_group,
99*603aed8fSIlpo Järvinen 	NULL,
100*603aed8fSIlpo Järvinen };
101*603aed8fSIlpo Järvinen EXPORT_SYMBOL_GPL(m10bmc_dev_groups);
102*603aed8fSIlpo Järvinen 
103*603aed8fSIlpo Järvinen int m10bmc_dev_init(struct intel_m10bmc *m10bmc, const struct intel_m10bmc_platform_info *info)
104*603aed8fSIlpo Järvinen {
105*603aed8fSIlpo Järvinen 	int ret;
106*603aed8fSIlpo Järvinen 
107*603aed8fSIlpo Järvinen 	m10bmc->info = info;
108*603aed8fSIlpo Järvinen 	dev_set_drvdata(m10bmc->dev, m10bmc);
109*603aed8fSIlpo Järvinen 
110*603aed8fSIlpo Järvinen 	ret = devm_mfd_add_devices(m10bmc->dev, PLATFORM_DEVID_AUTO,
111*603aed8fSIlpo Järvinen 				   info->cells, info->n_cells,
112*603aed8fSIlpo Järvinen 				   NULL, 0, NULL);
113*603aed8fSIlpo Järvinen 	if (ret)
114*603aed8fSIlpo Järvinen 		dev_err(m10bmc->dev, "Failed to register sub-devices: %d\n", ret);
115*603aed8fSIlpo Järvinen 
116*603aed8fSIlpo Järvinen 	return ret;
117*603aed8fSIlpo Järvinen }
118*603aed8fSIlpo Järvinen EXPORT_SYMBOL_GPL(m10bmc_dev_init);
119*603aed8fSIlpo Järvinen 
120*603aed8fSIlpo Järvinen MODULE_DESCRIPTION("Intel MAX 10 BMC core driver");
121*603aed8fSIlpo Järvinen MODULE_AUTHOR("Intel Corporation");
122*603aed8fSIlpo Järvinen MODULE_LICENSE("GPL v2");
123