diff mbox

ACPI / scan: force creation of platform device for the Surface tablets

Message ID 1463061992-11443-1-git-send-email-benjamin.tissoires@redhat.com (mailing list archive)
State Not Applicable, archived
Headers show

Commit Message

Benjamin Tissoires May 12, 2016, 2:06 p.m. UTC
As mentioned in drivers/platform/x86/surfacepro3_button.c, the various
Microsoft Surface tablets do not follow the ACPI SOC buttons specification.
They present an I2C device like this:

  Device (WBUT)
  {
      Method (_HID, 0, NotSerialized)  // _HID: Hardware ID
      {
          Return ("PNP0C40")
      }
 
      Name (_CID, "PNP0C40" /* Standard Button Controller */)  // _CID: Compatible ID
      Method (_STA, 0, NotSerialized)  // _STA: Status
      {
          Return (0x0F)
      }
 
      Method (_DSM, 4, Serialized)  // _DSM: Device-Specific Method
      {
          [stripped]
      }
  }
 
  Device (TEV2)
  {
      Name (_HID, "MSHW0028")  // _HID: Hardware ID
      Name (_DEP, Package (0x06)  // _DEP: Dependencies
      {
          GPO0,
          GPO2,
          GPO1,
          ^PCI0.I2C2,
          ^PCI0.I2C7,
          ^PCI0.I2C7.PMIC
      })
      Method (_CRS, 0, NotSerialized)  // _CRS: Current Resource Settings
      {
          Name (RBUF, ResourceTemplate ()
          {
              GpioInt (Edge, ActiveBoth, SharedAndWake, PullDefault, 0x09C4,
                  "\\_SB.GPO2", 0x00, ResourceConsumer, ,
                  )
                  {   // Pin list
                      0x0008
                  }
              GpioInt (Edge, ActiveBoth, SharedAndWake, PullDefault, 0x09C4,
                  "\\_SB.GPO2", 0x00, ResourceConsumer, ,
                  )
                  {   // Pin list
                      0x000A
                  }
              GpioInt (Edge, ActiveBoth, Shared, PullDefault, 0x09C4,
                  "\\_SB.GPO0", 0x00, ResourceConsumer, ,
                  )
                  {   // Pin list
                      0x005D
                  }
              GpioInt (Edge, ActiveBoth, Shared, PullDefault, 0x09C4,
                  "\\_SB.GPO1", 0x00, ResourceConsumer, ,
                  )
                  {   // Pin list
                      0x0008
                  }
              I2cSerialBus (0x002D, ControllerInitiated, 0x00061A80,
                  AddressingMode7Bit, "\\_SB.PCI0.I2C2",
                  0x00, ResourceConsumer, ,
                  )
              [stripped]
          })
          [stripped]
          If ((OBID <= 0x0C))
          {
              Return (RBUF) /* \_SB_.TEV2._CRS.RBUF */
          }
 
          Return (PBUF) /* \_SB_.TEV2._CRS.PBUF */
      }
 
      Method (_STA, 0, NotSerialized)  // _STA: Status
      {
          Return (0x0F)
      }
 
      Method (_DSM, 4, Serialized)  // _DSM: Device-Specific Method
      {
          [stripped]
      }
  }

The actual HW button is named MSHW0028 on the MS Surface (Pro) 3 and
is meant to be bound on the I2C bus 7. The problem is that the bus
doesn't see any device on the address 0x002D.

The Surface Pro devices have working ACPI events and thus we can use
surfacepro3_button which is a pure acpi driver. The Surface 3 however
does not generate any ACPI events and the buttons are not working
through surfacepro3_button (even when we add the name TEV2 in this module).

The solution consists in forcing the creation of an platform device
which we can handle in soc_button_array as any proper SOC GPIO buttons
should be.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---

Hi,

this is IMO the best way to handle this situation (besides fixing the DSDT
itself). The other solutions I thought were:
- add a specific acpi driver that will unbind the current I2C acpi handle
  and will create the platform_driver
- add a specific acpi driver that merges surfacepro3_button and soc_button_array
  but has a lot of code duplication

I am open to any other solution if we could have this list of ids in a different
place but I could not see any other.

Cheers,
Benjamin

 drivers/acpi/scan.c | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

Comments

Benjamin Tissoires May 12, 2016, 4:06 p.m. UTC | #1
On Thu, May 12, 2016 at 4:06 PM, Benjamin Tissoires
<benjamin.tissoires@redhat.com> wrote:
> As mentioned in drivers/platform/x86/surfacepro3_button.c, the various
> Microsoft Surface tablets do not follow the ACPI SOC buttons specification.
> They present an I2C device like this:
>
>   Device (WBUT)
>   {
>       Method (_HID, 0, NotSerialized)  // _HID: Hardware ID
>       {
>           Return ("PNP0C40")
>       }
>
>       Name (_CID, "PNP0C40" /* Standard Button Controller */)  // _CID: Compatible ID
>       Method (_STA, 0, NotSerialized)  // _STA: Status
>       {
>           Return (0x0F)
>       }
>
>       Method (_DSM, 4, Serialized)  // _DSM: Device-Specific Method
>       {
>           [stripped]
>       }
>   }
>
>   Device (TEV2)
>   {
>       Name (_HID, "MSHW0028")  // _HID: Hardware ID
>       Name (_DEP, Package (0x06)  // _DEP: Dependencies
>       {
>           GPO0,
>           GPO2,
>           GPO1,
>           ^PCI0.I2C2,
>           ^PCI0.I2C7,
>           ^PCI0.I2C7.PMIC
>       })
>       Method (_CRS, 0, NotSerialized)  // _CRS: Current Resource Settings
>       {
>           Name (RBUF, ResourceTemplate ()
>           {
>               GpioInt (Edge, ActiveBoth, SharedAndWake, PullDefault, 0x09C4,
>                   "\\_SB.GPO2", 0x00, ResourceConsumer, ,
>                   )
>                   {   // Pin list
>                       0x0008
>                   }
>               GpioInt (Edge, ActiveBoth, SharedAndWake, PullDefault, 0x09C4,
>                   "\\_SB.GPO2", 0x00, ResourceConsumer, ,
>                   )
>                   {   // Pin list
>                       0x000A
>                   }
>               GpioInt (Edge, ActiveBoth, Shared, PullDefault, 0x09C4,
>                   "\\_SB.GPO0", 0x00, ResourceConsumer, ,
>                   )
>                   {   // Pin list
>                       0x005D
>                   }
>               GpioInt (Edge, ActiveBoth, Shared, PullDefault, 0x09C4,
>                   "\\_SB.GPO1", 0x00, ResourceConsumer, ,
>                   )
>                   {   // Pin list
>                       0x0008
>                   }
>               I2cSerialBus (0x002D, ControllerInitiated, 0x00061A80,
>                   AddressingMode7Bit, "\\_SB.PCI0.I2C2",
>                   0x00, ResourceConsumer, ,
>                   )
>               [stripped]
>           })
>           [stripped]
>           If ((OBID <= 0x0C))
>           {
>               Return (RBUF) /* \_SB_.TEV2._CRS.RBUF */
>           }
>
>           Return (PBUF) /* \_SB_.TEV2._CRS.PBUF */
>       }
>
>       Method (_STA, 0, NotSerialized)  // _STA: Status
>       {
>           Return (0x0F)
>       }
>
>       Method (_DSM, 4, Serialized)  // _DSM: Device-Specific Method
>       {
>           [stripped]
>       }
>   }
>
> The actual HW button is named MSHW0028 on the MS Surface (Pro) 3 and
> is meant to be bound on the I2C bus 7. The problem is that the bus
> doesn't see any device on the address 0x002D.
>
> The Surface Pro devices have working ACPI events and thus we can use
> surfacepro3_button which is a pure acpi driver. The Surface 3 however
> does not generate any ACPI events and the buttons are not working
> through surfacepro3_button (even when we add the name TEV2 in this module).
>
> The solution consists in forcing the creation of an platform device
> which we can handle in soc_button_array as any proper SOC GPIO buttons
> should be.
>
> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
> ---
>
> Hi,
>
> this is IMO the best way to handle this situation (besides fixing the DSDT
> itself). The other solutions I thought were:
> - add a specific acpi driver that will unbind the current I2C acpi handle
>   and will create the platform_driver
> - add a specific acpi driver that merges surfacepro3_button and soc_button_array
>   but has a lot of code duplication
>
> I am open to any other solution if we could have this list of ids in a different
> place but I could not see any other.
>

My bad. A further check showed that the device is actually bound to a
I2C bus, and so an I2C driver can be enumerated. Now I need to have a
common code base with soc_button_array without duplicating everything.

Please disregard this patch (for now :-P ).

Cheers,
Benjamin
--
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
diff mbox

Patch

diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 5f28cf7..6fe9296 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -46,6 +46,12 @@  DEFINE_MUTEX(acpi_device_lock);
 LIST_HEAD(acpi_wakeup_device_list);
 static DEFINE_MUTEX(acpi_hp_context_lock);
 
+static const struct acpi_device_id i2c_whitelisted_id_list[] = {
+	{"MSHW0028", 0},	/* Surface (Pro) 3 buttons */
+	{"MSHW0040", 0},	/* Surface Pro 4 buttons */
+	{"", 0},
+};
+
 struct acpi_dep_data {
 	struct list_head node;
 	acpi_handle master;
@@ -1676,13 +1682,21 @@  static void acpi_default_enumeration(struct acpi_device *device)
 	bool is_spi_i2c_slave = false;
 
 	/*
-	 * Do not enemerate SPI/I2C slaves as they will be enuerated by their
+	 * Do not enemerate SPI/I2C slaves as they will be enumerated by their
 	 * respective parents.
 	 */
 	INIT_LIST_HEAD(&resource_list);
 	acpi_dev_get_resources(device, &resource_list, acpi_check_spi_i2c_slave,
 			       &is_spi_i2c_slave);
 	acpi_dev_free_resource_list(&resource_list);
+
+	/*
+	 * these devices are declared as I2C but should actually be
+	 * enumerated as platform devices.
+	 */
+	if (!acpi_match_device_ids(device, i2c_whitelisted_id_list))
+		is_spi_i2c_slave = false;
+
 	if (!is_spi_i2c_slave)
 		acpi_create_platform_device(device);
 }