drivers/irqchip/irq-gic-v5-its.c

Source file repositories/reference/linux-study-clean/drivers/irqchip/irq-gic-v5-its.c

File Facts

System
Linux kernel
Corpus path
drivers/irqchip/irq-gic-v5-its.c
Extension
.c
Size
36143 bytes
Lines
1344
Domain
Driver Families
Bucket
drivers/irqchip
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 gicv5_its_chip_data {
	struct	xarray			its_devices;
	struct	mutex			dev_alloc_lock;
	struct	fwnode_handle		*fwnode;
	struct gicv5_its_devtab_cfg	devtab_cfgr;
	void	__iomem			*its_base;
	u32				flags;
	unsigned int			msi_domain_flags;
};

struct gicv5_its_dev {
	struct gicv5_its_chip_data	*its_node;
	struct gicv5_its_itt_cfg	itt_cfg;
	unsigned long			*event_map;
	u32				device_id;
	u32				num_events;
	phys_addr_t			its_trans_phys_base;
};

static u32 its_readl_relaxed(struct gicv5_its_chip_data *its_node, const u32 reg_offset)
{
	return readl_relaxed(its_node->its_base + reg_offset);
}

static void its_writel_relaxed(struct gicv5_its_chip_data *its_node, const u32 val,
			       const u32 reg_offset)
{
	writel_relaxed(val, its_node->its_base + reg_offset);
}

static void its_writeq_relaxed(struct gicv5_its_chip_data *its_node, const u64 val,
			       const u32 reg_offset)
{
	writeq_relaxed(val, its_node->its_base + reg_offset);
}

static void gicv5_its_dcache_clean(struct gicv5_its_chip_data *its, void *start,
				   size_t sz)
{
	void *end = start + sz;

	if (its->flags & ITS_FLAGS_NON_COHERENT)
		dcache_clean_inval_poc((unsigned long)start, (unsigned long)end);
	else
		dsb(ishst);
}

static void its_write_table_entry(struct gicv5_its_chip_data *its, __le64 *entry,
				  u64 val)
{
	WRITE_ONCE(*entry, cpu_to_le64(val));
	gicv5_its_dcache_clean(its, entry, sizeof(*entry));
}

#define devtab_cfgr_field(its, f)	\
	FIELD_GET(GICV5_ITS_DT_CFGR_##f, (its)->devtab_cfgr.cfgr)

static int gicv5_its_cache_sync(struct gicv5_its_chip_data *its)
{
	return gicv5_wait_for_op_atomic(its->its_base, GICV5_ITS_STATUSR,
					GICV5_ITS_STATUSR_IDLE, NULL);
}

static void gicv5_its_syncr(struct gicv5_its_chip_data *its,
			    struct gicv5_its_dev *its_dev)
{
	u64 syncr;

	syncr = FIELD_PREP(GICV5_ITS_SYNCR_SYNC, 1) |
		FIELD_PREP(GICV5_ITS_SYNCR_DEVICEID, its_dev->device_id);

	its_writeq_relaxed(its, syncr, GICV5_ITS_SYNCR);

	gicv5_wait_for_op(its->its_base, GICV5_ITS_SYNC_STATUSR, GICV5_ITS_SYNC_STATUSR_IDLE);
}

/* Number of bits required for each L2 {device/interrupt translation} table size */
#define ITS_L2SZ_64K_L2_BITS	13
#define ITS_L2SZ_16K_L2_BITS	11
#define ITS_L2SZ_4K_L2_BITS	9

static unsigned int gicv5_its_l2sz_to_l2_bits(unsigned int sz)
{
	switch (sz) {
	case GICV5_ITS_DT_ITT_CFGR_L2SZ_64k:
		return ITS_L2SZ_64K_L2_BITS;
	case GICV5_ITS_DT_ITT_CFGR_L2SZ_16k:
		return ITS_L2SZ_16K_L2_BITS;
	case GICV5_ITS_DT_ITT_CFGR_L2SZ_4k:
	default:

Annotation

Implementation Notes