* Hid over I2C and ACPI interaction
@ 2012-07-04 13:46 Benjamin Tissoires
[not found] ` <4FF52C70.9010601@intel.com>
0 siblings, 1 reply; 10+ messages in thread
From: Benjamin Tissoires @ 2012-07-04 13:46 UTC (permalink / raw)
To: Jean Delvare, Ben Dooks, Wolfram Sang, Len Brown,
linux-acpi-u79uwXL29TY76Z2rM5mHXA,
linux-i2c-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: Jiri Kosina, Stéphane Chatty, JJ Ding
Hi Guys,
I'm the co-author and the maintainer of the hid-multitouch driver. To
support even more devices, I started the implementation of the HID
over I2C protocol specification which is introduced by Win8. I'm quite
comfortable with the hid and the I2C part, but I'm blocked with the
interaction with the ACPI for the pnp part.
I wanted to have your advice/help on this problem. I've add in the
recipients list the maintainers of i2c and ACPI, sorry for the noise
if you don't feel concerned about this.
So, let's go deeper in the problem ;-)
Microsoft's spec asks the OEM to fill the ACPI DSDT to provide the
following scope in the ASL layout:
>>>>>>>>> begin of ASL
Scope (\_SB) {
//--------------------
// General Purpose I/O, ports 0...127
//--------------------
Device(HIDI2C_DEVICE1) {
Name(_ADR,0)
Name (_HID, "MSFT1234”)
Name (_CID, "PNP0C50")
Name (_UID, 3)
Method(_CRS, 0x0, NotSerialized)
{
Name (RBUF, ResourceTemplate ()
{
// Address 0x07 on I2C-X (OEM selects this address)
//IHV SPECIFIC I2C3 = I2C Controller; TGD0 = GPIO Controller;
I2CSerialBus (0x07, ControllerInitiated,
100000,AddressingMode7Bit, "\\_SB.I2C3",,,,)
GpioInt(Level, ActiveLow, Exclusive, PullUp, 0, "\\_SB. TGD0",
0 , ResourceConsumer, , ) {40}
})
Return(RBUF)
}
Method(_DSM, 0x4, NotSerialized)
{
// BreakPoint
Store ("Method _DSM begin", Debug)
// DSM UUID
switch(ToBuffer(Arg0))
{
// ACPI DSM UUID for HIDI2C
case(ToUUID("3CDFF6F7-4267-4555-AD05-B30A3D8938DE"))
{
// DSM function which returns the HID Descriptor
Address (skipped)
}
default
{
// No other GUIDs supported
Return(Buffer(One) { 0x00 })
}
}
}
}
<<<<<<<<< end of ASL
Summary:
- a HID over I2C device has to present the Compatibility ID "PNP0C50"
- in the _CRS block, the address, the adapter and the gpioInt are
defined (or referenced)
- it presents a Device Specific Method (_DSM) which returns the HID
Descriptor register address. This register is our entry point for
retrieving the information about our hid device (so it's mandatory to
obtain it).
Where am I:
- I've written a first layer on top of i2c that retrieves the hid
register (currently the address 0x0001 is hardcoded), then get the
report desccriptors and the input events, and forward all this stuff
to the hid layer.
- It's working with a custom emulated HID over i2c touchpad, while
waiting for the one a manufacturer should send to me.
- The detection and the addition to the adapter is done by adding the
address in the lists and the name through the i2c "->detect" callback
(which is not very good, because I don't have the interrupt line
there).
- I've written a first acpi implementation that rely on the
DEVICE_ACPI_HANDLE macro to get the ACPI handle of the device (if
available).
- I'm not able to do some tests with the ACPI, as I don't know how to
implement this DSDT on my computer (I'm missing the I2C part), and the
manufacturer returned the mainboard with the right DSDT to the OEM.
My questions:
- will the current acpi implementation handle I2C devices?
- it seems to me that the .archdata field is left blank during the i2c
device initialization in all paths I've seen. Is that true?
- who puts the name int the struct i2c_board_info? (for hot-plugged
i2c devices).
- finally, what is the best way of handling ACPI for those I2C devices:
1) everything is fine, I should have the ACPI handle in .archdata.
2) someone has to implement the handling of I2C in the pnpACPI layer
(by adding I2CSerialBus handling and creating there the i2c slave).
3) I should create an acpi driver which handles "PNP0C50" and which
creates the i2c slaves.
The thing is that I'm not very comfortable with solutions 2 and 3
(i2c_new_device tells that it must not be called during
arch_initcall(), how can I get the adapter, shall I blacklist in
pnpacpi "PNP0C50" ...), so gentlemen, I'm waiting for your advice.
Many thanks,
Benjamin
^ permalink raw reply [flat|nested] 10+ messages in thread
[parent not found: <4FF52C70.9010601@intel.com>]
[parent not found: <4FF52C70.9010601-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>]
* Re: Fwd: Hid over I2C and ACPI interaction [not found] ` <4FF52C70.9010601-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org> @ 2012-07-05 7:01 ` Zhang Rui [not found] ` <1341471717.1682.125.camel-fuY85erJQUO75v1z/vFq2g@public.gmane.org> 0 siblings, 1 reply; 10+ messages in thread From: Zhang Rui @ 2012-07-05 7:01 UTC (permalink / raw) To: Lan Tianyu Cc: khali-PUYAD+kWke1g9hUCZPvPmw, ben-linux-elnMNo+KYs3YtjvyW6yDsg, w.sang-bIcnvbaLZ9MEGnE8C9+IrQ, lenb-DgEjT+Ai2ygdnm+yROfE0A, linux-acpi-u79uwXL29TY76Z2rM5mHXA, linux-i2c-u79uwXL29TY76Z2rM5mHXA, linux-kernel-u79uwXL29TY76Z2rM5mHXA, jkosina-AlSwsSmVLrQ, chatty-rXV5z7KbLFk, jj_ding-9cfG7bMpBgR9nmWX13WWKA > -------- Original Message -------- > Subject: Hid over I2C and ACPI interaction > Date: Wed, 4 Jul 2012 15:46:35 +0200 > From: Benjamin Tissoires <benjamin.tissoires-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> > To: Jean Delvare <khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org>, Ben Dooks <ben-linux-elnMNo+KYs3YtjvyW6yDsg@public.gmane.org>, Wolfram > Sang <w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>, Len Brown <lenb-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>, > <linux-acpi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>, <linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>, > <linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org> > CC: Jiri Kosina <jkosina-AlSwsSmVLrQ@public.gmane.org>, Stéphane Chatty <chatty@enac.fr>, JJ Ding > <jj_ding-9cfG7bMpBgR9nmWX13WWKA@public.gmane.org> > > Hi Guys, > > I'm the co-author and the maintainer of the hid-multitouch driver. To > support even more devices, I started the implementation of the HID > over I2C protocol specification which is introduced by Win8. I'm quite > comfortable with the hid and the I2C part, but I'm blocked with the > interaction with the ACPI for the pnp part. > > I wanted to have your advice/help on this problem. I've add in the > recipients list the maintainers of i2c and ACPI, sorry for the noise > if you don't feel concerned about this. > > So, let's go deeper in the problem ;-) > Microsoft's spec asks the OEM to fill the ACPI DSDT to provide the > following scope in the ASL layout: > > >>>>>>>>> begin of ASL > Scope (\_SB) { > //-------------------- > // General Purpose I/O, ports 0...127 > //-------------------- > > Device(HIDI2C_DEVICE1) { > Name(_ADR,0) > Name (_HID, "MSFT1234”) > Name (_CID, "PNP0C50") > Name (_UID, 3) > > Method(_CRS, 0x0, NotSerialized) > { > Name (RBUF, ResourceTemplate () > { > // Address 0x07 on I2C-X (OEM selects this address) > //IHV SPECIFIC I2C3 = I2C Controller; TGD0 = GPIO Controller; > I2CSerialBus (0x07, ControllerInitiated, > 100000,AddressingMode7Bit, "\\_SB.I2C3",,,,) > GpioInt(Level, ActiveLow, Exclusive, PullUp, 0, "\\_SB. TGD0", > 0 , ResourceConsumer, , ) {40} > }) > Return(RBUF) > } > > Method(_DSM, 0x4, NotSerialized) > { > // BreakPoint > Store ("Method _DSM begin", Debug) > > // DSM UUID > switch(ToBuffer(Arg0)) > { > // ACPI DSM UUID for HIDI2C > case(ToUUID("3CDFF6F7-4267-4555-AD05-B30A3D8938DE")) > { > // DSM function which returns the HID Descriptor > Address (skipped) > } > > default > { > // No other GUIDs supported > Return(Buffer(One) { 0x00 }) > } > } > } > } > <<<<<<<<< end of ASL > yep, this is an ACPI enumerated I2C controller. > Summary: > - a HID over I2C device has to present the Compatibility ID "PNP0C50" > - in the _CRS block, the address, the adapter and the gpioInt are > defined (or referenced) > - it presents a Device Specific Method (_DSM) which returns the HID > Descriptor register address. This register is our entry point for > retrieving the information about our hid device (so it's mandatory to > obtain it). > > Where am I: > - I've written a first layer on top of i2c that retrieves the hid > register (currently the address 0x0001 is hardcoded), then get the > report desccriptors and the input events, and forward all this stuff > to the hid layer. > - It's working with a custom emulated HID over i2c touchpad, while > waiting for the one a manufacturer should send to me. > - The detection and the addition to the adapter is done by adding the > address in the lists and the name through the i2c "->detect" callback > (which is not very good, because I don't have the interrupt line > there). > - I've written a first acpi implementation that rely on the > DEVICE_ACPI_HANDLE macro to get the ACPI handle of the device (if > available). > - I'm not able to do some tests with the ACPI, as I don't know how to > implement this DSDT on my computer (I'm missing the I2C part), and the > manufacturer returned the mainboard with the right DSDT to the OEM. > > My questions: > - will the current acpi implementation handle I2C devices? you still need to write your own device driver for the device. > - it seems to me that the .archdata field is left blank during the i2c > device initialization in all paths I've seen. Is that true? > - who puts the name int the struct i2c_board_info? (for hot-plugged > i2c devices). > > - finally, what is the best way of handling ACPI for those I2C devices: > 1) everything is fine, I should have the ACPI handle in .archdata. > 2) someone has to implement the handling of I2C in the pnpACPI layer > (by adding I2CSerialBus handling and creating there the i2c slave). > 3) I should create an acpi driver which handles "PNP0C50" and which > creates the i2c slaves. > exactly. As this I2C controller uses the GPIO interrupt, we need an ACPI GPIO controller driver for interrupts first. I already have such a patch in hand, but have not release it for some reason. Second, you need to write your own PNP I2C controller driver, to enumerate the I2C controller via ACPI, AND enumerate the I2C slave devices under this controller to I2C bus. I also have a similar driver for SPI controller and SD/MMC controller. Third, you need a I2C slave device driver to handle the I2C slave device in I2C bus. here is a BKM I wrote, hope it helps. And also any comments are welcome. :) From 0a0fa4ff7b4b06c6560de94a78b15c6adfd86e34 Mon Sep 17 00:00:00 2001 From: Zhang Rui <rui.zhang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org> Date: Mon, 26 Dec 2011 10:42:04 +0800 As many SoC IP blocks are not hardware self-enumerable, the firmware, aka, ACPI tables, is responsible for enumerating/reserving/assigning system resources to these devices. This tutorial talks about how to enumerate these devices via ACPI namespace. Signed-off-by: Zhang Rui <rui.zhang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org> --- Documentation/acpi/acpi-device-probing.txt | 466 ++++++++++++++++++++++++++++ 1 file changed, 466 insertions(+) create mode 100644 Documentation/acpi/acpi-device-probing.txt diff --git a/Documentation/acpi/acpi-device-probing.txt b/Documentation/acpi/acpi-device-probing.txt new file mode 100644 index 0000000..82efbf3 --- /dev/null +++ b/Documentation/acpi/acpi-device-probing.txt @@ -0,0 +1,466 @@ + +HOWTO enumerate devices via ACPI + +Copyright (c) 2011-2012 Intel Corporation + +Contrast to hardware self-enumerable devices(e.g. USB, PCI) on PC platform, +many SoC IP blocks can not be self enumerated. +We used to introduce platform specific code for these devices. +But now, with ACPI 5.0, there is no requirement for the hardware to be +self-discoverable, enumerable or re-locatable, as the firmware is responsible +for enumerating/reserving/assigning system resources (such as address ranges or +interrupts) to the device. + +This document will show how to enumerate and configure a device via ACPI. +If you want to get more details about why and when we need this, +please refer to ACPI spec 5.0 and +Intel Architecture Platform Compatibility Definition. + +Note that although these are ACPI devices, we prefer to use PnP drivers for them, +this is because: +1. all the non-ACPI-predefined Devices are exported as PnP devices as well +2. PnP bus is a well designed bus. Probing via PnP layer saves a lot of work + for the device driver, e.g. getting & parsing ACPI resources. + +============================================================================= +1. Understand device definition in ACPI namespace + [Case study 1] SD/MMC controller +2. Driver for a leaf device + 2.1 Make a list of supported PnP ids + 2.2 Implement .probe/.remove callbacks for the PnP driver + 2.3 Fill in the pnp_driver structure + 2.4 Register the PnP driver +3. Driver for a master device on a non-self-enumerable bus + [Case Study 2] SPI controller and its slave device + 3.1 Probe the master device + 3.2 Walk ACPI namesapce to get the child devices of the master device + 3.3 Register these child devices as slave devices + 3.4 Write slave device driver +4. Misc +============================================================================= + +----------------------------------------------------------------------------- +1. Understand device definition in ACPI namespace +----------------------------------------------------------------------------- + +To enumerate a device in ACPI namespace, we need to find out and understand +HOW the device is defined in ACPI namespace first. + +[Case study 1 ] SD/MMC Controller + +Here is an ASL example code for SD/MMC controller definition in ACPI namespace. + + Device (EMMC) + { + Name (_ADR, Zero) + /* I use PNPXXXX, an arbitrary string, here, as PnP id is device specific */ + Name (_HID, "PNPXXXX") + Name (_CID, "PNPXXXX") + Name (_UID, 4) + + Method (_CRS, 0, NotSerialized) + { + Name (RBUF, ResourceTemplate () + { + Memory32Fixed (ReadWrite, + 0xFFA50000, // Address Base + 0x00000100, // Address Length + ) + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, ,, ) + { + 0x0000001b, + } + }) + Return (RBUF) + } + + Method (_STA, 0, NotSerialized) + { + Return (0x0F) + } + } + +_ADR : the address of this device on its parent bus. Useless in this case. +_HID : the PnP id for this device. +_CID : the compatible PnP id. use this as the PnP id if _HID doesn't exist. +_CRS : the system resources currently allocated to this device. + the Memory32Fixed part shows an Mem space for the device, + and the Interrupt part shows the device interrupt. +_STA : the current status of the device, e.g. it's enabled/disabled/removed. + +By reading this example ASL code, we should know that there is a SD/MMC controller +on this platform, it's mem space base address is 0xFFA50000, length is 0x00000100, +and the irq for this device is 0x1b. + +In Chapter 2, we will use this piece of ASL code as an example to +show how to probe the SD/MMC controller via ACPI namespace. + +----------------------------------------------------------------------------- +2 Driver for a leaf device +----------------------------------------------------------------------------- + +2.1 Make a list of supported pnp ids. + +Use the string in _HID or _CID objects as the PnP ids so that the device can +be attached to the driver successfully. + +In this case, +struct pnp_device_id sdhci_pnp_ids[] = { + { .id = "PNPXXXX", + .driver_data = (unsigned long)&sdhci_mfd_pdata }, + { }, +}; + +2.2 Implement the .probe and .remove callback of PnP driver. + +If you're not clear about what should be done in the driver, you can consult +some similar driver, for example, drivers/mmc/host/sdhci-pci.c shows how +to probe a PCI SD/MMC controller, this helps us understand what should be done +in the .probe/.remove callback. + +By reading the sdhci-pci .probe function, we know that the .probe callback +needs to +a) alloc a sdhci host. +b) fill the sdhci host structure with necessary resources got from + PCI configure space, including irq and mem space for the sdhci host. +c) register the sdhci host. +And then, driver/mmc/host/sdhci.c, the SDHCI interface driver will handle +everything for us. + +So, basically, we need to do the same work in sdhci_pnp_probe callback, +except that we need to get the information from ACPI namesapce instead. + +To get the resources in _CRS, we do not need Linux ACPICA APIs as PnP layer +has done this for us already. + +pnp_irq() returns the device irq, which equals the "Interrupt" part in _CRS method. +pnp_get_resource(, IORESOURCE_MEM, 0) returns the first Mem space base address +and length of this device, which equals the "Memory32Fixed" Part of the _CRS. + +the code below shows how to use the PnP APIs to get ACPI resources and +register a sdhci host in the .probe callback. + +static int __devinit +sdhci_pnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) +{ +... + pnp_disable_dev(pdev); + ret = pnp_activate_dev(pdev); +... + iomem = pnp_get_resource(pdev, IORESOURCE_MEM, 0); +... + host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_pnp_dev)); +... + host->irq = pnp_irq(pdev, 0); +... + if (!request_mem_region(iomem->start, resource_size(iomem), + mmc_hostname(host->mmc))) { +... + host->ioaddr = ioremap_nocache(iomem->start, resource_size(iomem)); +... + ret = sdhci_add_host(host); +... + pnp_set_drvdata(pdev, sdhci); +... +} + +Once the .probe callback is done, we just need to release the resources and +unregister the host in the .remove callback. + +static void sdhci_pnp_remove(struct pnp_dev * pdev) +{ + struct sdhci_pnp_dev *sdhci = pnp_get_drvdata(pdev); + struct resources *iomem = pnp_get_resource(pdev, IORESOURCE_MEM, 0); +... + sdhci_remove_host(sdhci->host, dead); + sdhci_free_host(sdhci->host); + iounmap(sdhci->host->ioaddr); + release_mem_region(iomem->start, resource_size(iomem)); + pnp_set_drvdata(pdev, NULL); + pnp_disable_dev(pdev); +} + +2.3 Fill in the pnp_driver structure + +Next step is to fill in the pnp_driver structure with PnP ids and +.probe/.remove callbacks finished in section 2.1 and 2.2 + +static struct pnp_driver sdhci_pnp_driver = { + .name = DRIVER_NAME, + .id_table = sdhci_pnp_ids, + .probe = sdhci_pnp_probe, + .remove = __devexit_p(sdhci_pnp_remove), +}; + +Note that .name and .id_table cannot be NULL. + +2.4 Register the PnP driver + +Now we can register this PnP driver to the driver model. + +static int __init sdhci_pnp_init(void) +{ + return pnp_register_driver(&sdhci_pnp_driver); +} + +module_init(sdhci_pnp_init); + + +----------------------------------------------------------------------------- +3 Driver for a master device on a non-self-enumerable bus +----------------------------------------------------------------------------- +In some cases, enumerating via ACPI brings new requirements in the driver. +For example, the driver for a master device on a non-self-enumerable bus is +responsible for enumerating the slave devices on this bus as well, which are +described as child devices of this master device in ACPI namespace. + +Taking SPI bus for example, + +------------------------------------------------------------------- +PNP/ACPI layer + + spi-acpi driver + | + |-----------------| + | | + | | + V V + register itself register its children + as a master as slave devices + device | + | | +---------|-----------------|--------------------------------------- + | | + | | + | | + V V + -------------- ----------- + | SPI | | SPI | + | master | | slave | + -------------- ----------- + ^ + | + | + V + ----------------------------- + | SPI slave driver driver | + ----------------------------- +SPI Bus layer +------------------------------------------------------------------- + +The figure above shows the components needed to make a SPI slave device work +a) an PNP/ACPI driver to probe the SPI master and its slaves. +b) a SPI slave device driver for the SPI slave device. + +[Case Study 2] SPI controller and its slave device + +This piece of ASL code shows the definition of a SPI controller and its slave device, +MAX3110, in ACPI namespace. + +Device (SPI1) { + Name (_ADR, 0) + Name (_HID, "PNPYYYY") + Name (_CID, "PNPYYYY") + Name (_UID, 1) + + Method (_CRS, 0x0, NotSerialized) { + Name (RBUF, ResourceTemplate () + { + Memory32Fixed (ReadWrite, 0xff128400, 0x00000400) + Interrupt(ResourceConsumer, Level, ActiveHigh, Exclusive, , , ) {0x09} + }) + Return (RBUF) + } + + Method (_STA, 0x0, NotSerialized) { + Return(0xf) + } + + Device(MAX0) + { + Name(_HID, "PNPZZZZ") // Max3110 serial port + Name(_DDN, "Max3110 serial port") + Method(_CRS, 0x0, NotSerialized) + { + // SpiSerial Bus Connection Descriptor + Name(UBUF, ResourceTemplate () { + SPISerialBus( + 1, // Device selection + PolarityHigh, // Device selection polarity + ThreeWireMode, // wiremode + 8, // databit len + ControllerInitiated, // slave mode + 1000, // Connection speed + ClockPolarityHigh, // Clock polarity + ClockPhaseFirst, // clock phase + "\\_SB.SPI1", // ResourceSource: SPI bus controller name + 0, // ResourceSourceIndex + ResourceConsumer, // Resource usage + , // DescriptorName: creates name for offset of resource descriptor + ) // Vendor Data + // OUT pin, BT_EN pin Core GPIO 74 + GpioIo(Exclusive, PullDefault, 0, 0, IoRestrictionOutputOnly, "\ \_SB.GPIS", ) {0x4A} + }) + + Return (UBUF) + } + } +} + +By reading the ASL code, we can see that +a) There is a SPI controller on this platform. + with IRQ 0x09, and a 0x400 bytes Memory space started from 0xff128400. +b) a MAX3110 device is connect to a SPI controller. + all the information required for probing a SPI slave device is described + in the "SPISerailBus" part of the MAX0._CRS method. + +We will talk about how to probe these two devices in this chapter. + +3.1 Probe the master device + +Please follow the Chapter 2 to probe the SPI master device. + +static int __devinit +dw_spi_pnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) +{ +... + dws->paddr = pnp_mem_start(pdev, 0); + dws->iolen = pnp_mem_len(pdev, 0); + dws->irq = pnp_irq(pdev, 0); + dws->parent_dev = &pdev->dev; + dws->bus_num = index++; + dws->num_cs = 4; + dws->regs = ioremap_nocache((unsigned long)dws->paddr, + dws->iolen); +... + ret = dw_spi_mid_init(dws); +... + ret = dw_spi_add_host(dws); +... +} + +3.2 Walk ACPI namespace to probe all its child devices. + +As MAX3110 can not be enumerated automatically, we introduce +dw_spi_pnp_slaves_register() to find the MAX3110 device in ACPI namespace + +static int __devinit dw_spi_pnp_slaves_register(struct dw_spi_pnp* dwpnp) +{ + ... + struct acpi_device *adev; + adev = dwpnp->pdev->data; + + /* + * find spi child devices given in ACPI namespace, one lower level only + */ + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, adev->handle, 1, + spi_slave_register, NULL, + spi_slave_info, NULL); + ... +} + +3.3 Register its child devices as slave devices + +As spi_slave_register is invoked for each SPI1 child device, +we introduce spi_slave_fill_resourcetry and try to register +SPI slave devices in spi_slave_register. + +acpi_status __init spi_slave_register(acpi_handle spi_slave_handle, u32 level, + void* data, void** return_value) +{ + ... + struct spi_board_info *spi_slave_info; + ... + status = acpi_walk_resources(spi_slave_handle, METHOD_NAME__CRS, + spi_slave_fill_resource, data); + ... + /* register SPI slave device */ + ret = spi_register_board_info(spi_slave_info, 1); + ... +} + +acpi_status __devinit spi_slave_fill_resource(struct acpi_resource *resource, void* data) +{ + struct spi_board_info *spi_slave_info; + struct acpi_resource_spi_serialbus *spi_resource; + ... + spi_resource = &resource->data.spi_serial_bus; + spi_slave_info->chip_select = spi_resource->device_selection; + spi_slave_info->max_speed_hz = spi_resource->connection_speed; + spi_slave_info->mode = (spi_resource->clock_phase ? SPI_CPHA : 0) | + (spi_resource->clock_polarity ? SPI_CPOL : 0) | + (spi_resource->device_polarity ? SPI_CS_HIGH : 0) | + (spi_resource->wire_mode ? SPI_3WIRE : 0); + ... +} + +3.4 Write the slave device driver + +After 3.3 is done, the MAX3110 device is an slave device in the SPI bus, +but to make it work properly, we still need a SPI slave device driver. + +Note that this is a general SPI drivers independent of ACPI. + +We will not go into details of the slave device driver here as +this piece of code is bus/device specific. + +----------------------------------------------------------------------------- +4 Misc +----------------------------------------------------------------------------- + +4.1 Note + +As ACPI 5.0 is still in heavily developing, if you are unable to find out all the +required information for probing a device in ACPI namespace, it is possible +that the ASL code is not well written. +Please contact Zhang Rui <rui.zhang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org> with the acpidump output of your +platform attached if you suspect it's an BIOS problem. + +4.2 Some important ACPICA APIs for device driver implementation: + +-- acpi_status + acpi_walk_namespace(acpi_object_type type, + acpi_handle start_object, + u32 max_depth, + acpi_walk_callback pre_order_visit, + acpi_walk_callback post_order_visit, + void *context, void **return_value); +Traverse ACPI namespace subtree rooted at start_object, go down max_depth level +at most. Call pre_order_visit when the proper node with type is found the first +time, call post_order_visit is the node is previously visited. Context and +return_value is passed down during the traverse. + +And the prototype of acpi_walk_callback: +typedef +acpi_status(*acpi_walk_callback) (acpi_handle object, + u32 nesting_level, + void *context, void **return_value); + +-- acpi_status + acpi_get_handle(acpi_handle parent, + acpi_string pathname, acpi_handle * ret_handle); +Try to get handle with specified pathname under node parent. Usually used to +check whether a particular node is available or not. + +-- acpi_status + acpi_get_object_info(acpi_handle object, + struct acpi_device_info **return_buffer); +Get acpi_device_info from object handle. Useful for retrieving ACPI object +name, type, and status etc. + +-- acpi_status + acpi_walk_resources(acpi_handle device, + char *name, + acpi_walk_resource_callback user_function, void *context); +Traverse resource node specified by name(e.g. METHOD_NAME__CRS) in ACPI +namespace subtree rooted at device. Call user_function for each entry in +acpi_resource list. The list may containe acpi_resource entries with various +types. So it is important to handle the interested resource type properly. +The acpi_resource with ACPI_RESOURCE_TYPE_END_TAG indicates end-of-list. + +And the prototype of acpi_walk_resource_callback: +typedef +acpi_status(*acpi_walk_resource_callback) (struct acpi_resource * resource, + void *context); + +More ACPICA external interfaces available in include/acpi/acpixf.h -- 1.7.10 ^ permalink raw reply related [flat|nested] 10+ messages in thread
[parent not found: <1341471717.1682.125.camel-fuY85erJQUO75v1z/vFq2g@public.gmane.org>]
* Re: Fwd: Hid over I2C and ACPI interaction [not found] ` <1341471717.1682.125.camel-fuY85erJQUO75v1z/vFq2g@public.gmane.org> @ 2012-07-05 7:20 ` Zhang Rui 2012-07-05 8:44 ` Benjamin Tissoires 2012-07-06 5:52 ` Mika Westerberg 1 sibling, 1 reply; 10+ messages in thread From: Zhang Rui @ 2012-07-05 7:20 UTC (permalink / raw) To: benjamin.tissoires-Re5JQEeQqe8AvxtiuMwx3w Cc: khali-PUYAD+kWke1g9hUCZPvPmw, ben-linux-elnMNo+KYs3YtjvyW6yDsg, w.sang-bIcnvbaLZ9MEGnE8C9+IrQ, lenb-DgEjT+Ai2ygdnm+yROfE0A, linux-acpi-u79uwXL29TY76Z2rM5mHXA, linux-i2c-u79uwXL29TY76Z2rM5mHXA, linux-kernel-u79uwXL29TY76Z2rM5mHXA, jkosina-AlSwsSmVLrQ, chatty-rXV5z7KbLFk, jj_ding-9cfG7bMpBgR9nmWX13WWKA Hah, seems I forgot to reply to Benjamin. On 四, 2012-07-05 at 15:01 +0800, Zhang Rui wrote: > > -------- Original Message -------- > > Subject: Hid over I2C and ACPI interaction > > Date: Wed, 4 Jul 2012 15:46:35 +0200 > > From: Benjamin Tissoires <benjamin.tissoires-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> > > To: Jean Delvare <khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org>, Ben Dooks <ben-linux@fluff.org>, Wolfram > > Sang <w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>, Len Brown <lenb-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>, > > <linux-acpi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>, <linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>, > > <linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org> > > CC: Jiri Kosina <jkosina-AlSwsSmVLrQ@public.gmane.org>, Stéphane Chatty <chatty@enac.fr>, JJ Ding > > <jj_ding-9cfG7bMpBgR9nmWX13WWKA@public.gmane.org> > > > > Hi Guys, > > > > I'm the co-author and the maintainer of the hid-multitouch driver. To > > support even more devices, I started the implementation of the HID > > over I2C protocol specification which is introduced by Win8. I'm quite > > comfortable with the hid and the I2C part, but I'm blocked with the > > interaction with the ACPI for the pnp part. > > > > I wanted to have your advice/help on this problem. I've add in the > > recipients list the maintainers of i2c and ACPI, sorry for the noise > > if you don't feel concerned about this. > > > > So, let's go deeper in the problem ;-) > > Microsoft's spec asks the OEM to fill the ACPI DSDT to provide the > > following scope in the ASL layout: > > > > >>>>>>>>> begin of ASL > > Scope (\_SB) { > > //-------------------- > > // General Purpose I/O, ports 0...127 > > //-------------------- > > > > Device(HIDI2C_DEVICE1) { > > Name(_ADR,0) > > Name (_HID, "MSFT1234”) > > Name (_CID, "PNP0C50") > > Name (_UID, 3) > > > > Method(_CRS, 0x0, NotSerialized) > > { > > Name (RBUF, ResourceTemplate () > > { > > // Address 0x07 on I2C-X (OEM selects this address) > > //IHV SPECIFIC I2C3 = I2C Controller; TGD0 = GPIO Controller; > > I2CSerialBus (0x07, ControllerInitiated, > > 100000,AddressingMode7Bit, "\\_SB.I2C3",,,,) > > GpioInt(Level, ActiveLow, Exclusive, PullUp, 0, "\\_SB. TGD0", > > 0 , ResourceConsumer, , ) {40} > > }) > > Return(RBUF) > > } > > > > Method(_DSM, 0x4, NotSerialized) > > { > > // BreakPoint > > Store ("Method _DSM begin", Debug) > > > > // DSM UUID > > switch(ToBuffer(Arg0)) > > { > > // ACPI DSM UUID for HIDI2C > > case(ToUUID("3CDFF6F7-4267-4555-AD05-B30A3D8938DE")) > > { > > // DSM function which returns the HID Descriptor > > Address (skipped) > > } > > > > default > > { > > // No other GUIDs supported > > Return(Buffer(One) { 0x00 }) > > } > > } > > } > > } > > <<<<<<<<< end of ASL > > > yep, this is an ACPI enumerated I2C controller. > > > Summary: > > - a HID over I2C device has to present the Compatibility ID "PNP0C50" > > - in the _CRS block, the address, the adapter and the gpioInt are > > defined (or referenced) > > - it presents a Device Specific Method (_DSM) which returns the HID > > Descriptor register address. This register is our entry point for > > retrieving the information about our hid device (so it's mandatory to > > obtain it). > > > > Where am I: > > - I've written a first layer on top of i2c that retrieves the hid > > register (currently the address 0x0001 is hardcoded), then get the > > report desccriptors and the input events, and forward all this stuff > > to the hid layer. > > - It's working with a custom emulated HID over i2c touchpad, while > > waiting for the one a manufacturer should send to me. > > - The detection and the addition to the adapter is done by adding the > > address in the lists and the name through the i2c "->detect" callback > > (which is not very good, because I don't have the interrupt line > > there). > > - I've written a first acpi implementation that rely on the > > DEVICE_ACPI_HANDLE macro to get the ACPI handle of the device (if > > available). > > - I'm not able to do some tests with the ACPI, as I don't know how to > > implement this DSDT on my computer (I'm missing the I2C part), and the > > manufacturer returned the mainboard with the right DSDT to the OEM. > > > > My questions: > > - will the current acpi implementation handle I2C devices? > > you still need to write your own device driver for the device. > > > - it seems to me that the .archdata field is left blank during the i2c > > device initialization in all paths I've seen. Is that true? > > - who puts the name int the struct i2c_board_info? (for hot-plugged > > i2c devices). > > > > - finally, what is the best way of handling ACPI for those I2C devices: > > 1) everything is fine, I should have the ACPI handle in .archdata. > > 2) someone has to implement the handling of I2C in the pnpACPI layer > > (by adding I2CSerialBus handling and creating there the i2c slave). > > 3) I should create an acpi driver which handles "PNP0C50" and which > > creates the i2c slaves. > > > exactly. > > As this I2C controller uses the GPIO interrupt, we need an ACPI GPIO > controller driver for interrupts first. > I already have such a patch in hand, but have not release it for some > reason. > Second, you need to write your own PNP I2C controller driver, to > enumerate the I2C controller via ACPI, AND enumerate the I2C slave > devices under this controller to I2C bus. I also have a similar driver > for SPI controller and SD/MMC controller. > Third, you need a I2C slave device driver to handle the I2C slave device > in I2C bus. > > here is a BKM I wrote, hope it helps. > > And also any comments are welcome. :) > > From 0a0fa4ff7b4b06c6560de94a78b15c6adfd86e34 Mon Sep 17 00:00:00 2001 > From: Zhang Rui <rui.zhang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org> > Date: Mon, 26 Dec 2011 10:42:04 +0800 > > As many SoC IP blocks are not hardware self-enumerable, the > firmware, aka, ACPI tables, is responsible for > enumerating/reserving/assigning system resources to these > devices. This tutorial talks about how to enumerate these > devices via ACPI namespace. > > Signed-off-by: Zhang Rui <rui.zhang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org> > --- > Documentation/acpi/acpi-device-probing.txt | 466 > ++++++++++++++++++++++++++++ > 1 file changed, 466 insertions(+) > create mode 100644 Documentation/acpi/acpi-device-probing.txt > > diff --git a/Documentation/acpi/acpi-device-probing.txt > b/Documentation/acpi/acpi-device-probing.txt > new file mode 100644 > index 0000000..82efbf3 > --- /dev/null > +++ b/Documentation/acpi/acpi-device-probing.txt > @@ -0,0 +1,466 @@ > + > +HOWTO enumerate devices via ACPI > + > +Copyright (c) 2011-2012 Intel Corporation > + > +Contrast to hardware self-enumerable devices(e.g. USB, PCI) on PC > platform, > +many SoC IP blocks can not be self enumerated. > +We used to introduce platform specific code for these devices. > +But now, with ACPI 5.0, there is no requirement for the hardware to be > +self-discoverable, enumerable or re-locatable, as the firmware is > responsible > +for enumerating/reserving/assigning system resources (such as address > ranges or > +interrupts) to the device. > + > +This document will show how to enumerate and configure a device via > ACPI. > +If you want to get more details about why and when we need this, > +please refer to ACPI spec 5.0 and > +Intel Architecture Platform Compatibility Definition. > + > +Note that although these are ACPI devices, we prefer to use PnP drivers > for them, > +this is because: > +1. all the non-ACPI-predefined Devices are exported as PnP devices as > well > +2. PnP bus is a well designed bus. Probing via PnP layer saves a lot of > work > + for the device driver, e.g. getting & parsing ACPI resources. > + > +============================================================================= > +1. Understand device definition in ACPI namespace > + [Case study 1] SD/MMC controller > +2. Driver for a leaf device > + 2.1 Make a list of supported PnP ids > + 2.2 Implement .probe/.remove callbacks for the PnP driver > + 2.3 Fill in the pnp_driver structure > + 2.4 Register the PnP driver > +3. Driver for a master device on a non-self-enumerable bus > + [Case Study 2] SPI controller and its slave device > + 3.1 Probe the master device > + 3.2 Walk ACPI namesapce to get the child devices of the master > device > + 3.3 Register these child devices as slave devices > + 3.4 Write slave device driver > +4. Misc > +============================================================================= > + > +----------------------------------------------------------------------------- > +1. Understand device definition in ACPI namespace > +----------------------------------------------------------------------------- > + > +To enumerate a device in ACPI namespace, we need to find out and > understand > +HOW the device is defined in ACPI namespace first. > + > +[Case study 1 ] SD/MMC Controller > + > +Here is an ASL example code for SD/MMC controller definition in ACPI > namespace. > + > + Device (EMMC) > + { > + Name (_ADR, Zero) > + /* I use PNPXXXX, an arbitrary string, here, as PnP id is > device specific */ > + Name (_HID, "PNPXXXX") > + Name (_CID, "PNPXXXX") > + Name (_UID, 4) > + > + Method (_CRS, 0, NotSerialized) > + { > + Name (RBUF, ResourceTemplate () > + { > + Memory32Fixed (ReadWrite, > + 0xFFA50000, // Address Base > + 0x00000100, // Address Length > + ) > + Interrupt (ResourceConsumer, Level, ActiveLow, > Exclusive, ,, ) > + { > + 0x0000001b, > + } > + }) > + Return (RBUF) > + } > + > + Method (_STA, 0, NotSerialized) > + { > + Return (0x0F) > + } > + } > + > +_ADR : the address of this device on its parent bus. Useless in this > case. > +_HID : the PnP id for this device. > +_CID : the compatible PnP id. use this as the PnP id if _HID doesn't > exist. > +_CRS : the system resources currently allocated to this device. > + the Memory32Fixed part shows an Mem space for the device, > + and the Interrupt part shows the device interrupt. > +_STA : the current status of the device, e.g. it's > enabled/disabled/removed. > + > +By reading this example ASL code, we should know that there is a SD/MMC > controller > +on this platform, it's mem space base address is 0xFFA50000, length is > 0x00000100, > +and the irq for this device is 0x1b. > + > +In Chapter 2, we will use this piece of ASL code as an example to > +show how to probe the SD/MMC controller via ACPI namespace. > + > +----------------------------------------------------------------------------- > +2 Driver for a leaf device > +----------------------------------------------------------------------------- > + > +2.1 Make a list of supported pnp ids. > + > +Use the string in _HID or _CID objects as the PnP ids so that the > device can > +be attached to the driver successfully. > + > +In this case, > +struct pnp_device_id sdhci_pnp_ids[] = { > + { .id = "PNPXXXX", > + .driver_data = (unsigned long)&sdhci_mfd_pdata }, > + { }, > +}; > + > +2.2 Implement the .probe and .remove callback of PnP driver. > + > +If you're not clear about what should be done in the driver, you can > consult > +some similar driver, for example, drivers/mmc/host/sdhci-pci.c shows > how > +to probe a PCI SD/MMC controller, this helps us understand what should > be done > +in the .probe/.remove callback. > + > +By reading the sdhci-pci .probe function, we know that the .probe > callback > +needs to > +a) alloc a sdhci host. > +b) fill the sdhci host structure with necessary resources got from > + PCI configure space, including irq and mem space for the sdhci host. > +c) register the sdhci host. > +And then, driver/mmc/host/sdhci.c, the SDHCI interface driver will > handle > +everything for us. > + > +So, basically, we need to do the same work in sdhci_pnp_probe callback, > +except that we need to get the information from ACPI namesapce instead. > + > +To get the resources in _CRS, we do not need Linux ACPICA APIs as PnP > layer > +has done this for us already. > + > +pnp_irq() returns the device irq, which equals the "Interrupt" part in > _CRS method. > +pnp_get_resource(, IORESOURCE_MEM, 0) returns the first Mem space base > address > +and length of this device, which equals the "Memory32Fixed" Part of the > _CRS. > + > +the code below shows how to use the PnP APIs to get ACPI resources and > +register a sdhci host in the .probe callback. > + > +static int __devinit > +sdhci_pnp_probe(struct pnp_dev *pdev, const struct pnp_device_id > *dev_id) > +{ > +... > + pnp_disable_dev(pdev); > + ret = pnp_activate_dev(pdev); > +... > + iomem = pnp_get_resource(pdev, IORESOURCE_MEM, 0); > +... > + host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_pnp_dev)); > +... > + host->irq = pnp_irq(pdev, 0); > +... > + if (!request_mem_region(iomem->start, resource_size(iomem), > + mmc_hostname(host->mmc))) { > +... > + host->ioaddr = ioremap_nocache(iomem->start, > resource_size(iomem)); > +... > + ret = sdhci_add_host(host); > +... > + pnp_set_drvdata(pdev, sdhci); > +... > +} > + > +Once the .probe callback is done, we just need to release the resources > and > +unregister the host in the .remove callback. > + > +static void sdhci_pnp_remove(struct pnp_dev * pdev) > +{ > + struct sdhci_pnp_dev *sdhci = pnp_get_drvdata(pdev); > + struct resources *iomem = pnp_get_resource(pdev, IORESOURCE_MEM, 0); > +... > + sdhci_remove_host(sdhci->host, dead); > + sdhci_free_host(sdhci->host); > + iounmap(sdhci->host->ioaddr); > + release_mem_region(iomem->start, resource_size(iomem)); > + pnp_set_drvdata(pdev, NULL); > + pnp_disable_dev(pdev); > +} > + > +2.3 Fill in the pnp_driver structure > + > +Next step is to fill in the pnp_driver structure with PnP ids and > +.probe/.remove callbacks finished in section 2.1 and 2.2 > + > +static struct pnp_driver sdhci_pnp_driver = { > + .name = DRIVER_NAME, > + .id_table = sdhci_pnp_ids, > + .probe = sdhci_pnp_probe, > + .remove = __devexit_p(sdhci_pnp_remove), > +}; > + > +Note that .name and .id_table cannot be NULL. > + > +2.4 Register the PnP driver > + > +Now we can register this PnP driver to the driver model. > + > +static int __init sdhci_pnp_init(void) > +{ > + return pnp_register_driver(&sdhci_pnp_driver); > +} > + > +module_init(sdhci_pnp_init); > + > + > +----------------------------------------------------------------------------- > +3 Driver for a master device on a non-self-enumerable bus > +----------------------------------------------------------------------------- > +In some cases, enumerating via ACPI brings new requirements in the > driver. > +For example, the driver for a master device on a non-self-enumerable > bus is > +responsible for enumerating the slave devices on this bus as well, > which are > +described as child devices of this master device in ACPI namespace. > + > +Taking SPI bus for example, > + > +------------------------------------------------------------------- > +PNP/ACPI layer > + > + spi-acpi driver > + | > + |-----------------| > + | | > + | | > + V V > + register itself register its children > + as a master as slave devices > + device | > + | | > +---------|-----------------|--------------------------------------- > + | | > + | | > + | | > + V V > + -------------- ----------- > + | SPI | | SPI | > + | master | | slave | > + -------------- ----------- > + ^ > + | > + | > + V > + ----------------------------- > + | SPI slave driver driver | > + ----------------------------- > +SPI Bus layer > +------------------------------------------------------------------- > + > +The figure above shows the components needed to make a SPI slave device > work > +a) an PNP/ACPI driver to probe the SPI master and its slaves. > +b) a SPI slave device driver for the SPI slave device. > + > +[Case Study 2] SPI controller and its slave device > + > +This piece of ASL code shows the definition of a SPI controller and its > slave device, > +MAX3110, in ACPI namespace. > + > +Device (SPI1) { > + Name (_ADR, 0) > + Name (_HID, "PNPYYYY") > + Name (_CID, "PNPYYYY") > + Name (_UID, 1) > + > + Method (_CRS, 0x0, NotSerialized) { > + Name (RBUF, ResourceTemplate () > + { > + Memory32Fixed (ReadWrite, 0xff128400, 0x00000400) > + Interrupt(ResourceConsumer, Level, ActiveHigh, Exclusive, , , ) > {0x09} > + }) > + Return (RBUF) > + } > + > + Method (_STA, 0x0, NotSerialized) { > + Return(0xf) > + } > + > + Device(MAX0) > + { > + Name(_HID, "PNPZZZZ") // Max3110 serial port > + Name(_DDN, "Max3110 serial port") > + Method(_CRS, 0x0, NotSerialized) > + { > + // SpiSerial Bus Connection Descriptor > + Name(UBUF, ResourceTemplate () { > + SPISerialBus( > + 1, // Device selection > + PolarityHigh, // Device selection polarity > + ThreeWireMode, // wiremode > + 8, // databit len > + ControllerInitiated, // slave mode > + 1000, // Connection speed > + ClockPolarityHigh, // Clock polarity > + ClockPhaseFirst, // clock phase > + "\\_SB.SPI1", // ResourceSource: SPI bus controller name > + 0, // ResourceSourceIndex > + ResourceConsumer, // Resource usage > + , // DescriptorName: creates name for offset > of resource descriptor > + ) // Vendor Data > + // OUT pin, BT_EN pin Core GPIO 74 > + GpioIo(Exclusive, PullDefault, 0, 0, IoRestrictionOutputOnly, "\ > \_SB.GPIS", ) {0x4A} > + }) > + > + Return (UBUF) > + } > + } > +} > + > +By reading the ASL code, we can see that > +a) There is a SPI controller on this platform. > + with IRQ 0x09, and a 0x400 bytes Memory space started from > 0xff128400. > +b) a MAX3110 device is connect to a SPI controller. > + all the information required for probing a SPI slave device is > described > + in the "SPISerailBus" part of the MAX0._CRS method. > + > +We will talk about how to probe these two devices in this chapter. > + > +3.1 Probe the master device > + > +Please follow the Chapter 2 to probe the SPI master device. > + > +static int __devinit > +dw_spi_pnp_probe(struct pnp_dev *pdev, const struct pnp_device_id > *dev_id) > +{ > +... > + dws->paddr = pnp_mem_start(pdev, 0); > + dws->iolen = pnp_mem_len(pdev, 0); > + dws->irq = pnp_irq(pdev, 0); > + dws->parent_dev = &pdev->dev; > + dws->bus_num = index++; > + dws->num_cs = 4; > + dws->regs = ioremap_nocache((unsigned long)dws->paddr, > + dws->iolen); > +... > + ret = dw_spi_mid_init(dws); > +... > + ret = dw_spi_add_host(dws); > +... > +} > + > +3.2 Walk ACPI namespace to probe all its child devices. > + > +As MAX3110 can not be enumerated automatically, we introduce > +dw_spi_pnp_slaves_register() to find the MAX3110 device in ACPI > namespace > + > +static int __devinit dw_spi_pnp_slaves_register(struct dw_spi_pnp* > dwpnp) > +{ > + ... > + struct acpi_device *adev; > + adev = dwpnp->pdev->data; > + > + /* > + * find spi child devices given in ACPI namespace, one lower level > only > + */ > + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, adev->handle, 1, > + spi_slave_register, NULL, > + spi_slave_info, NULL); > + ... > +} > + > +3.3 Register its child devices as slave devices > + > +As spi_slave_register is invoked for each SPI1 child device, > +we introduce spi_slave_fill_resourcetry and try to register > +SPI slave devices in spi_slave_register. > + > +acpi_status __init spi_slave_register(acpi_handle spi_slave_handle, u32 > level, > + void* data, void** return_value) > +{ > + ... > + struct spi_board_info *spi_slave_info; > + ... > + status = acpi_walk_resources(spi_slave_handle, METHOD_NAME__CRS, > + spi_slave_fill_resource, data); > + ... > + /* register SPI slave device */ > + ret = spi_register_board_info(spi_slave_info, 1); > + ... > +} > + > +acpi_status __devinit spi_slave_fill_resource(struct acpi_resource > *resource, void* data) > +{ > + struct spi_board_info *spi_slave_info; > + struct acpi_resource_spi_serialbus *spi_resource; > + ... > + spi_resource = &resource->data.spi_serial_bus; > + spi_slave_info->chip_select = spi_resource->device_selection; > + spi_slave_info->max_speed_hz = spi_resource->connection_speed; > + spi_slave_info->mode = (spi_resource->clock_phase ? SPI_CPHA : 0) | > + (spi_resource->clock_polarity ? SPI_CPOL : 0) | > + (spi_resource->device_polarity ? SPI_CS_HIGH : 0) | > + (spi_resource->wire_mode ? SPI_3WIRE : 0); > + ... > +} > + > +3.4 Write the slave device driver > + > +After 3.3 is done, the MAX3110 device is an slave device in the SPI > bus, > +but to make it work properly, we still need a SPI slave device driver. > + > +Note that this is a general SPI drivers independent of ACPI. > + > +We will not go into details of the slave device driver here as > +this piece of code is bus/device specific. > + > +----------------------------------------------------------------------------- > +4 Misc > +----------------------------------------------------------------------------- > + > +4.1 Note > + > +As ACPI 5.0 is still in heavily developing, if you are unable to find > out all the > +required information for probing a device in ACPI namespace, it is > possible > +that the ASL code is not well written. > +Please contact Zhang Rui <rui.zhang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org> with the acpidump output > of your > +platform attached if you suspect it's an BIOS problem. > + > +4.2 Some important ACPICA APIs for device driver implementation: > + > +-- acpi_status > + acpi_walk_namespace(acpi_object_type type, > + acpi_handle start_object, > + u32 max_depth, > + acpi_walk_callback pre_order_visit, > + acpi_walk_callback post_order_visit, > + void *context, void **return_value); > +Traverse ACPI namespace subtree rooted at start_object, go down > max_depth level > +at most. Call pre_order_visit when the proper node with type is found > the first > +time, call post_order_visit is the node is previously visited. Context > and > +return_value is passed down during the traverse. > + > +And the prototype of acpi_walk_callback: > +typedef > +acpi_status(*acpi_walk_callback) (acpi_handle object, > + u32 nesting_level, > + void *context, void **return_value); > + > +-- acpi_status > + acpi_get_handle(acpi_handle parent, > + acpi_string pathname, acpi_handle * ret_handle); > +Try to get handle with specified pathname under node parent. Usually > used to > +check whether a particular node is available or not. > + > +-- acpi_status > + acpi_get_object_info(acpi_handle object, > + struct acpi_device_info **return_buffer); > +Get acpi_device_info from object handle. Useful for retrieving ACPI > object > +name, type, and status etc. > + > +-- acpi_status > + acpi_walk_resources(acpi_handle device, > + char *name, > + acpi_walk_resource_callback user_function, void *context); > +Traverse resource node specified by name(e.g. METHOD_NAME__CRS) in ACPI > +namespace subtree rooted at device. Call user_function for each entry > in > +acpi_resource list. The list may containe acpi_resource entries with > various > +types. So it is important to handle the interested resource type > properly. > +The acpi_resource with ACPI_RESOURCE_TYPE_END_TAG indicates > end-of-list. > + > +And the prototype of acpi_walk_resource_callback: > +typedef > +acpi_status(*acpi_walk_resource_callback) (struct acpi_resource * > resource, > + void *context); > + > +More ACPICA external interfaces available in include/acpi/acpixf.h ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Fwd: Hid over I2C and ACPI interaction 2012-07-05 7:20 ` Zhang Rui @ 2012-07-05 8:44 ` Benjamin Tissoires 2012-07-09 0:41 ` Zhang Rui 0 siblings, 1 reply; 10+ messages in thread From: Benjamin Tissoires @ 2012-07-05 8:44 UTC (permalink / raw) To: Zhang Rui Cc: khali, ben-linux, w.sang, lenb, linux-acpi, linux-i2c, linux-kernel, jkosina, chatty, jj_ding Hi, Many thanks for these information. It seems like I was on the right track, but I didn't saw the hidden part of the iceberg. I've already written the i2c slave part (and the acpi handling to get the HID register by using the DSM should work), but I need now the whole ACPI pnp drivers... But without a real ACPI 5.0 mainboard, I think it will be quite difficult to implement and debug this ACPI stuff. Cheers, Benjamin On Thu, Jul 5, 2012 at 9:20 AM, Zhang Rui <rui.zhang@intel.com> wrote: > Hah, seems I forgot to reply to Benjamin. > > On 四, 2012-07-05 at 15:01 +0800, Zhang Rui wrote: >> > -------- Original Message -------- >> > Subject: Hid over I2C and ACPI interaction >> > Date: Wed, 4 Jul 2012 15:46:35 +0200 >> > From: Benjamin Tissoires <benjamin.tissoires@gmail.com> >> > To: Jean Delvare <khali@linux-fr.org>, Ben Dooks <ben-linux@fluff.org>, Wolfram >> > Sang <w.sang@pengutronix.de>, Len Brown <lenb@kernel.org>, >> > <linux-acpi@vger.kernel.org>, <linux-i2c@vger.kernel.org>, >> > <linux-kernel@vger.kernel.org> >> > CC: Jiri Kosina <jkosina@suse.cz>, Stéphane Chatty <chatty@enac.fr>, JJ Ding >> > <jj_ding@emc.com.tw> >> > >> > Hi Guys, >> > >> > I'm the co-author and the maintainer of the hid-multitouch driver. To >> > support even more devices, I started the implementation of the HID >> > over I2C protocol specification which is introduced by Win8. I'm quite >> > comfortable with the hid and the I2C part, but I'm blocked with the >> > interaction with the ACPI for the pnp part. >> > >> > I wanted to have your advice/help on this problem. I've add in the >> > recipients list the maintainers of i2c and ACPI, sorry for the noise >> > if you don't feel concerned about this. >> > >> > So, let's go deeper in the problem ;-) >> > Microsoft's spec asks the OEM to fill the ACPI DSDT to provide the >> > following scope in the ASL layout: >> > >> > >>>>>>>>> begin of ASL >> > Scope (\_SB) { >> > //-------------------- >> > // General Purpose I/O, ports 0...127 >> > //-------------------- >> > >> > Device(HIDI2C_DEVICE1) { >> > Name(_ADR,0) >> > Name (_HID, "MSFT1234”) >> > Name (_CID, "PNP0C50") >> > Name (_UID, 3) >> > >> > Method(_CRS, 0x0, NotSerialized) >> > { >> > Name (RBUF, ResourceTemplate () >> > { >> > // Address 0x07 on I2C-X (OEM selects this address) >> > //IHV SPECIFIC I2C3 = I2C Controller; TGD0 = GPIO Controller; >> > I2CSerialBus (0x07, ControllerInitiated, >> > 100000,AddressingMode7Bit, "\\_SB.I2C3",,,,) >> > GpioInt(Level, ActiveLow, Exclusive, PullUp, 0, "\\_SB. TGD0", >> > 0 , ResourceConsumer, , ) {40} >> > }) >> > Return(RBUF) >> > } >> > >> > Method(_DSM, 0x4, NotSerialized) >> > { >> > // BreakPoint >> > Store ("Method _DSM begin", Debug) >> > >> > // DSM UUID >> > switch(ToBuffer(Arg0)) >> > { >> > // ACPI DSM UUID for HIDI2C >> > case(ToUUID("3CDFF6F7-4267-4555-AD05-B30A3D8938DE")) >> > { >> > // DSM function which returns the HID Descriptor >> > Address (skipped) >> > } >> > >> > default >> > { >> > // No other GUIDs supported >> > Return(Buffer(One) { 0x00 }) >> > } >> > } >> > } >> > } >> > <<<<<<<<< end of ASL >> > >> yep, this is an ACPI enumerated I2C controller. >> >> > Summary: >> > - a HID over I2C device has to present the Compatibility ID "PNP0C50" >> > - in the _CRS block, the address, the adapter and the gpioInt are >> > defined (or referenced) >> > - it presents a Device Specific Method (_DSM) which returns the HID >> > Descriptor register address. This register is our entry point for >> > retrieving the information about our hid device (so it's mandatory to >> > obtain it). >> > >> > Where am I: >> > - I've written a first layer on top of i2c that retrieves the hid >> > register (currently the address 0x0001 is hardcoded), then get the >> > report desccriptors and the input events, and forward all this stuff >> > to the hid layer. >> > - It's working with a custom emulated HID over i2c touchpad, while >> > waiting for the one a manufacturer should send to me. >> > - The detection and the addition to the adapter is done by adding the >> > address in the lists and the name through the i2c "->detect" callback >> > (which is not very good, because I don't have the interrupt line >> > there). >> > - I've written a first acpi implementation that rely on the >> > DEVICE_ACPI_HANDLE macro to get the ACPI handle of the device (if >> > available). >> > - I'm not able to do some tests with the ACPI, as I don't know how to >> > implement this DSDT on my computer (I'm missing the I2C part), and the >> > manufacturer returned the mainboard with the right DSDT to the OEM. >> > >> > My questions: >> > - will the current acpi implementation handle I2C devices? >> >> you still need to write your own device driver for the device. >> >> > - it seems to me that the .archdata field is left blank during the i2c >> > device initialization in all paths I've seen. Is that true? >> > - who puts the name int the struct i2c_board_info? (for hot-plugged >> > i2c devices). >> > >> > - finally, what is the best way of handling ACPI for those I2C devices: >> > 1) everything is fine, I should have the ACPI handle in .archdata. >> > 2) someone has to implement the handling of I2C in the pnpACPI layer >> > (by adding I2CSerialBus handling and creating there the i2c slave). >> > 3) I should create an acpi driver which handles "PNP0C50" and which >> > creates the i2c slaves. >> > >> exactly. >> >> As this I2C controller uses the GPIO interrupt, we need an ACPI GPIO >> controller driver for interrupts first. >> I already have such a patch in hand, but have not release it for some >> reason. >> Second, you need to write your own PNP I2C controller driver, to >> enumerate the I2C controller via ACPI, AND enumerate the I2C slave >> devices under this controller to I2C bus. I also have a similar driver >> for SPI controller and SD/MMC controller. >> Third, you need a I2C slave device driver to handle the I2C slave device >> in I2C bus. >> >> here is a BKM I wrote, hope it helps. >> >> And also any comments are welcome. :) >> >> From 0a0fa4ff7b4b06c6560de94a78b15c6adfd86e34 Mon Sep 17 00:00:00 2001 >> From: Zhang Rui <rui.zhang@intel.com> >> Date: Mon, 26 Dec 2011 10:42:04 +0800 >> >> As many SoC IP blocks are not hardware self-enumerable, the >> firmware, aka, ACPI tables, is responsible for >> enumerating/reserving/assigning system resources to these >> devices. This tutorial talks about how to enumerate these >> devices via ACPI namespace. >> >> Signed-off-by: Zhang Rui <rui.zhang@intel.com> >> --- >> Documentation/acpi/acpi-device-probing.txt | 466 >> ++++++++++++++++++++++++++++ >> 1 file changed, 466 insertions(+) >> create mode 100644 Documentation/acpi/acpi-device-probing.txt >> >> diff --git a/Documentation/acpi/acpi-device-probing.txt >> b/Documentation/acpi/acpi-device-probing.txt >> new file mode 100644 >> index 0000000..82efbf3 >> --- /dev/null >> +++ b/Documentation/acpi/acpi-device-probing.txt >> @@ -0,0 +1,466 @@ >> + >> +HOWTO enumerate devices via ACPI >> + >> +Copyright (c) 2011-2012 Intel Corporation >> + >> +Contrast to hardware self-enumerable devices(e.g. USB, PCI) on PC >> platform, >> +many SoC IP blocks can not be self enumerated. >> +We used to introduce platform specific code for these devices. >> +But now, with ACPI 5.0, there is no requirement for the hardware to be >> +self-discoverable, enumerable or re-locatable, as the firmware is >> responsible >> +for enumerating/reserving/assigning system resources (such as address >> ranges or >> +interrupts) to the device. >> + >> +This document will show how to enumerate and configure a device via >> ACPI. >> +If you want to get more details about why and when we need this, >> +please refer to ACPI spec 5.0 and >> +Intel Architecture Platform Compatibility Definition. >> + >> +Note that although these are ACPI devices, we prefer to use PnP drivers >> for them, >> +this is because: >> +1. all the non-ACPI-predefined Devices are exported as PnP devices as >> well >> +2. PnP bus is a well designed bus. Probing via PnP layer saves a lot of >> work >> + for the device driver, e.g. getting & parsing ACPI resources. >> + >> +============================================================================= >> +1. Understand device definition in ACPI namespace >> + [Case study 1] SD/MMC controller >> +2. Driver for a leaf device >> + 2.1 Make a list of supported PnP ids >> + 2.2 Implement .probe/.remove callbacks for the PnP driver >> + 2.3 Fill in the pnp_driver structure >> + 2.4 Register the PnP driver >> +3. Driver for a master device on a non-self-enumerable bus >> + [Case Study 2] SPI controller and its slave device >> + 3.1 Probe the master device >> + 3.2 Walk ACPI namesapce to get the child devices of the master >> device >> + 3.3 Register these child devices as slave devices >> + 3.4 Write slave device driver >> +4. Misc >> +============================================================================= >> + >> +----------------------------------------------------------------------------- >> +1. Understand device definition in ACPI namespace >> +----------------------------------------------------------------------------- >> + >> +To enumerate a device in ACPI namespace, we need to find out and >> understand >> +HOW the device is defined in ACPI namespace first. >> + >> +[Case study 1 ] SD/MMC Controller >> + >> +Here is an ASL example code for SD/MMC controller definition in ACPI >> namespace. >> + >> + Device (EMMC) >> + { >> + Name (_ADR, Zero) >> + /* I use PNPXXXX, an arbitrary string, here, as PnP id is >> device specific */ >> + Name (_HID, "PNPXXXX") >> + Name (_CID, "PNPXXXX") >> + Name (_UID, 4) >> + >> + Method (_CRS, 0, NotSerialized) >> + { >> + Name (RBUF, ResourceTemplate () >> + { >> + Memory32Fixed (ReadWrite, >> + 0xFFA50000, // Address Base >> + 0x00000100, // Address Length >> + ) >> + Interrupt (ResourceConsumer, Level, ActiveLow, >> Exclusive, ,, ) >> + { >> + 0x0000001b, >> + } >> + }) >> + Return (RBUF) >> + } >> + >> + Method (_STA, 0, NotSerialized) >> + { >> + Return (0x0F) >> + } >> + } >> + >> +_ADR : the address of this device on its parent bus. Useless in this >> case. >> +_HID : the PnP id for this device. >> +_CID : the compatible PnP id. use this as the PnP id if _HID doesn't >> exist. >> +_CRS : the system resources currently allocated to this device. >> + the Memory32Fixed part shows an Mem space for the device, >> + and the Interrupt part shows the device interrupt. >> +_STA : the current status of the device, e.g. it's >> enabled/disabled/removed. >> + >> +By reading this example ASL code, we should know that there is a SD/MMC >> controller >> +on this platform, it's mem space base address is 0xFFA50000, length is >> 0x00000100, >> +and the irq for this device is 0x1b. >> + >> +In Chapter 2, we will use this piece of ASL code as an example to >> +show how to probe the SD/MMC controller via ACPI namespace. >> + >> +----------------------------------------------------------------------------- >> +2 Driver for a leaf device >> +----------------------------------------------------------------------------- >> + >> +2.1 Make a list of supported pnp ids. >> + >> +Use the string in _HID or _CID objects as the PnP ids so that the >> device can >> +be attached to the driver successfully. >> + >> +In this case, >> +struct pnp_device_id sdhci_pnp_ids[] = { >> + { .id = "PNPXXXX", >> + .driver_data = (unsigned long)&sdhci_mfd_pdata }, >> + { }, >> +}; >> + >> +2.2 Implement the .probe and .remove callback of PnP driver. >> + >> +If you're not clear about what should be done in the driver, you can >> consult >> +some similar driver, for example, drivers/mmc/host/sdhci-pci.c shows >> how >> +to probe a PCI SD/MMC controller, this helps us understand what should >> be done >> +in the .probe/.remove callback. >> + >> +By reading the sdhci-pci .probe function, we know that the .probe >> callback >> +needs to >> +a) alloc a sdhci host. >> +b) fill the sdhci host structure with necessary resources got from >> + PCI configure space, including irq and mem space for the sdhci host. >> +c) register the sdhci host. >> +And then, driver/mmc/host/sdhci.c, the SDHCI interface driver will >> handle >> +everything for us. >> + >> +So, basically, we need to do the same work in sdhci_pnp_probe callback, >> +except that we need to get the information from ACPI namesapce instead. >> + >> +To get the resources in _CRS, we do not need Linux ACPICA APIs as PnP >> layer >> +has done this for us already. >> + >> +pnp_irq() returns the device irq, which equals the "Interrupt" part in >> _CRS method. >> +pnp_get_resource(, IORESOURCE_MEM, 0) returns the first Mem space base >> address >> +and length of this device, which equals the "Memory32Fixed" Part of the >> _CRS. >> + >> +the code below shows how to use the PnP APIs to get ACPI resources and >> +register a sdhci host in the .probe callback. >> + >> +static int __devinit >> +sdhci_pnp_probe(struct pnp_dev *pdev, const struct pnp_device_id >> *dev_id) >> +{ >> +... >> + pnp_disable_dev(pdev); >> + ret = pnp_activate_dev(pdev); >> +... >> + iomem = pnp_get_resource(pdev, IORESOURCE_MEM, 0); >> +... >> + host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_pnp_dev)); >> +... >> + host->irq = pnp_irq(pdev, 0); >> +... >> + if (!request_mem_region(iomem->start, resource_size(iomem), >> + mmc_hostname(host->mmc))) { >> +... >> + host->ioaddr = ioremap_nocache(iomem->start, >> resource_size(iomem)); >> +... >> + ret = sdhci_add_host(host); >> +... >> + pnp_set_drvdata(pdev, sdhci); >> +... >> +} >> + >> +Once the .probe callback is done, we just need to release the resources >> and >> +unregister the host in the .remove callback. >> + >> +static void sdhci_pnp_remove(struct pnp_dev * pdev) >> +{ >> + struct sdhci_pnp_dev *sdhci = pnp_get_drvdata(pdev); >> + struct resources *iomem = pnp_get_resource(pdev, IORESOURCE_MEM, 0); >> +... >> + sdhci_remove_host(sdhci->host, dead); >> + sdhci_free_host(sdhci->host); >> + iounmap(sdhci->host->ioaddr); >> + release_mem_region(iomem->start, resource_size(iomem)); >> + pnp_set_drvdata(pdev, NULL); >> + pnp_disable_dev(pdev); >> +} >> + >> +2.3 Fill in the pnp_driver structure >> + >> +Next step is to fill in the pnp_driver structure with PnP ids and >> +.probe/.remove callbacks finished in section 2.1 and 2.2 >> + >> +static struct pnp_driver sdhci_pnp_driver = { >> + .name = DRIVER_NAME, >> + .id_table = sdhci_pnp_ids, >> + .probe = sdhci_pnp_probe, >> + .remove = __devexit_p(sdhci_pnp_remove), >> +}; >> + >> +Note that .name and .id_table cannot be NULL. >> + >> +2.4 Register the PnP driver >> + >> +Now we can register this PnP driver to the driver model. >> + >> +static int __init sdhci_pnp_init(void) >> +{ >> + return pnp_register_driver(&sdhci_pnp_driver); >> +} >> + >> +module_init(sdhci_pnp_init); >> + >> + >> +----------------------------------------------------------------------------- >> +3 Driver for a master device on a non-self-enumerable bus >> +----------------------------------------------------------------------------- >> +In some cases, enumerating via ACPI brings new requirements in the >> driver. >> +For example, the driver for a master device on a non-self-enumerable >> bus is >> +responsible for enumerating the slave devices on this bus as well, >> which are >> +described as child devices of this master device in ACPI namespace. >> + >> +Taking SPI bus for example, >> + >> +------------------------------------------------------------------- >> +PNP/ACPI layer >> + >> + spi-acpi driver >> + | >> + |-----------------| >> + | | >> + | | >> + V V >> + register itself register its children >> + as a master as slave devices >> + device | >> + | | >> +---------|-----------------|--------------------------------------- >> + | | >> + | | >> + | | >> + V V >> + -------------- ----------- >> + | SPI | | SPI | >> + | master | | slave | >> + -------------- ----------- >> + ^ >> + | >> + | >> + V >> + ----------------------------- >> + | SPI slave driver driver | >> + ----------------------------- >> +SPI Bus layer >> +------------------------------------------------------------------- >> + >> +The figure above shows the components needed to make a SPI slave device >> work >> +a) an PNP/ACPI driver to probe the SPI master and its slaves. >> +b) a SPI slave device driver for the SPI slave device. >> + >> +[Case Study 2] SPI controller and its slave device >> + >> +This piece of ASL code shows the definition of a SPI controller and its >> slave device, >> +MAX3110, in ACPI namespace. >> + >> +Device (SPI1) { >> + Name (_ADR, 0) >> + Name (_HID, "PNPYYYY") >> + Name (_CID, "PNPYYYY") >> + Name (_UID, 1) >> + >> + Method (_CRS, 0x0, NotSerialized) { >> + Name (RBUF, ResourceTemplate () >> + { >> + Memory32Fixed (ReadWrite, 0xff128400, 0x00000400) >> + Interrupt(ResourceConsumer, Level, ActiveHigh, Exclusive, , , ) >> {0x09} >> + }) >> + Return (RBUF) >> + } >> + >> + Method (_STA, 0x0, NotSerialized) { >> + Return(0xf) >> + } >> + >> + Device(MAX0) >> + { >> + Name(_HID, "PNPZZZZ") // Max3110 serial port >> + Name(_DDN, "Max3110 serial port") >> + Method(_CRS, 0x0, NotSerialized) >> + { >> + // SpiSerial Bus Connection Descriptor >> + Name(UBUF, ResourceTemplate () { >> + SPISerialBus( >> + 1, // Device selection >> + PolarityHigh, // Device selection polarity >> + ThreeWireMode, // wiremode >> + 8, // databit len >> + ControllerInitiated, // slave mode >> + 1000, // Connection speed >> + ClockPolarityHigh, // Clock polarity >> + ClockPhaseFirst, // clock phase >> + "\\_SB.SPI1", // ResourceSource: SPI bus controller name >> + 0, // ResourceSourceIndex >> + ResourceConsumer, // Resource usage >> + , // DescriptorName: creates name for offset >> of resource descriptor >> + ) // Vendor Data >> + // OUT pin, BT_EN pin Core GPIO 74 >> + GpioIo(Exclusive, PullDefault, 0, 0, IoRestrictionOutputOnly, "\ >> \_SB.GPIS", ) {0x4A} >> + }) >> + >> + Return (UBUF) >> + } >> + } >> +} >> + >> +By reading the ASL code, we can see that >> +a) There is a SPI controller on this platform. >> + with IRQ 0x09, and a 0x400 bytes Memory space started from >> 0xff128400. >> +b) a MAX3110 device is connect to a SPI controller. >> + all the information required for probing a SPI slave device is >> described >> + in the "SPISerailBus" part of the MAX0._CRS method. >> + >> +We will talk about how to probe these two devices in this chapter. >> + >> +3.1 Probe the master device >> + >> +Please follow the Chapter 2 to probe the SPI master device. >> + >> +static int __devinit >> +dw_spi_pnp_probe(struct pnp_dev *pdev, const struct pnp_device_id >> *dev_id) >> +{ >> +... >> + dws->paddr = pnp_mem_start(pdev, 0); >> + dws->iolen = pnp_mem_len(pdev, 0); >> + dws->irq = pnp_irq(pdev, 0); >> + dws->parent_dev = &pdev->dev; >> + dws->bus_num = index++; >> + dws->num_cs = 4; >> + dws->regs = ioremap_nocache((unsigned long)dws->paddr, >> + dws->iolen); >> +... >> + ret = dw_spi_mid_init(dws); >> +... >> + ret = dw_spi_add_host(dws); >> +... >> +} >> + >> +3.2 Walk ACPI namespace to probe all its child devices. >> + >> +As MAX3110 can not be enumerated automatically, we introduce >> +dw_spi_pnp_slaves_register() to find the MAX3110 device in ACPI >> namespace >> + >> +static int __devinit dw_spi_pnp_slaves_register(struct dw_spi_pnp* >> dwpnp) >> +{ >> + ... >> + struct acpi_device *adev; >> + adev = dwpnp->pdev->data; >> + >> + /* >> + * find spi child devices given in ACPI namespace, one lower level >> only >> + */ >> + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, adev->handle, 1, >> + spi_slave_register, NULL, >> + spi_slave_info, NULL); >> + ... >> +} >> + >> +3.3 Register its child devices as slave devices >> + >> +As spi_slave_register is invoked for each SPI1 child device, >> +we introduce spi_slave_fill_resourcetry and try to register >> +SPI slave devices in spi_slave_register. >> + >> +acpi_status __init spi_slave_register(acpi_handle spi_slave_handle, u32 >> level, >> + void* data, void** return_value) >> +{ >> + ... >> + struct spi_board_info *spi_slave_info; >> + ... >> + status = acpi_walk_resources(spi_slave_handle, METHOD_NAME__CRS, >> + spi_slave_fill_resource, data); >> + ... >> + /* register SPI slave device */ >> + ret = spi_register_board_info(spi_slave_info, 1); >> + ... >> +} >> + >> +acpi_status __devinit spi_slave_fill_resource(struct acpi_resource >> *resource, void* data) >> +{ >> + struct spi_board_info *spi_slave_info; >> + struct acpi_resource_spi_serialbus *spi_resource; >> + ... >> + spi_resource = &resource->data.spi_serial_bus; >> + spi_slave_info->chip_select = spi_resource->device_selection; >> + spi_slave_info->max_speed_hz = spi_resource->connection_speed; >> + spi_slave_info->mode = (spi_resource->clock_phase ? SPI_CPHA : 0) | >> + (spi_resource->clock_polarity ? SPI_CPOL : 0) | >> + (spi_resource->device_polarity ? SPI_CS_HIGH : 0) | >> + (spi_resource->wire_mode ? SPI_3WIRE : 0); >> + ... >> +} >> + >> +3.4 Write the slave device driver >> + >> +After 3.3 is done, the MAX3110 device is an slave device in the SPI >> bus, >> +but to make it work properly, we still need a SPI slave device driver. >> + >> +Note that this is a general SPI drivers independent of ACPI. >> + >> +We will not go into details of the slave device driver here as >> +this piece of code is bus/device specific. >> + >> +----------------------------------------------------------------------------- >> +4 Misc >> +----------------------------------------------------------------------------- >> + >> +4.1 Note >> + >> +As ACPI 5.0 is still in heavily developing, if you are unable to find >> out all the >> +required information for probing a device in ACPI namespace, it is >> possible >> +that the ASL code is not well written. >> +Please contact Zhang Rui <rui.zhang@intel.com> with the acpidump output >> of your >> +platform attached if you suspect it's an BIOS problem. >> + >> +4.2 Some important ACPICA APIs for device driver implementation: >> + >> +-- acpi_status >> + acpi_walk_namespace(acpi_object_type type, >> + acpi_handle start_object, >> + u32 max_depth, >> + acpi_walk_callback pre_order_visit, >> + acpi_walk_callback post_order_visit, >> + void *context, void **return_value); >> +Traverse ACPI namespace subtree rooted at start_object, go down >> max_depth level >> +at most. Call pre_order_visit when the proper node with type is found >> the first >> +time, call post_order_visit is the node is previously visited. Context >> and >> +return_value is passed down during the traverse. >> + >> +And the prototype of acpi_walk_callback: >> +typedef >> +acpi_status(*acpi_walk_callback) (acpi_handle object, >> + u32 nesting_level, >> + void *context, void **return_value); >> + >> +-- acpi_status >> + acpi_get_handle(acpi_handle parent, >> + acpi_string pathname, acpi_handle * ret_handle); >> +Try to get handle with specified pathname under node parent. Usually >> used to >> +check whether a particular node is available or not. >> + >> +-- acpi_status >> + acpi_get_object_info(acpi_handle object, >> + struct acpi_device_info **return_buffer); >> +Get acpi_device_info from object handle. Useful for retrieving ACPI >> object >> +name, type, and status etc. >> + >> +-- acpi_status >> + acpi_walk_resources(acpi_handle device, >> + char *name, >> + acpi_walk_resource_callback user_function, void *context); >> +Traverse resource node specified by name(e.g. METHOD_NAME__CRS) in ACPI >> +namespace subtree rooted at device. Call user_function for each entry >> in >> +acpi_resource list. The list may containe acpi_resource entries with >> various >> +types. So it is important to handle the interested resource type >> properly. >> +The acpi_resource with ACPI_RESOURCE_TYPE_END_TAG indicates >> end-of-list. >> + >> +And the prototype of acpi_walk_resource_callback: >> +typedef >> +acpi_status(*acpi_walk_resource_callback) (struct acpi_resource * >> resource, >> + void *context); >> + >> +More ACPICA external interfaces available in include/acpi/acpixf.h > > -- 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 ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Fwd: Hid over I2C and ACPI interaction 2012-07-05 8:44 ` Benjamin Tissoires @ 2012-07-09 0:41 ` Zhang Rui 0 siblings, 0 replies; 10+ messages in thread From: Zhang Rui @ 2012-07-09 0:41 UTC (permalink / raw) To: Benjamin Tissoires Cc: khali-PUYAD+kWke1g9hUCZPvPmw, ben-linux-elnMNo+KYs3YtjvyW6yDsg, w.sang-bIcnvbaLZ9MEGnE8C9+IrQ, lenb-DgEjT+Ai2ygdnm+yROfE0A, linux-acpi-u79uwXL29TY76Z2rM5mHXA, linux-i2c-u79uwXL29TY76Z2rM5mHXA, linux-kernel-u79uwXL29TY76Z2rM5mHXA, jkosina-AlSwsSmVLrQ, chatty-rXV5z7KbLFk, jj_ding-9cfG7bMpBgR9nmWX13WWKA On 四, 2012-07-05 at 10:44 +0200, Benjamin Tissoires wrote: > Hi, > > Many thanks for these information. It seems like I was on the right > track, but I didn't saw the hidden part of the iceberg. yep. > I've already written the i2c slave part (and the acpi handling to get > the HID register by using the DSM should work), but I need now the > whole ACPI pnp drivers... > you need the ACPI/PNP I2C controller driver. > But without a real ACPI 5.0 mainboard, I think it will be quite > difficult to implement and debug this ACPI stuff. > yes, that's the problem I have. I can not send out the code based on some example ASL code. :) thanks, rui > Cheers, > Benjamin > > On Thu, Jul 5, 2012 at 9:20 AM, Zhang Rui <rui.zhang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org> wrote: > > Hah, seems I forgot to reply to Benjamin. > > > > On 四, 2012-07-05 at 15:01 +0800, Zhang Rui wrote: > >> > -------- Original Message -------- > >> > Subject: Hid over I2C and ACPI interaction > >> > Date: Wed, 4 Jul 2012 15:46:35 +0200 > >> > From: Benjamin Tissoires <benjamin.tissoires-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> > >> > To: Jean Delvare <khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org>, Ben Dooks <ben-linux@fluff.org>, Wolfram > >> > Sang <w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>, Len Brown <lenb-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>, > >> > <linux-acpi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>, <linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>, > >> > <linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org> > >> > CC: Jiri Kosina <jkosina-AlSwsSmVLrQ@public.gmane.org>, Stéphane Chatty <chatty@enac.fr>, JJ Ding > >> > <jj_ding-9cfG7bMpBgR9nmWX13WWKA@public.gmane.org> > >> > > >> > Hi Guys, > >> > > >> > I'm the co-author and the maintainer of the hid-multitouch driver. To > >> > support even more devices, I started the implementation of the HID > >> > over I2C protocol specification which is introduced by Win8. I'm quite > >> > comfortable with the hid and the I2C part, but I'm blocked with the > >> > interaction with the ACPI for the pnp part. > >> > > >> > I wanted to have your advice/help on this problem. I've add in the > >> > recipients list the maintainers of i2c and ACPI, sorry for the noise > >> > if you don't feel concerned about this. > >> > > >> > So, let's go deeper in the problem ;-) > >> > Microsoft's spec asks the OEM to fill the ACPI DSDT to provide the > >> > following scope in the ASL layout: > >> > > >> > >>>>>>>>> begin of ASL > >> > Scope (\_SB) { > >> > //-------------------- > >> > // General Purpose I/O, ports 0...127 > >> > //-------------------- > >> > > >> > Device(HIDI2C_DEVICE1) { > >> > Name(_ADR,0) > >> > Name (_HID, "MSFT1234”) > >> > Name (_CID, "PNP0C50") > >> > Name (_UID, 3) > >> > > >> > Method(_CRS, 0x0, NotSerialized) > >> > { > >> > Name (RBUF, ResourceTemplate () > >> > { > >> > // Address 0x07 on I2C-X (OEM selects this address) > >> > //IHV SPECIFIC I2C3 = I2C Controller; TGD0 = GPIO Controller; > >> > I2CSerialBus (0x07, ControllerInitiated, > >> > 100000,AddressingMode7Bit, "\\_SB.I2C3",,,,) > >> > GpioInt(Level, ActiveLow, Exclusive, PullUp, 0, "\\_SB. TGD0", > >> > 0 , ResourceConsumer, , ) {40} > >> > }) > >> > Return(RBUF) > >> > } > >> > > >> > Method(_DSM, 0x4, NotSerialized) > >> > { > >> > // BreakPoint > >> > Store ("Method _DSM begin", Debug) > >> > > >> > // DSM UUID > >> > switch(ToBuffer(Arg0)) > >> > { > >> > // ACPI DSM UUID for HIDI2C > >> > case(ToUUID("3CDFF6F7-4267-4555-AD05-B30A3D8938DE")) > >> > { > >> > // DSM function which returns the HID Descriptor > >> > Address (skipped) > >> > } > >> > > >> > default > >> > { > >> > // No other GUIDs supported > >> > Return(Buffer(One) { 0x00 }) > >> > } > >> > } > >> > } > >> > } > >> > <<<<<<<<< end of ASL > >> > > >> yep, this is an ACPI enumerated I2C controller. > >> > >> > Summary: > >> > - a HID over I2C device has to present the Compatibility ID "PNP0C50" > >> > - in the _CRS block, the address, the adapter and the gpioInt are > >> > defined (or referenced) > >> > - it presents a Device Specific Method (_DSM) which returns the HID > >> > Descriptor register address. This register is our entry point for > >> > retrieving the information about our hid device (so it's mandatory to > >> > obtain it). > >> > > >> > Where am I: > >> > - I've written a first layer on top of i2c that retrieves the hid > >> > register (currently the address 0x0001 is hardcoded), then get the > >> > report desccriptors and the input events, and forward all this stuff > >> > to the hid layer. > >> > - It's working with a custom emulated HID over i2c touchpad, while > >> > waiting for the one a manufacturer should send to me. > >> > - The detection and the addition to the adapter is done by adding the > >> > address in the lists and the name through the i2c "->detect" callback > >> > (which is not very good, because I don't have the interrupt line > >> > there). > >> > - I've written a first acpi implementation that rely on the > >> > DEVICE_ACPI_HANDLE macro to get the ACPI handle of the device (if > >> > available). > >> > - I'm not able to do some tests with the ACPI, as I don't know how to > >> > implement this DSDT on my computer (I'm missing the I2C part), and the > >> > manufacturer returned the mainboard with the right DSDT to the OEM. > >> > > >> > My questions: > >> > - will the current acpi implementation handle I2C devices? > >> > >> you still need to write your own device driver for the device. > >> > >> > - it seems to me that the .archdata field is left blank during the i2c > >> > device initialization in all paths I've seen. Is that true? > >> > - who puts the name int the struct i2c_board_info? (for hot-plugged > >> > i2c devices). > >> > > >> > - finally, what is the best way of handling ACPI for those I2C devices: > >> > 1) everything is fine, I should have the ACPI handle in .archdata. > >> > 2) someone has to implement the handling of I2C in the pnpACPI layer > >> > (by adding I2CSerialBus handling and creating there the i2c slave). > >> > 3) I should create an acpi driver which handles "PNP0C50" and which > >> > creates the i2c slaves. > >> > > >> exactly. > >> > >> As this I2C controller uses the GPIO interrupt, we need an ACPI GPIO > >> controller driver for interrupts first. > >> I already have such a patch in hand, but have not release it for some > >> reason. > >> Second, you need to write your own PNP I2C controller driver, to > >> enumerate the I2C controller via ACPI, AND enumerate the I2C slave > >> devices under this controller to I2C bus. I also have a similar driver > >> for SPI controller and SD/MMC controller. > >> Third, you need a I2C slave device driver to handle the I2C slave device > >> in I2C bus. > >> > >> here is a BKM I wrote, hope it helps. > >> > >> And also any comments are welcome. :) > >> > >> From 0a0fa4ff7b4b06c6560de94a78b15c6adfd86e34 Mon Sep 17 00:00:00 2001 > >> From: Zhang Rui <rui.zhang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org> > >> Date: Mon, 26 Dec 2011 10:42:04 +0800 > >> > >> As many SoC IP blocks are not hardware self-enumerable, the > >> firmware, aka, ACPI tables, is responsible for > >> enumerating/reserving/assigning system resources to these > >> devices. This tutorial talks about how to enumerate these > >> devices via ACPI namespace. > >> > >> Signed-off-by: Zhang Rui <rui.zhang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org> > >> --- > >> Documentation/acpi/acpi-device-probing.txt | 466 > >> ++++++++++++++++++++++++++++ > >> 1 file changed, 466 insertions(+) > >> create mode 100644 Documentation/acpi/acpi-device-probing.txt > >> > >> diff --git a/Documentation/acpi/acpi-device-probing.txt > >> b/Documentation/acpi/acpi-device-probing.txt > >> new file mode 100644 > >> index 0000000..82efbf3 > >> --- /dev/null > >> +++ b/Documentation/acpi/acpi-device-probing.txt > >> @@ -0,0 +1,466 @@ > >> + > >> +HOWTO enumerate devices via ACPI > >> + > >> +Copyright (c) 2011-2012 Intel Corporation > >> + > >> +Contrast to hardware self-enumerable devices(e.g. USB, PCI) on PC > >> platform, > >> +many SoC IP blocks can not be self enumerated. > >> +We used to introduce platform specific code for these devices. > >> +But now, with ACPI 5.0, there is no requirement for the hardware to be > >> +self-discoverable, enumerable or re-locatable, as the firmware is > >> responsible > >> +for enumerating/reserving/assigning system resources (such as address > >> ranges or > >> +interrupts) to the device. > >> + > >> +This document will show how to enumerate and configure a device via > >> ACPI. > >> +If you want to get more details about why and when we need this, > >> +please refer to ACPI spec 5.0 and > >> +Intel Architecture Platform Compatibility Definition. > >> + > >> +Note that although these are ACPI devices, we prefer to use PnP drivers > >> for them, > >> +this is because: > >> +1. all the non-ACPI-predefined Devices are exported as PnP devices as > >> well > >> +2. PnP bus is a well designed bus. Probing via PnP layer saves a lot of > >> work > >> + for the device driver, e.g. getting & parsing ACPI resources. > >> + > >> +============================================================================= > >> +1. Understand device definition in ACPI namespace > >> + [Case study 1] SD/MMC controller > >> +2. Driver for a leaf device > >> + 2.1 Make a list of supported PnP ids > >> + 2.2 Implement .probe/.remove callbacks for the PnP driver > >> + 2.3 Fill in the pnp_driver structure > >> + 2.4 Register the PnP driver > >> +3. Driver for a master device on a non-self-enumerable bus > >> + [Case Study 2] SPI controller and its slave device > >> + 3.1 Probe the master device > >> + 3.2 Walk ACPI namesapce to get the child devices of the master > >> device > >> + 3.3 Register these child devices as slave devices > >> + 3.4 Write slave device driver > >> +4. Misc > >> +============================================================================= > >> + > >> +----------------------------------------------------------------------------- > >> +1. Understand device definition in ACPI namespace > >> +----------------------------------------------------------------------------- > >> + > >> +To enumerate a device in ACPI namespace, we need to find out and > >> understand > >> +HOW the device is defined in ACPI namespace first. > >> + > >> +[Case study 1 ] SD/MMC Controller > >> + > >> +Here is an ASL example code for SD/MMC controller definition in ACPI > >> namespace. > >> + > >> + Device (EMMC) > >> + { > >> + Name (_ADR, Zero) > >> + /* I use PNPXXXX, an arbitrary string, here, as PnP id is > >> device specific */ > >> + Name (_HID, "PNPXXXX") > >> + Name (_CID, "PNPXXXX") > >> + Name (_UID, 4) > >> + > >> + Method (_CRS, 0, NotSerialized) > >> + { > >> + Name (RBUF, ResourceTemplate () > >> + { > >> + Memory32Fixed (ReadWrite, > >> + 0xFFA50000, // Address Base > >> + 0x00000100, // Address Length > >> + ) > >> + Interrupt (ResourceConsumer, Level, ActiveLow, > >> Exclusive, ,, ) > >> + { > >> + 0x0000001b, > >> + } > >> + }) > >> + Return (RBUF) > >> + } > >> + > >> + Method (_STA, 0, NotSerialized) > >> + { > >> + Return (0x0F) > >> + } > >> + } > >> + > >> +_ADR : the address of this device on its parent bus. Useless in this > >> case. > >> +_HID : the PnP id for this device. > >> +_CID : the compatible PnP id. use this as the PnP id if _HID doesn't > >> exist. > >> +_CRS : the system resources currently allocated to this device. > >> + the Memory32Fixed part shows an Mem space for the device, > >> + and the Interrupt part shows the device interrupt. > >> +_STA : the current status of the device, e.g. it's > >> enabled/disabled/removed. > >> + > >> +By reading this example ASL code, we should know that there is a SD/MMC > >> controller > >> +on this platform, it's mem space base address is 0xFFA50000, length is > >> 0x00000100, > >> +and the irq for this device is 0x1b. > >> + > >> +In Chapter 2, we will use this piece of ASL code as an example to > >> +show how to probe the SD/MMC controller via ACPI namespace. > >> + > >> +----------------------------------------------------------------------------- > >> +2 Driver for a leaf device > >> +----------------------------------------------------------------------------- > >> + > >> +2.1 Make a list of supported pnp ids. > >> + > >> +Use the string in _HID or _CID objects as the PnP ids so that the > >> device can > >> +be attached to the driver successfully. > >> + > >> +In this case, > >> +struct pnp_device_id sdhci_pnp_ids[] = { > >> + { .id = "PNPXXXX", > >> + .driver_data = (unsigned long)&sdhci_mfd_pdata }, > >> + { }, > >> +}; > >> + > >> +2.2 Implement the .probe and .remove callback of PnP driver. > >> + > >> +If you're not clear about what should be done in the driver, you can > >> consult > >> +some similar driver, for example, drivers/mmc/host/sdhci-pci.c shows > >> how > >> +to probe a PCI SD/MMC controller, this helps us understand what should > >> be done > >> +in the .probe/.remove callback. > >> + > >> +By reading the sdhci-pci .probe function, we know that the .probe > >> callback > >> +needs to > >> +a) alloc a sdhci host. > >> +b) fill the sdhci host structure with necessary resources got from > >> + PCI configure space, including irq and mem space for the sdhci host. > >> +c) register the sdhci host. > >> +And then, driver/mmc/host/sdhci.c, the SDHCI interface driver will > >> handle > >> +everything for us. > >> + > >> +So, basically, we need to do the same work in sdhci_pnp_probe callback, > >> +except that we need to get the information from ACPI namesapce instead. > >> + > >> +To get the resources in _CRS, we do not need Linux ACPICA APIs as PnP > >> layer > >> +has done this for us already. > >> + > >> +pnp_irq() returns the device irq, which equals the "Interrupt" part in > >> _CRS method. > >> +pnp_get_resource(, IORESOURCE_MEM, 0) returns the first Mem space base > >> address > >> +and length of this device, which equals the "Memory32Fixed" Part of the > >> _CRS. > >> + > >> +the code below shows how to use the PnP APIs to get ACPI resources and > >> +register a sdhci host in the .probe callback. > >> + > >> +static int __devinit > >> +sdhci_pnp_probe(struct pnp_dev *pdev, const struct pnp_device_id > >> *dev_id) > >> +{ > >> +... > >> + pnp_disable_dev(pdev); > >> + ret = pnp_activate_dev(pdev); > >> +... > >> + iomem = pnp_get_resource(pdev, IORESOURCE_MEM, 0); > >> +... > >> + host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_pnp_dev)); > >> +... > >> + host->irq = pnp_irq(pdev, 0); > >> +... > >> + if (!request_mem_region(iomem->start, resource_size(iomem), > >> + mmc_hostname(host->mmc))) { > >> +... > >> + host->ioaddr = ioremap_nocache(iomem->start, > >> resource_size(iomem)); > >> +... > >> + ret = sdhci_add_host(host); > >> +... > >> + pnp_set_drvdata(pdev, sdhci); > >> +... > >> +} > >> + > >> +Once the .probe callback is done, we just need to release the resources > >> and > >> +unregister the host in the .remove callback. > >> + > >> +static void sdhci_pnp_remove(struct pnp_dev * pdev) > >> +{ > >> + struct sdhci_pnp_dev *sdhci = pnp_get_drvdata(pdev); > >> + struct resources *iomem = pnp_get_resource(pdev, IORESOURCE_MEM, 0); > >> +... > >> + sdhci_remove_host(sdhci->host, dead); > >> + sdhci_free_host(sdhci->host); > >> + iounmap(sdhci->host->ioaddr); > >> + release_mem_region(iomem->start, resource_size(iomem)); > >> + pnp_set_drvdata(pdev, NULL); > >> + pnp_disable_dev(pdev); > >> +} > >> + > >> +2.3 Fill in the pnp_driver structure > >> + > >> +Next step is to fill in the pnp_driver structure with PnP ids and > >> +.probe/.remove callbacks finished in section 2.1 and 2.2 > >> + > >> +static struct pnp_driver sdhci_pnp_driver = { > >> + .name = DRIVER_NAME, > >> + .id_table = sdhci_pnp_ids, > >> + .probe = sdhci_pnp_probe, > >> + .remove = __devexit_p(sdhci_pnp_remove), > >> +}; > >> + > >> +Note that .name and .id_table cannot be NULL. > >> + > >> +2.4 Register the PnP driver > >> + > >> +Now we can register this PnP driver to the driver model. > >> + > >> +static int __init sdhci_pnp_init(void) > >> +{ > >> + return pnp_register_driver(&sdhci_pnp_driver); > >> +} > >> + > >> +module_init(sdhci_pnp_init); > >> + > >> + > >> +----------------------------------------------------------------------------- > >> +3 Driver for a master device on a non-self-enumerable bus > >> +----------------------------------------------------------------------------- > >> +In some cases, enumerating via ACPI brings new requirements in the > >> driver. > >> +For example, the driver for a master device on a non-self-enumerable > >> bus is > >> +responsible for enumerating the slave devices on this bus as well, > >> which are > >> +described as child devices of this master device in ACPI namespace. > >> + > >> +Taking SPI bus for example, > >> + > >> +------------------------------------------------------------------- > >> +PNP/ACPI layer > >> + > >> + spi-acpi driver > >> + | > >> + |-----------------| > >> + | | > >> + | | > >> + V V > >> + register itself register its children > >> + as a master as slave devices > >> + device | > >> + | | > >> +---------|-----------------|--------------------------------------- > >> + | | > >> + | | > >> + | | > >> + V V > >> + -------------- ----------- > >> + | SPI | | SPI | > >> + | master | | slave | > >> + -------------- ----------- > >> + ^ > >> + | > >> + | > >> + V > >> + ----------------------------- > >> + | SPI slave driver driver | > >> + ----------------------------- > >> +SPI Bus layer > >> +------------------------------------------------------------------- > >> + > >> +The figure above shows the components needed to make a SPI slave device > >> work > >> +a) an PNP/ACPI driver to probe the SPI master and its slaves. > >> +b) a SPI slave device driver for the SPI slave device. > >> + > >> +[Case Study 2] SPI controller and its slave device > >> + > >> +This piece of ASL code shows the definition of a SPI controller and its > >> slave device, > >> +MAX3110, in ACPI namespace. > >> + > >> +Device (SPI1) { > >> + Name (_ADR, 0) > >> + Name (_HID, "PNPYYYY") > >> + Name (_CID, "PNPYYYY") > >> + Name (_UID, 1) > >> + > >> + Method (_CRS, 0x0, NotSerialized) { > >> + Name (RBUF, ResourceTemplate () > >> + { > >> + Memory32Fixed (ReadWrite, 0xff128400, 0x00000400) > >> + Interrupt(ResourceConsumer, Level, ActiveHigh, Exclusive, , , ) > >> {0x09} > >> + }) > >> + Return (RBUF) > >> + } > >> + > >> + Method (_STA, 0x0, NotSerialized) { > >> + Return(0xf) > >> + } > >> + > >> + Device(MAX0) > >> + { > >> + Name(_HID, "PNPZZZZ") // Max3110 serial port > >> + Name(_DDN, "Max3110 serial port") > >> + Method(_CRS, 0x0, NotSerialized) > >> + { > >> + // SpiSerial Bus Connection Descriptor > >> + Name(UBUF, ResourceTemplate () { > >> + SPISerialBus( > >> + 1, // Device selection > >> + PolarityHigh, // Device selection polarity > >> + ThreeWireMode, // wiremode > >> + 8, // databit len > >> + ControllerInitiated, // slave mode > >> + 1000, // Connection speed > >> + ClockPolarityHigh, // Clock polarity > >> + ClockPhaseFirst, // clock phase > >> + "\\_SB.SPI1", // ResourceSource: SPI bus controller name > >> + 0, // ResourceSourceIndex > >> + ResourceConsumer, // Resource usage > >> + , // DescriptorName: creates name for offset > >> of resource descriptor > >> + ) // Vendor Data > >> + // OUT pin, BT_EN pin Core GPIO 74 > >> + GpioIo(Exclusive, PullDefault, 0, 0, IoRestrictionOutputOnly, "\ > >> \_SB.GPIS", ) {0x4A} > >> + }) > >> + > >> + Return (UBUF) > >> + } > >> + } > >> +} > >> + > >> +By reading the ASL code, we can see that > >> +a) There is a SPI controller on this platform. > >> + with IRQ 0x09, and a 0x400 bytes Memory space started from > >> 0xff128400. > >> +b) a MAX3110 device is connect to a SPI controller. > >> + all the information required for probing a SPI slave device is > >> described > >> + in the "SPISerailBus" part of the MAX0._CRS method. > >> + > >> +We will talk about how to probe these two devices in this chapter. > >> + > >> +3.1 Probe the master device > >> + > >> +Please follow the Chapter 2 to probe the SPI master device. > >> + > >> +static int __devinit > >> +dw_spi_pnp_probe(struct pnp_dev *pdev, const struct pnp_device_id > >> *dev_id) > >> +{ > >> +... > >> + dws->paddr = pnp_mem_start(pdev, 0); > >> + dws->iolen = pnp_mem_len(pdev, 0); > >> + dws->irq = pnp_irq(pdev, 0); > >> + dws->parent_dev = &pdev->dev; > >> + dws->bus_num = index++; > >> + dws->num_cs = 4; > >> + dws->regs = ioremap_nocache((unsigned long)dws->paddr, > >> + dws->iolen); > >> +... > >> + ret = dw_spi_mid_init(dws); > >> +... > >> + ret = dw_spi_add_host(dws); > >> +... > >> +} > >> + > >> +3.2 Walk ACPI namespace to probe all its child devices. > >> + > >> +As MAX3110 can not be enumerated automatically, we introduce > >> +dw_spi_pnp_slaves_register() to find the MAX3110 device in ACPI > >> namespace > >> + > >> +static int __devinit dw_spi_pnp_slaves_register(struct dw_spi_pnp* > >> dwpnp) > >> +{ > >> + ... > >> + struct acpi_device *adev; > >> + adev = dwpnp->pdev->data; > >> + > >> + /* > >> + * find spi child devices given in ACPI namespace, one lower level > >> only > >> + */ > >> + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, adev->handle, 1, > >> + spi_slave_register, NULL, > >> + spi_slave_info, NULL); > >> + ... > >> +} > >> + > >> +3.3 Register its child devices as slave devices > >> + > >> +As spi_slave_register is invoked for each SPI1 child device, > >> +we introduce spi_slave_fill_resourcetry and try to register > >> +SPI slave devices in spi_slave_register. > >> + > >> +acpi_status __init spi_slave_register(acpi_handle spi_slave_handle, u32 > >> level, > >> + void* data, void** return_value) > >> +{ > >> + ... > >> + struct spi_board_info *spi_slave_info; > >> + ... > >> + status = acpi_walk_resources(spi_slave_handle, METHOD_NAME__CRS, > >> + spi_slave_fill_resource, data); > >> + ... > >> + /* register SPI slave device */ > >> + ret = spi_register_board_info(spi_slave_info, 1); > >> + ... > >> +} > >> + > >> +acpi_status __devinit spi_slave_fill_resource(struct acpi_resource > >> *resource, void* data) > >> +{ > >> + struct spi_board_info *spi_slave_info; > >> + struct acpi_resource_spi_serialbus *spi_resource; > >> + ... > >> + spi_resource = &resource->data.spi_serial_bus; > >> + spi_slave_info->chip_select = spi_resource->device_selection; > >> + spi_slave_info->max_speed_hz = spi_resource->connection_speed; > >> + spi_slave_info->mode = (spi_resource->clock_phase ? SPI_CPHA : 0) | > >> + (spi_resource->clock_polarity ? SPI_CPOL : 0) | > >> + (spi_resource->device_polarity ? SPI_CS_HIGH : 0) | > >> + (spi_resource->wire_mode ? SPI_3WIRE : 0); > >> + ... > >> +} > >> + > >> +3.4 Write the slave device driver > >> + > >> +After 3.3 is done, the MAX3110 device is an slave device in the SPI > >> bus, > >> +but to make it work properly, we still need a SPI slave device driver. > >> + > >> +Note that this is a general SPI drivers independent of ACPI. > >> + > >> +We will not go into details of the slave device driver here as > >> +this piece of code is bus/device specific. > >> + > >> +----------------------------------------------------------------------------- > >> +4 Misc > >> +----------------------------------------------------------------------------- > >> + > >> +4.1 Note > >> + > >> +As ACPI 5.0 is still in heavily developing, if you are unable to find > >> out all the > >> +required information for probing a device in ACPI namespace, it is > >> possible > >> +that the ASL code is not well written. > >> +Please contact Zhang Rui <rui.zhang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org> with the acpidump output > >> of your > >> +platform attached if you suspect it's an BIOS problem. > >> + > >> +4.2 Some important ACPICA APIs for device driver implementation: > >> + > >> +-- acpi_status > >> + acpi_walk_namespace(acpi_object_type type, > >> + acpi_handle start_object, > >> + u32 max_depth, > >> + acpi_walk_callback pre_order_visit, > >> + acpi_walk_callback post_order_visit, > >> + void *context, void **return_value); > >> +Traverse ACPI namespace subtree rooted at start_object, go down > >> max_depth level > >> +at most. Call pre_order_visit when the proper node with type is found > >> the first > >> +time, call post_order_visit is the node is previously visited. Context > >> and > >> +return_value is passed down during the traverse. > >> + > >> +And the prototype of acpi_walk_callback: > >> +typedef > >> +acpi_status(*acpi_walk_callback) (acpi_handle object, > >> + u32 nesting_level, > >> + void *context, void **return_value); > >> + > >> +-- acpi_status > >> + acpi_get_handle(acpi_handle parent, > >> + acpi_string pathname, acpi_handle * ret_handle); > >> +Try to get handle with specified pathname under node parent. Usually > >> used to > >> +check whether a particular node is available or not. > >> + > >> +-- acpi_status > >> + acpi_get_object_info(acpi_handle object, > >> + struct acpi_device_info **return_buffer); > >> +Get acpi_device_info from object handle. Useful for retrieving ACPI > >> object > >> +name, type, and status etc. > >> + > >> +-- acpi_status > >> + acpi_walk_resources(acpi_handle device, > >> + char *name, > >> + acpi_walk_resource_callback user_function, void *context); > >> +Traverse resource node specified by name(e.g. METHOD_NAME__CRS) in ACPI > >> +namespace subtree rooted at device. Call user_function for each entry > >> in > >> +acpi_resource list. The list may containe acpi_resource entries with > >> various > >> +types. So it is important to handle the interested resource type > >> properly. > >> +The acpi_resource with ACPI_RESOURCE_TYPE_END_TAG indicates > >> end-of-list. > >> + > >> +And the prototype of acpi_walk_resource_callback: > >> +typedef > >> +acpi_status(*acpi_walk_resource_callback) (struct acpi_resource * > >> resource, > >> + void *context); > >> + > >> +More ACPICA external interfaces available in include/acpi/acpixf.h > > > > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Fwd: Hid over I2C and ACPI interaction [not found] ` <1341471717.1682.125.camel-fuY85erJQUO75v1z/vFq2g@public.gmane.org> 2012-07-05 7:20 ` Zhang Rui @ 2012-07-06 5:52 ` Mika Westerberg 2012-07-09 3:24 ` Lan Tianyu 1 sibling, 1 reply; 10+ messages in thread From: Mika Westerberg @ 2012-07-06 5:52 UTC (permalink / raw) To: Zhang Rui Cc: Lan Tianyu, khali-PUYAD+kWke1g9hUCZPvPmw, ben-linux-elnMNo+KYs3YtjvyW6yDsg, w.sang-bIcnvbaLZ9MEGnE8C9+IrQ, lenb-DgEjT+Ai2ygdnm+yROfE0A, linux-acpi-u79uwXL29TY76Z2rM5mHXA, linux-i2c-u79uwXL29TY76Z2rM5mHXA, linux-kernel-u79uwXL29TY76Z2rM5mHXA, jkosina-AlSwsSmVLrQ, chatty-rXV5z7KbLFk, jj_ding-9cfG7bMpBgR9nmWX13WWKA On Thu, Jul 05, 2012 at 03:01:57PM +0800, Zhang Rui wrote: > +Note that although these are ACPI devices, we prefer to use PnP drivers > for them, > +this is because: > +1. all the non-ACPI-predefined Devices are exported as PnP devices as > well > +2. PnP bus is a well designed bus. Probing via PnP layer saves a lot of > work > + for the device driver, e.g. getting & parsing ACPI resources. (Nice BKM, thanks for sharing) I have few questions about using PnP drivers instead of pure ACPI drivers. ACPI 5.0 defined some new resources, for example "Fixed DMA descriptor" that has information about the request line + channel for the device to use. Hovewer, PnP drivers pass resources as 'struct resource', which basically only has start and end - how do you represent all this new stuff using 'struct resource'? Or should we use acpi_walk_resources() where 'struct resource' is not suitable? ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Fwd: Hid over I2C and ACPI interaction 2012-07-06 5:52 ` Mika Westerberg @ 2012-07-09 3:24 ` Lan Tianyu [not found] ` <4FFA4EFD.6090708-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org> 2012-07-09 7:51 ` Mika Westerberg 0 siblings, 2 replies; 10+ messages in thread From: Lan Tianyu @ 2012-07-09 3:24 UTC (permalink / raw) To: Mika Westerberg Cc: Zhang Rui, khali, ben-linux, w.sang, lenb, linux-acpi, linux-i2c, linux-kernel, jkosina, chatty, jj_ding, bhelgaas, abelay On 2012年07月06日 13:52, Mika Westerberg wrote: > On Thu, Jul 05, 2012 at 03:01:57PM +0800, Zhang Rui wrote: >> +Note that although these are ACPI devices, we prefer to use PnP drivers >> for them, >> +this is because: >> +1. all the non-ACPI-predefined Devices are exported as PnP devices as >> well >> +2. PnP bus is a well designed bus. Probing via PnP layer saves a lot of >> work >> + for the device driver, e.g. getting& parsing ACPI resources. > > (Nice BKM, thanks for sharing) > > I have few questions about using PnP drivers instead of pure ACPI drivers. > > ACPI 5.0 defined some new resources, for example "Fixed DMA descriptor" > that has information about the request line + channel for the device to > use. Hovewer, PnP drivers pass resources as 'struct resource', which > basically only has start and end - how do you represent all this new stuff > using 'struct resource'? > I think we can add new interface to get acpi specific resources. e.g struct acpi_resource pnp_get_acpi_resource(...). When the pnp acpi devices were initialized, put those acpi specific resources into a new resource list pnpdev->acpi_resources. What pnp_get_acpi_resource does is to get specified type acpi resources and return. We also need to define some acpi resource types. ACPI_RESOURCE_DMA ACPI_RESOURCE_I2C_SERIALBUS ACPI_RESOURCE_SPI_SERIALBUS ACPI_RESOURCE_UART_SERIALBUS ACPI_RESOURCE_COMMON_SERIALBUS ... How about this? welcome to comments. > Or should we use acpi_walk_resources() where 'struct resource' is not > suitable? > -- Best Regards Tianyu Lan linux kernel enabling team -- 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 ^ permalink raw reply [flat|nested] 10+ messages in thread
[parent not found: <4FFA4EFD.6090708-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>]
* RE: Fwd: Hid over I2C and ACPI interaction [not found] ` <4FFA4EFD.6090708-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org> @ 2012-07-09 4:02 ` Moore, Robert 2012-07-09 7:28 ` Lan Tianyu 0 siblings, 1 reply; 10+ messages in thread From: Moore, Robert @ 2012-07-09 4:02 UTC (permalink / raw) To: Lan, Tianyu, Mika Westerberg Cc: Zhang, Rui, khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org, ben-linux-elnMNo+KYs3YtjvyW6yDsg@public.gmane.org, w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org, lenb-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org, linux-acpi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, jkosina-AlSwsSmVLrQ@public.gmane.org, chatty-rXV5z7KbLFk@public.gmane.org, jj_ding-9cfG7bMpBgR9nmWX13WWKA@public.gmane.org, bhelgaas-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org, abelay-3s7WtUTddSA@public.gmane.org, Lin, Ming M, Tang, Feng These are already defined in acpica - in the file acrestyp.h ACPI_RESOURCE_FIXED_DMA FixedDma; ACPI_RESOURCE_GPIO Gpio; ACPI_RESOURCE_I2C_SERIALBUS I2cSerialBus; ACPI_RESOURCE_SPI_SERIALBUS SpiSerialBus; ACPI_RESOURCE_UART_SERIALBUS UartSerialBus; ACPI_RESOURCE_COMMON_SERIALBUS CommonSerialBus; >-----Original Message----- >From: linux-acpi-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org [mailto:linux-acpi- >owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org] On Behalf Of Lan Tianyu >Sent: Sunday, July 08, 2012 8:25 PM >To: Mika Westerberg >Cc: Zhang, Rui; khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org; ben-linux-elnMNo+KYs3YtjvyW6yDsg@public.gmane.org; >w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org; lenb-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org; linux-acpi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; linux- >i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; jkosina-AlSwsSmVLrQ@public.gmane.org; >chatty-rXV5z7KbLFk@public.gmane.org; jj_ding-9cfG7bMpBgR9nmWX13WWKA@public.gmane.org; bhelgaas-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org; abelay-3s7WtUTddSA@public.gmane.org >Subject: Re: Fwd: Hid over I2C and ACPI interaction > >On 2012年07月06日 13:52, Mika Westerberg wrote: >> On Thu, Jul 05, 2012 at 03:01:57PM +0800, Zhang Rui wrote: >>> +Note that although these are ACPI devices, we prefer to use PnP drivers >>> for them, >>> +this is because: >>> +1. all the non-ACPI-predefined Devices are exported as PnP devices as >>> well >>> +2. PnP bus is a well designed bus. Probing via PnP layer saves a lot of >>> work >>> + for the device driver, e.g. getting& parsing ACPI resources. >> >> (Nice BKM, thanks for sharing) >> >> I have few questions about using PnP drivers instead of pure ACPI >drivers. >> >> ACPI 5.0 defined some new resources, for example "Fixed DMA descriptor" >> that has information about the request line + channel for the device to >> use. Hovewer, PnP drivers pass resources as 'struct resource', which >> basically only has start and end - how do you represent all this new >stuff >> using 'struct resource'? >> >I think we can add new interface to get acpi specific resources. e.g >struct acpi_resource pnp_get_acpi_resource(...). When the pnp acpi devices >were initialized, put those acpi specific resources into a new resource >list >pnpdev->acpi_resources. What pnp_get_acpi_resource does is to get specified >type acpi resources and return. We also need to define some acpi resource >types. > >ACPI_RESOURCE_DMA >ACPI_RESOURCE_I2C_SERIALBUS >ACPI_RESOURCE_SPI_SERIALBUS >ACPI_RESOURCE_UART_SERIALBUS >ACPI_RESOURCE_COMMON_SERIALBUS >... > >How about this? welcome to comments. > >> Or should we use acpi_walk_resources() where 'struct resource' is not >> suitable? >> > >-- >Best Regards >Tianyu Lan >linux kernel enabling team >-- >To unsubscribe from this list: send the line "unsubscribe linux-acpi" in >the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org >More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Fwd: Hid over I2C and ACPI interaction 2012-07-09 4:02 ` Moore, Robert @ 2012-07-09 7:28 ` Lan Tianyu 0 siblings, 0 replies; 10+ messages in thread From: Lan Tianyu @ 2012-07-09 7:28 UTC (permalink / raw) To: Moore, Robert Cc: Mika Westerberg, Zhang, Rui, khali@linux-fr.org, ben-linux@fluff.org, w.sang@pengutronix.de, lenb@kernel.org, linux-acpi@vger.kernel.org, linux-i2c@vger.kernel.org, linux-kernel@vger.kernel.org, jkosina@suse.cz, chatty@enac.fr, jj_ding@emc.com.tw, bhelgaas@google.com, abelay@mit.edu, Lin, Ming M, Tang, Feng On 2012年07月09日 12:02, Moore, Robert wrote: > These are already defined in acpica - in the file acrestyp.h > > ACPI_RESOURCE_FIXED_DMA FixedDma; > > ACPI_RESOURCE_GPIO Gpio; > ACPI_RESOURCE_I2C_SERIALBUS I2cSerialBus; > ACPI_RESOURCE_SPI_SERIALBUS SpiSerialBus; > ACPI_RESOURCE_UART_SERIALBUS UartSerialBus; > ACPI_RESOURCE_COMMON_SERIALBUS CommonSerialBus; > Yeah. Thanks for Bob's reminder. We can reuse these macros. > > >> -----Original Message----- >> From: linux-acpi-owner@vger.kernel.org [mailto:linux-acpi- >> owner@vger.kernel.org] On Behalf Of Lan Tianyu >> Sent: Sunday, July 08, 2012 8:25 PM >> To: Mika Westerberg >> Cc: Zhang, Rui; khali@linux-fr.org; ben-linux@fluff.org; >> w.sang@pengutronix.de; lenb@kernel.org; linux-acpi@vger.kernel.org; linux- >> i2c@vger.kernel.org; linux-kernel@vger.kernel.org; jkosina@suse.cz; >> chatty@enac.fr; jj_ding@emc.com.tw; bhelgaas@google.com; abelay@mit.edu >> Subject: Re: Fwd: Hid over I2C and ACPI interaction >> >> On 2012年07月06日 13:52, Mika Westerberg wrote: >>> On Thu, Jul 05, 2012 at 03:01:57PM +0800, Zhang Rui wrote: >>>> +Note that although these are ACPI devices, we prefer to use PnP drivers >>>> for them, >>>> +this is because: >>>> +1. all the non-ACPI-predefined Devices are exported as PnP devices as >>>> well >>>> +2. PnP bus is a well designed bus. Probing via PnP layer saves a lot of >>>> work >>>> + for the device driver, e.g. getting& parsing ACPI resources. >>> >>> (Nice BKM, thanks for sharing) >>> >>> I have few questions about using PnP drivers instead of pure ACPI >> drivers. >>> >>> ACPI 5.0 defined some new resources, for example "Fixed DMA descriptor" >>> that has information about the request line + channel for the device to >>> use. Hovewer, PnP drivers pass resources as 'struct resource', which >>> basically only has start and end - how do you represent all this new >> stuff >>> using 'struct resource'? >>> >> I think we can add new interface to get acpi specific resources. e.g >> struct acpi_resource pnp_get_acpi_resource(...). When the pnp acpi devices >> were initialized, put those acpi specific resources into a new resource >> list >> pnpdev->acpi_resources. What pnp_get_acpi_resource does is to get specified >> type acpi resources and return. We also need to define some acpi resource >> types. >> >> ACPI_RESOURCE_DMA >> ACPI_RESOURCE_I2C_SERIALBUS >> ACPI_RESOURCE_SPI_SERIALBUS >> ACPI_RESOURCE_UART_SERIALBUS >> ACPI_RESOURCE_COMMON_SERIALBUS >> ... >> >> How about this? welcome to comments. >> >>> Or should we use acpi_walk_resources() where 'struct resource' is not >>> suitable? >>> >> >> -- >> Best Regards >> Tianyu Lan >> linux kernel enabling team >> -- >> 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 -- Best Regards Tianyu Lan linux kernel enabling team ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Fwd: Hid over I2C and ACPI interaction 2012-07-09 3:24 ` Lan Tianyu [not found] ` <4FFA4EFD.6090708-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org> @ 2012-07-09 7:51 ` Mika Westerberg 1 sibling, 0 replies; 10+ messages in thread From: Mika Westerberg @ 2012-07-09 7:51 UTC (permalink / raw) To: Lan Tianyu Cc: Zhang Rui, khali, ben-linux, w.sang, lenb, linux-acpi, linux-i2c, linux-kernel, jkosina, chatty, jj_ding, bhelgaas, abelay On Mon, Jul 09, 2012 at 11:24:45AM +0800, Lan Tianyu wrote: > I think we can add new interface to get acpi specific resources. e.g > struct acpi_resource pnp_get_acpi_resource(...). When the pnp acpi devices > were initialized, put those acpi specific resources into a new resource list > pnpdev->acpi_resources. What pnp_get_acpi_resource does is to get specified > type acpi resources and return. We also need to define some acpi resource types. Yeah, that sounds good to me. ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2012-07-09 7:49 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2012-07-04 13:46 Hid over I2C and ACPI interaction Benjamin Tissoires [not found] ` <4FF52C70.9010601@intel.com> [not found] ` <4FF52C70.9010601-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org> 2012-07-05 7:01 ` Fwd: " Zhang Rui [not found] ` <1341471717.1682.125.camel-fuY85erJQUO75v1z/vFq2g@public.gmane.org> 2012-07-05 7:20 ` Zhang Rui 2012-07-05 8:44 ` Benjamin Tissoires 2012-07-09 0:41 ` Zhang Rui 2012-07-06 5:52 ` Mika Westerberg 2012-07-09 3:24 ` Lan Tianyu [not found] ` <4FFA4EFD.6090708-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org> 2012-07-09 4:02 ` Moore, Robert 2012-07-09 7:28 ` Lan Tianyu 2012-07-09 7:51 ` Mika Westerberg
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).