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

Source file repositories/reference/linux-study-clean/drivers/mfd/intel-m10-bmc-core.c

File Facts

System
Linux kernel
Corpus path
drivers/mfd/intel-m10-bmc-core.c
Extension
.c
Size
6102 bytes
Lines
209
Domain
Driver Families
Bucket
drivers/mfd
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0
/*
 * Intel MAX 10 Board Management Controller chip - common code
 *
 * Copyright (C) 2018-2020 Intel Corporation. All rights reserved.
 */

#include <linux/bitfield.h>
#include <linux/device.h>
#include <linux/dev_printk.h>
#include <linux/mfd/core.h>
#include <linux/mfd/intel-m10-bmc.h>
#include <linux/module.h>

void m10bmc_fw_state_set(struct intel_m10bmc *m10bmc, enum m10bmc_fw_state new_state)
{
	/* bmcfw_state is only needed if handshake_sys_reg_nranges > 0 */
	if (!m10bmc->info->handshake_sys_reg_nranges)
		return;

	down_write(&m10bmc->bmcfw_lock);
	m10bmc->bmcfw_state = new_state;
	up_write(&m10bmc->bmcfw_lock);
}
EXPORT_SYMBOL_NS_GPL(m10bmc_fw_state_set, "INTEL_M10_BMC_CORE");

/*
 * For some Intel FPGA devices, the BMC firmware is not available to service
 * handshake registers during a secure update.
 */
static bool m10bmc_reg_always_available(struct intel_m10bmc *m10bmc, unsigned int offset)
{
	if (!m10bmc->info->handshake_sys_reg_nranges)
		return true;

	return !regmap_reg_in_ranges(offset, m10bmc->info->handshake_sys_reg_ranges,
				     m10bmc->info->handshake_sys_reg_nranges);
}

/*
 * m10bmc_handshake_reg_unavailable - Checks if reg access collides with secure update state
 * @m10bmc: M10 BMC structure
 *
 * For some Intel FPGA devices, the BMC firmware is not available to service
 * handshake registers during a secure update erase and write phases.
 *
 * Context: @m10bmc->bmcfw_lock must be held.
 */
static bool m10bmc_handshake_reg_unavailable(struct intel_m10bmc *m10bmc)
{
	return m10bmc->bmcfw_state == M10BMC_FW_STATE_SEC_UPDATE_PREPARE ||
	       m10bmc->bmcfw_state == M10BMC_FW_STATE_SEC_UPDATE_WRITE;
}

/*
 * This function helps to simplify the accessing of the system registers.
 *
 * The base of the system registers is configured through the struct
 * csr_map.
 */
int m10bmc_sys_read(struct intel_m10bmc *m10bmc, unsigned int offset, unsigned int *val)
{
	const struct m10bmc_csr_map *csr_map = m10bmc->info->csr_map;
	int ret;

	if (m10bmc_reg_always_available(m10bmc, offset))
		return m10bmc_raw_read(m10bmc, csr_map->base + offset, val);

	down_read(&m10bmc->bmcfw_lock);
	if (m10bmc_handshake_reg_unavailable(m10bmc))
		ret = -EBUSY;	/* Reg not available during secure update */
	else
		ret = m10bmc_raw_read(m10bmc, csr_map->base + offset, val);
	up_read(&m10bmc->bmcfw_lock);

	return ret;
}
EXPORT_SYMBOL_NS_GPL(m10bmc_sys_read, "INTEL_M10_BMC_CORE");

int m10bmc_sys_update_bits(struct intel_m10bmc *m10bmc, unsigned int offset,
			   unsigned int msk, unsigned int val)
{
	const struct m10bmc_csr_map *csr_map = m10bmc->info->csr_map;
	int ret;

	if (m10bmc_reg_always_available(m10bmc, offset))
		return regmap_update_bits(m10bmc->regmap, csr_map->base + offset, msk, val);

	down_read(&m10bmc->bmcfw_lock);
	if (m10bmc_handshake_reg_unavailable(m10bmc))

Annotation

Implementation Notes