drivers/mfd/menelaus.c

Source file repositories/reference/linux-study-clean/drivers/mfd/menelaus.c

File Facts

System
Linux kernel
Corpus path
drivers/mfd/menelaus.c
Extension
.c
Size
29932 bytes
Lines
1252
Domain
Driver Families
Bucket
drivers/mfd
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 menelaus_chip {
	struct mutex		lock;
	struct i2c_client	*client;
	struct work_struct	work;
#ifdef CONFIG_RTC_DRV_TWL92330
	struct rtc_device	*rtc;
	u8			rtc_control;
	unsigned		uie:1;
#endif
	unsigned		vcore_hw_mode:1;
	u8			mask1, mask2;
	void			(*handlers[16])(struct menelaus_chip *);
	void			(*mmc_callback)(void *data, u8 mask);
	void			*mmc_callback_data;
};

static struct menelaus_chip *the_menelaus;

static int menelaus_write_reg(int reg, u8 value)
{
	int val = i2c_smbus_write_byte_data(the_menelaus->client, reg, value);

	if (val < 0) {
		pr_err(DRIVER_NAME ": write error");
		return val;
	}

	return 0;
}

static int menelaus_read_reg(int reg)
{
	int val = i2c_smbus_read_byte_data(the_menelaus->client, reg);

	if (val < 0)
		pr_err(DRIVER_NAME ": read error");

	return val;
}

static int menelaus_enable_irq(int irq)
{
	if (irq > 7) {
		irq -= 8;
		the_menelaus->mask2 &= ~(1 << irq);
		return menelaus_write_reg(MENELAUS_INT_MASK2,
				the_menelaus->mask2);
	} else {
		the_menelaus->mask1 &= ~(1 << irq);
		return menelaus_write_reg(MENELAUS_INT_MASK1,
				the_menelaus->mask1);
	}
}

static int menelaus_disable_irq(int irq)
{
	if (irq > 7) {
		irq -= 8;
		the_menelaus->mask2 |= (1 << irq);
		return menelaus_write_reg(MENELAUS_INT_MASK2,
				the_menelaus->mask2);
	} else {
		the_menelaus->mask1 |= (1 << irq);
		return menelaus_write_reg(MENELAUS_INT_MASK1,
				the_menelaus->mask1);
	}
}

static int menelaus_ack_irq(int irq)
{
	if (irq > 7)
		return menelaus_write_reg(MENELAUS_INT_ACK2, 1 << (irq - 8));
	else
		return menelaus_write_reg(MENELAUS_INT_ACK1, 1 << irq);
}

/* Adds a handler for an interrupt. Does not run in interrupt context */
static int menelaus_add_irq_work(int irq,
		void (*handler)(struct menelaus_chip *))
{
	int ret = 0;

	mutex_lock(&the_menelaus->lock);
	the_menelaus->handlers[irq] = handler;
	ret = menelaus_enable_irq(irq);
	mutex_unlock(&the_menelaus->lock);

	return ret;
}

Annotation

Implementation Notes