1603aed8fSIlpo Järvinen // SPDX-License-Identifier: GPL-2.0 2603aed8fSIlpo Järvinen /* 3603aed8fSIlpo Järvinen * Intel MAX 10 Board Management Controller chip - common code 4603aed8fSIlpo Järvinen * 5603aed8fSIlpo Järvinen * Copyright (C) 2018-2020 Intel Corporation. All rights reserved. 6603aed8fSIlpo Järvinen */ 7603aed8fSIlpo Järvinen 8603aed8fSIlpo Järvinen #include <linux/bitfield.h> 9603aed8fSIlpo Järvinen #include <linux/device.h> 10603aed8fSIlpo Järvinen #include <linux/dev_printk.h> 11603aed8fSIlpo Järvinen #include <linux/mfd/core.h> 12603aed8fSIlpo Järvinen #include <linux/mfd/intel-m10-bmc.h> 13603aed8fSIlpo Järvinen #include <linux/module.h> 14603aed8fSIlpo Järvinen 15*e9c154eeSIlpo Järvinen /* 16*e9c154eeSIlpo Järvinen * This function helps to simplify the accessing of the system registers. 17*e9c154eeSIlpo Järvinen * 18*e9c154eeSIlpo Järvinen * The base of the system registers is configured through the struct 19*e9c154eeSIlpo Järvinen * csr_map. 20*e9c154eeSIlpo Järvinen */ 21*e9c154eeSIlpo Järvinen int m10bmc_sys_read(struct intel_m10bmc *m10bmc, unsigned int offset, unsigned int *val) 22*e9c154eeSIlpo Järvinen { 23*e9c154eeSIlpo Järvinen const struct m10bmc_csr_map *csr_map = m10bmc->info->csr_map; 24*e9c154eeSIlpo Järvinen 25*e9c154eeSIlpo Järvinen return m10bmc_raw_read(m10bmc, csr_map->base + offset, val); 26*e9c154eeSIlpo Järvinen } 27*e9c154eeSIlpo Järvinen EXPORT_SYMBOL_NS_GPL(m10bmc_sys_read, INTEL_M10_BMC_CORE); 28*e9c154eeSIlpo Järvinen 29c452e3bdSIlpo Järvinen int m10bmc_sys_update_bits(struct intel_m10bmc *m10bmc, unsigned int offset, 30c452e3bdSIlpo Järvinen unsigned int msk, unsigned int val) 31c452e3bdSIlpo Järvinen { 32c452e3bdSIlpo Järvinen const struct m10bmc_csr_map *csr_map = m10bmc->info->csr_map; 33c452e3bdSIlpo Järvinen 34c452e3bdSIlpo Järvinen return regmap_update_bits(m10bmc->regmap, csr_map->base + offset, msk, val); 35c452e3bdSIlpo Järvinen } 36c452e3bdSIlpo Järvinen EXPORT_SYMBOL_NS_GPL(m10bmc_sys_update_bits, INTEL_M10_BMC_CORE); 37c452e3bdSIlpo Järvinen 38603aed8fSIlpo Järvinen static ssize_t bmc_version_show(struct device *dev, 39603aed8fSIlpo Järvinen struct device_attribute *attr, char *buf) 40603aed8fSIlpo Järvinen { 41603aed8fSIlpo Järvinen struct intel_m10bmc *ddata = dev_get_drvdata(dev); 42603aed8fSIlpo Järvinen unsigned int val; 43603aed8fSIlpo Järvinen int ret; 44603aed8fSIlpo Järvinen 456052a005SIlpo Järvinen ret = m10bmc_sys_read(ddata, ddata->info->csr_map->build_version, &val); 46603aed8fSIlpo Järvinen if (ret) 47603aed8fSIlpo Järvinen return ret; 48603aed8fSIlpo Järvinen 49603aed8fSIlpo Järvinen return sprintf(buf, "0x%x\n", val); 50603aed8fSIlpo Järvinen } 51603aed8fSIlpo Järvinen static DEVICE_ATTR_RO(bmc_version); 52603aed8fSIlpo Järvinen 53603aed8fSIlpo Järvinen static ssize_t bmcfw_version_show(struct device *dev, 54603aed8fSIlpo Järvinen struct device_attribute *attr, char *buf) 55603aed8fSIlpo Järvinen { 56603aed8fSIlpo Järvinen struct intel_m10bmc *ddata = dev_get_drvdata(dev); 57603aed8fSIlpo Järvinen unsigned int val; 58603aed8fSIlpo Järvinen int ret; 59603aed8fSIlpo Järvinen 606052a005SIlpo Järvinen ret = m10bmc_sys_read(ddata, ddata->info->csr_map->fw_version, &val); 61603aed8fSIlpo Järvinen if (ret) 62603aed8fSIlpo Järvinen return ret; 63603aed8fSIlpo Järvinen 64603aed8fSIlpo Järvinen return sprintf(buf, "0x%x\n", val); 65603aed8fSIlpo Järvinen } 66603aed8fSIlpo Järvinen static DEVICE_ATTR_RO(bmcfw_version); 67603aed8fSIlpo Järvinen 68603aed8fSIlpo Järvinen static ssize_t mac_address_show(struct device *dev, 69603aed8fSIlpo Järvinen struct device_attribute *attr, char *buf) 70603aed8fSIlpo Järvinen { 71603aed8fSIlpo Järvinen struct intel_m10bmc *ddata = dev_get_drvdata(dev); 72603aed8fSIlpo Järvinen unsigned int macaddr_low, macaddr_high; 73603aed8fSIlpo Järvinen int ret; 74603aed8fSIlpo Järvinen 756052a005SIlpo Järvinen ret = m10bmc_sys_read(ddata, ddata->info->csr_map->mac_low, &macaddr_low); 76603aed8fSIlpo Järvinen if (ret) 77603aed8fSIlpo Järvinen return ret; 78603aed8fSIlpo Järvinen 796052a005SIlpo Järvinen ret = m10bmc_sys_read(ddata, ddata->info->csr_map->mac_high, &macaddr_high); 80603aed8fSIlpo Järvinen if (ret) 81603aed8fSIlpo Järvinen return ret; 82603aed8fSIlpo Järvinen 83603aed8fSIlpo Järvinen return sysfs_emit(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n", 84bcababfcSIlpo Järvinen (u8)FIELD_GET(M10BMC_N3000_MAC_BYTE1, macaddr_low), 85bcababfcSIlpo Järvinen (u8)FIELD_GET(M10BMC_N3000_MAC_BYTE2, macaddr_low), 86bcababfcSIlpo Järvinen (u8)FIELD_GET(M10BMC_N3000_MAC_BYTE3, macaddr_low), 87bcababfcSIlpo Järvinen (u8)FIELD_GET(M10BMC_N3000_MAC_BYTE4, macaddr_low), 88bcababfcSIlpo Järvinen (u8)FIELD_GET(M10BMC_N3000_MAC_BYTE5, macaddr_high), 89bcababfcSIlpo Järvinen (u8)FIELD_GET(M10BMC_N3000_MAC_BYTE6, macaddr_high)); 90603aed8fSIlpo Järvinen } 91603aed8fSIlpo Järvinen static DEVICE_ATTR_RO(mac_address); 92603aed8fSIlpo Järvinen 93603aed8fSIlpo Järvinen static ssize_t mac_count_show(struct device *dev, 94603aed8fSIlpo Järvinen struct device_attribute *attr, char *buf) 95603aed8fSIlpo Järvinen { 96603aed8fSIlpo Järvinen struct intel_m10bmc *ddata = dev_get_drvdata(dev); 97603aed8fSIlpo Järvinen unsigned int macaddr_high; 98603aed8fSIlpo Järvinen int ret; 99603aed8fSIlpo Järvinen 1006052a005SIlpo Järvinen ret = m10bmc_sys_read(ddata, ddata->info->csr_map->mac_high, &macaddr_high); 101603aed8fSIlpo Järvinen if (ret) 102603aed8fSIlpo Järvinen return ret; 103603aed8fSIlpo Järvinen 104bcababfcSIlpo Järvinen return sysfs_emit(buf, "%u\n", (u8)FIELD_GET(M10BMC_N3000_MAC_COUNT, macaddr_high)); 105603aed8fSIlpo Järvinen } 106603aed8fSIlpo Järvinen static DEVICE_ATTR_RO(mac_count); 107603aed8fSIlpo Järvinen 108603aed8fSIlpo Järvinen static struct attribute *m10bmc_attrs[] = { 109603aed8fSIlpo Järvinen &dev_attr_bmc_version.attr, 110603aed8fSIlpo Järvinen &dev_attr_bmcfw_version.attr, 111603aed8fSIlpo Järvinen &dev_attr_mac_address.attr, 112603aed8fSIlpo Järvinen &dev_attr_mac_count.attr, 113603aed8fSIlpo Järvinen NULL, 114603aed8fSIlpo Järvinen }; 115603aed8fSIlpo Järvinen 116603aed8fSIlpo Järvinen static const struct attribute_group m10bmc_group = { 117603aed8fSIlpo Järvinen .attrs = m10bmc_attrs, 118603aed8fSIlpo Järvinen }; 119603aed8fSIlpo Järvinen 120603aed8fSIlpo Järvinen const struct attribute_group *m10bmc_dev_groups[] = { 121603aed8fSIlpo Järvinen &m10bmc_group, 122603aed8fSIlpo Järvinen NULL, 123603aed8fSIlpo Järvinen }; 124b3ecc7f3SIlpo Järvinen EXPORT_SYMBOL_NS_GPL(m10bmc_dev_groups, INTEL_M10_BMC_CORE); 125603aed8fSIlpo Järvinen 126603aed8fSIlpo Järvinen int m10bmc_dev_init(struct intel_m10bmc *m10bmc, const struct intel_m10bmc_platform_info *info) 127603aed8fSIlpo Järvinen { 128603aed8fSIlpo Järvinen int ret; 129603aed8fSIlpo Järvinen 130603aed8fSIlpo Järvinen m10bmc->info = info; 131603aed8fSIlpo Järvinen dev_set_drvdata(m10bmc->dev, m10bmc); 132603aed8fSIlpo Järvinen 133603aed8fSIlpo Järvinen ret = devm_mfd_add_devices(m10bmc->dev, PLATFORM_DEVID_AUTO, 134603aed8fSIlpo Järvinen info->cells, info->n_cells, 135603aed8fSIlpo Järvinen NULL, 0, NULL); 136603aed8fSIlpo Järvinen if (ret) 137603aed8fSIlpo Järvinen dev_err(m10bmc->dev, "Failed to register sub-devices: %d\n", ret); 138603aed8fSIlpo Järvinen 139603aed8fSIlpo Järvinen return ret; 140603aed8fSIlpo Järvinen } 141b3ecc7f3SIlpo Järvinen EXPORT_SYMBOL_NS_GPL(m10bmc_dev_init, INTEL_M10_BMC_CORE); 142603aed8fSIlpo Järvinen 143603aed8fSIlpo Järvinen MODULE_DESCRIPTION("Intel MAX 10 BMC core driver"); 144603aed8fSIlpo Järvinen MODULE_AUTHOR("Intel Corporation"); 145603aed8fSIlpo Järvinen MODULE_LICENSE("GPL v2"); 146