1. 09 11月, 2016 1 次提交
    • A
      ACPI / gpio: avoid warning for gpio hogging code · c82064f2
      Arnd Bergmann 提交于
      The newly added acpi_gpiochip_scan_gpios function produces a few harmless
      warnings:
      
      drivers/gpio/gpiolib-acpi.c: In function ‘acpi_gpiochip_add’:
      drivers/gpio/gpiolib-acpi.c:925:7: error: ‘dflags’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
      drivers/gpio/gpiolib-acpi.c:925:9: error: ‘lflags’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
      
      The problem is that he compiler cannot know that a negative return value
      from fwnode_property_read_u32_array() or acpi_gpiochip_pin_to_gpio_offset()
      implies that the IS_ERR(gpio_desc) is true, as the value could in theory
      be below -MAX_ERRNO.
      
      The function already initializes its output values to zero, and moving
      that intialization a little higher up ensures that we can never have
      uninitialized data in the caller.
      
      Fixes: c80f1ba7 ("ACPI / gpio: Add hogging support")
      Signed-off-by: NArnd Bergmann <arnd@arndb.de>
      Acked-by: NMika Westerberg <mika.westerberg@linux.intel.com>
      Signed-off-by: NLinus Walleij <linus.walleij@linaro.org>
      c82064f2
  2. 31 10月, 2016 2 次提交
  3. 24 10月, 2016 3 次提交
  4. 04 10月, 2016 1 次提交
    • L
      gpio: acpi: separation of concerns · 031ba28a
      Linus Walleij 提交于
      The generic GPIO library directly implement code for acpi_find_gpio()
      which is only used with CONFIG_ACPI. This was probably done because
      OF did the same thing, but I removed that so remove this too.
      
      Rename the internal acpi_find_gpio() in gpiolib-acpi.c to
      acpi_populate_gpio_lookup() which seems to be more appropriate anyway
      so as to avoid a namespace clash with the same function.
      
      Make the stub return -ENOENT rather than -ENOSYS (as that is for
      syscalls!).
      
      For some reason the sunxi pin control driver was including the private
      gpiolib header, it works just fine without it so remove that oneliner.
      
      Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
      Acked-by: NMika Westerberg <mika.westerberg@linux.intel.com>
      Signed-off-by: NLinus Walleij <linus.walleij@linaro.org>
      031ba28a
  5. 15 6月, 2016 1 次提交
  6. 30 4月, 2016 1 次提交
    • V
      gpiolib-acpi: Duplicate con_id string when adding it to the crs lookup list · 7df89e92
      Ville Syrjälä 提交于
      Calling gpiod_get() from a module and then unloading the module leads to an
      oops due to acpi_can_fallback_to_crs() storing the pointer to the passed
      'con_id' string onto acpi_crs_lookup_list. The next guy to come along will then
      try to access the string but the memory may now be gone with the module.
      Make a copy of the passed string instead, and store the copy on the list.
      
      BUG: unable to handle kernel paging request at ffffffffa03e7855
      IP: [<ffffffff81338322>] strcmp+0x12/0x30
      PGD 2a07067 PUD 2a08063 PMD 74720067 PTE 0
      Oops: 0000 [#1] PREEMPT SMP
      Modules linked in: i915(+) drm_kms_helper drm intel_gtt snd_hda_codec snd_hda_core i2c_algo_bit syscopya
      rea sysfillrect sysimgblt fb_sys_fops agpgart snd_soc_sst_bytcr_rt5640 coretemp hwmon intel_rapl intel_soc_dts_thermal
      punit_atom_debug snd_soc_rt5640 snd_soc_rl6231 serio snd_intel_sst_acpi snd_intel_sst_core video snd_soc_sst_mfld_platf
      orm snd_soc_sst_match backlight int3402_thermal processor_thermal_device int3403_thermal int3400_thermal acpi_thermal_r
      el snd_soc_core intel_soc_dts_iosf int340x_thermal_zone snd_compress i2c_hid hid snd_pcm snd_timer snd soundcore evdev
      sch_fq_codel efivarfs ipv6 autofs4 [last unloaded: drm]
      CPU: 2 PID: 3064 Comm: modprobe Tainted: G     U  W       4.6.0-rc3-ffrd-ipvr+ #302
      Hardware name: Intel Corp. VALLEYVIEW C0 PLATFORM/BYT-T FFD8, BIOS BLAKFF81.X64.0088.R10.1403240443 FFD8
      _X64_R_2014_13_1_00 03/24/2014
      task: ffff8800701cd200 ti: ffff880070034000 task.ti: ffff880070034000
      RIP: 0010:[<ffffffff81338322>]  [<ffffffff81338322>] strcmp+0x12/0x30
      RSP: 0000:ffff880070037748  EFLAGS: 00010286
      RAX: 0000000080000000 RBX: ffff88007a342800 RCX: 0000000000000006
      RDX: 0000000000000006 RSI: ffffffffa054f856 RDI: ffffffffa03e7856
      RBP: ffff880070037748 R08: 0000000000000000 R09: 0000000000000001
      R10: 0000000000000000 R11: 0000000000000000 R12: ffffffffa054f855
      R13: ffff88007281cae0 R14: 0000000000000010 R15: ffffffffffffffea
      FS:  00007faa51447700(0000) GS:ffff880079300000(0000) knlGS:0000000000000000
      CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
      CR2: ffffffffa03e7855 CR3: 0000000041eba000 CR4: 00000000001006e0
      Stack:
       ffff880070037770 ffffffff8136ad28 ffffffffa054f855 0000000000000000
       ffff88007a0a2098 ffff8800700377e8 ffffffff8136852e ffff88007a342800
       00000007700377a0 ffff8800700377a0 ffffffff81412442 70672d6c656e6170
      Call Trace:
       [<ffffffff8136ad28>] acpi_can_fallback_to_crs+0x88/0x100
       [<ffffffff8136852e>] gpiod_get_index+0x25e/0x310
       [<ffffffff81412442>] ? mipi_dsi_attach+0x22/0x30
       [<ffffffff813685f2>] gpiod_get+0x12/0x20
       [<ffffffffa04fcf41>] intel_dsi_init+0x421/0x480 [i915]
       [<ffffffffa04d3783>] intel_modeset_init+0x853/0x16b0 [i915]
       [<ffffffffa0504864>] ? intel_setup_gmbus+0x214/0x260 [i915]
       [<ffffffffa0510158>] i915_driver_load+0xdc8/0x19b0 [i915]
       [<ffffffff8160fb53>] ? _raw_spin_unlock_irqrestore+0x43/0x70
       [<ffffffffa026b13b>] drm_dev_register+0xab/0xc0 [drm]
       [<ffffffffa026d7b3>] drm_get_pci_dev+0x93/0x1f0 [drm]
       [<ffffffff8160fb53>] ? _raw_spin_unlock_irqrestore+0x43/0x70
       [<ffffffffa043f1f4>] i915_pci_probe+0x34/0x50 [i915]
       [<ffffffff81379751>] pci_device_probe+0x91/0x100
       [<ffffffff8141a75a>] driver_probe_device+0x20a/0x2d0
       [<ffffffff8141a8be>] __driver_attach+0x9e/0xb0
       [<ffffffff8141a820>] ? driver_probe_device+0x2d0/0x2d0
       [<ffffffff81418439>] bus_for_each_dev+0x69/0xa0
       [<ffffffff8141a04e>] driver_attach+0x1e/0x20
       [<ffffffff81419c20>] bus_add_driver+0x1c0/0x240
       [<ffffffff8141b6d0>] driver_register+0x60/0xe0
       [<ffffffff81377d20>] __pci_register_driver+0x60/0x70
       [<ffffffffa026d9f4>] drm_pci_init+0xe4/0x110 [drm]
       [<ffffffff810ce04e>] ? trace_hardirqs_on+0xe/0x10
       [<ffffffffa02f1000>] ? 0xffffffffa02f1000
       [<ffffffffa02f1094>] i915_init+0x94/0x9b [i915]
       [<ffffffff810003bb>] do_one_initcall+0x8b/0x1c0
       [<ffffffff810eb616>] ? rcu_read_lock_sched_held+0x86/0x90
       [<ffffffff811de6d6>] ? kmem_cache_alloc_trace+0x1f6/0x270
       [<ffffffff81183826>] do_init_module+0x60/0x1dc
       [<ffffffff81115a8d>] load_module+0x1d0d/0x2390
       [<ffffffff811120b0>] ? __symbol_put+0x70/0x70
       [<ffffffff811f41b2>] ? kernel_read_file+0x92/0x120
       [<ffffffff811162f4>] SYSC_finit_module+0xa4/0xb0
       [<ffffffff8111631e>] SyS_finit_module+0xe/0x10
       [<ffffffff81001ff3>] do_syscall_64+0x63/0x350
       [<ffffffff816103da>] entry_SYSCALL64_slow_path+0x25/0x25
      Code: f7 48 8d 76 01 48 8d 52 01 0f b6 4e ff 84 c9 88 4a ff 75 ed 5d c3 0f 1f 00 55 48 89 e5 eb 04 84 c0
       74 18 48 8d 7f 01 48 8d 76 01 <0f> b6 47 ff 3a 46 ff 74 eb 19 c0 83 c8 01 5d c3 31 c0 5d c3 66
      RIP  [<ffffffff81338322>] strcmp+0x12/0x30
       RSP <ffff880070037748>
      CR2: ffffffffa03e7855
      
      v2: Make the copied con_id const
      
      Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
      Cc: Mika Westerberg <mika.westerberg@linux.intel.com>
      Cc: Alexandre Courbot <gnurou@gmail.com>
      Cc: stable@vger.kernel.org
      Fixes: 10cf4899 ("gpiolib: tighten up ACPI legacy gpio lookups")
      Signed-off-by: NVille Syrjälä <ville.syrjala@linux.intel.com>
      Acked-by: NMika Westerberg <mika.westerberg@linux.intel.com>
      Reviewed-by: NDmitry Torokhov <dmitry.torokhov@gmail.com>
      Signed-off-by: NLinus Walleij <linus.walleij@linaro.org>
      7df89e92
  7. 16 2月, 2016 1 次提交
  8. 01 1月, 2016 1 次提交
  9. 14 12月, 2015 1 次提交
  10. 19 11月, 2015 2 次提交
  11. 01 11月, 2015 1 次提交
    • M
      gpio / ACPI: Allow shared GPIO event to be read via operation region · c103a10f
      Mika Westerberg 提交于
      In Microsoft Surface3 the GPIO detecting lid state is shared between GPIO
      event and operation region. Below is simplied version of the DSDT from
      Surface3 including relevant parts:
      
          Scope (GPO0)
          {
              Name (_AEI, ResourceTemplate ()
              {
                  GpioInt (Edge, ActiveBoth, Shared, PullNone, 0x0000,
                      "\\_SB.GPO0", 0x00, ResourceConsumer, ,
                      )
                      {   // Pin list
                          0x004C
                      }
              })
      
              OperationRegion (GPOR, GeneralPurposeIo, Zero, One)
              Field (GPOR, ByteAcc, NoLock, Preserve)
              {
                  Connection (
                      GpioIo (Shared, PullNone, 0x0000, 0x0000,
                          IoRestrictionNone, "\\_SB.GPO0", 0x00,
                          ResourceConsumer,,)
                          {   // Pin list
                              0x004C
                          }
                  ),
                  HELD,   1
              }
      
              Method (_E4C, 0, Serialized)  // _Exx: Edge-Triggered GPE
              {
                  If ((HELD == One))
                  {
                      ^^LID.LIDB = One
                  }
                  Else
                  {
                      ^^LID.LIDB = Zero
                      Notify (LID, 0x80) // Status Change
                  }
      
                  Notify (^^PCI0.SPI1.NTRG, One) // Device Check
              }
          }
      
      When GPIO 0x4c changes we call ASL method _E4C which tries to read HELD
      field (the same GPIO). This triggers following error on the console:
      
          ACPI Error: Method parse/execution failed [\_SB.GPO0._E4C]
              (Node ffff88013f4b4438), AE_ERROR (20150930/psparse-542)
      
      The error happens because ACPI GPIO operation region handler
      (acpi_gpio_adr_space_handler()) tries to acquire the very same GPIO which
      returns an error (-EBUSY) because the GPIO is already reserved for the GPIO
      event.
      
      Fix this so that we "borrow" the event GPIO if we find the GPIO belongs to
      an event. Allow this only for GPIOs that are read.
      
      To be able to go through acpi_gpio->events list for operation region access
      we need to make sure the list is properly initialized whenever GPIO chip is
      registered.
      
      Link: https://bugzilla.kernel.org/show_bug.cgi?id=106571Signed-off-by: NMika Westerberg <mika.westerberg@linux.intel.com>
      Signed-off-by: NLinus Walleij <linus.walleij@linaro.org>
      c103a10f
  12. 15 9月, 2015 2 次提交
  13. 07 8月, 2015 1 次提交
  14. 11 6月, 2015 1 次提交
  15. 10 6月, 2015 1 次提交
  16. 11 5月, 2015 1 次提交
    • M
      gpio / ACPI: Add support for retrieving GpioInt resources from a device · c884fbd4
      Mika Westerberg 提交于
      ACPI specification knows two types of GPIOs: GpioIo and GpioInt. The latter
      is used to describe that a given device interrupt line is connected to a
      specific GPIO pin. Typical ACPI _CRS entry for such device looks like
      below:
      
          Name (_CRS, ResourceTemplate ()
          {
              I2cSerialBus (0x004A, ControllerInitiated, 0x00061A80,
                            AddressingMode7Bit, "\\_SB.PCI0.I2C6",
                            0x00, ResourceConsumer)
              GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
                      IoRestrictionOutputOnly, "\\_SB.GPO0",
                      0x00, ResourceConsumer)
              {
                  0x004B
              }
              GpioInt (Level, ActiveLow, Shared, PullDefault, 0x0000,
                       "\\_SB.GPO0", 0x00, ResourceConsumer)
              {
                  0x004C
              }
          })
      
      Currently drivers need to request a GPIO corresponding to the right GpioInt
      and then translate that to Linux IRQ number. This adds unnecessary lines of
      boiler-plate code.
      
      We can ease this a bit by introducing acpi_dev_gpio_irq_get() analogous to
      of_irq_get(). This function translates given GpioInt resource under the
      device in question to the suitable Linux IRQ number.
      Signed-off-by: NMika Westerberg <mika.westerberg@linux.intel.com>
      Acked-by: NRafael J. Wysocki <rafael.j.wysocki@intel.com>
      Signed-off-by: NLinus Walleij <linus.walleij@linaro.org>
      c884fbd4
  17. 27 4月, 2015 1 次提交
  18. 19 3月, 2015 2 次提交
  19. 05 3月, 2015 1 次提交
  20. 06 11月, 2014 1 次提交
  21. 05 11月, 2014 2 次提交
    • R
      ACPI / GPIO: Driver GPIO mappings for ACPI GPIOs · f028d524
      Rafael J. Wysocki 提交于
      Provide a way for device drivers using GPIOs described by ACPI
      GpioIo resources in _CRS to tell the GPIO subsystem what names
      (connection IDs) to associate with specific GPIO pins defined
      in there.
      
      To do that, a driver needs to define a mapping table as a
      NULL-terminated array of struct acpi_gpio_mapping objects
      that each contain a name, a pointer to an array of line data
      (struct acpi_gpio_params) objects and the size of that array.
      
      Each struct acpi_gpio_params object consists of three fields,
      crs_entry_index, line_index, active_low, representing the index of
      the target GpioIo()/GpioInt() resource in _CRS starting from zero,
      the index of the target line in that resource starting from zero,
      and the active-low flag for that line, respectively.
      
      Next, the mapping table needs to be passed as the second
      argument to acpi_dev_add_driver_gpios() that will register it with
      the ACPI device object pointed to by its first argument.  That
      should be done in the driver's .probe() routine.
      
      On removal, the driver should unregister its GPIO mapping table
      by calling acpi_dev_remove_driver_gpios() on the ACPI device
      object where that table was previously registered.
      
      Included are fixes from Mika Westerberg.
      Acked-by: NAlexandre Courbot <acourbot@nvidia.com>
      Reviewed-by: NLinus Walleij <linus.walleij@linaro.org>
      Signed-off-by: NRafael J. Wysocki <rafael.j.wysocki@intel.com>
      f028d524
    • M
      gpio / ACPI: Add support for _DSD device properties · 0d9a693c
      Mika Westerberg 提交于
      With release of ACPI 5.1 and _DSD method we can finally name GPIOs (and
      other things as well) returned by _CRS. Previously we were only able to
      use integer index to find the corresponding GPIO, which is pretty error
      prone if the order changes.
      
      With _DSD we can now query GPIOs using name instead of an integer index,
      like the below example shows:
      
        // Bluetooth device with reset and shutdown GPIOs
        Device (BTH)
        {
            Name (_HID, ...)
      
            Name (_CRS, ResourceTemplate ()
            {
                GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
                        "\\_SB.GPO0", 0, ResourceConsumer) {15}
                GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
                        "\\_SB.GPO0", 0, ResourceConsumer) {27, 31}
            })
      
            Name (_DSD, Package ()
            {
                ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
                Package ()
      	  {
                    Package () {"reset-gpio", Package() {^BTH, 1, 1, 0 }},
                    Package () {"shutdown-gpio", Package() {^BTH, 0, 0, 0 }},
                }
            })
        }
      
      The format of the supported GPIO property is:
      
        Package () { "name", Package () { ref, index, pin, active_low }}
      
        ref - The device that has _CRS containing GpioIo()/GpioInt() resources,
              typically this is the device itself (BTH in our case).
        index - Index of the GpioIo()/GpioInt() resource in _CRS starting from zero.
        pin - Pin in the GpioIo()/GpioInt() resource. Typically this is zero.
        active_low - If 1 the GPIO is marked as active_low.
      
      Since ACPI GpioIo() resource does not have field saying whether it is
      active low or high, the "active_low" argument can be used here. Setting
      it to 1 marks the GPIO as active low.
      
      In our Bluetooth example the "reset-gpio" refers to the second GpioIo()
      resource, second pin in that resource with the GPIO number of 31.
      
      This patch implements necessary support to gpiolib for extracting GPIOs
      using _DSD device properties.
      Signed-off-by: NMika Westerberg <mika.westerberg@linux.intel.com>
      Acked-by: NLinus Walleij <linus.walleij@linaro.org>
      Acked-by: NGrant Likely <grant.likely@linaro.org>
      Signed-off-by: NRafael J. Wysocki <rafael.j.wysocki@intel.com>
      0d9a693c
  22. 04 11月, 2014 1 次提交
  23. 29 10月, 2014 1 次提交
  24. 25 9月, 2014 1 次提交
  25. 29 8月, 2014 2 次提交
  26. 28 7月, 2014 1 次提交
  27. 23 7月, 2014 1 次提交
  28. 23 5月, 2014 1 次提交
  29. 14 4月, 2014 2 次提交
    • M
      gpio / ACPI: Prevent potential wrap of GPIO value on OpRegion read · b5539fa2
      Mika Westerberg 提交于
      Dan Carpenter's static code checker reports:
      
       The patch 473ed7be: "gpio / ACPI: Add support for ACPI GPIO
       operation regions" from Mar 14, 2014, leads to the following static
       checker warning:
      
        drivers/gpio/gpiolib-acpi.c:454 acpi_gpio_adr_space_handler()
        warn: should 'gpiod_get_raw_value(desc) << i' be a 64 bit type?
      
      This is due the fact that *value is of type u64 and gpiod_get_raw_value()
      returns int. Since i can be larger than 31, it is possible that the value
      returned gets wrapped.
      
      Fix this by casting the return of gpiod_get_raw_value() to u64 first before
      shift.
      Reported-by: NDan Carpenter <dan.carpenter@oracle.com>
      Signed-off-by: NMika Westerberg <mika.westerberg@linux.intel.com>
      Signed-off-by: NLinus Walleij <linus.walleij@linaro.org>
      b5539fa2
    • M
      gpio / ACPI: Don't crash on NULL chip->dev · e9595f84
      Mika Westerberg 提交于
      Commit aa92b6f6 (gpio / ACPI: Allocate ACPI specific data directly in
      acpi_gpiochip_add()) moved ACPI handle checking to acpi_gpiochip_add() but
      forgot to check whether chip->dev is NULL before dereferencing it.
      
      Since chip->dev pointer is optional we can end up with crash like following:
      
       BUG: unable to handle kernel NULL pointer dereference at 00000138
       IP: [<c126c2b3>] acpi_gpiochip_add+0x13/0x190
       *pde = 00000000
       Oops: 0000 [#1] PREEMPT SMP
       Modules linked in: ssb(+) ...
       CPU: 0 PID: 512 Comm: modprobe Tainted: G        W     3.14.0-rc7-next-20140324-t1 #24
       Hardware name: Dell Inc. Latitude D830                   /0UY141, BIOS A02 06/07/2007
       task: f5799900 ti: f543e000 task.ti: f543e000
       EIP: 0060:[<c126c2b3>] EFLAGS: 00010282 CPU: 0
       EIP is at acpi_gpiochip_add+0x13/0x190
       EAX: 00000000 EBX: f57824c4 ECX: 00000000 EDX: 00000000
       ESI: f57824c4 EDI: 00000010 EBP: f543fc54 ESP: f543fc40
        DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068
       CR0: 8005003b CR2: 00000138 CR3: 355f8000 CR4: 000007d0
       Stack:
        f543fc5c fd1f7790 f57824c4 000000be 00000010 f543fc84 c1269f4e f543fc74
        fd1f78bd 00008002 f57822b0 f5782090 fd1f8400 00000286 fd1f9994 00000000
        f5782000 f543fc8c fd1f7e39 f543fcc8 fd1f0bd8 000000c0 00000000 00000000
       Call Trace:
        [<fd1f7790>] ? ssb_pcie_mdio_write+0xa0/0xd0 [ssb]
        [<c1269f4e>] gpiochip_add+0xee/0x300
        [<fd1f78bd>] ? ssb_pcicore_serdes_workaround+0xfd/0x140 [ssb]
        [<fd1f7e39>] ssb_gpio_init+0x89/0xa0 [ssb]
        [<fd1f0bd8>] ssb_attach_queued_buses+0xc8/0x2d0 [ssb]
        [<fd1f0f65>] ssb_bus_register+0x185/0x1f0 [ssb]
        [<fd1f3120>] ? ssb_pci_xtal+0x220/0x220 [ssb]
        [<fd1f106c>] ssb_bus_pcibus_register+0x2c/0x80 [ssb]
        [<fd1f40dc>] ssb_pcihost_probe+0x9c/0x110 [ssb]
        [<c1276c8f>] pci_device_probe+0x6f/0xc0
        [<c11bdb55>] ? sysfs_create_link+0x25/0x40
        [<c131d8b9>] driver_probe_device+0x79/0x360
        [<c1276512>] ? pci_match_device+0xb2/0xc0
        [<c131dc51>] __driver_attach+0x71/0x80
        [<c131dbe0>] ? __device_attach+0x40/0x40
        [<c131bd87>] bus_for_each_dev+0x47/0x80
        [<c131d3ae>] driver_attach+0x1e/0x20
        [<c131dbe0>] ? __device_attach+0x40/0x40
        [<c131d007>] bus_add_driver+0x157/0x230
        [<c131e219>] driver_register+0x59/0xe0
        ...
      
      Fix this by checking chip->dev pointer against NULL first. Also we can now
      remove redundant check in acpi_gpiochip_request/free_interrupts().
      Reported-by: NSabrina Dubroca <sd@queasysnail.net>
      Signed-off-by: NMika Westerberg <mika.westerberg@linux.intel.com>
      Tested-by: NSabrina Dubroca <sd@queasysnail.net>
      Acked-by: NAlexandre Courbot <acourbot@nvidia.com>
      Tested-by: NJosh Boyer <jwboyer@fedoraproject.org>
      Signed-off-by: NLinus Walleij <linus.walleij@linaro.org>
      e9595f84
  30. 15 3月, 2014 1 次提交
    • M
      gpio / ACPI: Add support for ACPI GPIO operation regions · 473ed7be
      Mika Westerberg 提交于
      GPIO operation regions is a new feature introduced in ACPI 5.0
      specification. This feature adds a way for platform ASL code to call back
      to OS GPIO driver and toggle GPIO pins.
      
      An example ASL code from Lenovo Miix 2 tablet with only relevant part
      listed:
      
       Device (\_SB.GPO0)
       {
           Name (AVBL, Zero)
           Method (_REG, 2, NotSerialized)
           {
               If (LEqual (Arg0, 0x08))
               {
                   // Marks the region available
                   Store (Arg1, AVBL)
               }
           }
      
           OperationRegion (GPOP, GeneralPurposeIo, Zero, 0x0C)
           Field (GPOP, ByteAcc, NoLock, Preserve)
           {
               Connection (
                   GpioIo (Exclusive, PullDefault, 0, 0, IoRestrictionOutputOnly,
                           "\\_SB.GPO0", 0x00, ResourceConsumer,,)
                   {
                       0x003B
                   }
               ),
               SHD3,   1,
           }
       }
      
       Device (SHUB)
       {
           Method (_PS0, 0, Serialized)
           {
               If (LEqual (\_SB.GPO0.AVBL, One))
               {
                   Store (One, \_SB.GPO0.SHD3)
                   Sleep (0x32)
               }
           }
           Method (_PS3, 0, Serialized)
           {
               If (LEqual (\_SB.GPO0.AVBL, One))
               {
                   Store (Zero, \_SB.GPO0.SHD3)
               }
           }
       }
      
      How this works is that whenever _PS0 or _PS3 method is run (typically when
      SHUB device is transitioned to D0 or D3 respectively), ASL code checks if
      the GPIO operation region is available (\_SB.GPO0.AVBL). If it is we go and
      store either 0 or 1 to \_SB.GPO0.SHD3.
      
      Now, when ACPICA notices ACPI GPIO operation region access (the store
      above) it will call acpi_gpio_adr_space_handler() that then toggles the
      GPIO accordingly using standard gpiolib interfaces.
      
      Implement the support by registering GPIO operation region handlers for all
      GPIO devices that have an ACPI handle. First time the GPIO is used by the
      ASL code we make sure that the GPIO stays requested until the GPIO chip
      driver itself is unloaded. If we find out that the GPIO is already
      requested we just toggle it according to the value got from ASL code.
      Signed-off-by: NMika Westerberg <mika.westerberg@linux.intel.com>
      Signed-off-by: NLinus Walleij <linus.walleij@linaro.org>
      473ed7be
  31. 13 3月, 2014 1 次提交
    • M
      gpio / ACPI: Rework ACPI GPIO event handling · 6072b9dc
      Mika Westerberg 提交于
      The current ACPI GPIO event handling code was never tested against real
      hardware with functioning GPIO triggered events (at the time such hardware
      wasn't available). Thus it misses certain things like requesting the GPIOs
      properly, passing correct flags to the interrupt handler and so on.
      
      This patch reworks ACPI GPIO event handling so that we:
      
       1) Use struct acpi_gpio_event for all GPIO signaled events.
       2) Switch to use GPIO descriptor API and request GPIOs by calling
          gpiochip_request_own_desc() that we added in a previous patch.
       3) Pass proper flags from ACPI GPIO resource to request_threaded_irq().
      
      Also instead of open-coding the _AEI iteration loop we can use
      acpi_walk_resources(). This simplifies the code a bit and fixes memory leak
      that was caused by missing kfree() for buffer returned by
      acpi_get_event_resources().
      
      Since the remove path now calls gpiochip_free_own_desc() which takes GPIO
      spinlock we need to call acpi_gpiochip_remove() outside of that lock
      (analogous to acpi_gpiochip_add() path where the lock is released before
      those funtions are called).
      Signed-off-by: NMika Westerberg <mika.westerberg@linux.intel.com>
      Reviewed-by: NRafael J. Wysocki <rafael.j.wysocki@intel.com>
      Signed-off-by: NLinus Walleij <linus.walleij@linaro.org>
      6072b9dc