drivers/input/misc/palmas-pwrbutton.c

Source file repositories/reference/linux-study-clean/drivers/input/misc/palmas-pwrbutton.c

File Facts

System
Linux kernel
Corpus path
drivers/input/misc/palmas-pwrbutton.c
Extension
.c
Size
8020 bytes
Lines
326
Domain
Driver Families
Bucket
drivers/input
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 palmas_pwron {
	struct palmas *palmas;
	struct input_dev *input_dev;
	struct delayed_work input_work;
	int irq;
};

/**
 * struct palmas_pwron_config - configuration of palmas power on
 * @long_press_time_val:	value for long press h/w shutdown event
 * @pwron_debounce_val:		value for debounce of power button
 */
struct palmas_pwron_config {
	u8 long_press_time_val;
	u8 pwron_debounce_val;
};

/**
 * palmas_power_button_work() - Detects the button release event
 * @work:	work item to detect button release
 */
static void palmas_power_button_work(struct work_struct *work)
{
	struct palmas_pwron *pwron = container_of(work,
						  struct palmas_pwron,
						  input_work.work);
	struct input_dev *input_dev = pwron->input_dev;
	unsigned int reg;
	int error;

	error = palmas_read(pwron->palmas, PALMAS_INTERRUPT_BASE,
			    PALMAS_INT1_LINE_STATE, &reg);
	if (error) {
		dev_err(input_dev->dev.parent,
			"Cannot read palmas PWRON status: %d\n", error);
	} else if (reg & BIT(1)) {
		/* The button is released, report event. */
		input_report_key(input_dev, KEY_POWER, 0);
		input_sync(input_dev);
	} else {
		/* The button is still depressed, keep checking. */
		schedule_delayed_work(&pwron->input_work,
				msecs_to_jiffies(PALMAS_PWR_KEY_Q_TIME_MS));
	}
}

/**
 * pwron_irq() - button press isr
 * @irq:		irq
 * @palmas_pwron:	pwron struct
 *
 * Return: IRQ_HANDLED
 */
static irqreturn_t pwron_irq(int irq, void *palmas_pwron)
{
	struct palmas_pwron *pwron = palmas_pwron;
	struct input_dev *input_dev = pwron->input_dev;

	input_report_key(input_dev, KEY_POWER, 1);
	pm_wakeup_event(input_dev->dev.parent, 0);
	input_sync(input_dev);

	mod_delayed_work(system_dfl_wq, &pwron->input_work,
			 msecs_to_jiffies(PALMAS_PWR_KEY_Q_TIME_MS));

	return IRQ_HANDLED;
}

/**
 * palmas_pwron_params_ofinit() - device tree parameter parser
 * @dev:	palmas button device
 * @config:	configuration params that this fills up
 */
static void palmas_pwron_params_ofinit(struct device *dev,
				       struct palmas_pwron_config *config)
{
	struct device_node *np;
	u32 val;
	int i, error;
	static const u8 lpk_times[] = { 6, 8, 10, 12 };
	static const int pwr_on_deb_ms[] = { 15, 100, 500, 1000 };

	memset(config, 0, sizeof(*config));

	/* Default config parameters */
	config->long_press_time_val = ARRAY_SIZE(lpk_times) - 1;

	np = dev->of_node;
	if (!np)
		return;

Annotation

Implementation Notes