arch/x86/platform/olpc/olpc-xo1-sci.c

Source file repositories/reference/linux-study-clean/arch/x86/platform/olpc/olpc-xo1-sci.c

File Facts

System
Linux kernel
Corpus path
arch/x86/platform/olpc/olpc-xo1-sci.c
Extension
.c
Size
14976 bytes
Lines
628
Domain
Architecture Layer
Bucket
arch/x86
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

switch (data) {
		case EC_SCI_SRC_BATERR:
		case EC_SCI_SRC_BATSOC:
		case EC_SCI_SRC_BATTERY:
		case EC_SCI_SRC_BATCRIT:
			battery_status_changed();
			break;
		case EC_SCI_SRC_ACPWR:
			ac_status_changed();
			break;
		}

		if (data == EC_SCI_SRC_EBOOK && propagate_events)
			send_ebook_state();
	} while (data);

	if (r)
		pr_err(PFX "Failed to clear SCI queue");
}

static void process_sci_queue_work(struct work_struct *work)
{
	process_sci_queue(true);
}

static DECLARE_WORK(sci_work, process_sci_queue_work);

static irqreturn_t xo1_sci_intr(int irq, void *dev_id)
{
	struct platform_device *pdev = dev_id;
	u32 sts;
	u32 gpe;

	sts = inl(acpi_base + CS5536_PM1_STS);
	outl(sts | 0xffff, acpi_base + CS5536_PM1_STS);

	gpe = inl(acpi_base + CS5536_PM_GPE0_STS);
	outl(0xffffffff, acpi_base + CS5536_PM_GPE0_STS);

	dev_dbg(&pdev->dev, "sts %x gpe %x\n", sts, gpe);

	if (sts & CS5536_PWRBTN_FLAG) {
		if (!(sts & CS5536_WAK_FLAG)) {
			/* Only report power button input when it was pressed
			 * during regular operation (as opposed to when it
			 * was used to wake the system). */
			input_report_key(power_button_idev, KEY_POWER, 1);
			input_sync(power_button_idev);
			input_report_key(power_button_idev, KEY_POWER, 0);
			input_sync(power_button_idev);
		}
		/* Report the wakeup event in all cases. */
		pm_wakeup_event(&power_button_idev->dev, 0);
	}

	if ((sts & (CS5536_RTC_FLAG | CS5536_WAK_FLAG)) ==
			(CS5536_RTC_FLAG | CS5536_WAK_FLAG)) {
		/* When the system is woken by the RTC alarm, report the
		 * event on the rtc device. */
		struct device *rtc = bus_find_device_by_name(
			&platform_bus_type, NULL, "rtc_cmos");
		if (rtc) {
			pm_wakeup_event(rtc, 0);
			put_device(rtc);
		}
	}

	if (gpe & CS5536_GPIOM7_PME_FLAG) { /* EC GPIO */
		cs5535_gpio_set(OLPC_GPIO_ECSCI, GPIO_NEGATIVE_EDGE_STS);
		schedule_work(&sci_work);
	}

	cs5535_gpio_set(OLPC_GPIO_LID, GPIO_NEGATIVE_EDGE_STS);
	cs5535_gpio_set(OLPC_GPIO_LID, GPIO_POSITIVE_EDGE_STS);
	detect_lid_state();
	send_lid_state();

	return IRQ_HANDLED;
}

static int xo1_sci_suspend(struct platform_device *pdev, pm_message_t state)
{
	if (device_may_wakeup(&power_button_idev->dev))
		olpc_xo1_pm_wakeup_set(CS5536_PM_PWRBTN);
	else
		olpc_xo1_pm_wakeup_clear(CS5536_PM_PWRBTN);

	if (device_may_wakeup(&ebook_switch_idev->dev))
		olpc_ec_wakeup_set(EC_SCI_SRC_EBOOK);
	else

Annotation

Implementation Notes