drivers/bus/mhi/ep/mmio.c

Source file repositories/reference/linux-study-clean/drivers/bus/mhi/ep/mmio.c

File Facts

System
Linux kernel
Corpus path
drivers/bus/mhi/ep/mmio.c
Extension
.c
Size
7109 bytes
Lines
274
Domain
Driver Families
Bucket
drivers/bus
Inferred role
Driver Families: implementation source
Status
source 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
/*
 * Copyright (C) 2022 Linaro Ltd.
 * Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
 */

#include <linux/bitfield.h>
#include <linux/io.h>
#include <linux/mhi_ep.h>

#include "internal.h"

u32 mhi_ep_mmio_read(struct mhi_ep_cntrl *mhi_cntrl, u32 offset)
{
	return readl(mhi_cntrl->mmio + offset);
}

void mhi_ep_mmio_write(struct mhi_ep_cntrl *mhi_cntrl, u32 offset, u32 val)
{
	writel(val, mhi_cntrl->mmio + offset);
}

void mhi_ep_mmio_masked_write(struct mhi_ep_cntrl *mhi_cntrl, u32 offset, u32 mask, u32 val)
{
	u32 regval;

	regval = mhi_ep_mmio_read(mhi_cntrl, offset);
	regval &= ~mask;
	regval |= (val << __ffs(mask)) & mask;
	mhi_ep_mmio_write(mhi_cntrl, offset, regval);
}

u32 mhi_ep_mmio_masked_read(struct mhi_ep_cntrl *dev, u32 offset, u32 mask)
{
	u32 regval;

	regval = mhi_ep_mmio_read(dev, offset);
	regval &= mask;
	regval >>= __ffs(mask);

	return regval;
}

void mhi_ep_mmio_get_mhi_state(struct mhi_ep_cntrl *mhi_cntrl, enum mhi_state *state,
				bool *mhi_reset)
{
	u32 regval;

	regval = mhi_ep_mmio_read(mhi_cntrl, EP_MHICTRL);
	*state = FIELD_GET(MHICTRL_MHISTATE_MASK, regval);
	*mhi_reset = !!FIELD_GET(MHICTRL_RESET_MASK, regval);
}

static void mhi_ep_mmio_set_chdb(struct mhi_ep_cntrl *mhi_cntrl, u32 ch_id, bool enable)
{
	u32 chid_mask, chid_shift, chdb_idx, val;

	chid_shift = ch_id % 32;
	chid_mask = BIT(chid_shift);
	chdb_idx = ch_id / 32;

	val = enable ? 1 : 0;

	mhi_ep_mmio_masked_write(mhi_cntrl, MHI_CHDB_INT_MASK_n(chdb_idx), chid_mask, val);

	/* Update the local copy of the channel mask */
	mhi_cntrl->chdb[chdb_idx].mask &= ~chid_mask;
	mhi_cntrl->chdb[chdb_idx].mask |= val << chid_shift;
}

void mhi_ep_mmio_enable_chdb(struct mhi_ep_cntrl *mhi_cntrl, u32 ch_id)
{
	mhi_ep_mmio_set_chdb(mhi_cntrl, ch_id, true);
}

void mhi_ep_mmio_disable_chdb(struct mhi_ep_cntrl *mhi_cntrl, u32 ch_id)
{
	mhi_ep_mmio_set_chdb(mhi_cntrl, ch_id, false);
}

static void mhi_ep_mmio_set_chdb_interrupts(struct mhi_ep_cntrl *mhi_cntrl, bool enable)
{
	u32 val, i;

	val = enable ? MHI_CHDB_INT_MASK_n_EN_ALL : 0;

	for (i = 0; i < MHI_MASK_ROWS_CH_DB; i++) {
		mhi_ep_mmio_write(mhi_cntrl, MHI_CHDB_INT_MASK_n(i), val);
		mhi_cntrl->chdb[i].mask = val;
	}

Annotation

Implementation Notes