Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 17b1639b authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

Merge branch 'acpi-lpss'

* acpi-lpss:
  ACPI / platform: create LPSS clocks if Lynxpoint devices are found during scan
  clk: x86: add support for Lynxpoint LPSS clocks
  x86: add support for Intel Low Power Subsystem
  ACPI / platform: fix comment about the platform device name
  ACPI: add support for CSRT table
parents a9834cb2 e375325c
Loading
Loading
Loading
Loading
+10 −0
Original line number Original line Diff line number Diff line
@@ -454,6 +454,16 @@ config X86_MDFLD


endif
endif


config X86_INTEL_LPSS
	bool "Intel Low Power Subsystem Support"
	depends on ACPI
	select COMMON_CLK
	---help---
	  Select to build support for Intel Low Power Subsystem such as
	  found on Intel Lynxpoint PCH. Selecting this option enables
	  things like clock tree (common clock framework) which are needed
	  by the LPSS peripheral drivers.

config X86_RDC321X
config X86_RDC321X
	bool "RDC R-321x SoC"
	bool "RDC R-321x SoC"
	depends on X86_32
	depends on X86_32
+1 −0
Original line number Original line Diff line number Diff line
@@ -38,6 +38,7 @@ acpi-y += processor_core.o
acpi-y				+= ec.o
acpi-y				+= ec.o
acpi-$(CONFIG_ACPI_DOCK)	+= dock.o
acpi-$(CONFIG_ACPI_DOCK)	+= dock.o
acpi-y				+= pci_root.o pci_link.o pci_irq.o
acpi-y				+= pci_root.o pci_link.o pci_irq.o
acpi-y				+= csrt.o
acpi-y				+= acpi_platform.o
acpi-y				+= acpi_platform.o
acpi-y				+= power.o
acpi-y				+= power.o
acpi-y				+= event.o
acpi-y				+= event.o
+25 −2
Original line number Original line Diff line number Diff line
@@ -13,6 +13,7 @@


#include <linux/acpi.h>
#include <linux/acpi.h>
#include <linux/device.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/platform_device.h>
@@ -21,17 +22,34 @@


ACPI_MODULE_NAME("platform");
ACPI_MODULE_NAME("platform");


static int acpi_create_platform_clks(struct acpi_device *adev)
{
	static struct platform_device *pdev;

	/* Create Lynxpoint LPSS clocks */
	if (!pdev && !strncmp(acpi_device_hid(adev), "INT33C", 6)) {
		pdev = platform_device_register_simple("clk-lpt", -1, NULL, 0);
		if (IS_ERR(pdev))
			return PTR_ERR(pdev);
	}

	return 0;
}

/**
/**
 * acpi_create_platform_device - Create platform device for ACPI device node
 * acpi_create_platform_device - Create platform device for ACPI device node
 * @adev: ACPI device node to create a platform device for.
 * @adev: ACPI device node to create a platform device for.
 * @flags: ACPI_PLATFORM_* flags that affect the creation of the platform
 *	   devices.
 *
 *
 * Check if the given @adev can be represented as a platform device and, if
 * Check if the given @adev can be represented as a platform device and, if
 * that's the case, create and register a platform device, populate its common
 * that's the case, create and register a platform device, populate its common
 * resources and returns a pointer to it.  Otherwise, return %NULL.
 * resources and returns a pointer to it.  Otherwise, return %NULL.
 *
 *
 * The platform device's name will be taken from the @adev's _HID and _UID.
 * Name of the platform device will be the same as @adev's.
 */
 */
struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
						    unsigned long flags)
{
{
	struct platform_device *pdev = NULL;
	struct platform_device *pdev = NULL;
	struct acpi_device *acpi_parent;
	struct acpi_device *acpi_parent;
@@ -41,6 +59,11 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
	struct resource *resources;
	struct resource *resources;
	int count;
	int count;


	if ((flags & ACPI_PLATFORM_CLK) && acpi_create_platform_clks(adev)) {
		dev_err(&adev->dev, "failed to create clocks\n");
		return NULL;
	}

	/* If the ACPI node already has a physical device attached, skip it. */
	/* If the ACPI node already has a physical device attached, skip it. */
	if (adev->physical_node_count)
	if (adev->physical_node_count)
		return NULL;
		return NULL;

drivers/acpi/csrt.c

0 → 100644
+159 −0
Original line number Original line Diff line number Diff line
/*
 * Support for Core System Resources Table (CSRT)
 *
 * Copyright (C) 2013, Intel Corporation
 * Authors: Mika Westerberg <mika.westerberg@linux.intel.com>
 *	    Andy Shevchenko <andriy.shevchenko@linux.intel.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#define pr_fmt(fmt) "ACPI: CSRT: " fmt

#include <linux/acpi.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/sizes.h>

ACPI_MODULE_NAME("CSRT");

static int __init acpi_csrt_parse_shared_info(struct platform_device *pdev,
					      const struct acpi_csrt_group *grp)
{
	const struct acpi_csrt_shared_info *si;
	struct resource res[3];
	size_t nres;
	int ret;

	memset(res, 0, sizeof(res));
	nres = 0;

	si = (const struct acpi_csrt_shared_info *)&grp[1];
	/*
	 * The peripherals that are listed on CSRT typically support only
	 * 32-bit addresses so we only use the low part of MMIO base for
	 * now.
	 */
	if (!si->mmio_base_high && si->mmio_base_low) {
		/*
		 * There is no size of the memory resource in shared_info
		 * so we assume that it is 4k here.
		 */
		res[nres].start = si->mmio_base_low;
		res[nres].end = res[0].start + SZ_4K - 1;
		res[nres++].flags = IORESOURCE_MEM;
	}

	if (si->gsi_interrupt) {
		int irq = acpi_register_gsi(NULL, si->gsi_interrupt,
					    si->interrupt_mode,
					    si->interrupt_polarity);
		res[nres].start = irq;
		res[nres].end = irq;
		res[nres++].flags = IORESOURCE_IRQ;
	}

	if (si->base_request_line || si->num_handshake_signals) {
		/*
		 * We pass the driver a DMA resource describing the range
		 * of request lines the device supports.
		 */
		res[nres].start = si->base_request_line;
		res[nres].end = res[nres].start + si->num_handshake_signals - 1;
		res[nres++].flags = IORESOURCE_DMA;
	}

	ret = platform_device_add_resources(pdev, res, nres);
	if (ret) {
		if (si->gsi_interrupt)
			acpi_unregister_gsi(si->gsi_interrupt);
		return ret;
	}

	return 0;
}

static int __init
acpi_csrt_parse_resource_group(const struct acpi_csrt_group *grp)
{
	struct platform_device *pdev;
	char vendor[5], name[16];
	int ret, i;

	vendor[0] = grp->vendor_id;
	vendor[1] = grp->vendor_id >> 8;
	vendor[2] = grp->vendor_id >> 16;
	vendor[3] = grp->vendor_id >> 24;
	vendor[4] = '\0';

	if (grp->shared_info_length != sizeof(struct acpi_csrt_shared_info))
		return -ENODEV;

	snprintf(name, sizeof(name), "%s%04X", vendor, grp->device_id);
	pdev = platform_device_alloc(name, PLATFORM_DEVID_AUTO);
	if (!pdev)
		return -ENOMEM;

	/* Add resources based on the shared info */
	ret = acpi_csrt_parse_shared_info(pdev, grp);
	if (ret)
		goto fail;

	ret = platform_device_add(pdev);
	if (ret)
		goto fail;

	for (i = 0; i < pdev->num_resources; i++)
		dev_dbg(&pdev->dev, "%pR\n", &pdev->resource[i]);

	return 0;

fail:
	platform_device_put(pdev);
	return ret;
}

/*
 * CSRT or Core System Resources Table is a proprietary ACPI table
 * introduced by Microsoft. This table can contain devices that are not in
 * the system DSDT table. In particular DMA controllers might be described
 * here.
 *
 * We present these devices as normal platform devices that don't have ACPI
 * IDs or handle. The platform device name will be something like
 * <VENDOR><DEVID>.<n>.auto for example: INTL9C06.0.auto.
 */
void __init acpi_csrt_init(void)
{
	struct acpi_csrt_group *grp, *end;
	struct acpi_table_csrt *csrt;
	acpi_status status;
	int ret;

	status = acpi_get_table(ACPI_SIG_CSRT, 0,
				(struct acpi_table_header **)&csrt);
	if (ACPI_FAILURE(status)) {
		if (status != AE_NOT_FOUND)
			pr_warn("failed to get the CSRT table\n");
		return;
	}

	pr_debug("parsing CSRT table for devices\n");

	grp = (struct acpi_csrt_group *)(csrt + 1);
	end = (struct acpi_csrt_group *)((void *)csrt + csrt->header.length);

	while (grp < end) {
		ret = acpi_csrt_parse_resource_group(grp);
		if (ret) {
			pr_warn("error in parsing resource group: %d\n", ret);
			return;
		}

		grp = (struct acpi_csrt_group *)((void *)grp + grp->length);
	}
}
+6 −1
Original line number Original line Diff line number Diff line
@@ -26,6 +26,7 @@
int init_acpi_device_notify(void);
int init_acpi_device_notify(void);
int acpi_scan_init(void);
int acpi_scan_init(void);
int acpi_sysfs_init(void);
int acpi_sysfs_init(void);
void acpi_csrt_init(void);


#ifdef CONFIG_DEBUG_FS
#ifdef CONFIG_DEBUG_FS
extern struct dentry *acpi_debugfs_dir;
extern struct dentry *acpi_debugfs_dir;
@@ -117,6 +118,10 @@ static inline void suspend_nvs_restore(void) {}
  -------------------------------------------------------------------------- */
  -------------------------------------------------------------------------- */
struct platform_device;
struct platform_device;


struct platform_device *acpi_create_platform_device(struct acpi_device *adev);
/* Flags for acpi_create_platform_device */
#define ACPI_PLATFORM_CLK	BIT(0)

struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
						    unsigned long flags);


#endif /* _ACPI_INTERNAL_H_ */
#endif /* _ACPI_INTERNAL_H_ */
Loading