brintos

brintos / linux-shallow public Read only

0
0
Text · 5.9 KiB · 8ad5b38 Raw
209 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Intel MAX 10 Board Management Controller chip - common code4 *5 * Copyright (C) 2018-2020 Intel Corporation. All rights reserved.6 */7 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>14 15void m10bmc_fw_state_set(struct intel_m10bmc *m10bmc, enum m10bmc_fw_state new_state)16{17	/* bmcfw_state is only needed if handshake_sys_reg_nranges > 0 */18	if (!m10bmc->info->handshake_sys_reg_nranges)19		return;20 21	down_write(&m10bmc->bmcfw_lock);22	m10bmc->bmcfw_state = new_state;23	up_write(&m10bmc->bmcfw_lock);24}25EXPORT_SYMBOL_NS_GPL(m10bmc_fw_state_set, INTEL_M10_BMC_CORE);26 27/*28 * For some Intel FPGA devices, the BMC firmware is not available to service29 * handshake registers during a secure update.30 */31static bool m10bmc_reg_always_available(struct intel_m10bmc *m10bmc, unsigned int offset)32{33	if (!m10bmc->info->handshake_sys_reg_nranges)34		return true;35 36	return !regmap_reg_in_ranges(offset, m10bmc->info->handshake_sys_reg_ranges,37				     m10bmc->info->handshake_sys_reg_nranges);38}39 40/*41 * m10bmc_handshake_reg_unavailable - Checks if reg access collides with secure update state42 * @m10bmc: M10 BMC structure43 *44 * For some Intel FPGA devices, the BMC firmware is not available to service45 * handshake registers during a secure update erase and write phases.46 *47 * Context: @m10bmc->bmcfw_lock must be held.48 */49static bool m10bmc_handshake_reg_unavailable(struct intel_m10bmc *m10bmc)50{51	return m10bmc->bmcfw_state == M10BMC_FW_STATE_SEC_UPDATE_PREPARE ||52	       m10bmc->bmcfw_state == M10BMC_FW_STATE_SEC_UPDATE_WRITE;53}54 55/*56 * This function helps to simplify the accessing of the system registers.57 *58 * The base of the system registers is configured through the struct59 * csr_map.60 */61int m10bmc_sys_read(struct intel_m10bmc *m10bmc, unsigned int offset, unsigned int *val)62{63	const struct m10bmc_csr_map *csr_map = m10bmc->info->csr_map;64	int ret;65 66	if (m10bmc_reg_always_available(m10bmc, offset))67		return m10bmc_raw_read(m10bmc, csr_map->base + offset, val);68 69	down_read(&m10bmc->bmcfw_lock);70	if (m10bmc_handshake_reg_unavailable(m10bmc))71		ret = -EBUSY;	/* Reg not available during secure update */72	else73		ret = m10bmc_raw_read(m10bmc, csr_map->base + offset, val);74	up_read(&m10bmc->bmcfw_lock);75 76	return ret;77}78EXPORT_SYMBOL_NS_GPL(m10bmc_sys_read, INTEL_M10_BMC_CORE);79 80int m10bmc_sys_update_bits(struct intel_m10bmc *m10bmc, unsigned int offset,81			   unsigned int msk, unsigned int val)82{83	const struct m10bmc_csr_map *csr_map = m10bmc->info->csr_map;84	int ret;85 86	if (m10bmc_reg_always_available(m10bmc, offset))87		return regmap_update_bits(m10bmc->regmap, csr_map->base + offset, msk, val);88 89	down_read(&m10bmc->bmcfw_lock);90	if (m10bmc_handshake_reg_unavailable(m10bmc))91		ret = -EBUSY;	/* Reg not available during secure update */92	else93		ret = regmap_update_bits(m10bmc->regmap, csr_map->base + offset, msk, val);94	up_read(&m10bmc->bmcfw_lock);95 96	return ret;97}98EXPORT_SYMBOL_NS_GPL(m10bmc_sys_update_bits, INTEL_M10_BMC_CORE);99 100static ssize_t bmc_version_show(struct device *dev,101				struct device_attribute *attr, char *buf)102{103	struct intel_m10bmc *ddata = dev_get_drvdata(dev);104	unsigned int val;105	int ret;106 107	ret = m10bmc_sys_read(ddata, ddata->info->csr_map->build_version, &val);108	if (ret)109		return ret;110 111	return sprintf(buf, "0x%x\n", val);112}113static DEVICE_ATTR_RO(bmc_version);114 115static ssize_t bmcfw_version_show(struct device *dev,116				  struct device_attribute *attr, char *buf)117{118	struct intel_m10bmc *ddata = dev_get_drvdata(dev);119	unsigned int val;120	int ret;121 122	ret = m10bmc_sys_read(ddata, ddata->info->csr_map->fw_version, &val);123	if (ret)124		return ret;125 126	return sprintf(buf, "0x%x\n", val);127}128static DEVICE_ATTR_RO(bmcfw_version);129 130static ssize_t mac_address_show(struct device *dev,131				struct device_attribute *attr, char *buf)132{133	struct intel_m10bmc *ddata = dev_get_drvdata(dev);134	unsigned int macaddr_low, macaddr_high;135	int ret;136 137	ret = m10bmc_sys_read(ddata, ddata->info->csr_map->mac_low, &macaddr_low);138	if (ret)139		return ret;140 141	ret = m10bmc_sys_read(ddata, ddata->info->csr_map->mac_high, &macaddr_high);142	if (ret)143		return ret;144 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));152}153static DEVICE_ATTR_RO(mac_address);154 155static ssize_t mac_count_show(struct device *dev,156			      struct device_attribute *attr, char *buf)157{158	struct intel_m10bmc *ddata = dev_get_drvdata(dev);159	unsigned int macaddr_high;160	int ret;161 162	ret = m10bmc_sys_read(ddata, ddata->info->csr_map->mac_high, &macaddr_high);163	if (ret)164		return ret;165 166	return sysfs_emit(buf, "%u\n", (u8)FIELD_GET(M10BMC_N3000_MAC_COUNT, macaddr_high));167}168static DEVICE_ATTR_RO(mac_count);169 170static 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,175	NULL,176};177 178static const struct attribute_group m10bmc_group = {179	.attrs = m10bmc_attrs,180};181 182const struct attribute_group *m10bmc_dev_groups[] = {183	&m10bmc_group,184	NULL,185};186EXPORT_SYMBOL_NS_GPL(m10bmc_dev_groups, INTEL_M10_BMC_CORE);187 188int m10bmc_dev_init(struct intel_m10bmc *m10bmc, const struct intel_m10bmc_platform_info *info)189{190	int ret;191 192	m10bmc->info = info;193	dev_set_drvdata(m10bmc->dev, m10bmc);194	init_rwsem(&m10bmc->bmcfw_lock);195 196	ret = devm_mfd_add_devices(m10bmc->dev, PLATFORM_DEVID_AUTO,197				   info->cells, info->n_cells,198				   NULL, 0, NULL);199	if (ret)200		dev_err(m10bmc->dev, "Failed to register sub-devices: %d\n", ret);201 202	return ret;203}204EXPORT_SYMBOL_NS_GPL(m10bmc_dev_init, INTEL_M10_BMC_CORE);205 206MODULE_DESCRIPTION("Intel MAX 10 BMC core driver");207MODULE_AUTHOR("Intel Corporation");208MODULE_LICENSE("GPL v2");209