drivers/irqchip/irq-pruss-intc.c

Source file repositories/reference/linux-study-clean/drivers/irqchip/irq-pruss-intc.c

File Facts

System
Linux kernel
Corpus path
drivers/irqchip/irq-pruss-intc.c
Extension
.c
Size
17690 bytes
Lines
659
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 pruss_intc_map_record {
	u8 value;
	u8 ref_count;
};

/**
 * struct pruss_intc_match_data - match data to handle SoC variations
 * @num_system_events: number of input system events handled by the PRUSS INTC
 * @num_host_events: number of host events (which is equal to number of
 *		     channels) supported by the PRUSS INTC
 */
struct pruss_intc_match_data {
	u8 num_system_events;
	u8 num_host_events;
};

/**
 * struct pruss_intc - PRUSS interrupt controller structure
 * @event_channel: current state of system event to channel mappings
 * @channel_host: current state of channel to host mappings
 * @irqs: kernel irq numbers corresponding to PRUSS host interrupts
 * @base: base virtual address of INTC register space
 * @domain: irq domain for this interrupt controller
 * @soc_config: cached PRUSS INTC IP configuration data
 * @dev: PRUSS INTC device pointer
 * @lock: mutex to serialize interrupts mapping
 */
struct pruss_intc {
	struct pruss_intc_map_record event_channel[MAX_PRU_SYS_EVENTS];
	struct pruss_intc_map_record channel_host[MAX_PRU_CHANNELS];
	unsigned int irqs[MAX_NUM_HOST_IRQS];
	void __iomem *base;
	struct irq_domain *domain;
	const struct pruss_intc_match_data *soc_config;
	struct device *dev;
	struct mutex lock; /* PRUSS INTC lock */
};

/**
 * struct pruss_host_irq_data - PRUSS host irq data structure
 * @intc: PRUSS interrupt controller pointer
 * @host_irq: host irq number
 */
struct pruss_host_irq_data {
	struct pruss_intc *intc;
	u8 host_irq;
};

static inline u32 pruss_intc_read_reg(struct pruss_intc *intc, unsigned int reg)
{
	return readl_relaxed(intc->base + reg);
}

static inline void pruss_intc_write_reg(struct pruss_intc *intc,
					unsigned int reg, u32 val)
{
	writel_relaxed(val, intc->base + reg);
}

static void pruss_intc_update_cmr(struct pruss_intc *intc, unsigned int evt,
				  u8 ch)
{
	u32 idx, offset, val;

	idx = evt / CMR_EVT_PER_REG;
	offset = (evt % CMR_EVT_PER_REG) * CMR_EVT_MAP_BITS;

	val = pruss_intc_read_reg(intc, PRU_INTC_CMR(idx));
	val &= ~(CMR_EVT_MAP_MASK << offset);
	val |= ch << offset;
	pruss_intc_write_reg(intc, PRU_INTC_CMR(idx), val);

	dev_dbg(intc->dev, "SYSEV%u -> CH%d (CMR%d 0x%08x)\n", evt, ch,
		idx, pruss_intc_read_reg(intc, PRU_INTC_CMR(idx)));
}

static void pruss_intc_update_hmr(struct pruss_intc *intc, u8 ch, u8 host)
{
	u32 idx, offset, val;

	idx = ch / HMR_CH_PER_REG;
	offset = (ch % HMR_CH_PER_REG) * HMR_CH_MAP_BITS;

	val = pruss_intc_read_reg(intc, PRU_INTC_HMR(idx));
	val &= ~(HMR_CH_MAP_MASK << offset);
	val |= host << offset;
	pruss_intc_write_reg(intc, PRU_INTC_HMR(idx), val);

	dev_dbg(intc->dev, "CH%d -> HOST%d (HMR%d 0x%08x)\n", ch, host, idx,
		pruss_intc_read_reg(intc, PRU_INTC_HMR(idx)));

Annotation

Implementation Notes