From: Lee Jones <lee.jones@linaro.org>
To: Octavian Purdila <octavian.purdila@intel.com>
Cc: linus.walleij@linaro.org, rjw@rjwysocki.net, johan@kernel.org,
linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-gpio@vger.kernel.org, heikki.krogerus@intel.com,
mika.westerberg@linux.intel.com, linux-acpi@vger.kernel.org
Subject: Re: [PATCH 3/4] mfd: dln2: add support for ACPI
Date: Tue, 20 Jan 2015 15:20:25 +0000 [thread overview]
Message-ID: <20150120152025.GY13701@x1> (raw)
In-Reply-To: <1418746353-3481-4-git-send-email-octavian.purdila@intel.com>
I need an ACPI Ack on this.
> This patch adds support to load a custom ACPI table that describes
> devices connected via the DLN2 USB to I2C/SPI/GPIO bridge.
>
> The ACPI table can be loaded either externally (from QEMU or with
> CONFIG_ACPI_CUSTOM_DSDT) or it can be loaded as firmware file with the
> name dln2.aml. The driver looks for an ACPI device entry with _HID set
> to "DLN20000" and makes it the ACPI companion for DLN2 USB
> sub-drivers.
>
> Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
> ---
> Documentation/acpi/dln2-acpi.txt | 62 ++++++++++++++++++
> drivers/mfd/dln2.c | 134 +++++++++++++++++++++++++++++++++++++++
> 2 files changed, 196 insertions(+)
> create mode 100644 Documentation/acpi/dln2-acpi.txt
>
> diff --git a/Documentation/acpi/dln2-acpi.txt b/Documentation/acpi/dln2-acpi.txt
> new file mode 100644
> index 0000000..d76605f
> --- /dev/null
> +++ b/Documentation/acpi/dln2-acpi.txt
> @@ -0,0 +1,62 @@
> +Diolan DLN2 custom APCI table
> +
> +The Diolan DLN2 is an USB to I2C/SPI/GPIO bridge and as such it can be used to
> +connect to various I2C or SPI devices. Because these busses lack an enumeration
> +protocol, the driver obtains various information about the device (such as I2C
> +address and GPIO pins) from either ACPI or device tree.
> +
> +To allow enumerating devices and their properties via ACPI, the Diolan
> +driver looks for an ACPI tree with the root _HID set to "DLN20000". If
> +it finds such an ACPI object it will set the ACPI companion to the
> +DLN2 MFD driver and from their it will be propagated to all its
> +sub-devices (I2C, GPIO, SPI).
> +
> +The user can either load the custom DSDT table with three methods:
> +
> +1. Via QEMU (see -acpitable)
> +
> +2. Via the CONFIG_ACPI_CUSTOM_DSDT kernel config option (see
> +Documentation/acpi/dsdt-override.txt)
> +
> +3. By placing the custom DSDT in the firmware paths in a file name
> +dln2.aml.
> +
> +Here is an example ACPI table that enumerates a BMC150 accelerometer
> +and defines its I2C address and GPIO pin used as an interrupt source:
> +
> +DefinitionBlock ("ssdt.aml", "SSDT", 1, "INTEL ", "CpuDptf", 0x00000003)
> +{
> + Device (DLN0)
> + {
> + Name (_ADR, Zero)
> + Name (_HID, "DLN2000")
> +
> + Device (STAC)
> + {
> + Name (_ADR, Zero)
> + Name (_HID, "BMC150A")
> + Name (_CID, "INTACCL")
> + Name (_UID, One)
> +
> + Method (_CRS, 0, Serialized)
> + {
> + Name (RBUF, ResourceTemplate ()
> + {
> + I2cSerialBus (0x0010, ControllerInitiated, 0x00061A80,
> + AddressingMode7Bit, "\\DLN0",
> + 0x00, ResourceConsumer, ,)
> +
> + GpioInt (Level, ActiveHigh, Exclusive, PullDown, 0x0000,
> + "\\DLN0", 0x00, ResourceConsumer, , )
> + { // Pin list
> + 0
> + }
> + })
> + Return (RBUF)
> + }
> + }
> + }
> +}
> +
> +The resources defined in the devices under the DLN0 are those
> +supported by the I2C, GPIO and SPI sub-systems.
> diff --git a/drivers/mfd/dln2.c b/drivers/mfd/dln2.c
> index f9c4a0b..93f6d1d 100644
> --- a/drivers/mfd/dln2.c
> +++ b/drivers/mfd/dln2.c
> @@ -23,6 +23,8 @@
> #include <linux/mfd/core.h>
> #include <linux/mfd/dln2.h>
> #include <linux/rculist.h>
> +#include <linux/acpi.h>
> +#include <linux/firmware.h>
>
> struct dln2_header {
> __le16 size;
> @@ -714,6 +716,134 @@ static void dln2_stop(struct dln2_dev *dln2)
>
> dln2_stop_rx_urbs(dln2);
> }
> +
> +#if IS_ENABLED(CONFIG_ACPI)
> +
> +static struct dln2_acpi_info {
> + const struct firmware *fw;
> + acpi_owner_id table_id;
> + struct acpi_device *dev;
> + int users;
> +} dln2_acpi_info;
> +
> +static DEFINE_MUTEX(dln2_acpi_lock);
> +
> +static acpi_status dln2_find_acpi_handle(acpi_handle handle, u32 level,
> + void *ctxt, void **retv)
> +{
> + acpi_handle *dln2_handle = (acpi_handle *)retv;
> +
> + *dln2_handle = handle;
> +
> + return AE_CTRL_TERMINATE;
> +}
> +
> +static void dln2_probe_acpi(struct dln2_dev *dln2)
> +{
> + struct device *dev = &dln2->interface->dev;
> + struct dln2_acpi_info *ai = &dln2_acpi_info;
> + acpi_handle h = NULL;
> + int ret;
> + bool fw_loaded = false;
> +
> + mutex_lock(&dln2_acpi_lock);
> +
> + if (ai->dev)
> + goto out_success;
> +
> + /*
> + * Look for the DLN2000 HID in case the ACPI table was loaded
> + * externally (e.g. from qemu).
> + */
> + acpi_get_devices("DLN20000", dln2_find_acpi_handle, NULL, &h);
> + if (!h) {
> + /* Try to load the ACPI table via a firmware file */
> + ret = request_firmware(&ai->fw, "dln2.aml", NULL);
> + if (ret)
> + goto out_unlock;
> +
> + ret = acpi_load_table((void *)ai->fw->data);
> + if (ret) {
> + dev_err(dev, "invalid ACPI table\n");
> + goto out_release_fw;
> + }
> +
> + acpi_get_devices("DLN20000", dln2_find_acpi_handle, NULL, &h);
> + if (!h) {
> + dev_err(dev, "not a DLN2 ACPI table\n");
> + goto out_leak_fw;
> + }
> +
> + ret = acpi_get_id(h, &ai->table_id);
> + if (ret) {
> + dev_err(dev, "acpi_get_id failed: %d\n", ret);
> + goto out_leak_fw;
> + }
> +
> + ret = acpi_bus_scan(h);
> + if (ret) {
> + dev_err(dev, "acpi_bus_scan failed: %d\n", ret);
> + goto out_leak_fw;
> + }
> +
> + fw_loaded = true;
> + }
> +
> + ret = acpi_bus_get_device(h, &ai->dev);
> + if (ret) {
> + dev_err(dev, "failed to get ACPI device: %d\n", ret);
> + if (fw_loaded) {
> + acpi_unload_table_id(ai->table_id);
> + goto out_leak_fw;
> + }
> + goto out_unlock;
> + }
> +
> +out_success:
> + ACPI_COMPANION_SET(dev, ai->dev);
> + ai->users++;
> + mutex_unlock(&dln2_acpi_lock);
> + return;
> +
> +out_release_fw:
> + release_firmware(ai->fw);
> +out_leak_fw:
> + /*
> + * Once a table is loaded we can't release the firmware anymore because
> + * acpi_unload_table does not actually unload the table but keeps it in
> + * memory to speed up subsequent loads.
> + */
> + ai->fw = NULL;
> +out_unlock:
> + mutex_unlock(&dln2_acpi_lock);
> +}
> +
> +static void dln2_disconnect_acpi(struct dln2_dev *dln2)
> +{
> + struct dln2_acpi_info *ai = &dln2_acpi_info;
> +
> + mutex_lock(&dln2_acpi_lock);
> + if (--ai->users == 0 && ai->fw) {
> + acpi_scan_lock_acquire();
> + acpi_bus_trim(ai->dev);
> + acpi_scan_lock_release();
> + acpi_unload_table_id(ai->table_id);
> + ai->dev = NULL;
> + /* we can't release firmware see comment in dln2_probe_acpi */
> + ai->fw = NULL;
> + }
> + mutex_unlock(&dln2_acpi_lock);
> +}
> +#else
> +static void dln2_probe_acpi(struct dln2_dev *dln2)
> +{
> +}
> +
> +static void dln2_disconnect_acpi(struct dln2_dev *dln2)
> +{
> +}
> +#endif
> +
> static void dln2_disconnect(struct usb_interface *interface)
> {
> struct dln2_dev *dln2 = usb_get_intfdata(interface);
> @@ -722,6 +852,8 @@ static void dln2_disconnect(struct usb_interface *interface)
>
> mfd_remove_devices(&interface->dev);
>
> + dln2_disconnect_acpi(dln2);
> +
> dln2_free(dln2);
> }
>
> @@ -774,6 +906,8 @@ static int dln2_probe(struct usb_interface *interface,
> goto out_stop_rx;
> }
>
> + dln2_probe_acpi(dln2);
> +
> ret = mfd_add_hotplug_devices(dev, dln2_devs, ARRAY_SIZE(dln2_devs));
> if (ret != 0) {
> dev_err(dev, "failed to add mfd devices to core\n");
> --
> 1.9.1
>
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
WARNING: multiple messages have this Message-ID (diff)
From: Lee Jones <lee.jones@linaro.org>
To: Octavian Purdila <octavian.purdila@intel.com>
Cc: linus.walleij@linaro.org, rjw@rjwysocki.net, johan@kernel.org,
linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-gpio@vger.kernel.org, heikki.krogerus@intel.com,
mika.westerberg@linux.intel.com, linux-acpi@vger.kernel.org
Subject: Re: [PATCH 3/4] mfd: dln2: add support for ACPI
Date: Tue, 20 Jan 2015 15:20:25 +0000 [thread overview]
Message-ID: <20150120152025.GY13701@x1> (raw)
In-Reply-To: <1418746353-3481-4-git-send-email-octavian.purdila@intel.com>
I need an ACPI Ack on this.
> This patch adds support to load a custom ACPI table that describes
> devices connected via the DLN2 USB to I2C/SPI/GPIO bridge.
>
> The ACPI table can be loaded either externally (from QEMU or with
> CONFIG_ACPI_CUSTOM_DSDT) or it can be loaded as firmware file with the
> name dln2.aml. The driver looks for an ACPI device entry with _HID set
> to "DLN20000" and makes it the ACPI companion for DLN2 USB
> sub-drivers.
>
> Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
> ---
> Documentation/acpi/dln2-acpi.txt | 62 ++++++++++++++++++
> drivers/mfd/dln2.c | 134 +++++++++++++++++++++++++++++++++++++++
> 2 files changed, 196 insertions(+)
> create mode 100644 Documentation/acpi/dln2-acpi.txt
>
> diff --git a/Documentation/acpi/dln2-acpi.txt b/Documentation/acpi/dln2-acpi.txt
> new file mode 100644
> index 0000000..d76605f
> --- /dev/null
> +++ b/Documentation/acpi/dln2-acpi.txt
> @@ -0,0 +1,62 @@
> +Diolan DLN2 custom APCI table
> +
> +The Diolan DLN2 is an USB to I2C/SPI/GPIO bridge and as such it can be used to
> +connect to various I2C or SPI devices. Because these busses lack an enumeration
> +protocol, the driver obtains various information about the device (such as I2C
> +address and GPIO pins) from either ACPI or device tree.
> +
> +To allow enumerating devices and their properties via ACPI, the Diolan
> +driver looks for an ACPI tree with the root _HID set to "DLN20000". If
> +it finds such an ACPI object it will set the ACPI companion to the
> +DLN2 MFD driver and from their it will be propagated to all its
> +sub-devices (I2C, GPIO, SPI).
> +
> +The user can either load the custom DSDT table with three methods:
> +
> +1. Via QEMU (see -acpitable)
> +
> +2. Via the CONFIG_ACPI_CUSTOM_DSDT kernel config option (see
> +Documentation/acpi/dsdt-override.txt)
> +
> +3. By placing the custom DSDT in the firmware paths in a file name
> +dln2.aml.
> +
> +Here is an example ACPI table that enumerates a BMC150 accelerometer
> +and defines its I2C address and GPIO pin used as an interrupt source:
> +
> +DefinitionBlock ("ssdt.aml", "SSDT", 1, "INTEL ", "CpuDptf", 0x00000003)
> +{
> + Device (DLN0)
> + {
> + Name (_ADR, Zero)
> + Name (_HID, "DLN2000")
> +
> + Device (STAC)
> + {
> + Name (_ADR, Zero)
> + Name (_HID, "BMC150A")
> + Name (_CID, "INTACCL")
> + Name (_UID, One)
> +
> + Method (_CRS, 0, Serialized)
> + {
> + Name (RBUF, ResourceTemplate ()
> + {
> + I2cSerialBus (0x0010, ControllerInitiated, 0x00061A80,
> + AddressingMode7Bit, "\\DLN0",
> + 0x00, ResourceConsumer, ,)
> +
> + GpioInt (Level, ActiveHigh, Exclusive, PullDown, 0x0000,
> + "\\DLN0", 0x00, ResourceConsumer, , )
> + { // Pin list
> + 0
> + }
> + })
> + Return (RBUF)
> + }
> + }
> + }
> +}
> +
> +The resources defined in the devices under the DLN0 are those
> +supported by the I2C, GPIO and SPI sub-systems.
> diff --git a/drivers/mfd/dln2.c b/drivers/mfd/dln2.c
> index f9c4a0b..93f6d1d 100644
> --- a/drivers/mfd/dln2.c
> +++ b/drivers/mfd/dln2.c
> @@ -23,6 +23,8 @@
> #include <linux/mfd/core.h>
> #include <linux/mfd/dln2.h>
> #include <linux/rculist.h>
> +#include <linux/acpi.h>
> +#include <linux/firmware.h>
>
> struct dln2_header {
> __le16 size;
> @@ -714,6 +716,134 @@ static void dln2_stop(struct dln2_dev *dln2)
>
> dln2_stop_rx_urbs(dln2);
> }
> +
> +#if IS_ENABLED(CONFIG_ACPI)
> +
> +static struct dln2_acpi_info {
> + const struct firmware *fw;
> + acpi_owner_id table_id;
> + struct acpi_device *dev;
> + int users;
> +} dln2_acpi_info;
> +
> +static DEFINE_MUTEX(dln2_acpi_lock);
> +
> +static acpi_status dln2_find_acpi_handle(acpi_handle handle, u32 level,
> + void *ctxt, void **retv)
> +{
> + acpi_handle *dln2_handle = (acpi_handle *)retv;
> +
> + *dln2_handle = handle;
> +
> + return AE_CTRL_TERMINATE;
> +}
> +
> +static void dln2_probe_acpi(struct dln2_dev *dln2)
> +{
> + struct device *dev = &dln2->interface->dev;
> + struct dln2_acpi_info *ai = &dln2_acpi_info;
> + acpi_handle h = NULL;
> + int ret;
> + bool fw_loaded = false;
> +
> + mutex_lock(&dln2_acpi_lock);
> +
> + if (ai->dev)
> + goto out_success;
> +
> + /*
> + * Look for the DLN2000 HID in case the ACPI table was loaded
> + * externally (e.g. from qemu).
> + */
> + acpi_get_devices("DLN20000", dln2_find_acpi_handle, NULL, &h);
> + if (!h) {
> + /* Try to load the ACPI table via a firmware file */
> + ret = request_firmware(&ai->fw, "dln2.aml", NULL);
> + if (ret)
> + goto out_unlock;
> +
> + ret = acpi_load_table((void *)ai->fw->data);
> + if (ret) {
> + dev_err(dev, "invalid ACPI table\n");
> + goto out_release_fw;
> + }
> +
> + acpi_get_devices("DLN20000", dln2_find_acpi_handle, NULL, &h);
> + if (!h) {
> + dev_err(dev, "not a DLN2 ACPI table\n");
> + goto out_leak_fw;
> + }
> +
> + ret = acpi_get_id(h, &ai->table_id);
> + if (ret) {
> + dev_err(dev, "acpi_get_id failed: %d\n", ret);
> + goto out_leak_fw;
> + }
> +
> + ret = acpi_bus_scan(h);
> + if (ret) {
> + dev_err(dev, "acpi_bus_scan failed: %d\n", ret);
> + goto out_leak_fw;
> + }
> +
> + fw_loaded = true;
> + }
> +
> + ret = acpi_bus_get_device(h, &ai->dev);
> + if (ret) {
> + dev_err(dev, "failed to get ACPI device: %d\n", ret);
> + if (fw_loaded) {
> + acpi_unload_table_id(ai->table_id);
> + goto out_leak_fw;
> + }
> + goto out_unlock;
> + }
> +
> +out_success:
> + ACPI_COMPANION_SET(dev, ai->dev);
> + ai->users++;
> + mutex_unlock(&dln2_acpi_lock);
> + return;
> +
> +out_release_fw:
> + release_firmware(ai->fw);
> +out_leak_fw:
> + /*
> + * Once a table is loaded we can't release the firmware anymore because
> + * acpi_unload_table does not actually unload the table but keeps it in
> + * memory to speed up subsequent loads.
> + */
> + ai->fw = NULL;
> +out_unlock:
> + mutex_unlock(&dln2_acpi_lock);
> +}
> +
> +static void dln2_disconnect_acpi(struct dln2_dev *dln2)
> +{
> + struct dln2_acpi_info *ai = &dln2_acpi_info;
> +
> + mutex_lock(&dln2_acpi_lock);
> + if (--ai->users == 0 && ai->fw) {
> + acpi_scan_lock_acquire();
> + acpi_bus_trim(ai->dev);
> + acpi_scan_lock_release();
> + acpi_unload_table_id(ai->table_id);
> + ai->dev = NULL;
> + /* we can't release firmware see comment in dln2_probe_acpi */
> + ai->fw = NULL;
> + }
> + mutex_unlock(&dln2_acpi_lock);
> +}
> +#else
> +static void dln2_probe_acpi(struct dln2_dev *dln2)
> +{
> +}
> +
> +static void dln2_disconnect_acpi(struct dln2_dev *dln2)
> +{
> +}
> +#endif
> +
> static void dln2_disconnect(struct usb_interface *interface)
> {
> struct dln2_dev *dln2 = usb_get_intfdata(interface);
> @@ -722,6 +852,8 @@ static void dln2_disconnect(struct usb_interface *interface)
>
> mfd_remove_devices(&interface->dev);
>
> + dln2_disconnect_acpi(dln2);
> +
> dln2_free(dln2);
> }
>
> @@ -774,6 +906,8 @@ static int dln2_probe(struct usb_interface *interface,
> goto out_stop_rx;
> }
>
> + dln2_probe_acpi(dln2);
> +
> ret = mfd_add_hotplug_devices(dev, dln2_devs, ARRAY_SIZE(dln2_devs));
> if (ret != 0) {
> dev_err(dev, "failed to add mfd devices to core\n");
> --
> 1.9.1
>
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
next prev parent reply other threads:[~2015-01-20 15:20 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-12-16 16:12 [PATCH 0/4] dln2: add support for ACPI Octavian Purdila
2014-12-16 16:12 ` [PATCH 1/4] ACPICA: take ACPI_MTX_INTERPRETER in acpi_unload_table_id Octavian Purdila
2014-12-16 18:14 ` Sergei Shtylyov
2014-12-16 19:32 ` Octavian Purdila
2015-01-22 6:37 ` [RFC PATCH] ACPI: Introduce acpi_unload_parent_table() usages in Linux kernel Lv Zheng
2015-01-22 6:37 ` Lv Zheng
2015-01-22 22:43 ` Rafael J. Wysocki
2015-01-22 22:43 ` Rafael J. Wysocki
2015-01-22 22:43 ` Bjorn Helgaas
2015-01-22 22:43 ` Bjorn Helgaas
2015-01-26 1:59 ` Zheng, Lv
2015-01-26 1:59 ` Zheng, Lv
2015-01-26 1:59 ` Zheng, Lv
[not found] ` <1418746353-3481-2-git-send-email-octavian.purdila-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
2015-01-30 0:03 ` [PATCH 1/4] ACPICA: take ACPI_MTX_INTERPRETER in acpi_unload_table_id Rafael J. Wysocki
2015-01-30 0:03 ` Rafael J. Wysocki
2014-12-16 16:12 ` [PATCH 2/4] ACPICA: don't release ACPI_MTX_TABLES in acpi_tb_install_standard_table Octavian Purdila
2014-12-16 16:12 ` [PATCH 3/4] mfd: dln2: add support for ACPI Octavian Purdila
2015-01-20 15:20 ` Lee Jones [this message]
2015-01-20 15:20 ` Lee Jones
2015-01-22 2:00 ` Rafael J. Wysocki
2015-01-22 10:13 ` Octavian Purdila
2015-01-22 22:09 ` Rafael J. Wysocki
2015-01-23 6:47 ` Octavian Purdila
2015-01-23 15:19 ` Rafael J. Wysocki
2014-12-16 16:12 ` [PATCH 4/4] gpio: dln2: add support for ACPI pin configuration Octavian Purdila
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20150120152025.GY13701@x1 \
--to=lee.jones@linaro.org \
--cc=heikki.krogerus@intel.com \
--cc=johan@kernel.org \
--cc=linus.walleij@linaro.org \
--cc=linux-acpi@vger.kernel.org \
--cc=linux-gpio@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=mika.westerberg@linux.intel.com \
--cc=octavian.purdila@intel.com \
--cc=rjw@rjwysocki.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.