drivers/firmware/imx/imx-scu-irq.c

Source file repositories/reference/linux-study-clean/drivers/firmware/imx/imx-scu-irq.c

File Facts

System
Linux kernel
Corpus path
drivers/firmware/imx/imx-scu-irq.c
Extension
.c
Size
5868 bytes
Lines
262
Domain
Driver Families
Bucket
drivers/firmware
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

struct imx_sc_msg_irq_get_status {
	struct imx_sc_rpc_msg hdr;
	union {
		struct {
			u16 resource;
			u8 group;
			u8 reserved;
		} __packed req;
		struct {
			u32 status;
		} resp;
	} data;
};

struct imx_sc_msg_irq_enable {
	struct imx_sc_rpc_msg hdr;
	u32 mask;
	u16 resource;
	u8 group;
	u8 enable;
} __packed;

struct scu_wakeup {
	u32 mask;
	u32 wakeup_src;
	bool valid;
};

/* Sysfs functions */
static struct kobject *wakeup_obj;
static ssize_t wakeup_source_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf);
static struct kobj_attribute wakeup_source_attr =
		__ATTR(wakeup_src, 0660, wakeup_source_show, NULL);

static struct scu_wakeup scu_irq_wakeup[IMX_SC_IRQ_NUM_GROUP];

static struct imx_sc_ipc *imx_sc_irq_ipc_handle;
static struct work_struct imx_sc_irq_work;
static BLOCKING_NOTIFIER_HEAD(imx_scu_irq_notifier_chain);

int imx_scu_irq_register_notifier(struct notifier_block *nb)
{
	return blocking_notifier_chain_register(
		&imx_scu_irq_notifier_chain, nb);
}
EXPORT_SYMBOL(imx_scu_irq_register_notifier);

int imx_scu_irq_unregister_notifier(struct notifier_block *nb)
{
	return blocking_notifier_chain_unregister(
		&imx_scu_irq_notifier_chain, nb);
}
EXPORT_SYMBOL(imx_scu_irq_unregister_notifier);

static int imx_scu_irq_notifier_call_chain(unsigned long status, u8 *group)
{
	return blocking_notifier_call_chain(&imx_scu_irq_notifier_chain,
		status, (void *)group);
}

static void imx_scu_irq_work_handler(struct work_struct *work)
{
	u32 irq_status;
	int ret;
	u8 i;

	for (i = 0; i < IMX_SC_IRQ_NUM_GROUP; i++) {
		if (scu_irq_wakeup[i].mask) {
			scu_irq_wakeup[i].valid = false;
			scu_irq_wakeup[i].wakeup_src = 0;
		}

		ret = imx_scu_irq_get_status(i, &irq_status);
		if (ret) {
			pr_err("get irq group %d status failed, ret %d\n",
			       i, ret);
			return;
		}

		if (!irq_status)
			continue;
		if (scu_irq_wakeup[i].mask & irq_status) {
			scu_irq_wakeup[i].valid = true;
			scu_irq_wakeup[i].wakeup_src = irq_status & scu_irq_wakeup[i].mask;
		} else {
			scu_irq_wakeup[i].wakeup_src = irq_status;
		}

		pm_system_wakeup();
		imx_scu_irq_notifier_call_chain(irq_status, &i);

Annotation

Implementation Notes