drivers/staging/most/dim2/hal.c

Source file repositories/reference/linux-study-clean/drivers/staging/most/dim2/hal.c

File Facts

System
Linux kernel
Corpus path
drivers/staging/most/dim2/hal.c
Extension
.c
Size
23149 bytes
Lines
972
Domain
Driver Families
Bucket
drivers/staging
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

struct async_tx_dbr {
	u8 ch_addr;
	u16 rpc;
	u16 wpc;
	u16 rest_size;
	u16 sz_queue[CDT0_RPC_MASK + 1];
};

struct lld_global_vars_t {
	bool dim_is_initialized;
	bool mcm_is_initialized;
	struct dim2_regs __iomem *dim2; /* DIM2 core base address */
	struct async_tx_dbr atx_dbr;
	u32 fcnt;
	u32 dbr_map[DBR_MAP_SIZE];
};

static struct lld_global_vars_t g = { false };

/* -------------------------------------------------------------------------- */

static int dbr_get_mask_size(u16 size)
{
	int i;

	for (i = 0; i < 6; i++)
		if (size <= (DBR_BLOCK_SIZE << i))
			return 1 << i;
	return 0;
}

/**
 * alloc_dbr() - Allocates DBR memory.
 * @size: Allocating memory size.
 * Returns: Offset in DBR memory by success or DBR_SIZE if out of memory.
 */
static int alloc_dbr(u16 size)
{
	int mask_size;
	int i, block_idx = 0;

	if (size <= 0)
		return DBR_SIZE; /* out of memory */

	mask_size = dbr_get_mask_size(size);
	if (mask_size == 0)
		return DBR_SIZE; /* out of memory */

	for (i = 0; i < DBR_MAP_SIZE; i++) {
		u32 const blocks = DIV_ROUND_UP(size, DBR_BLOCK_SIZE);
		u32 mask = ~((~(u32)0) << blocks);

		do {
			if ((g.dbr_map[i] & mask) == 0) {
				g.dbr_map[i] |= mask;
				return block_idx * DBR_BLOCK_SIZE;
			}
			block_idx += mask_size;
			/* do shift left with 2 steps in case mask_size == 32 */
			mask <<= mask_size - 1;
		} while ((mask <<= 1) != 0);
	}

	return DBR_SIZE; /* out of memory */
}

static void free_dbr(int offs, int size)
{
	int block_idx = offs / DBR_BLOCK_SIZE;
	u32 const blocks = DIV_ROUND_UP(size, DBR_BLOCK_SIZE);
	u32 mask = ~((~(u32)0) << blocks);

	mask <<= block_idx % 32;
	g.dbr_map[block_idx / 32] &= ~mask;
}

/* -------------------------------------------------------------------------- */

static void dim2_transfer_madr(u32 val)
{
	writel(val, &g.dim2->MADR);

	/* wait for transfer completion */
	while ((readl(&g.dim2->MCTL) & 1) != 1)
		continue;

	writel(0, &g.dim2->MCTL);   /* clear transfer complete */
}

static void dim2_clear_dbr(u16 addr, u16 size)

Annotation

Implementation Notes